private IntersectionInfo CreateRealIntersectionInfo(BspSplitInfo info, Point2d point, ObjectId targetId, HashSet <CurveVertex> vertexIntersects) { var extendType = CurveIntersectUtils.ParamToExtendTypeForLine(info.SourceParam); if (extendType != ExtendType.None) { return(null); } // Self intersection if ((info.SourceParam.EqualsWithTolerance(0.0) || info.SourceParam.EqualsWithTolerance(1.0)) && info.SourceSegment.EntityId == targetId) { // Need to take care of a special case: // Polyline AEB and CED intersect at E point // A\ D // \ | // \|_________B // C / E var vertexIntersect = new CurveVertex(new Point3d(point.X, point.Y, 0.0), info.SourceSegment.EntityId); // More than two intersects, then it's a self intersection. if (vertexIntersects.Contains(vertexIntersect)) { var intersection = new IntersectionInfo(info.SourceSegment.EntityId, ExtendType.None, targetId, ExtendType.None, new Point3d(point.X, point.Y, 0.0)); return(intersection); } vertexIntersects.Add(vertexIntersect); return(null); } else { var intersection = new IntersectionInfo(info.SourceSegment.EntityId, ExtendType.None, targetId, ExtendType.None, new Point3d(point.X, point.Y, 0.0)); return(intersection); } }
private void SplitSegment(BspSegment sourceSegment, BspSegment targetSegment, out BspSegment left, out BspSegment right, out BspSegment inline, out double startVal, out double endVal) { left = null; right = null; inline = null; startVal = 0.0; endVal = 0.0; var sourceStart = sourceSegment.LineSegment.StartPoint; var sourceEnd = sourceSegment.LineSegment.EndPoint; var targetStart = targetSegment.LineSegment.StartPoint; var targetEnd = targetSegment.LineSegment.EndPoint; // We need to make sure targetSegment is not a point if (targetStart == targetEnd) { return; } // Allan: I found IsLeft is not good to determine whether a point is left or right // if the segment is too long, so divide it by length. var sourceLength = sourceSegment.LineSegment.Length; var targetLength = targetSegment.LineSegment.Length; var length = sourceLength + targetLength; startVal = IsLeft(sourceStart, sourceEnd, targetStart) / length; endVal = IsLeft(sourceStart, sourceEnd, targetEnd) / length; //// For fixing some error by small values. //using (var switcher = new SafeToleranceOverride(0.0005, 0.0005)) //{ // if (targetStart.IsEqualTo(sourceStart) || targetStart.IsEqualTo(sourceEnd)) // startVal = 0.0; // if (targetEnd.IsEqualTo(sourceStart) || targetEnd.IsEqualTo(sourceEnd)) // endVal = 0.0; //} // Left if (startVal.EqualsWithTolerance(0.0) && endVal.EqualsWithTolerance(0.0)) { inline = targetSegment; } else if (startVal.Larger(0.0) && endVal.Larger(0.0)) { left = targetSegment; } else if (startVal.Smaller(0.0) && endVal.Smaller(0.0)) { right = targetSegment; } else if (startVal.EqualsWithTolerance(0.0)) { var sourceParam = sourceSegment.LineSegment.GetParameterOf(targetStart); var splitInfos = new List <BspSplitInfo>(); if (targetSegment.StartSplitInfos != null && targetSegment.StartSplitInfos.Any()) { splitInfos.AddRange(targetSegment.StartSplitInfos); } splitInfos.Add(new BspSplitInfo() { IsSplitted = false, SourceSegment = sourceSegment, SourceParam = sourceParam }); targetSegment.StartSplitInfos = splitInfos.ToArray(); if (endVal.Larger(0.0)) { left = targetSegment; } else { right = targetSegment; } } else if (endVal.EqualsWithTolerance(0.0)) { var sourceParam = sourceSegment.LineSegment.GetParameterOf(targetEnd); var splitInfos = new List <BspSplitInfo>(); if (targetSegment.EndSplitInfos != null && targetSegment.EndSplitInfos.Any()) { splitInfos.AddRange(targetSegment.EndSplitInfos); } splitInfos.Add(new BspSplitInfo() { IsSplitted = false, SourceSegment = sourceSegment, SourceParam = sourceParam }); targetSegment.EndSplitInfos = splitInfos.ToArray(); if (startVal.Larger(0.0)) { left = targetSegment; } else { right = targetSegment; } } else { // Split var line2d = new Line2d(sourceStart, sourceEnd); var points = line2d.IntersectWith(targetSegment.LineSegment); if (points != null && points.Length > 0) { // Only one intersect point here. var intersect = points[0]; var segmentStart = new LineSegment2d(targetStart, intersect); var segmentEnd = new LineSegment2d(intersect, targetEnd); // 如果segmentStart过短,就认为交点是targetStart。 // 否则在计算过程中就会矫枉过正,导致本不是相交点的地方成为相交点 if (segmentStart.Length.SmallerOrEqual(DoubleExtensions.STolerance)) { if (endVal.EqualsWithTolerance(0.0)) { inline = targetSegment; } else if (endVal.Larger(0.0)) { left = targetSegment; } else if (endVal.Smaller(0.0)) { right = targetSegment; } } else if (segmentEnd.Length.SmallerOrEqual(DoubleExtensions.STolerance)) { if (startVal.EqualsWithTolerance(0.0)) { inline = targetSegment; } else if (startVal.Larger(0.0)) { left = targetSegment; } else if (startVal.Smaller(0.0)) { right = targetSegment; } } else { var sourceParam = sourceSegment.LineSegment.GetParameterOf(intersect); var splitInfo = new BspSplitInfo() { SourceSegment = sourceSegment, SourceParam = sourceParam }; BspSegment templeft = null; if (segmentStart.Length.Larger(0.0)) { templeft = new BspSegment() { LineSegment = segmentStart, EntityId = targetSegment.EntityId, StartSplitInfos = targetSegment.StartSplitInfos, EndSplitInfos = new BspSplitInfo[] { splitInfo }, OriginalSegment = targetSegment }; } BspSegment tempRight = null; if (segmentEnd.Length.Larger(0.0)) { tempRight = new BspSegment() { LineSegment = segmentEnd, EntityId = targetSegment.EntityId, StartSplitInfos = new BspSplitInfo[] { splitInfo }, EndSplitInfos = targetSegment.EndSplitInfos, OriginalSegment = targetSegment }; } if (startVal.LargerOrEqual(0.0)) { left = templeft; right = tempRight; } else { left = tempRight; right = templeft; } } } else { // 如果没有任何交点,我们就认为它是inline的,因为往往因为计算精度, // 导致startVal和endVal的值在0.001左右,但是用IntersectWith计算不出任何交点 inline = targetSegment; } } }