Пример #1
0
        private static bool ValidateFlowDirection(
            [NotNull] IFeature feature,
            [NotNull] ILinearNetworkFeatureFinder featureFinder,
            [NotNull] NotificationCollection notifications)
        {
            if (((IFeatureClass)feature.Class).ShapeType != esriGeometryType.esriGeometryPolyline)
            {
                return(true);
            }

            IGeometry newGeometry = feature.Shape;

            IPolyline polyline = (IPolyline)newGeometry;

            bool hasCorrectOrientation = false;
            bool hasWrongOrientation   = false;
            int  fromEdgeCount         = ValidateConnections(feature, LineEnd.From, featureFinder,
                                                             ref hasCorrectOrientation,
                                                             ref hasWrongOrientation);

            int toEdgeCount = ValidateConnections(feature, LineEnd.To, featureFinder,
                                                  ref hasCorrectOrientation,
                                                  ref hasWrongOrientation);

            if (!hasWrongOrientation)
            {
                return(true);
            }

            if (!hasCorrectOrientation)
            {
                // all other connections are different -> flip
                polyline.ReverseOrientation();
                feature.Shape = polyline;
                feature.Store();

                _msg.InfoFormat("Feature {0} was flipped to enforce flow direction",
                                GdbObjectUtils.ToString(feature));
                return(true);
            }

            // Mixed situation:
            if (fromEdgeCount <= 1 && toEdgeCount <= 1)
            {
                // No bifurcation or confluence but still incorrect at one end -> error?
                NotificationUtils.Add(notifications,
                                      "Feature {0} does not have a consistent flow direction with respect to its connected edges",
                                      GdbObjectUtils.ToString(feature));
                return(false);
            }

            // Confluence or bifurcation -> probably ok
            return(true);
        }
Пример #2
0
        private bool ValidateGeometry([NotNull] IFeature feature,
                                      [NotNull] ILinearNetworkFeatureFinder featureFinder,
                                      [NotNull] NotificationCollection notifications)
        {
            bool result = ValidatePartCount(feature.Shape, GdbObjectUtils.ToString(feature),
                                            notifications);

            if (!AllowLoops)
            {
                result &= ValidateNoLoop(feature.Shape, GdbObjectUtils.ToString(feature),
                                         notifications);
            }

            return(result);
        }
Пример #3
0
        public LinearNetworkEditAgent(
            [NotNull] LinearNetworkDef networkDefinition,
            [NotNull] ILinearNetworkFeatureFinder networkFeatureFinder)
        {
            NetworkDefinition    = networkDefinition;
            NetworkFeatureFinder = networkFeatureFinder;

            // TODO: Use CustomTolerance if larger than tolerance
            _searchTolerance =
                SpatialReferenceUtils.GetXyTolerance(NetworkDefinition.GetSpatialReference());

            _createdInOperation = new HashSet <IFeature>();
            _updatedInOperation = new Dictionary <IFeature, IGeometry>(3);
            _deletedInOperation = new List <IFeature>(3);
        }
Пример #4
0
        /// <summary>
        /// Stores the result of a merge operation by updating the specified survivor feature
        /// with the merged geometry and deleting the features that are not needed any more.
        /// In case the features are geometric network edges the network junctions between the
        /// original features can be deleted, if required by the provided predicate.
        /// </summary>
        /// <param name="survivingFeature">The feature that should remain after the merge operation.</param>
        /// <param name="featuresToDelete">The features that should be deleted by the merge operation.</param>
        /// <param name="mergedGeometry">The merged geometry.</param>
        /// <param name="linearNetworkFeatureFinder"></param>
        /// <param name="deleteIntermediateNetworkJunctions">The predicate that determines
        /// which intermediate junctions (between the original edges) should be deleted.</param>
        /// <param name="deletedJunctionIDs">The junctions that were deleted.</param>
        /// <remarks>Should be called within an edit operation.</remarks>
        public static void StoreEdgeFeatureMerge(
            [NotNull] IFeature survivingFeature,
            [NotNull] IEnumerable <IFeature> featuresToDelete,
            [NotNull] IPolyline mergedGeometry,
            [CanBeNull] ILinearNetworkFeatureFinder linearNetworkFeatureFinder,
            [CanBeNull] Predicate <IFeature> deleteIntermediateNetworkJunctions,
            out List <int> deletedJunctionIDs)
        {
            Assert.ArgumentNotNull(survivingFeature, nameof(survivingFeature));
            Assert.ArgumentNotNull(featuresToDelete, nameof(featuresToDelete));
            Assert.ArgumentNotNull(mergedGeometry, nameof(mergedGeometry));

            deletedJunctionIDs = new List <int>();

            foreach (IFeature featureToDelete in featuresToDelete)
            {
                if (linearNetworkFeatureFinder != null)
                {
                    IPolyline edgePolyline = (IPolyline)featureToDelete.Shape;

                    IList <IFeature> fromJunctions =
                        linearNetworkFeatureFinder.FindJunctionFeaturesAt(edgePolyline.FromPoint);

                    deletedJunctionIDs.AddRange(
                        DeleteIntermediateJunctions(fromJunctions,
                                                    deleteIntermediateNetworkJunctions,
                                                    linearNetworkFeatureFinder,
                                                    mergedGeometry));

                    IList <IFeature> toJunctions =
                        linearNetworkFeatureFinder.FindJunctionFeaturesAt(edgePolyline.ToPoint);

                    deletedJunctionIDs.AddRange(
                        DeleteIntermediateJunctions(toJunctions,
                                                    deleteIntermediateNetworkJunctions,
                                                    linearNetworkFeatureFinder,
                                                    mergedGeometry));
                }

                featureToDelete.Delete();
            }

            GdbObjectUtils.SetFeatureShape(survivingFeature, mergedGeometry);

            survivingFeature.Store();
        }
Пример #5
0
        private static IEnumerable <int> DeleteIntermediateJunctions(
            [NotNull] IEnumerable <IFeature> junctions,
            [CanBeNull] Predicate <IFeature> predicate,
            [NotNull] ILinearNetworkFeatureFinder linearNetworkFeatureFinder,
            [NotNull] IPolyline mergedLine)
        {
            var result = new List <int>();

            foreach (IFeature junction in junctions)
            {
                if (predicate != null && !predicate(junction))
                {
                    continue;
                }

                IPoint junctionPoint = (IPoint)junction.Shape;

                int edgeCount = linearNetworkFeatureFinder.FindEdgeFeaturesAt(junctionPoint).Count;

                if (edgeCount <= 2)
                {
                    // Check if it is still needed for the merged geometry
                    IPoint fromPoint = mergedLine.FromPoint;
                    IPoint toPoint   = mergedLine.ToPoint;

                    bool neededForMergedLine =
                        GeometryUtils.AreEqualInXY(junctionPoint, fromPoint) ||
                        GeometryUtils.AreEqualInXY(junctionPoint, toPoint);

                    if (!neededForMergedLine)
                    {
                        result.Add(junction.OID);
                        junction.Delete();
                    }
                }
            }

            return(result);
        }
Пример #6
0
        public void PerformFinalValidation(
            [NotNull] Dictionary <IFeature, IGeometry> updates,
            [NotNull] IEnumerable <IFeature> inserts,
            [NotNull] ILinearNetworkFeatureFinder networkFeatureFinder)
        {
            bool valid = true;
            NotificationCollection notifications = new NotificationCollection();

            if (EnforceFlowDirection)
            {
                foreach (var update in updates)
                {
                    valid &= ValidateFlowDirection(update.Key, networkFeatureFinder, notifications);
                }

                foreach (IFeature insert in inserts)
                {
                    valid &= ValidateFlowDirection(insert, networkFeatureFinder, notifications);
                }
            }

            HandleValidationResult(valid, notifications);
        }
Пример #7
0
        public void ValidateIndividualGeometries(
            [NotNull] Dictionary <IFeature, IGeometry> updates,
            [NotNull] IEnumerable <IFeature> inserts,
            [NotNull] ILinearNetworkFeatureFinder networkFeatureFinder)
        {
            bool valid = true;

            var notifications = new NotificationCollection();

            foreach (var keyValuePair in updates)
            {
                IFeature feature = keyValuePair.Key;

                valid &= ValidateGeometry(feature, networkFeatureFinder, notifications);
            }

            foreach (IFeature newFeature in inserts)
            {
                valid &= ValidateGeometry(newFeature, networkFeatureFinder, notifications);
            }

            HandleValidationResult(valid, notifications);
        }
Пример #8
0
        private static int ValidateConnections([NotNull] IFeature feature,
                                               LineEnd atLineEnd,
                                               [NotNull] ILinearNetworkFeatureFinder featureFinder,
                                               ref bool hasCorrectOrientation,
                                               ref bool hasWrongOrientation)
        {
            IPolyline polyline = (IPolyline)feature.Shape;

            IList <IFeature> connectedEdgeFeatures =
                featureFinder.GetConnectedEdgeFeatures(feature, polyline, atLineEnd);

            IPoint thisLineEndPoint =
                atLineEnd == LineEnd.From ? polyline.FromPoint : polyline.ToPoint;

            foreach (IFeature connectedAtFrom in
                     connectedEdgeFeatures)
            {
                IPolyline connectedPolyline = (IPolyline)connectedAtFrom.Shape;

                IPoint otherLineEndPoint = atLineEnd == LineEnd.From
                                                                   ? connectedPolyline.ToPoint
                                                                   : connectedPolyline.FromPoint;

                if (GeometryUtils.AreEqual(otherLineEndPoint, thisLineEndPoint))
                {
                    // correct orientation
                    hasCorrectOrientation = true;
                }
                else
                {
                    hasWrongOrientation = true;
                }
            }

            return(connectedEdgeFeatures.Count);
        }
        public LinearNetworkNodeUpdater([NotNull] ILinearNetworkFeatureFinder networkFeatureFinder)
        {
            Assert.ArgumentNotNull(networkFeatureFinder, nameof(networkFeatureFinder));

            NetworkFeatureFinder = networkFeatureFinder;
        }
Пример #10
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);
        }