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
        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.º 3
0
        public void Execute()
        {
            Debug.Assert(ValidExecutionState(), "Called convex checker execution in an invalid state");
            if (States.CurrentSegment == null)
            {
                throw new NullReferenceException("Forgot to load the segments in, current segment is null");
            }

            States.State = ConvexState.Traversing;

            // We traverse around the suspected enclosed polygon with each of
            // the following rules:
            //    - NextSeg is the next attached segment in the cycle iteration
            //    - CurrentSeg and NextSeg share a 'pivot' vertex
            //    - CurrentEndpoint is the endpoint on the current segment that
            //      is not the pivot vertex
            //    - The third vertex is the vertex on the NextSeg that is not
            //      the pivot
            //
            // This is summed up by this image (assuming clockwise traversal):
            //
            //    Current endpoint             Pivot (aka: Opposite endpoint)
            //         (0)-----[CurrentSeg]-----(1)
            //                                   |
            //                                   |NextSeg
            //                                   |
            //                                  (2) Third vertex
            //
            // Each number is the vertex in the rotation order.
            BspSegment currentSeg   = States.CurrentSegment;
            Vec2D      firstVertex  = currentSeg[States.CurrentEndpoint].Struct();
            Vec2D      secondVertex = currentSeg.Opposite(States.CurrentEndpoint).Struct();
            int        pivotIndex   = currentSeg.OppositeIndex(States.CurrentEndpoint);

            // Since we know there are exactly two lines at each endpoint, we
            // can select the next segment by whichever of the two is not the
            // current segment.
            List <ConvexTraversalPoint> linesAtPivot = VertexMap[pivotIndex];

            Debug.Assert(linesAtPivot.Count == 2, "Expected two lines for every endpoint");

            BspSegment nextSeg = linesAtPivot[0].Segment;

            if (ReferenceEquals(currentSeg, nextSeg))
            {
                nextSeg = linesAtPivot[1].Segment;
            }

            Endpoint nextSegPivotEndpoint = nextSeg.EndpointFrom(pivotIndex);
            Vec2D    thirdVertex          = nextSeg.Opposite(nextSegPivotEndpoint).Struct();

            Rotation rotation = Seg2D.GetRotation(firstVertex, secondVertex, thirdVertex);

            if (rotation != Rotation.On)
            {
                if (States.Rotation == Rotation.On)
                {
                    States.Rotation = rotation;
                }
                else if (States.Rotation != rotation)
                {
                    States.State = ConvexState.FinishedIsSplittable;
                    return;
                }
            }

            States.ConvexTraversal.AddTraversal(currentSeg, States.CurrentEndpoint);
            States.CurrentSegment  = nextSeg;
            States.CurrentEndpoint = nextSegPivotEndpoint;
            States.SegsVisited++;

            if (!CompletedTraversalCycle(nextSeg))
            {
                return;
            }

            // If we never rotated, it's a straight degenerate line (and not a single
            // convex polygon).
            if (States.Rotation == Rotation.On)
            {
                States.State = ConvexState.FinishedIsDegenerate;
                return;
            }

            bool isConvex = (States.SegsVisited == States.TotalSegs);

            States.State = (isConvex ? ConvexState.FinishedIsConvex : ConvexState.FinishedIsSplittable);
        }