Ejemplo n.º 1
0
        internal static IList <double[]> GetLimits([NotNull] SegmentProxy segmentProxy,
                                                   [NotNull] IPolygon buffer)
        {
            // TODO this method would be extremely expensive when called on WksSegmentProxy instances

            var result = new List <double[]>();
            // Remark: segmentLine is altered by ITopologicalOperator.Intersect in  such a way
            // that equal segments may not be considered as equal anymore
            IPolyline segmentLine = segmentProxy.GetPolyline(true);
            //IPolyline segmentLine = segmentProxy.GetPolyline();
            var intersects = (IGeometryCollection)
                             ((ITopologicalOperator)buffer).Intersect(
                segmentLine,
                esriGeometryDimension.esriGeometry1Dimension);

            int intersectCount = intersects.GeometryCount;

            for (var i = 0; i < intersectCount; i++)
            {
                var part = (IPath)intersects.Geometry[i];

                double t0        = 0;
                double t1        = 0;
                double offset    = 0;
                var    rightSide = false;

                // TODO if called frequently, create abstract GetSegmentDistance(IPoint) on SegmentProxy,
                // with custom implementation on WksSegmentProxy.
                // Currently this seems to be called for AoSegmentProxys only, but this is not obvious.

                // TODO use a template point and part.QueryFromPoint() / part.QueryToPoint()?
                segmentLine.QueryPointAndDistance(esriSegmentExtension.esriExtendTangents,
                                                  part.FromPoint, true, HelpPoint,
                                                  ref t0, ref offset, ref rightSide);

                segmentLine.QueryPointAndDistance(esriSegmentExtension.esriExtendTangents,
                                                  part.ToPoint, true, HelpPoint,
                                                  ref t1, ref offset, ref rightSide);

                double tMin = Math.Min(t0, t1);
                double tMax = Math.Max(t0, t1);

                result.Add(new[] { tMin, tMax });
            }

            // Handle spatial tolerance problems for segments near tolerance size!
            if (intersectCount == 0 && !((IRelationalOperator)buffer).Disjoint(segmentLine))
            {
                ((ITopologicalOperator)segmentLine).Simplify();
                if (segmentLine.IsEmpty)
                {
                    result.Add(new[] { 0.0, 1.0 });
                }
            }

            return(result);
        }
Ejemplo n.º 2
0
        public static double GetClosestPointFraction([NotNull] SegmentProxy segmentProxy,
                                                     [NotNull] Pnt nearPoint,
                                                     out double?offset,
                                                     out bool?onRightSide,
                                                     bool as3D)
        {
            if (segmentProxy.IsLinear)
            {
                Pnt p0s = segmentProxy.GetStart(as3D);
                Pnt p0e = segmentProxy.GetEnd(as3D);
                Pnt l0  = p0e - p0s;
                offset      = null;
                onRightSide = null;
                return(GetAlongFraction(nearPoint - p0s, l0));
            }

            const bool forceCreation = true;
            IPolyline  segmentLine   = segmentProxy.GetPolyline(forceCreation);

            IPoint near = new PointClass();

            near.PutCoords(nearPoint.X, nearPoint.Y);

            IPoint onPoint = new PointClass();

            double     fraction    = 0;
            double     offsetValue = 0;
            var        rightSide   = false;
            const bool asRatio     = true;

            segmentLine.QueryPointAndDistance(esriSegmentExtension.esriNoExtension, near,
                                              asRatio, onPoint, ref fraction,
                                              ref offsetValue, ref rightSide);

            offset      = offsetValue;
            onRightSide = rightSide;
            return(fraction);
        }
Ejemplo n.º 3
0
        private static bool GetCoincident([NotNull] SegmentProxy segment,
                                          [NotNull] SegmentProxy hull,
                                          bool is3D,
                                          out NearSegment hullStartNear,
                                          out NearSegment hullEndNear)
        {
            hullStartNear = NearSegment.NotNear;           // TODO
            hullEndNear   = NearSegment.NotNear;           // TODO

            IPolyline segLine  = segment.GetPolyline(false);
            IPolyline hullLine = hull.GetPolyline(false);

            if (!((IRelationalOperator)segLine).Equals(hullLine))
            {
                return(false);
            }

            var coincident = true;

            Pnt segmentStart = segment.GetStart(is3D);
            Pnt segmentEnd   = segment.GetEnd(is3D);

            Pnt hullStart = hull.GetStart(is3D);
            Pnt hullEnd   = hull.GetEnd(is3D);

            double distFromSegFromHull;
            {
                double dx = segmentStart.X - hullStart.X;
                double dy = segmentStart.Y - hullStart.Y;
                distFromSegFromHull = dx * dx + dy * dy;
            }
            double distFromSegToHull;
            {
                double dx = segmentStart.X - hullEnd.X;
                double dy = segmentStart.Y - hullEnd.Y;
                distFromSegToHull = dx * dx + dy * dy;
            }

            bool isInverse = (distFromSegFromHull > distFromSegToHull);
            Pnt  hullMatchSegFrom;
            Pnt  hullMatchSegTo;

            if (!isInverse)
            {
                hullMatchSegFrom = hullStart;
                hullMatchSegTo   = hullEnd;
            }
            else
            {
                hullMatchSegFrom = hullEnd;
                hullMatchSegTo   = hullStart;
            }

            if (is3D)
            {
                double            zPrecision       = 0;
                ISpatialReference spatialReference = segment.SpatialReference;

                if (spatialReference != null && spatialReference.HasZPrecision())
                {
                    double falseZ;
                    double zUnits;
                    spatialReference.GetZFalseOriginAndUnits(out falseZ, out zUnits);
                    zPrecision = 1 / zUnits;
                }

                if (Math.Abs(hullMatchSegFrom[2] - segmentStart[2]) > zPrecision ||
                    Math.Abs(hullMatchSegTo[2] - segmentStart[2]) > zPrecision)
                {
                    coincident = false;
                }
            }

            if (coincident)
            {
                if (!isInverse)
                {
                    hullStartNear = NearSegment.NearStart;
                    hullEndNear   = NearSegment.NearEnd;
                }
                else
                {
                    hullStartNear = NearSegment.NearEnd;
                    hullEndNear   = NearSegment.NearStart;
                }
            }

            return(coincident);
        }