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); }
/// <summary> /// Checks if the indices from the values provided cross the void or /// not, where the void is the space outside the map. /// </summary> /// <param name="first">The index of the first segment.</param> /// <param name="second">The actual vertex coordinate of the /// second segment.</param> /// <returns>True if the two vertices are crossing the void, false if /// it is inside the map.</returns> public bool CheckCrossingVoid(BspVertex first, BspVertex second) { if (vertexToJunction.TryGetValue(first, out Junction junction)) { return(!junction.BetweenWedge(second.Struct())); } return(false); }
/// <summary> /// Tells the junction classifier that we will not be adding anymore /// junctions from `Add()` anymore. It will then compile all the /// junctions. /// </summary> /// <remarks> /// The only way to add new junctions after calling this should be /// through <see cref="AddSplitJunction"/>. This is unfortunately /// needed since creating the junctions on the fly while adding new /// segments would be extra work and extra code. It might be worth /// doing one day however since it is a code smell due to requiring /// users to know about this function. /// </remarks> private void NotifyDoneAdding() { foreach (var vertexJunctionPair in vertexToJunction) { BspVertex vertex = vertexJunctionPair.Key; Junction junction = vertexJunctionPair.Value; if (junction.HasUnexpectedSegCount()) { Log.Warn($"BSP junction at ({vertex}) has wrong amount of one-sided lines, BSP tree likely to be malformed"); } junction.GenerateWedges(); } }
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); }
/// <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); }
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); } }
/// <summary> /// Creates an index/time pair. /// </summary> /// <param name="vertex">The vertex.</param> /// <param name="splitterTime">The time this is relative to the /// splitter.</param> public VertexSplitterTime(BspVertex vertex, double splitterTime) { Vertex = vertex; SplitterTime = splitterTime; }