protected static bool Parallel([NotNull] Pnt p0, [NotNull] Pnt l0, [NotNull] Pnt p1, [NotNull] Pnt l1, double r2, out double tMin, out double tMax, ref NearSegment hullStartNear, ref NearSegment hullEndNear) { if (SegmentUtils.CutLineCircle(p0, l0, p1, r2, out tMin, out tMax) == false) { return(false); } hullStartNear = Near(tMin, tMax); double cMin, cMax; if (SegmentUtils.CutLineCircle(p0, l0, p1 + l1, r2, out cMin, out cMax)) { hullEndNear = Near(cMin, cMax); tMin = Math.Min(tMin, cMin); tMax = Math.Max(tMax, cMax); } return(true); }
private static bool CutArcLine(Pnt p, HullLineArc line, ref double tMin, ref double tMax) { bool intersects = false; double r = line.Radius; double tCircleMin, tCircleMax; if (SegmentUtils.CutLineCircle(line.Lin.Ps, line.Lin.L, p, r * r, out tCircleMin, out tCircleMax)) { intersects |= IsPointInArcDirection(p, line, tCircleMin, ref tMin, ref tMax); intersects |= IsPointInArcDirection(p, line, tCircleMax, ref tMin, ref tMax); } return(intersects); }
private bool CutLineEndpoint(double angle, HullLineArc line, ref double tMin, ref double tMax) { var intersects = false; double r = line.Radius; Pnt p = _center + new Pnt2D(_radius * Math.Cos(angle), _radius * Math.Sin(angle)); double tCircleMin, tCircleMax; if (SegmentUtils.CutLineCircle(line.Lin.Ps, line.Lin.L, p, r * r, out tCircleMin, out tCircleMax)) { intersects |= ValidateIntersects(p, line, tCircleMin, ref tMin, ref tMax); intersects |= ValidateIntersects(p, line, tCircleMax, ref tMin, ref tMax); } return(intersects); }
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 bool CutLineThis(Pnt p0, Pnt l0, ref double tMin, ref double tMax, SignedHullLineArc arc = null) { double r = _radius + (arc?.Radius ?? 0); double tCircleMin; double tCircleMax; if (!SegmentUtils.CutLineCircle( p0, l0, _center, r * r, out tCircleMin, out tCircleMax)) { return(false); } var cuts = false; double f = r > 0 ? 1 : -1; Pnt dirMin = p0 + tCircleMin * l0 - _center; if (ValidateAngles(f * dirMin, arc)) { cuts = true; tMin = Math.Min(tMin, tCircleMin); tMax = Math.Max(tMax, tCircleMin); } Pnt dirMax = p0 + tCircleMax * l0 - _center; if (ValidateAngles(f * dirMax, arc)) { cuts = true; tMin = Math.Min(tMin, tCircleMax); tMax = Math.Max(tMax, tCircleMax); } return(cuts); }
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); } } } } } }
protected static bool Near([NotNull] Pnt p0, [NotNull] Pnt l0, [NotNull] Pnt p1, [NotNull] Pnt l1, double r2, double l12, ref double tMin, ref double tMax, ref NearSegment hullStartNear, ref NearSegment hullEndNear) { double cMin, cMax; double u0 = (p0 + tMin * l0 - p1) * l1 / l12; double u1 = (p0 + tMax * l0 - p1) * l1 / l12; if (u0 < 0) { if (SegmentUtils.CutLineCircle(p0, l0, p1, r2, out cMin, out cMax) == false) { return(false); } hullStartNear = Near(cMin, cMax); // Debug.Assert(cMin > tMin); numerical exceptions possible tMin = cMin; if (u1 < 0) { //Debug.Assert(cMax < tMax); numerical exceptions possible tMax = cMax; } } else if (u0 > 1) { if (SegmentUtils.CutLineCircle(p0, l0, p1 + l1, r2, out cMin, out cMax) == false) { return(false); } hullEndNear = Near(cMin, cMax); //Debug.Assert(cMin > tMin); numerical exceptions possible tMin = cMin; if (u1 > 1) { //Debug.Assert(cMax < tMax); numerical exceptions possible tMax = cMax; } } if (u1 < 0 && u0 >= 0) { if (SegmentUtils.CutLineCircle(p0, l0, p1, r2, out cMin, out cMax) == false) { //throw new InvalidProgramException( // "error in software design assumption"); numerical exceptions possible tMax = tMin + u0 / (u0 - u1) * (tMax - tMin); hullStartNear = Near(tMin, tMax); } else { hullStartNear = Near(cMin, cMax); //Debug.Assert(cMax < tMax); numerical exceptions possible tMax = cMax; } } else if (u1 > 1 && u0 <= 1) { if (SegmentUtils.CutLineCircle(p0, l0, p1 + l1, r2, out cMin, out cMax) == false) { //throw new InvalidProgramException( // "error in software design assumption"); numerical exceptions possible tMax = tMin + (1 - u0) / (u1 - u0) * (tMax - tMin); hullEndNear = Near(tMin, tMax); } else { hullEndNear = Near(cMin, cMax); //Debug.Assert(cMax < tMax); numerical exceptions possible tMax = cMax; } } return(true); }