public bool Cut(HullLineArc line, ref double tMin, ref double tMax)
        {
            double angS = line.StartDirection;
            double r    = line.Radius;

            // Handle start point of line-arc
            var   aS         = new Pnt2D(r * Math.Cos(angS), r * Math.Sin(angS));
            Lin2D s          = line.Lin.GetParallel(aS);
            bool  intersects = CutLineThis(s.Ps, s.L, ref tMin, ref tMax);

            // Handle end point of line-arc
            double angE = angS + line.Angle;
            var    aE   = new Pnt2D(r * Math.Cos(angE), r * Math.Sin(angE));
            Lin2D  e    = line.Lin.GetParallel(aE);

            intersects |= CutLineThis(e.Ps, e.L, ref tMin, ref tMax);

            if (Angle.HasValue)
            {
                intersects |=
                    CutLineEndpoint(StartDirection + Angle.Value, line, ref tMin, ref tMax);

                intersects |= CutLineEndpoint(StartDirection, line, ref tMin, ref tMax);
            }

            intersects |= CutLineThis(line.Lin.Ps, line.Lin.L, ref tMin, ref tMax,
                                      new SignedHullLineArc(line, deflate: false));
            intersects |= CutLineThis(line.Lin.Ps, line.Lin.L, ref tMin, ref tMax,
                                      new SignedHullLineArc(line, deflate: true));
            return(intersects);
        }
        public bool Cut(HullLineLine line, ref double tMin, ref double tMax)
        {
            // Handle start point of endPart
            Pnt   lS         = line.EndPart.Ps;
            Lin2D s          = line.Lin.GetParallel(lS);
            bool  intersects = CutLineThis(s.Ps, s.L, ref tMin, ref tMax);

            // Handle end point of endPart
            Pnt   lE = line.EndPart.Pe;
            Lin2D e  = line.Lin.GetParallel(lE);

            intersects |= CutLineThis(e.Ps, e.L, ref tMin, ref tMax);

            if (Angle.HasValue)
            {
                double r = _radius;
                // Handle start point of arc
                double angS = StartDirection;
                Pnt    aS   = new Pnt2D(r * Math.Cos(angS), r * Math.Sin(angS)) + _center - lS;
                Lin2D  eS   = line.EndPart.GetParallel(aS);
                intersects |= LineHullPart.CutLin(eS, e, ref tMin, ref tMax);

                // Handle end point of arc
                double angE = StartDirection + Angle.Value;
                Pnt    aE   = new Pnt2D(r * Math.Cos(angE), r * Math.Sin(angE)) + _center - lS;
                Lin2D  eE   = line.EndPart.GetParallel(aE);
                intersects |= LineHullPart.CutLin(eE, e, ref tMin, ref tMax);
            }

            // Handle tangents
            Pnt    eNormal = line.EndPart.LNormal;
            double dir     = Angle.HasValue
                                             ? Math.Atan2(eNormal.Y, eNormal.X)
                                             : double.NaN;

            if (!Angle.HasValue || IsInArcAngle(dir))
            {
                Lin2D eT0 = line.EndPart.GetParallel(_center + _radius * eNormal - lS);
                intersects |= LineHullPart.CutLin(eT0, e, ref tMin, ref tMax);
            }

            if (!Angle.HasValue || IsInArcAngle(dir + Math.PI))
            {
                Lin2D eT1 = line.EndPart.GetParallel(_center - _radius * eNormal - lS);
                intersects |= LineHullPart.CutLin(eT1, e, ref tMin, ref tMax);
            }

            return(intersects);
        }
Exemple #3
0
        public override IEnumerable <IHullPart> GetInflatedHullParts(Pnt at, Pnt opposite,
                                                                     double offset,
                                                                     double inflate)
        {
            Pnt    l     = opposite - at;
            double l0    = Math.Sqrt(l * l);
            Pnt    lNorm = new Pnt2D(l.X / l0, l.Y / l0);
            Pnt    vNorm = new Pnt2D(lNorm.Y, -lNorm.X);

            Pnt pntOffset = Math.Max(0, offset - _length) * vNorm;

            yield return(new CircleHullPart(at + pntOffset, _length + inflate));

            Pnt cap = at - (_length + inflate) * lNorm;

            yield return(new LineHullPart(cap + pntOffset, cap - pntOffset));

            yield return(new CircleHullPart(at - pntOffset, _length + inflate));
        }
Exemple #4
0
        public bool Cut(HullLineArc line, ref double tMin, ref double tMax)
        {
            double angS = line.StartDirection;
            double r    = line.Radius;

            // Handle start point of arc
            var   aS         = new Pnt2D(r * Math.Cos(angS), r * Math.Sin(angS));
            Lin2D s          = line.Lin.GetParallel(aS);
            bool  intersects = CutLin(_lin, s, ref tMin, ref tMax);

            // Handle end point of arc
            double angE = angS + line.Angle;
            var    aE   = new Pnt2D(r * Math.Cos(angE), r * Math.Sin(angE));
            Lin2D  e    = line.Lin.GetParallel(aE);

            intersects |= CutLin(_lin, e, ref tMin, ref tMax);

            // Handle this start/end point
            intersects |= CutArcLine(_lin.Ps, line, ref tMin, ref tMax);
            intersects |= CutArcLine(_lin.Pe, line, ref tMin, ref tMax);

            // handle sides
            double arcAngle  = GetNormedAngle(line.Angle);
            Pnt    normal    = _lin.LNormal;
            double normalDir = _lin.DirectionAngle + Math.PI / 2;

            // handle left side
            if (GetNormedAngle(normalDir - line.StartDirection) < arcAngle)
            {
                intersects |= CutLin(_lin.GetParallel(r * normal), line.Lin, ref tMin, ref tMax);
            }

            // handle right side
            if (GetNormedAngle(normalDir + Math.PI - line.StartDirection) < arcAngle)
            {
                intersects |= CutLin(_lin.GetParallel(-r * normal), line.Lin, ref tMin, ref tMax);
            }

            return(intersects);
        }
        private static double GetDistanceToCurve(
            [NotNull] IPoint point,
            [NotNull] IFeature neighbourFeature,
            [NotNull] IPoint nearestPoint,
            double maxNeededDistance,
            out bool onRightSide)
        {
            var neighborCurve = (ICurve)neighbourFeature.Shape;

            if (UseQueryPointAndDistance)
            {
                const bool asRatio   = false;
                double     along     = 0;
                double     distance  = 0;
                var        rightSide = false;

                // TLMQA-292 (EBG - BB): most time spent here (> 90%)
                neighborCurve.QueryPointAndDistance(esriSegmentExtension.esriNoExtension,
                                                    point, asRatio, nearestPoint,
                                                    ref along, ref distance, ref rightSide);
                onRightSide = rightSide;
                return(distance);
            }

            {
                double       nearestDistance    = maxNeededDistance * 1.01;
                bool?        nearestOnRightSide = null;
                SegmentProxy nearestSegment     = null;
                double       nearestFraction    = 0;

                double x;
                double y;
                point.QueryCoords(out x, out y);
                Pnt qaPoint = new Pnt2D(x, y);
                foreach (SegmentProxy segmentProxy in
                         EnumSegments(qaPoint, neighbourFeature, maxNeededDistance))
                {
                    bool?  onSegmentRightSide;
                    double alongFraction;
                    double offset = GetOffset(qaPoint, segmentProxy,
                                              out alongFraction, out onSegmentRightSide);
                    if (offset <= nearestDistance)
                    {
                        if (!onSegmentRightSide.HasValue && !nearestOnRightSide.HasValue &&
                            nearestSegment != null)
                        {
                            nearestOnRightSide = GetOnRightSide(
                                nearestSegment, nearestFraction, segmentProxy, alongFraction,
                                neighborCurve);
                        }
                        else if (offset < nearestDistance)
                        {
                            nearestOnRightSide = onSegmentRightSide;
                        }

                        nearestDistance = offset;
                        nearestSegment  = segmentProxy;
                        nearestFraction = alongFraction;
                    }
                }

                if (nearestSegment != null)
                {
                    double f = Math.Min(1, Math.Max(0, nearestFraction));
                    IPnt   p = nearestSegment.GetPointAt(f, as3D: true);
                    nearestPoint.PutCoords(p.X, p.Y);
                    nearestPoint.Z = p[2];

                    if (!nearestOnRightSide.HasValue)
                    {
                        // Extend segment lineary to determine right side
                        Pnt s = nearestSegment.GetStart(as3D: false);
                        Pnt e = nearestSegment.GetEnd(as3D: false);

                        if (nearestFraction >= 1)
                        {
                            nearestOnRightSide = (e - s).VectorProduct(e - qaPoint) > 0;
                        }
                        else if (nearestFraction <= 0)
                        {
                            nearestOnRightSide = (e - s).VectorProduct(s - qaPoint) > 0;
                        }
                    }
                }

                onRightSide = nearestOnRightSide ?? false;
                return(nearestDistance);
            }
        }
Exemple #6
0
        public static bool SnapPoint([NotNull] IPoint newEndPoint,
                                     [NotNull] IList <IFeature> candidateTargetEdges,
                                     [NotNull] ILinearNetworkFeatureFinder networkFeatureFinder)
        {
            if (networkFeatureFinder.SearchTolerance <= 0)
            {
                return(false);
            }

            Pnt2D newEndPnt = new Pnt2D(newEndPoint.X, newEndPoint.Y);

            IPoint fromPoint = new PointClass()
            {
                SpatialReference = newEndPoint.SpatialReference
            };
            IPoint toPoint = new PointClass()
            {
                SpatialReference = newEndPoint.SpatialReference
            };

            double searchToleranceSquared = networkFeatureFinder.SearchTolerance *
                                            networkFeatureFinder.SearchTolerance;

            bool snapped = false;

            foreach (IFeature feature in candidateTargetEdges)
            {
                IPolyline otherPolyline = (IPolyline)feature.Shape;

                otherPolyline.QueryFromPoint(fromPoint);
                Pnt2D fromPnt = new Pnt2D(fromPoint.X, fromPoint.Y);

                double fromDistance2 = fromPnt.Dist2(newEndPnt);

                otherPolyline.QueryToPoint(toPoint);
                Pnt2D toPnt = new Pnt2D(toPoint.X, toPoint.Y);

                double toDistance2 = toPnt.Dist2(newEndPnt);

                if (fromDistance2 > searchToleranceSquared && toDistance2 > searchToleranceSquared)
                {
                    continue;
                }

                if (Math.Min(fromDistance2, toDistance2) < GetXyResolutionSquared(feature))
                {
                    // already snapped
                    continue;
                }

                IPoint sourcePoint = fromDistance2 < toDistance2 ? fromPoint : toPoint;

                snapped = true;
                CopyCoords(sourcePoint, newEndPoint);
            }

            if (!snapped)
            {
                // Try snapping onto curve interior
                foreach (IFeature feature in candidateTargetEdges)
                {
                    IPolyline otherPolyline = (IPolyline)feature.Shape;

                    double distanceFromCurve =
                        GeometryUtils.GetDistanceFromCurve(newEndPoint, otherPolyline, fromPoint);

                    if (distanceFromCurve >= 0 &&
                        distanceFromCurve < networkFeatureFinder.SearchTolerance)
                    {
                        snapped = true;
                        CopyCoords(fromPoint, newEndPoint);
                    }
                }
            }

            return(snapped);
        }