예제 #1
0
        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);
                }
            }
        }
예제 #2
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);
                }
            }
        }
예제 #3
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);
                            }
                        }
                    }
                }
            }
        }