/// <summary> /// Creates the IntersectionPoint3D of type <see cref="IntersectionPointType.LinearIntersectionEnd"/> /// that corresponds to the second intersection along the source segment. /// </summary> /// <param name="intersection">The intersection</param> /// <param name="sourceSegments"></param> /// <param name="targetSegments"></param> /// <returns></returns> public static IntersectionPoint3D GetLinearIntersectionEnd( [NotNull] SegmentIntersection intersection, [NotNull] ISegmentList sourceSegments, [NotNull] ISegmentList targetSegments) { Line3D sourceSegment = sourceSegments[intersection.SourceIndex]; double endFactor; Pnt3D toPoint = intersection.GetLinearIntersectionEnd(sourceSegment, out endFactor); int sourcePartIdx; int sourceSegmentIndex = sourceSegments.GetLocalSegmentIndex( intersection.SourceIndex, out sourcePartIdx); IntersectionPoint3D result = new IntersectionPoint3D( toPoint, sourceSegmentIndex + endFactor, intersection) { Type = IntersectionPointType.LinearIntersectionEnd, SourcePartIndex = sourcePartIdx }; int targetPartIdx; result.VirtualTargetVertex = CalculateVirtualTargetVertex( targetSegments, result.Type, intersection, out targetPartIdx); result.TargetPartIndex = targetPartIdx; return(result); }
private static IEnumerable <SegmentIntersection> FilterIntersections( [NotNull] IEnumerable <SegmentIntersection> intersectionsForSourceSegment, [NotNull] ISegmentList source, [NotNull] IDictionary <int, HashSet <double> > usedIntersectionFactorsByPart) { foreach (SegmentIntersection intersection in intersectionsForSourceSegment) { var filter = false; if (!intersection.HasLinearIntersection && intersection.SingleInteriorIntersectionFactor == null) { double intersectionFactor; if (intersection.SourceStartIntersects) { intersectionFactor = 0; } else if (intersection.SourceEndIntersects) { intersectionFactor = 1; } else if (intersection.TargetStartIntersects) { intersectionFactor = Assert.NotNull(intersection.TargetStartFactor).Value; } else { intersectionFactor = Assert.NotNull(intersection.TargetEndFactor).Value; } int partIndex; int localSegmentIndex = source.GetLocalSegmentIndex(intersection.SourceIndex, out partIndex); double intersectionFactorPartGlobal = localSegmentIndex + intersectionFactor; // TODO: Extract class IntersectionFactors which encapsulates all the // Contains, Add etc. methods, probably even the filtering if (ContainsIntersection(usedIntersectionFactorsByPart, partIndex, intersectionFactorPartGlobal)) { filter = true; } else { AddIntersectionFactor(intersectionFactorPartGlobal, partIndex, usedIntersectionFactorsByPart, source); } } if (!filter) { yield return(intersection); } } }
private static void CollectIntersection( [NotNull] SegmentIntersection intersection, [NotNull] ISegmentList source, [NotNull] IDictionary <int, HashSet <double> > allLinearIntersectionFactors, [NotNull] ICollection <SegmentIntersection> intersectionsForCurrentSourceSegment) { // Collect segments for current index in list, unless they are clearly not needed // (and would need to be filtered by a later linear intersection if added) bool isLinear = intersection.HasLinearIntersection; if (isLinear) { int partIndex; int localSegmentIndex = source.GetLocalSegmentIndex(intersection.SourceIndex, out partIndex); double linearIntersectionStartFactor = localSegmentIndex + intersection.GetLinearIntersectionStartFactor(true); double linearIntersectionEndFactor = localSegmentIndex + intersection.GetLinearIntersectionEndFactor(true); if (intersection.IsSourceZeroLength2D && ContainsIntersection(allLinearIntersectionFactors, partIndex, linearIntersectionEndFactor)) { // avoid double linear segments if the source segment is vertical return; } AddIntersectionFactor(linearIntersectionStartFactor, partIndex, allLinearIntersectionFactors, source); AddIntersectionFactor(linearIntersectionEndFactor, partIndex, allLinearIntersectionFactors, source); } if (!isLinear && intersection.SourceStartIntersects && source.IsFirstSegmentInPart(intersection.SourceIndex) && source.IsClosed) { // will be reported again at the end return; } if (!isLinear && intersection.SourceEndIntersects && !source.IsLastSegmentInPart(intersection.SourceIndex)) { // will be reported again at next segment return; } intersectionsForCurrentSourceSegment.Add(intersection); }
private static double CalculateVirtualTargetVertex(ISegmentList targetSegments, IntersectionPointType intersectionType, SegmentIntersection segmentIntersection, out int targetPartIndex) { int targetSegmentIndex = targetSegments.GetLocalSegmentIndex( segmentIntersection.TargetIndex, out targetPartIndex); double result; switch (intersectionType) { case IntersectionPointType.LinearIntersectionStart: result = targetSegmentIndex + segmentIntersection.GetRatioAlongTargetLinearStart(); break; case IntersectionPointType.LinearIntersectionEnd: case IntersectionPointType.LinearIntersectionIntermediate: result = targetSegmentIndex + segmentIntersection.GetRatioAlongTargetLinearEnd(); break; case IntersectionPointType.Crossing: case IntersectionPointType.TouchingInPoint: result = targetSegmentIndex + segmentIntersection.GetIntersectionPointFactorAlongTarget(); break; default: throw new InvalidOperationException( $"Unsupported type :{intersectionType}"); } return(result); }
public static IntersectionPoint3D CreateSingleIntersectionPoint( [NotNull] SegmentIntersection intersection, [NotNull] ISegmentList sourceSegments, [NotNull] ISegmentList targetSegments, double tolerance) { Line3D sourceSegment = sourceSegments.GetSegment(intersection.SourceIndex); double?targetIntersectionFactorOnSource = intersection.GetIntersectionPointFactorAlongSource(); int sourcePartIdx; int sourceSegmentIndex = sourceSegments.GetLocalSegmentIndex( intersection.SourceIndex, out sourcePartIdx); Pnt3D point; double sourceIndex; // ReSharper disable once CompareOfFloatsByEqualityOperator if (targetIntersectionFactorOnSource == 0) { point = sourceSegment.StartPoint; sourceIndex = sourceSegmentIndex; } // ReSharper disable once CompareOfFloatsByEqualityOperator else if (targetIntersectionFactorOnSource == 1) { point = sourceSegment.EndPoint; sourceIndex = sourceSegmentIndex + 1; } else { point = sourceSegment.GetPointAlong( targetIntersectionFactorOnSource.Value, true); sourceIndex = sourceSegmentIndex + targetIntersectionFactorOnSource.Value; } IntersectionPoint3D result = new IntersectionPoint3D(point, sourceIndex, intersection) { SourcePartIndex = sourcePartIdx }; bool?targetDeviatesToLeft; result.Type = intersection.IsCrossingInPoint( sourceSegments, targetSegments, tolerance, out targetDeviatesToLeft) ? IntersectionPointType.Crossing : IntersectionPointType.TouchingInPoint; result.TargetDeviatesToLeftOfSource = targetDeviatesToLeft; int targetPartIdx; result.VirtualTargetVertex = CalculateVirtualTargetVertex( targetSegments, result.Type, intersection, out targetPartIdx); result.TargetPartIndex = targetPartIdx; return(result); }