public Pnt3D GetNonIntersectingTargetPoint( [NotNull] Linestring targetRing, double distanceFromIntersectionAsRatio) { if (Type == IntersectionPointType.LinearIntersectionIntermediate || Type == IntersectionPointType.Unknown) { throw new InvalidOperationException( $"Cannot get the non-intersecting target point for an intersection point type {Type}"); } bool?deviationIsBackward = null; if (Type == IntersectionPointType.LinearIntersectionStart || Type == IntersectionPointType.LinearIntersectionEnd) { // the direction matters: deviationIsBackward = Type == IntersectionPointType.LinearIntersectionStart; if (SegmentIntersection.LinearIntersectionInOppositeDirection) { deviationIsBackward = !deviationIsBackward; } } double targetFactor; int targetSegmentIdx = GetLocalTargetIntersectionSegmentIdx(targetRing, out targetFactor); double adjustedTargetFactor; if (deviationIsBackward == true) { adjustedTargetFactor = targetFactor - distanceFromIntersectionAsRatio; } else { // forward or null (i.e. does not matter) adjustedTargetFactor = targetFactor + distanceFromIntersectionAsRatio; if (adjustedTargetFactor > 1) { int?nextIdx = targetRing.NextSegmentIndex(targetSegmentIdx); if (nextIdx != null) { targetSegmentIdx = nextIdx.Value; adjustedTargetFactor -= 1; } else if (deviationIsBackward == null) { // cannot go forward, try backward: adjustedTargetFactor = targetFactor - distanceFromIntersectionAsRatio; } } } if (adjustedTargetFactor < 0) { int?previousIdx = targetRing.PreviousSegmentIndex(targetSegmentIdx); if (previousIdx == null) { return(null); } targetSegmentIdx = previousIdx.Value; adjustedTargetFactor += 1; } return(targetRing[targetSegmentIdx].GetPointAlong(adjustedTargetFactor, true)); }
/// <summary> /// Gets the line that enters the intersection point when moving along as specified /// with the direction parameters alongSource and forward. /// </summary> /// <param name="intoIntersection"></param> /// <param name="target"></param> /// <param name="alongSource"></param> /// <param name="forward"></param> /// <param name="source"></param> /// <returns></returns> protected static Line3D GetEntryLine([NotNull] IntersectionPoint3D intoIntersection, [NotNull] Linestring source, [NotNull] Linestring target, bool alongSource, bool forward) { Line3D entryLine; if (alongSource) { double distanceAlongSource; int sourceSegmentIdx = intoIntersection.GetLocalSourceIntersectionSegmentIdx( source, out distanceAlongSource); entryLine = distanceAlongSource > 0 ? source[sourceSegmentIdx] : source.PreviousSegmentInRing(sourceSegmentIdx); } else { double distanceAlongTarget; int targetSegmentIdx = intoIntersection.GetLocalTargetIntersectionSegmentIdx( target, out distanceAlongTarget); if (forward) { if (distanceAlongTarget > 0) { entryLine = target[targetSegmentIdx]; } else { // There must be a previous segment if we have come along the target int previousTargetIdx = Assert.NotNull(target.PreviousSegmentIndex(targetSegmentIdx)).Value; entryLine = target[previousTargetIdx]; } } else { if (distanceAlongTarget < 1) { entryLine = target[targetSegmentIdx]; } else { // There must be a next segment if we have come backwards along the target int nextTargetIdx = Assert.NotNull(target.NextSegmentIndex(targetSegmentIdx)).Value; entryLine = target[nextTargetIdx]; } entryLine = entryLine.Clone(); entryLine.ReverseOrientation(); } } return(entryLine); }