public void Cut(Pnt segStart, Pnt segLine, double offset, ref double tMin, ref double tMax) { Pnt near0 = _p0 - segStart; double offset0 = SegmentUtils.GetOffset(near0, segLine); double along0 = SegmentUtils.GetAlongFraction(near0, segLine); Pnt near1 = _p1 - segStart; double offset1 = SegmentUtils.GetOffset(near1, segLine); double along1 = SegmentUtils.GetAlongFraction(near1, segLine); if (Math.Abs(offset0) <= offset) { double t = along0; tMin = Math.Min(t, tMin); tMax = Math.Max(t, tMax); } if (Math.Abs(offset1) <= offset) { double t = along1; tMin = Math.Min(t, tMin); tMax = Math.Max(t, tMax); } if ((offset0 < offset) == (offset1 > offset)) { double f0 = offset0 - offset; double f1 = offset1 - offset; double sumF = Math.Abs(f0) + Math.Abs(f1); if (sumF > 0) { double t = along0 + Math.Abs(f0) / sumF * (along1 - along0); tMin = Math.Min(t, tMin); tMax = Math.Max(t, tMax); } } if (offset > 0 && (offset0 < -offset) == (offset1 > -offset)) { double f0 = offset0 + offset; double f1 = offset1 + offset; double sumF = Math.Abs(f0) + Math.Abs(f1); if (sumF > 0) { double t = along0 + Math.Abs(f0) / sumF * (along1 - along0); tMin = Math.Min(t, tMin); tMax = Math.Max(t, tMax); } } }
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); } } }
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); } } } } } }