/// <summary> /// Search real intersections of bsp node /// </summary> /// <param name="node"></param> private void SearchRealIntersectionsOfNode(CurveBspNode node, List <IntersectionInfo> intersections, HashSet <CurveVertex> vertexIntersects, bool includeInline) { var segments = node.Segments; foreach (var bspSegment in segments) { if (bspSegment.StartSplitInfos != null) { foreach (var splitInfo in bspSegment.StartSplitInfos) { var intersection = CreateRealIntersectionInfo(splitInfo, bspSegment.LineSegment.StartPoint, bspSegment.EntityId, vertexIntersects); if (intersection != null) { intersections.Add(intersection); } } } if (bspSegment.EndSplitInfos != null) { foreach (var splitInfo in bspSegment.EndSplitInfos) { var intersection = CreateRealIntersectionInfo(splitInfo, bspSegment.LineSegment.EndPoint, bspSegment.EntityId, vertexIntersects); if (intersection != null) { intersections.Add(intersection); } } } } // Inline segments's comparasion if (segments.Length > 1 && includeInline) { var inlineIntersections = InlineSegmentsIntersections(segments); intersections.AddRange(inlineIntersections); } if (node.LeftChild != null) { SearchRealIntersectionsOfNode(node.LeftChild, intersections, vertexIntersects, includeInline); } if (node.RightChild != null) { SearchRealIntersectionsOfNode(node.RightChild, intersections, vertexIntersects, includeInline); } }
public Curve2dBspTree(IEnumerable <BspSegment> segments) { if (segments == null) { throw new ArgumentNullException("segments"); } int numProc = System.Environment.ProcessorCount; this._parallelDepth = -1; while (numProc >> ++this._parallelDepth > 1) { ; } this.Root = Create(segments, 0, null, false); }
void SearchNearSegmentsSegmentsOfNode(CurveBspNode node, HashSet <KeyValuePair <BspSegment, BspSegment> > result) { var segments = node.Segments; foreach (var bspSegment in segments) { var originalestTarget = GetOriginalSourceBspSegment(bspSegment); if (bspSegment.StartSplitInfos != null) { foreach (var splitInfo in bspSegment.StartSplitInfos) { // Self intersect is ignored. if (splitInfo.SourceSegment.EntityId == bspSegment.EntityId) { continue; } // If not real intersection. var extendType = CurveIntersectUtils.ParamToExtendTypeForLine(splitInfo.SourceParam); if (extendType != ExtendType.None) { continue; } var originalestSource = GetOriginalSourceBspSegment(splitInfo.SourceSegment); if (result.Contains(new KeyValuePair <BspSegment, BspSegment>(originalestSource, originalestTarget)) || result.Contains(new KeyValuePair <BspSegment, BspSegment>(originalestTarget, originalestSource))) { continue; } result.Add(new KeyValuePair <BspSegment, BspSegment>(originalestSource, originalestTarget)); } } if (bspSegment.EndSplitInfos != null) { foreach (var splitInfo in bspSegment.EndSplitInfos) { // Self intersect is ignored. if (splitInfo.SourceSegment.EntityId == bspSegment.EntityId) { continue; } // If not real intersection. var extendType = CurveIntersectUtils.ParamToExtendTypeForLine(splitInfo.SourceParam); if (extendType != ExtendType.None) { continue; } var originalestSource = GetOriginalSourceBspSegment(splitInfo.SourceSegment); if (result.Contains(new KeyValuePair <BspSegment, BspSegment>(originalestSource, originalestTarget)) || result.Contains(new KeyValuePair <BspSegment, BspSegment>(originalestTarget, originalestSource))) { continue; } result.Add(new KeyValuePair <BspSegment, BspSegment>(originalestSource, originalestTarget)); } } } if (node.LeftChild != null) { SearchNearSegmentsSegmentsOfNode(node.LeftChild, result); } if (node.RightChild != null) { SearchNearSegmentsSegmentsOfNode(node.RightChild, result); } }
private CurveBspNode Create(IEnumerable <BspSegment> segments, int depth, CurveBspNode parent, bool isLeft) { if (segments == null || !segments.Any()) { return(null); } BspSegment segment = null; // We need to make sure segment is not a point foreach (var bspSegment in segments) { var startPoint = bspSegment.LineSegment.StartPoint; var endPoint = bspSegment.LineSegment.EndPoint; if (startPoint != endPoint) { segment = bspSegment; break; } } if (segment == null) { return(null); } var node = new CurveBspNode(segment); node.Depth = depth; node.Parent = parent; node.IsLeft = isLeft; // Left segments var leftSegments = new List <BspSegment>(); // Right segments var rightSegments = new List <BspSegment>(); // Inline segments var inlineSegments = new List <BspSegment>(); inlineSegments.Add(segment); var leftSegsStartOnSplitLine = new List <BspSegment>(); var leftSegsEndOnSplitLine = new List <BspSegment>(); var rightSegsStartOnSplitLine = new List <BspSegment>(); var rightSegsEndOnSplitLine = new List <BspSegment>(); foreach (var nextSegment in segments) { if (nextSegment == segment) { continue; } BspSegment left, right, inline; double startVal, endVal; SplitSegment(segment, nextSegment, out left, out right, out inline, out startVal, out endVal); if (left != null) { leftSegments.Add(left); } if (right != null) { rightSegments.Add(right); } if (inline != null) { inlineSegments.Add(inline); } if (left != null && right == null) { if (startVal.EqualsWithTolerance(0.0)) { leftSegsStartOnSplitLine.Add(left); } else if (endVal.EqualsWithTolerance(0.0)) { leftSegsEndOnSplitLine.Add(left); } } else if (left == null && right != null) { if (startVal.EqualsWithTolerance(0.0)) { rightSegsStartOnSplitLine.Add(right); } else if (endVal.EqualsWithTolerance(0.0)) { rightSegsEndOnSplitLine.Add(right); } } } // Update node's segment's information. if (inlineSegments.Count > 1) { node.Segments = inlineSegments.ToArray(); // Update all left segments and right segment's split info foreach (var leftSegment in leftSegments) { UpdateSplitInfoForInlineSegments(leftSegment, inlineSegments); } foreach (var rightSegment in rightSegments) { UpdateSplitInfoForInlineSegments(rightSegment, inlineSegments); } } // if (leftSegsStartOnSplitLine.Count > 0) { foreach (var bspSegment in leftSegsStartOnSplitLine) { var startPoint = bspSegment.LineSegment.StartPoint; var rightStartSegs = rightSegsStartOnSplitLine.Where( it => it.LineSegment.StartPoint.IsEqualTo(startPoint)); var rightEndSegs = rightSegsEndOnSplitLine.Where( it => it.LineSegment.EndPoint.IsEqualTo(startPoint)); var splitInfos = new List <BspSplitInfo>(); foreach (var rightStartSeg in rightStartSegs) { splitInfos.Add(new BspSplitInfo() { IsSplitted = false, SourceSegment = rightStartSeg, SourceParam = 0.0 }); } foreach (var rightEndSeg in rightEndSegs) { splitInfos.Add(new BspSplitInfo() { IsSplitted = false, SourceSegment = rightEndSeg, SourceParam = 1.0 }); } if (splitInfos.Count > 0) { if (bspSegment.StartSplitInfos != null && bspSegment.StartSplitInfos.Length > 0) { splitInfos.InsertRange(0, bspSegment.StartSplitInfos); } bspSegment.StartSplitInfos = splitInfos.ToArray(); } } } if (leftSegsEndOnSplitLine.Count > 0) { foreach (var bspSegment in leftSegsEndOnSplitLine) { var endPoint = bspSegment.LineSegment.EndPoint; var rightStartSegs = rightSegsStartOnSplitLine.Where( it => it.LineSegment.StartPoint.IsEqualTo(endPoint)); var rightEndSegs = rightSegsEndOnSplitLine.Where( it => it.LineSegment.EndPoint.IsEqualTo(endPoint)); var splitInfos = new List <BspSplitInfo>(); foreach (var rightStartSeg in rightStartSegs) { splitInfos.Add(new BspSplitInfo() { IsSplitted = false, SourceSegment = rightStartSeg, SourceParam = 0.0 }); } foreach (var rightEndSeg in rightEndSegs) { splitInfos.Add(new BspSplitInfo() { IsSplitted = false, SourceSegment = rightEndSeg, SourceParam = 1.0 }); } if (splitInfos.Count > 0) { if (bspSegment.EndSplitInfos != null && bspSegment.EndSplitInfos.Length > 0) { splitInfos.InsertRange(0, bspSegment.EndSplitInfos); } bspSegment.EndSplitInfos = splitInfos.ToArray(); } } } if (depth < this._parallelDepth) { // Parellel to improve performance. System.Threading.Tasks.Parallel.Invoke( () => node.LeftChild = Create(leftSegments, depth + 1, node, true), () => node.RightChild = Create(rightSegments, depth + 1, node, false)); } else { node.LeftChild = Create(leftSegments, depth + 1, node, true); node.RightChild = Create(rightSegments, depth + 1, node, false); } return(node); }