Esempio n. 1
0
        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));
            }
        }
Esempio n. 2
0
        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);
        }
Esempio n. 3
0
        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);
                }
            }
        }
Esempio n. 4
0
 internal static double GetAlongFraction([NotNull] Pnt nearPoint,
                                         [NotNull] Pnt segmentLine)
 {
     return(nearPoint * segmentLine / segmentLine.OrigDist2());
 }
Esempio n. 5
0
        internal static double GetOffset([NotNull] Pnt nearPoint, [NotNull] Pnt segmentLine)
        {
            double segmentLength = Math.Sqrt(segmentLine.OrigDist2());

            return(nearPoint.VectorProduct(segmentLine) / segmentLength);
        }
Esempio n. 6
0
        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);
                            }
                        }
                    }
                }
            }
        }