/// <summary> /// Gets the segment at the vertices provided if it exists, or creates /// it if not. /// </summary> /// <param name="start">The start vertex.</param> /// <param name="end">The end vertex.</param> /// <param name="line">The line (optional).</param> /// <returns>Either a newly allocated BSP segment, or the one that /// already exists with the information provided.</returns> public BspSegment GetOrCreate(BspVertex start, BspVertex end, IBspUsableLine line = null) { Debug.Assert(start != end, "Cannot create a segment that is a point"); (int smallerIndex, int largerIndex) = start.Index.MinMax(end.Index); if (segmentTable.TryGetValue(smallerIndex, out var largerValues)) { if (largerValues.TryGetValue(largerIndex, out int segIndex)) { return(segments[segIndex]); } largerValues[largerIndex] = segments.Count; int newCollinearIndex = GetCollinearIndex(start, end); return(CreateNewSegment(start, end, newCollinearIndex, line)); } var largerIndexDict = new Dictionary <int, int> { [largerIndex] = segments.Count }; int collinearIndex = GetCollinearIndex(start, end); segmentTable[smallerIndex] = largerIndexDict; return(CreateNewSegment(start, end, collinearIndex, line)); }
private BspSegment CreateNewSegment(BspVertex start, BspVertex end, int collinearIndex, IBspUsableLine line = null) { BspSegment seg = new BspSegment(start, end, collinearIndex, line); segments.Add(seg); return(seg); }
/// <summary> /// Checks if a segment exists with the start/end index combination. /// The order of the indices does not matter. /// </summary> /// <param name="start">The start index.</param> /// <param name="end">The end index.</param> /// <returns>True if a segment (start, end) or (end, start) exists in /// this allocator, false otherwise.</returns> public bool ContainsSegment(BspVertex start, BspVertex end) { (int smallerIndex, int largerIndex) = start.Index.MinMax(end.Index); if (segmentTable.TryGetValue(smallerIndex, out var largerValues)) { return(largerValues.ContainsKey(largerIndex)); } return(false); }
/// <summary> /// Performs a split on the segment at some time t (which should be in /// the normal range). /// </summary> /// <param name="seg">The segment to split.</param> /// <param name="t">The time to split at, which should be in (0, 1). It /// is an error for it to be equal to 0.0 or 1.0 as that would create /// a point for a segment (which is no longer a segment).</param> /// <returns>The two segments, where the first element is the segment /// from [start, middle], and the second segment element is from the /// [middle, end].</returns> public (BspSegment first, BspSegment second) Split(BspSegment seg, double t) { Debug.Assert(t > 0.0 && t < 1.0, "Trying to split BSP out of the (0.0, 1.0) range"); Vec2D middle = seg.FromTime(t); BspVertex middleVertex = vertexAllocator[middle]; BspSegment firstSeg = GetOrCreate(seg.StartVertex, middleVertex, seg.Line.Value); BspSegment secondSeg = GetOrCreate(middleVertex, seg.EndVertex, seg.Line.Value); return(firstSeg, secondSeg); }
private int GetCollinearIndex(BspVertex start, BspVertex end) { return(collinearTracker.GetOrCreateIndex(start, end)); }