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); }
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); }
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); } }