Ejemplo n.º 1
0
        protected void HandleEndpointIntersectionSplit(BspSegment splitter, BspSegment segmentToSplit, Endpoint endpoint)
        {
            // We know that the endpoint argument is the vertex that was
            // intersected by the splitter. This means the other endpoint is
            // on the left or the right side of the splitter, so we'll use
            // that 'opposite' endpoint to check the side we should place the
            // segment on.
            BspVertex oppositeVertex = segmentToSplit.Opposite(endpoint);
            Rotation  side           = splitter.ToSide(oppositeVertex);

            Debug.Assert(side != Rotation.On, "Ambiguous split, segment too small to determine splitter side");

            if (side == Rotation.Right)
            {
                States.RightSegments.Add(segmentToSplit);
            }
            else
            {
                States.LeftSegments.Add(segmentToSplit);
            }

            BspVertex vertex = segmentToSplit.VertexFrom(endpoint);

            States.CollinearVertices.Add(vertex);
        }
Ejemplo n.º 2
0
        protected void HandleCollinearSegment(BspSegment splitter, BspSegment segment)
        {
            Debug.Assert(!segment.IsMiniseg, "Should never be collinear to a miniseg");

            States.CollinearVertices.Add(segment.StartVertex);
            States.CollinearVertices.Add(segment.EndVertex);

            // We don't want the back side of a one-sided line (which doesn't
            // exist) to be visible to the side of the partition that shouldn't
            // care about it.
            if (segment.OneSided)
            {
                if (splitter.SameDirection(segment))
                {
                    States.RightSegments.Add(segment);
                }
                else
                {
                    States.LeftSegments.Add(segment);
                }
            }
            else
            {
                States.RightSegments.Add(segment);
                States.LeftSegments.Add(segment);
            }
        }
Ejemplo n.º 3
0
        private static List <SubsectorEdge> CreateSubsectorEdges(ConvexTraversal convexTraversal, Rotation rotation)
        {
            List <ConvexTraversalPoint> traversal = convexTraversal.Traversal;

            Debug.Assert(traversal.Count >= 3, "Traversal must yield at least a triangle in size");

            List <SubsectorEdge> subsectorEdges = new List <SubsectorEdge>();

            ConvexTraversalPoint firstTraversal = traversal.First();
            Vec2D startPoint = firstTraversal.Vertex;

            foreach (ConvexTraversalPoint traversalPoint in traversal)
            {
                BspSegment segment            = traversalPoint.Segment;
                Vec2D      endingPoint        = segment.Opposite(traversalPoint.Endpoint).Struct();
                bool       traversedFrontSide = CheckIfTraversedFrontSide(traversalPoint, rotation);

                SubsectorEdge edge = new SubsectorEdge(startPoint, endingPoint, segment.Line.Value, traversedFrontSide);
                subsectorEdges.Add(edge);

                Debug.Assert(startPoint != endingPoint, "Traversal produced the wrong endpoint indices");
                startPoint = endingPoint;
            }

            Debug.Assert(subsectorEdges.Count == traversal.Count, "Added too many subsector edges in traversal");
            return(subsectorEdges);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// To be called every time a one sided segment is discovered when
        /// reading the valid map entry collection. After that, then the
        /// <see cref="NotifyDoneAdding"/> should be invoked.
        /// </summary>
        /// <remarks>
        /// This does not make any junctions, that has to be held off until
        /// later for both code cleanliness and performance reasons.
        /// </remarks>
        /// <param name="segment">The segment to track.</param>
        private void Add(BspSegment segment)
        {
            if (!segment.OneSided)
            {
                return;
            }

            if (!vertexToJunction.TryGetValue(segment.EndVertex, out Junction endJunction))
            {
                endJunction = new Junction();
                vertexToJunction.Add(segment.EndVertex, endJunction);
            }

            Debug.Assert(!endJunction.InboundSegments.Contains(segment), "Adding same segment to inbound junction twice");
            endJunction.InboundSegments.Add(segment);

            if (!vertexToJunction.TryGetValue(segment.StartVertex, out Junction startJunction))
            {
                startJunction = new Junction();
                vertexToJunction.Add(segment.StartVertex, startJunction);
            }

            Debug.Assert(!startJunction.OutboundSegments.Contains(segment), "Adding same segment to outbound junction twice");
            startJunction.OutboundSegments.Add(segment);
        }
Ejemplo n.º 5
0
        public void Execute()
        {
            Debug.Assert(States.State != SplitterState.Finished, "Trying to run a split checker when finished");
            Debug.Assert(States.CurrentSegmentIndex < States.Segments.Count, "Out of range split calculator segment index");
            BspSegment splitter = States.Segments[States.CurrentSegmentIndex];

            if (!seenCollinear.Get(splitter.CollinearIndex))
            {
                States.CurrentSegScore = CalculateScore(splitter);

                if (States.CurrentSegScore < States.BestSegScore)
                {
                    Debug.Assert(!splitter.IsMiniseg, "Should never be selecting a miniseg as a splitter");
                    States.BestSegScore = States.CurrentSegScore;
                    States.BestSplitter = splitter;
                }

                seenCollinear.Set(splitter.CollinearIndex, true);
            }

            States.CurrentSegmentIndex++;

            bool hasSegmentsLeft = States.CurrentSegmentIndex < States.Segments.Count;

            States.State = (hasSegmentsLeft ? SplitterState.Working : SplitterState.Finished);
        }
Ejemplo n.º 6
0
        private static double CalculateDistanceToNearestEndpoint(BspSegment segment, double tSegment)
        {
            Vec2D endpointVertex    = (tSegment < 0.5 ? segment.Start.Struct() : segment.End.Struct());
            Vec2D intersectionPoint = segment.FromTime(tSegment);

            return(endpointVertex.Distance(intersectionPoint));
        }
Ejemplo n.º 7
0
        /// <summary>
        /// Creates a wedge from the inbound and outbound segments.
        /// </summary>
        /// <param name="inbound">The inbound segment, which means its ending
        /// point is shared with the outbound starting vertex.</param>
        /// <param name="outbound">The outbound segment, which means its
        /// starting point matches the inbounds ending point.</param>
        public JunctionWedge(BspSegment inbound, BspSegment outbound)
        {
            Debug.Assert(inbound.EndIndex == outbound.StartIndex, "The inbound and outbound do not meet at a shared vertex");

            Inbound  = inbound;
            Outbound = outbound;
            Obtuse   = !inbound.OnRight(outbound);
        }
Ejemplo n.º 8
0
 protected void HandleSegmentOnSide(BspSegment splitter, BspSegment segmentToSplit)
 {
     if (splitter.OnRight(segmentToSplit))
     {
         States.RightSegments.Add(segmentToSplit);
     }
     else
     {
         States.LeftSegments.Add(segmentToSplit);
     }
 }
Ejemplo n.º 9
0
        public void Execute()
        {
            Debug.Assert(States.State != PartitionState.Finished, "Trying to partition when it's already completed");
            if (States.Splitter == null)
            {
                throw new NullReferenceException("Unexpected null splitter");
            }

            BspSegment splitter   = States.Splitter;
            BspSegment segToSplit = States.SegsToSplit[States.CurrentSegToPartitionIndex];

            States.CurrentSegToPartitionIndex++;

            bool doneAllSplitting = (States.CurrentSegToPartitionIndex >= States.SegsToSplit.Count);

            States.State = (doneAllSplitting ? PartitionState.Finished : PartitionState.Working);

            if (ReferenceEquals(segToSplit, splitter))
            {
                HandleSplitter(splitter);
                return;
            }

            if (segToSplit.Parallel(splitter))
            {
                HandleParallelSegment(splitter, segToSplit);
                return;
            }

            bool splits = splitter.IntersectionAsLine(segToSplit, out double splitterTime, out double segmentTime);

            Debug.Assert(splits, "A non-parallel line should intersect");

            // Note that it is possible for two segments that share endpoints
            // to calculate intersections to each other outside of the normal
            // range due (ex: D2M29 has one at approx t = 1.0000000000000002).
            // Because they share a point and aren't parallel, then the line
            // must be on one of the sides and isn't intersecting. This will
            // also avoid very small cuts as well since we definitely do not
            // want a cut happening at the pathological time seen above!
            if (splitter.SharesAnyEndpoints(segToSplit))
            {
                HandleSegmentOnSide(splitter, segToSplit);
            }
            else if (segmentTime.InNormalRange())
            {
                HandleSplit(splitter, segToSplit, segmentTime, splitterTime);
            }
            else
            {
                HandleSegmentOnSide(splitter, segToSplit);
            }
        }
Ejemplo n.º 10
0
        private void SetStateLoadedInfo(List <BspSegment> segments)
        {
            // We're just picking a random vertex, and taking some random segment that
            // comes out of that vertex.
            int randomVertexIndex = VertexMap.Keys.First();
            ConvexTraversalPoint randomLinePoint = VertexMap[randomVertexIndex].First();
            BspSegment           startSegment    = randomLinePoint.Segment;

            States.CurrentEndpoint = randomLinePoint.Endpoint;
            States.StartSegment    = startSegment;
            States.CurrentSegment  = startSegment;
            States.TotalSegs       = segments.Count;
        }
Ejemplo n.º 11
0
        protected void HandleSplit(BspSegment splitter, BspSegment segmentToSplit, double segmentTime, double splitterTime)
        {
            Debug.Assert(!BetweenEndpoints(splitterTime), "Should not have a segment crossing the splitter");

            if (IntersectionTimeAtEndpoint(segmentToSplit, segmentTime, out Endpoint endpoint))
            {
                HandleEndpointIntersectionSplit(splitter, segmentToSplit, endpoint);
            }
            else
            {
                HandleNonEndpointIntersectionSplit(splitter, segmentToSplit, segmentTime);
            }
        }
Ejemplo n.º 12
0
        private static bool IsEffectivelyRightOfSplitter(BspSegment splitter, BspSegment segment)
        {
            Rotation startSide = splitter.ToSide(segment.Start);

            if (startSide == Rotation.On)
            {
                Rotation endSide = splitter.ToSide(segment.End);
                Debug.Assert(endSide != Rotation.On, "Splitter and segment are too close to determine sides");

                return(endSide == Rotation.Right);
            }

            return(startSide == Rotation.Right);
        }
Ejemplo n.º 13
0
 protected void HandleParallelSegment(BspSegment splitter, BspSegment segment)
 {
     if (splitter.Collinear(segment))
     {
         HandleCollinearSegment(splitter, segment);
     }
     else if (splitter.OnRight(segment.Start))
     {
         States.RightSegments.Add(segment);
     }
     else
     {
         States.LeftSegments.Add(segment);
     }
 }
Ejemplo n.º 14
0
        public void Load(BspSegment splitter, HashSet <BspVertex> collinearVertices)
        {
            Debug.Assert(collinearVertices.Count >= 2, "Requires two or more vertices for miniseg generation (the splitter should have contributed two)");

            States = new MinisegStates();

            foreach (BspVertex vertex in collinearVertices)
            {
                double             splitterTime       = splitter.ToTime(vertex);
                VertexSplitterTime vertexSplitterTime = new VertexSplitterTime(vertex, splitterTime);
                States.Vertices.Add(vertexSplitterTime);
            }

            States.Vertices.Sort();
        }
Ejemplo n.º 15
0
        public void Load(BspSegment splitter, List <BspSegment> segments)
        {
            if (splitter == null)
            {
                throw new NullReferenceException("Invalid split calculator state (likely convex polygon that was classified as splittable wrongly)");
            }
            Debug.Assert(!splitter.IsMiniseg, "Cannot have a miniseg as a splitter");

            // OPTIMIZE: A better way of finding segments to split would be to
            // take the result when we did the checking for the best splitter
            // and remember having all the segments to be split for the best
            // segment. We throw away all that work, and then do an O(n) check
            // again on top of it.
            States = new PartitionStates {
                Splitter = splitter, SegsToSplit = segments
            };
        }
Ejemplo n.º 16
0
        private void AddSegmentEndpoint(BspSegment segment, int index, Endpoint endpoint)
        {
            ConvexTraversalPoint linePoint = new ConvexTraversalPoint(segment, endpoint);

            if (VertexMap.TryGetValue(index, out List <ConvexTraversalPoint> linePoints))
            {
                linePoints.Add(linePoint);
                VertexTracker.Track(linePoints.Count);
            }
            else
            {
                List <ConvexTraversalPoint> newLinePoints = new List <ConvexTraversalPoint> {
                    linePoint
                };
                VertexMap.Add(index, newLinePoints);
                VertexTracker.Track(newLinePoints.Count);
            }
        }
Ejemplo n.º 17
0
        private List <BspSegment> ReadLinesFrom(MapData map)
        {
            List <BspSegment> segments = new List <BspSegment>();

            foreach (MapLinedef line in map.Linedefs)
            {
                MapVertex startMapVertex = map.Vertices[line.StartVertex];
                MapVertex endMapVertex   = map.Vertices[line.EndVertex];

                BspVertex start = VertexAllocator[startMapVertex.Struct()];
                BspVertex end   = VertexAllocator[endMapVertex.Struct()];

                BspSegment segment = SegmentAllocator.GetOrCreate(start, end, line);
                segments.Add(segment);
            }

            return(segments);
        }
Ejemplo n.º 18
0
        protected bool IntersectionTimeAtEndpoint(BspSegment segmentToSplit, double segmentTime, out Endpoint endpoint)
        {
            // Note that we cannot attempt to look up the endpoint, because it
            // is possible that it may detect an unrelated vertex from a split
            // on another side which happens to be right where the split would
            // happen.
            //
            // For example, suppose a perpendicular split is going to occur.
            // The vertical splitter line would intersect it like so at the X:
            //
            //      o
            //      | Splitter
            //      o
            //
            // o----X----o
            //   Segment
            //
            // Now suppose that the bottom side of `Segment` was recursed on
            // first, and some splitter happened to already create a vertex at
            // the exact point that `Splitter` would hit `Segment` on the X. If
            // we were to check the vertex allocator for whether a vertex is
            // near/at X or not, it will return true. However this split will
            // clearly not be hitting an endpoint of `Segment`, so we'd get a
            // 'true' result when it is definitely not intersecting at/near an
            // endpoint.
            //
            // Therefore our only solution is to do it by checking distances.
            Vec2D vertex = segmentToSplit.FromTime(segmentTime);

            if (vertex.Distance(segmentToSplit.Start) <= BspConfig.VertexWeldingEpsilon)
            {
                endpoint = Endpoint.Start;
                return(true);
            }

            if (vertex.Distance(segmentToSplit.End) <= BspConfig.VertexWeldingEpsilon)
            {
                endpoint = Endpoint.End;
                return(true);
            }

            endpoint = default;
            return(false);
        }
Ejemplo n.º 19
0
        private void ExecuteSegmentPartitioning()
        {
            switch (Partitioner.States.State)
            {
            case PartitionState.Loaded:
            case PartitionState.Working:
                Partitioner.Execute();
                break;

            case PartitionState.Finished:
                if (Partitioner.States.Splitter == null)
                {
                    throw new NullReferenceException("Unexpected null partition splitter");
                }
                BspSegment splitter = Partitioner.States.Splitter;
                MinisegCreator.Load(splitter, Partitioner.States.CollinearVertices);
                State = BspState.GeneratingMinisegs;
                break;
            }
        }
Ejemplo n.º 20
0
        /// <summary>
        /// A function called during BSP partitioning where we create a new
        /// junction when we split a one sided line in two.
        /// </summary>
        /// <param name="inboundSegment">The inbound segment.</param>
        /// <param name="outboundSegment">The outbound segment.</param>
        public void AddSplitJunction(BspSegment inboundSegment, BspSegment outboundSegment)
        {
            Debug.Assert(!ReferenceEquals(inboundSegment, outboundSegment), "Trying to add the same segment as an inbound/outbound junction");
            BspVertex middleVertex = inboundSegment.EndVertex;

            Debug.Assert(outboundSegment.StartVertex == middleVertex, "Adding split junction where inbound/outbound segs are not connected");
            Debug.Assert(!vertexToJunction.ContainsKey(middleVertex), "When creating a split, the middle vertex shouldn't already exist as a junction");

            // We create new junctions because this function is called from a
            // newly created split. This means the middle vertex is new and the
            // junction cannot exist by virtue of the pivot point never having
            // existed.
            Junction junction = new Junction();

            vertexToJunction[middleVertex] = junction;

            junction.InboundSegments.Add(inboundSegment);
            junction.OutboundSegments.Add(outboundSegment);
            junction.AddWedge(inboundSegment, outboundSegment);
        }
Ejemplo n.º 21
0
        protected void HandleSplitter(BspSegment splitter)
        {
            // The reason we add these is because we (frequently) have cases
            // where there is only one intersection from the splitter to some
            // other line. Usually we relied on the endpoints of lines counting
            // as an intersection and causing them to end up in the collinear
            // vertex set, but we had to change that due to rounding issues.
            //
            // This change meant that it no longer recognized the endpoints of
            // the lines attached to the splitter as ones that will end up in
            // the collinear set. We have to provide these ones here so that
            // miniseg generation has at least one reference point.
            States.CollinearVertices.Add(splitter.StartVertex);
            States.CollinearVertices.Add(splitter.EndVertex);

            States.RightSegments.Add(splitter);
            if (splitter.TwoSided)
            {
                States.LeftSegments.Add(splitter);
            }
        }
Ejemplo n.º 22
0
        protected void HandleMinisegGeneration(BspVertex first, BspVertex second)
        {
            States.VoidStatus = VoidStatus.NotInVoid;

            // If a segment exists for the vertices then we're walking along a
            // segment that was collinear with the splitter, so we don't need a
            // miniseg.
            if (SegmentAllocator.ContainsSegment(first, second))
            {
                return;
            }

            if (JunctionClassifier.CheckCrossingVoid(first, second))
            {
                States.VoidStatus = VoidStatus.InVoid;
            }
            else
            {
                BspSegment miniseg = SegmentAllocator.GetOrCreate(first, second);
                States.Minisegs.Add(miniseg);
            }
        }
Ejemplo n.º 23
0
        /// <summary>
        /// Calculates a 'score', which is an arbitrary number that tells us
        /// how close the angle is for the wedge provided.
        /// </summary>
        /// <remarks>
        /// For example, if there were 3 segs A, B, and C, where we were
        /// trying to see whether AB has a smaller wedge than AC, if the
        /// score of AB is less than that of AC, it has a smaller angle.
        /// </remarks>
        /// <param name="inbound">The inbound segment.</param>
        /// <param name="outbound">The outbound segment.</param>
        /// <returns>A score that is to be used only for ordering reasons
        /// (where a lower score means it's a tighter angle than a larger
        /// score).</returns>
        private static double CalculateAngleScore(BspSegment inbound, BspSegment outbound)
        {
            Vec2D endToOriginPoint   = (inbound.Start - inbound.End).Struct();
            Vec2D startToOriginPoint = (outbound.End - outbound.Start).Struct();

            double dot      = startToOriginPoint.Dot(endToOriginPoint);
            double length   = startToOriginPoint.Length() * endToOriginPoint.Length();
            double cosTheta = dot / length;

            double score = cosTheta;

            if (inbound.OnRight(outbound.End))
            {
                score = -score;
            }
            else
            {
                score += 2.0;
            }

            return(score);
        }
Ejemplo n.º 24
0
        private bool IsProperlyConnectedEndpoint(BspSegment segment, Endpoint endpoint)
        {
            if (Traversal.Empty())
            {
                return(true);
            }

            ConvexTraversalPoint lastPoint    = Traversal.Last();
            BspSegment           lastSeg      = lastPoint.Segment;
            Endpoint             lastEndpoint = lastPoint.Endpoint;

            if (ReferenceEquals(segment, lastSeg))
            {
                Debug.Assert(false, "Trying to add the same segment twice");
                return(false);
            }

            // Because our traversal uses the first endpoint we reached, that
            // means the last segment's opposite endpoint should match this
            // segment's current endpoint. Graphically, this means:
            //
            // LastEndpoint  Endpoint
            //     o-----------o------------o
            //         LastSeg    Segment
            //
            // Notice that the opposite endpoint of LastEndpoint is equal to
            // the middle vertex labeled Endpoint. This is what we want to make
            // sure are equal since it is not a valid traversal if they do not
            // match.
            if (segment.IndexFrom(endpoint) != lastSeg.OppositeIndex(lastEndpoint))
            {
                Debug.Assert(false, "Expect a tail-to-head connection");
                return(false);
            }

            return(true);
        }
Ejemplo n.º 25
0
        /// <summary>
        /// Generates all the wedges from the tracked in/outbound segments.
        /// </summary>
        public void GenerateWedges()
        {
            // TODO: Is there a way we can get rid of having to explicitly call
            // this function? I don't like 'having to know to call functions'
            // on a class to make it work. Why not generate it lazily as we need
            // it?
            Debug.Assert(Wedges.Empty(), "Trying to create BSP junction wedges when they already were made");

            // This is a guard against malformed/dangling one-sided lines.
            if (OutboundSegments.Empty())
            {
                return;
            }

            // TODO: Since we know we have one or more outbound segments, we
            //       can ignore the check at the start. Any way LINQ can help
            //       us write this in a lot less lines of code?
            foreach (BspSegment inbound in InboundSegments)
            {
                BspSegment closestOutbound = OutboundSegments[0];
                double     bestScore       = CalculateAngleScore(inbound, closestOutbound);

                for (int i = 1; i < OutboundSegments.Count; i++)
                {
                    double score = CalculateAngleScore(inbound, OutboundSegments[i]);

                    if (score < bestScore)
                    {
                        bestScore       = score;
                        closestOutbound = OutboundSegments[i];
                    }
                }

                Wedges.Add(new JunctionWedge(inbound, closestOutbound));
            }
        }
Ejemplo n.º 26
0
        protected void HandleNonEndpointIntersectionSplit(BspSegment splitter, BspSegment segmentToSplit, double segmentTime)
        {
            // Note for the future: If we ever change to using pointers or some
            // kind of reference that invalidates on a list resizing (like a
            // std::vector in C++), this will lead to undefined behavior since
            // it will add new segments and cause them to become dangling.
            (BspSegment segA, BspSegment segB) = SegmentAllocator.Split(segmentToSplit, segmentTime);

            // Since we split the segment such that the line is:
            //
            //    Seg A  |  Seg B
            // [A]=======o=========[B]
            //           |
            //           | <-- Splitter
            //           X
            //
            // We can find which side of the splitter the segments are on by
            // looking at where [A] or [B] ended up. Since the split causes us
            // to know that the middle index is at the first segment's endpoint
            // (and the second segment start point), either or of these would
            // tell us which side the segment is on... and when we know which
            // one is on which side of the splitter, we automatically know the
            // other segment from the split is on the other.
            Rotation side = splitter.ToSide(segA.Start);

            // It may be possible that a split occurs so close to the endpoint
            // (by some unfortunate map geometry) which screws up detecting
            // which side we are on for the splitting. In such a case, we'll
            // try checking both endpoints to see if this is the case and make
            // our decision accordingly.
            if (side == Rotation.On)
            {
                Log.Warn("Very tight endpoint split perform with segment {0}", segmentToSplit);

                Rotation otherSide = splitter.ToSide(segmentToSplit.End);
                Debug.Assert(otherSide != Rotation.On, "Segment being split is too small to detect which side of the splitter it's on");
                side = (otherSide == Rotation.Left ? Rotation.Right : Rotation.Left);
            }

            if (side == Rotation.Right)
            {
                States.RightSegments.Add(segA);
                States.LeftSegments.Add(segB);
            }
            else
            {
                States.LeftSegments.Add(segA);
                States.RightSegments.Add(segB);
            }

            // The reason we know it's the end index of segA is because the
            // splitter always has the first seg splitting based on the start.
            // A corollary is that this would be equal to segB.getStartIndex()
            // since they are equal.
            States.CollinearVertices.Add(segA.EndVertex);

            if (segmentToSplit.OneSided)
            {
                JunctionClassifier.AddSplitJunction(segA, segB);
            }
        }
Ejemplo n.º 27
0
        /// <summary>
        /// Adds a new segment to the traversal. It is assumed that this is a
        /// valid addition.
        /// </summary>
        /// <param name="segment">The segment visited.</param>
        /// <param name="endpoint">The first vertex endpoint that was visited
        /// when traversing the convex subsector.</param>
        public void AddTraversal(BspSegment segment, Endpoint endpoint)
        {
            Debug.Assert(IsProperlyConnectedEndpoint(segment, endpoint), "Provided a disconnected segment");

            Traversal.Add(new ConvexTraversalPoint(segment, endpoint));
        }
Ejemplo n.º 28
0
 /// <summary>
 /// Creates a parent node from some split.
 /// </summary>
 /// <param name="left">The left child.</param>
 /// <param name="right">The right child.</param>
 /// <param name="splitter">The splitter that divided the children.
 /// </param>
 public BspNode(BspNode left, BspNode right, BspSegment splitter)
 {
     Left     = left;
     Right    = right;
     Splitter = splitter;
 }
Ejemplo n.º 29
0
 /// <summary>
 /// Adds a wedge, which implies we know that this is a valid segment.
 /// </summary>
 /// <remarks>
 /// This is intended for when a one-sided segment is split by some
 /// splitter, since we know that new split point will create a wedge.
 /// </remarks>
 /// <param name="inbound">The inbound segment.</param>
 /// <param name="outbound">The outbound segment.</param>
 public void AddWedge(BspSegment inbound, BspSegment outbound)
 {
     Wedges.Add(new JunctionWedge(inbound, outbound));
 }
Ejemplo n.º 30
0
 /// <summary>
 /// Creates a new traversal point.
 /// </summary>
 /// <param name="segment">The segment for the point we are referencing.
 /// </param>
 /// <param name="endpoint">The endpoint on the segment we are
 /// referencing.</param>
 public ConvexTraversalPoint(BspSegment segment, Endpoint endpoint)
 {
     Segment  = segment;
     Endpoint = endpoint;
     Vertex   = Segment.VertexFrom(Endpoint).Struct();
 }