protected double GetSegmentDistance() { double l02 = L0.L.OrigDist2(); if (IsParallel) { Pnt s = L1.Ps - L0.Ps; double f0 = s * L0.L / l02; if (f0 >= 0 && f0 <= 1) { return(Math.Abs(L0.L.VectorProduct(s) / Math.Sqrt(l02))); } Pnt e = L1.Pe - L0.Ps; double f1 = e * L0.L / l02; if ((f1 >= 0 && f1 <= 1) || (f0 < 0 != f1 < 0)) { return(Math.Abs(L0.L.VectorProduct(s) / Math.Sqrt(l02))); } double d2 = Math.Min(s.OrigDist2(), e.OrigDist2()); d2 = Math.Min(d2, (L1.Ps - L0.Pe).OrigDist2()); d2 = Math.Min(d2, (L1.Pe - L0.Pe).OrigDist2()); return(Math.Sqrt(d2)); } { Pnt s = L1.Ps - L0.Ps; double f1S = L0.L.VectorProduct(s); Pnt e = L1.Pe - L0.Ps; double f1E = L0.L.VectorProduct(e); double f1 = -f1S / (f1E - f1S); Pnt cut = L1.Ps + f1 * L1.L; double f0 = L0.L * (cut - L0.Ps) / l02; if (f0 >= 0 && f0 <= 1 && f1 >= 0 && f1 <= 1) { return(0); } double d2 = Math.Min(GetPointDistance(L0.L, l02, s, f1S), GetPointDistance(L0.L, l02, e, f1E)); d2 = Math.Min(d2, GetPointDistance(L1.L, L1.L2, L0.Ps - L1.Ps, null)); d2 = Math.Min(d2, GetPointDistance(L1.L, L1.L2, L0.Pe - L1.Ps, null)); return(Math.Sqrt(d2)); } }
private static double GetPointDistance([NotNull] Pnt line, double line2, [NotNull] Pnt p, double?vectorProd) { double d2; double f = line * p / line2; if (f >= 0 && f <= 1) { double v = vectorProd ?? line.VectorProduct(p); d2 = v * v / line2; } else { d2 = Math.Min(p.OrigDist2(), (p - line).OrigDist2()); } return(d2); }
private void CutCircle(Pnt segStart, Pnt segmentLine, double offset, ref double tMin, ref double tMax) { Pnt near = _center - segStart; double centerOffset = SegmentUtils.GetOffset(near, segmentLine); if (Math.Abs(centerOffset) < offset) { double centerAlong = SegmentUtils.GetAlongFraction(near, segmentLine); double segmentLength = Math.Sqrt(segmentLine.OrigDist2()); tMin = Math.Min(tMin, centerAlong - _radius / segmentLength); tMax = Math.Max(tMax, centerAlong + _radius / segmentLength); } else if (_radius + offset > Math.Abs(centerOffset)) { Pnt offsetCenter; if (offset <= 0) { offsetCenter = _center; } else { double centerAlong = SegmentUtils.GetAlongFraction(near, segmentLine); Pnt along = segStart + centerAlong * segmentLine; double f = (Math.Abs(centerOffset) - offset) / Math.Abs(centerOffset); offsetCenter = along + f * (_center - along); } double tCircleMin, tCircleMax; if (SegmentUtils.CutLineCircle(segStart, segmentLine, offsetCenter, _radius * _radius, out tCircleMin, out tCircleMax)) { tMin = Math.Min(tMin, tCircleMin); tMax = Math.Max(tMax, tCircleMax); } } }
internal static double GetAlongFraction([NotNull] Pnt nearPoint, [NotNull] Pnt segmentLine) { return(nearPoint * segmentLine / segmentLine.OrigDist2()); }
internal static double GetOffset([NotNull] Pnt nearPoint, [NotNull] Pnt segmentLine) { double segmentLength = Math.Sqrt(segmentLine.OrigDist2()); return(nearPoint.VectorProduct(segmentLine) / segmentLength); }
private void CutArc(Pnt segStart, Pnt segmentLine, double offset, ref double tMin, ref double tMax) { Pnt near = _center - segStart; double centerOffset = SegmentUtils.GetOffset(near, segmentLine); if (Math.Abs(centerOffset) < offset) { var canReturn = false; double lineAngle = Math.Atan2(segmentLine.Y, segmentLine.X); double centerAlong = SegmentUtils.GetAlongFraction(near, segmentLine); double segmentLength = Math.Sqrt(segmentLine.OrigDist2()); if (IsInArcAngle(lineAngle)) { canReturn = true; tMax = Math.Max(tMax, centerAlong + _radius / segmentLength); } double reverseLineAngle = lineAngle - Math.PI; if (IsInArcAngle(reverseLineAngle)) { tMin = Math.Min(tMin, centerAlong - _radius / segmentLength); if (canReturn) { return; } } } Pnt start = _center + _radius * new Pnt2D(Math.Cos(StartDirection), Math.Sin(StartDirection)) - segStart; double startOffset = SegmentUtils.GetOffset(start, segmentLine); if (Math.Abs(startOffset) < offset) { double startAlong = SegmentUtils.GetAlongFraction(start, segmentLine); tMin = Math.Min(tMin, startAlong); tMax = Math.Max(tMax, startAlong); } double endDirection = StartDirection + (Angle ?? 0); Pnt end = _center + _radius * new Pnt2D(Math.Cos(endDirection), Math.Sin(endDirection)) - segStart; double endOffset = SegmentUtils.GetOffset(end, segmentLine); if (Math.Abs(endOffset) < offset) { double endAlong = SegmentUtils.GetAlongFraction(end, segmentLine); tMin = Math.Min(tMin, endAlong); tMax = Math.Max(tMax, endAlong); } if (_radius + offset > Math.Abs(centerOffset)) { var segmentStarts = new List <Pnt>(); { double segmentLength = Math.Sqrt(segmentLine.OrigDist2()); Pnt off = offset / segmentLength * new Pnt2D(-segmentLine.Y, segmentLine.X); segmentStarts.Add(segStart + off); segmentStarts.Add(segStart - off); } foreach (Pnt segmentStart in segmentStarts) { double tCircleMin, tCircleMax; if (SegmentUtils.CutLineCircle(segmentStart, segmentLine, _center, _radius * _radius, out tCircleMin, out tCircleMax)) { foreach (double t in new[] { tCircleMin, tCircleMax }) { Pnt dirPnt = segmentStart + t * segmentLine - _center; double dirAngle = Math.Atan2(dirPnt.Y, dirPnt.X); if (IsInArcAngle(dirAngle)) { tMin = Math.Min(tMin, t); tMax = Math.Max(tMax, t); } } } } } }