Esempio n. 1
0
        private static void AddReshapeConnect(IPath connectionLineAtCutOff,
                                              IPath pathOnTarget,
                                              IDictionary <AdjustedCutSubcurve, IGeometry>
                                              toConnectPaths,
                                              IGeometry geometryToReshape)
        {
            bool connectsAtFromPoint =
                GeometryUtils.AreEqualInXY(connectionLineAtCutOff.ToPoint, pathOnTarget.FromPoint);

            IPath connectLineAtFrom = connectsAtFromPoint
                                                          ? connectionLineAtCutOff
                                                          : null;

            IPath connectLineAtTo = connectsAtFromPoint
                                                        ? null
                                                        : connectionLineAtCutOff;

            var adjustedCutSubcurve = new AdjustedCutSubcurve(
                pathOnTarget, connectLineAtFrom, connectLineAtTo);

            //if (GeometryUtils.AreEqualInXY(connectionLineAtCutOff.FromPoint,
            //							   pathOnTarget.FromPoint))
            //{
            //	connectionLineAtCutOff.ReverseOrientation();
            //}

            //ISegmentCollection pathOnTargetClone =
            //	(ISegmentCollection) GeometryFactory.Clone(pathOnTarget);

            //((ISegmentCollection) connectionLineAtCutOff).AddSegmentCollection(
            //	pathOnTargetClone);

            toConnectPaths.Add(adjustedCutSubcurve, geometryToReshape);
        }
Esempio n. 2
0
        private bool ApplyReshapePath(
            [NotNull] IGeometry geometryToReshape,
            [NotNull] AdjustedCutSubcurve adjustCurve,
            NotificationCollection notifications,
            IDictionary <IGeometry, NotificationCollection> reshapedGeometries)
        {
            // if the connect line crosses the geometry's boundary only reshape to the first intersection
            // and subsequently try the remaining bits. Otherwise this could result in a flipped geometry (reshape to the wrong side)

            IPath remainderAtFrom, remainderAtTo;

            IPath cutConnectLineAtFrom = SplitConnectline(adjustCurve, geometryToReshape, true,
                                                          out remainderAtFrom);
            IPath cutConnectLineAtTo = SplitConnectline(adjustCurve, geometryToReshape, false,
                                                        out remainderAtTo);

            var mainSubcurve = new AdjustedCutSubcurve(
                adjustCurve.PathOnTarget, cutConnectLineAtFrom,
                cutConnectLineAtTo);

            IPath reshapePath = mainSubcurve.Path;

            bool reshaped = Reshape(geometryToReshape, reshapePath);

            reshaped |= remainderAtFrom != null &&
                        Reshape(geometryToReshape, remainderAtFrom);

            reshaped |= remainderAtTo != null &&
                        Reshape(geometryToReshape, remainderAtTo);

            if (reshaped)
            {
                // to avoid incorrect relational operator results in for the next path on target
                ((ISegmentCollection)geometryToReshape).SegmentsChanged();
            }

            NotificationCollection reshapeNotifications = null;

            // TODO: get from out ReshapeInfo;

            // move adding notfications to caller?
            if (reshaped && !reshapedGeometries.ContainsKey(geometryToReshape))
            {
                reshapedGeometries.Add(geometryToReshape, reshapeNotifications);
            }
            else
            {
                if (reshapeNotifications != null)
                {
                    NotificationUtils.Add(notifications, reshapeNotifications.Concatenate(" "));
                }
            }

            return(reshaped);
        }
Esempio n. 3
0
        public static AdjustedCutSubcurve CalculateAdjustedPath(
            [NotNull] IPath adjustLine,
            [NotNull] ICurve sourcePart,
            [NotNull] IConnectLineCalculator connectCalculator)
        {
            Stopwatch watch = _msg.DebugStartTiming();

            AdjustedCutSubcurve adjustedSubcurve = null;

            IPath startFallback;
            IPath endFallback;

            IPath startSourceConnection = connectCalculator.FindConnection(
                sourcePart, adjustLine, true, out startFallback);

            IPath endSourceConnection = connectCalculator.FindConnection(
                sourcePart, adjustLine, false, out endFallback);

            if (_msg.IsVerboseDebugEnabled)
            {
                _msg.DebugFormat("CalculatedAdjustedPath start connection: {0}",
                                 GeometryUtils.ToString(startSourceConnection));

                _msg.DebugFormat("CalculateAdjustedPath: end connection: {0}",
                                 GeometryUtils.ToString(endSourceConnection));
            }

            // Possible criteria to consider the path valid:
            // - length of connections vs. length of path
            // - angle between path and connections
            // - size of the reshape-area (difference before/after reshape) vs. length of path (sliver condition?)
            ValidateConnectLines(sourcePart, ref startSourceConnection, ref endSourceConnection,
                                 startFallback, endFallback);

            if (startSourceConnection != null && endSourceConnection != null)
            {
                adjustedSubcurve = CreateAdjustedCutSubcurve(adjustLine,
                                                             startSourceConnection,
                                                             endSourceConnection);
            }

            _msg.DebugStopTiming(watch,
                                 "Calculated adjusted subcurve including connection lines to target");

            return(adjustedSubcurve);
        }
Esempio n. 4
0
        private static IPath SplitConnectline(AdjustedCutSubcurve adjustCurve,
                                              IGeometry geometryToReshape, bool atFrom,
                                              out IPath remainder)
        {
            IPath connectLine = atFrom
                                                    ? adjustCurve.ConnectLineAtFromPoint
                                                    : adjustCurve.ConnectLineAtToPoint;

            remainder = null;

            if (connectLine == null)
            {
                return(null);
            }

            if (((IPointCollection)connectLine).PointCount > 2)
            {
                // it's along a real geometry
                return(connectLine);
            }

            var highLevelConnectline =
                (IPolyline)GeometryUtils.GetHighLevelGeometry(connectLine);

            IPointCollection crossingPoints = GetCrossingPoints(highLevelConnectline,
                                                                geometryToReshape);

            if (crossingPoints.PointCount == 0)
            {
                return(connectLine);
            }

            IPoint connectPoint = atFrom
                                                      ? adjustCurve.PathOnTarget.FromPoint
                                                      : adjustCurve.PathOnTarget.ToPoint;

            IPoint nearestPoint = ((IProximityOperator)crossingPoints).ReturnNearestPoint(
                connectPoint, esriSegmentExtension.esriNoExtension);

            bool splitHappened;
            int  newPartIdx;
            int  newSegmentIdx;

            highLevelConnectline.SplitAtPoint(nearestPoint, false, true,
                                              out splitHappened, out newPartIdx,
                                              out newSegmentIdx);

            var connectLineParts = ((IGeometryCollection)highLevelConnectline);

            IPath result;

            if (GeometryUtils.AreEqualInXY(highLevelConnectline.FromPoint, connectPoint))
            {
                result    = (IPath)connectLineParts.get_Geometry(0);
                remainder = (IPath)connectLineParts.get_Geometry(1);
            }
            else
            {
                result    = (IPath)connectLineParts.get_Geometry(1);
                remainder = (IPath)connectLineParts.get_Geometry(0);
            }

            return(result);
        }
Esempio n. 5
0
        /// <summary>
        ///     o
        ///   ___\_________
        ///  |    \ |      |
        ///  |     \|      |
        ///  |      |      |
        ///  |      |      |
        ///  |      |      |
        ///  |      |      |
        ///  |______|___ __|
        ///
        /// Reshape line: o
        ///                 \
        ///                  \
        /// Applies the relevant reshapes of the provided adjust curves at the outer boundary of two adjacent polygons
        /// by connecting the last vertex before the cut-off (in this case the top left corner of the left polygon)
        /// with the target intersection point.
        /// </summary>
        /// <param name="connectLinesAtCutOffs"></param>
        /// <param name="reshapedGeometries"></param>
        /// <param name="notifications"></param>
        private void ApplySharedBoundaryOuterEndReshape(
            Dictionary <AdjustedCutSubcurve, IGeometry> connectLinesAtCutOffs,
            IDictionary <IGeometry, NotificationCollection> reshapedGeometries,
            NotificationCollection notifications)
        {
            IList <IGeometry> allGeometriesToReshape =
                _reshapeGeometryCloneByOriginal.Values.ToList();

            foreach (
                KeyValuePair <AdjustedCutSubcurve, IGeometry> connectLinesAtCutOff in
                connectLinesAtCutOffs)
            {
                AdjustedCutSubcurve adjustedCurve     = connectLinesAtCutOff.Key;
                IGeometry           geometryToReshape = connectLinesAtCutOff.Value;

                IPath connectLine = adjustedCurve.ConnectLineAtFromPoint ??
                                    adjustedCurve.ConnectLineAtToPoint;

                IGeometry highLevelPathOnTarget =
                    GeometryUtils.GetHighLevelGeometry(adjustedCurve.PathOnTarget, true);

                IPoint targetPointOnSketch =
                    GeometryUtils.Touches(connectLine.FromPoint, highLevelPathOnTarget)
                                                ? connectLine.FromPoint
                                                : connectLine.ToPoint;

                Marshal.ReleaseComObject(highLevelPathOnTarget);

                // it must connect to an actual target intersection point:
                if (!GeometryUtils.Intersects(
                        targetPointOnSketch,
                        (IGeometry)_stickyIntersections.GetTargetPointCollection()))
                {
                    continue;
                }

                if (PointIntersectsBoundary(targetPointOnSketch, geometryToReshape))
                {
                    // no need to connect, target point already on polygon boundary (it could only destroy a nicely reshaped geometry)
                    continue;
                }

                var highLevelAdjustLine =
                    (IPolyline)GeometryUtils.GetHighLevelGeometry(adjustedCurve.Path);

                var boundaryCutBackWithTargetPointOutsideCount = 0;

                foreach (IGeometry geometry in allGeometriesToReshape)
                {
                    bool interiorIntersects = GeometryUtils.InteriorIntersects(geometry,
                                                                               highLevelAdjustLine);

                    bool boundaryConnectWithTargetOutside =
                        geometry == geometryToReshape &&
                        !interiorIntersects &&
                        !GeometryUtils.Intersects(targetPointOnSketch, geometry) &&
                        BothEndsTouchGeometry(highLevelAdjustLine, (IPolygon)geometry);

                    if (boundaryConnectWithTargetOutside)
                    {
                        boundaryCutBackWithTargetPointOutsideCount++;
                    }
                }

                // To connect to a target intersection point at the outer boundary of a set of polygons it must be
                //

                if (boundaryCutBackWithTargetPointOutsideCount == 1 &&
                    !IsWithinAnyOriginalPolygon(targetPointOnSketch))
                {
                    ApplyReshapePath(geometryToReshape, adjustedCurve.Path, notifications, null,
                                     reshapedGeometries);
                }
            }
        }
Esempio n. 6
0
        /// <summary>
        ///  _____________
        ///  |             |
        ///  |             |
        ///  |_____________|
        ///  |  \   |  /   |
        ///  |   \  | /    |
        ///  |    o-|-     |
        ///  |      |      |
        ///  |      |      |
        ///  |      |      |
        ///  |______|___ __|
        ///
        /// Reshape line:
        ///    \      /
        ///     \    /
        ///      o---
        /// Applies the relevant reshapes of the provided adjust curves at a cut-back of a shared boundary in a border
        /// triangle situation by connecting the last vertex before the cut-off (in this case the lower end of the
        /// shared boundary between the two lower polygons) with the target intersection point.
        /// </summary>
        /// <param name="connectLinesAtCutOffs"></param>
        /// <param name="sourceTargetPairs"></param>
        /// <param name="reshapedGeometries"></param>
        /// <param name="notifications"></param>
        private void ApplySharedBoundaryCutBackConnectAtTriangleIntersections(
            Dictionary <AdjustedCutSubcurve, IGeometry> connectLinesAtCutOffs,
            IList <KeyValuePair <IPoint, IPoint> > sourceTargetPairs,
            IDictionary <IGeometry, NotificationCollection> reshapedGeometries,
            NotificationCollection notifications)
        {
            foreach (
                KeyValuePair <AdjustedCutSubcurve, AdjustedCutSubcurve> keyValuePair in
                CollectionUtils.GetAllTuples(connectLinesAtCutOffs.Keys))
            {
                AdjustedCutSubcurve adjustCurve1 = keyValuePair.Key;
                AdjustedCutSubcurve adjustCurve2 = keyValuePair.Value;

                IGeometry geometry1 = connectLinesAtCutOffs[adjustCurve1];
                IGeometry geometry2 = connectLinesAtCutOffs[adjustCurve2];

                // Two (different) neighbouring geometries
                if (geometry1 == geometry2)
                {
                    continue;
                }

                // must have the same connect line geometry
                IPath connectLine1 = adjustCurve1.ConnectLineAtFromPoint ??
                                     adjustCurve1.ConnectLineAtToPoint;
                IPath connectLine2 = adjustCurve2.ConnectLineAtFromPoint ??
                                     adjustCurve2.ConnectLineAtToPoint;

                // compare in xy only, they can be flipped
                IGeometry highLevelConnectLine1 = GeometryUtils.GetHighLevelGeometry(
                    connectLine1, true);

                IGeometry highLevelConnectLine2 = GeometryUtils.GetHighLevelGeometry(
                    connectLine2, true);

                if (!GeometryUtils.AreEqualInXY(highLevelConnectLine1, highLevelConnectLine2))
                {
                    continue;
                }

                // The connect lines are equal. Now analyze the geometries with respect to the relevant source-target pair
                KeyValuePair <IPoint, IPoint> sourceTargetPair = sourceTargetPairs.FirstOrDefault(
                    pair =>
                    GeometryUtils.AreEqualInXY(connectLine1.ToPoint, pair.Value) ||
                    GeometryUtils.AreEqualInXY(connectLine1.FromPoint, pair.Value));

                IPoint sourcePoint = sourceTargetPair.Key;

                if (sourcePoint == null)
                {
                    continue;
                }

                // It must have been a shared-boundary cut-back, i.e. none of the geometries was extended
                // and now contains the original source intersection point:
                if (GeometryUtils.Intersects(geometry1, sourcePoint) ||
                    GeometryUtils.Intersects(geometry2, sourcePoint))
                {
                    continue;
                }

                // The cut back shared boundary must be *between* the two geometries
                // i.e. the following must be the case
                // - One geometry touches the target intersection point. The original geometry contained the point.
                // - AND the other geometry must not touch the target intersection point (but be disjoint). The original geometry is also disjoint.
                if (GeometryUtils.Touches(geometry1, sourceTargetPair.Value) ^
                    GeometryUtils.Touches(geometry2, sourceTargetPair.Value))
                {
                    ApplyReshapePath(geometry1, adjustCurve1, notifications, reshapedGeometries);
                    ApplyReshapePath(geometry2, adjustCurve2, notifications, reshapedGeometries);
                }
            }
        }