Exemple #1
0
        public void CanFormatRowWithFieldNameContainedInOtherField()
        {
            // TOP-5056: Field PLZ_ZZ and PLZ are both present in the feature class:
            const string name      = "TESTCLASS";
            const string aliasName = "Test FeatureClass";

            var featureClassMock = new FeatureClassMock(
                1, name, aliasName, esriGeometryType.esriGeometryPolyline);

            featureClassMock.AddField("NAME", esriFieldType.esriFieldTypeString);
            featureClassMock.AddField("PLZ", esriFieldType.esriFieldTypeInteger);
            featureClassMock.AddField("PLZ_ZZ", esriFieldType.esriFieldTypeInteger);

            IFeature feature = featureClassMock.CreateFeature();

            var plz = 5023;
            var zz  = 2;

            feature.Value[feature.Fields.FindField("PLZ")]    = plz;
            feature.Value[feature.Fields.FindField("PLZ_ZZ")] = zz;

            Assert.AreEqual($"{plz}_{zz}", RowFormat.Format(@"{PLZ}_{PLZ_ZZ}", feature));
        }
Exemple #2
0
        public void CanFormatRow()
        {
            const string name      = "TESTCLASS";
            const string aliasName = "Test FeatureClass";

            var featureClassMock = new FeatureClassMock(
                1, name, aliasName, esriGeometryType.esriGeometryPolyline);

            featureClassMock.AddField("NAME", esriFieldType.esriFieldTypeString);
            featureClassMock.AddField("PLZ", esriFieldType.esriFieldTypeInteger);

            IFeature feature = featureClassMock.CreateFeature();

            Assert.AreEqual($"{feature.OID}", RowFormat.Format(feature));
            Assert.AreEqual($"{aliasName} - {feature.OID}", RowFormat.Format(feature, true));

            var plz = 5023;

            feature.Value[feature.Fields.FindField("PLZ")] = plz;

            Assert.AreEqual($": {plz}", RowFormat.Format(@"{NAME}: {PLZ}", feature));
            Assert.AreEqual($"<null>: {plz}",
                            RowFormat.Format(@"{NAME}: {PLZ}", feature, "<null>"));
        }
Exemple #3
0
        public static IEnumerable <IGeometry> GetSelectableOverlaps(
            [NotNull] IFeature sourceFeature,
            [NotNull] SpatialHashSearcher <IFeature> overlappingFeatures,
            [CanBeNull] NotificationCollection notifications = null,
            [CanBeNull] ITrackCancel trackCancel             = null)
        {
            IGeometry sourceGeometry = sourceFeature.Shape;

            if (sourceGeometry == null || sourceGeometry.IsEmpty)
            {
                yield break;
            }

            IEnvelope sourceEnvelope = sourceGeometry.Envelope;

            double tolerance = GeometryUtils.GetXyTolerance(sourceGeometry);

            foreach (IFeature targetFeature in overlappingFeatures.Search(
                         sourceEnvelope.XMin, sourceEnvelope.YMin,
                         sourceEnvelope.XMax, sourceEnvelope.YMax, tolerance))
            {
                if (trackCancel != null && !trackCancel.Continue())
                {
                    yield break;
                }

                _msg.VerboseDebugFormat("Calculating overlap from {0}",
                                        GdbObjectUtils.ToString(targetFeature));

                IGeometry targetGeometry = targetFeature.Shape;

                if (GeometryUtils.Disjoint(targetGeometry, sourceGeometry))
                {
                    continue;
                }

                if (GeometryUtils.Contains(targetGeometry, sourceGeometry))
                {
                    // Idea for the future: Optionally allow also deleting features (probably using a black display feedback)
                    NotificationUtils.Add(notifications,
                                          "Source feature {0} is completely within target {1} and would become empty if the overlap was removed. The overlap is supressed.",
                                          RowFormat.Format(sourceFeature),
                                          RowFormat.Format(targetFeature));
                    continue;
                }

                if (sourceGeometry.GeometryType == esriGeometryType.esriGeometryMultiPatch)
                {
                    sourceGeometry = GeometryFactory.CreatePolygon(sourceGeometry);
                }

                IGeometry intersection = TryGetIntersection(sourceGeometry, targetGeometry);

                if (intersection == null)
                {
                    continue;
                }

                if (GeometryUtils.GetPartCount(intersection) > 1)
                {
                    foreach (var part in GeometryUtils.Explode(intersection))
                    {
                        yield return(part);
                    }
                }
                else
                {
                    yield return(intersection);
                }
            }
        }
        /// <summary>
        /// Gets points weeded at the specified tolerance and under consideration of shared vertices if required.
        /// </summary>
        /// <param name="forFeatureVertexInfos"></param>
        /// <param name="weedTolerance"></param>
        /// <param name="only2D"></param>
        /// <param name="inPerimeter"></param>
        /// <param name="trackCancel"></param>
        /// <returns></returns>
        public static void CalculateWeedPoints(
            [NotNull] IEnumerable <FeatureVertexInfo> forFeatureVertexInfos,
            double weedTolerance,
            bool only2D,
            [CanBeNull] IGeometry inPerimeter,
            [CanBeNull] ITrackCancel trackCancel)
        {
            foreach (FeatureVertexInfo featureVertexInfo in forFeatureVertexInfos)
            {
                if (trackCancel != null && !trackCancel.Continue())
                {
                    return;
                }

                IFeature feature = featureVertexInfo.Feature;

                _msg.DebugFormat("Calculating weed points for {0}",
                                 GdbObjectUtils.ToString(feature));

                try
                {
                    // intersect on perimeter and cut into separate paths at protected points
                    IPolycurve originalGeometry = GetOriginalGeometry(feature,
                                                                      featureVertexInfo);
                    IPointCollection weededPoints;
                    try
                    {
                        weededPoints = CrackUtils.GetWeedPoints(
                            originalGeometry, weedTolerance, only2D, inPerimeter);
                    }
                    catch (Exception e)
                    {
                        _msg.Debug("Generalisation error.", e);
                        _msg.WarnFormat("Cannot generalize {0}: {1}", RowFormat.Format(feature),
                                        e.Message);
                        continue;
                    }

                    // NOTE: At least in advanced generalize consider only showing those crack points that
                    //		 actually protect an existing vertex (i.e. only those on an existing vertex)
                    //		 -> could be done in RemovableSegments
                    //		 In theory it would also be nice to see the points that would be weeded if they were not protected
                    //		 however this means double the processing and the result is not always consistent because
                    //		 if an otherwise protected point is weeded some other point would probably remain (problem
                    //		 of different start point).
                    //		 It might be helpful if only those crack points would be shown that are
                    //		 actual vertices but again in case of un-selected neighbour it nicely shows the cut points
                    //		 of the weeding and makes the weed points more plausible in certain cases.
                    //		 -> consider making the symbol slightly bigger for real-vertex crack points (or square)

                    // this is good for protecting shared vertices between selected and unselected features
                    // for guaranteed identical generalization of shared edges between selected features
                    // build topology graph!

                    // NOTE: in theory this is only necessary if the input is not cut into separate paths at all protected points
                    // -> consider only cutting at intersection points between sources (shared line end points)
                    // NOTE: sometimes the intersection is rather inaccurate -> this still reduces points!
                    featureVertexInfo.NonDeletablePoints = RemoveProtectedPoints(weededPoints,
                                                                                 featureVertexInfo);

                    featureVertexInfo.PointsToDelete = weededPoints;
                }
                catch (Exception)
                {
                    _msg.ErrorFormat("Error calculating generalized points for {0}",
                                     GdbObjectUtils.ToString(feature));
                    throw;
                }
            }
        }
        public void AddCrackPoints([NotNull] IFeature targetFeature,
                                   [NotNull] CrackPointCalculator crackPointCalculator)
        {
            // TODO: consider moving this to CrackUtils
            Stopwatch watch =
                _msg.DebugStartTiming("Calculating intersection points between {0} and {1}",
                                      GdbObjectUtils.ToString(Feature),
                                      GdbObjectUtils.ToString(targetFeature));

            IPointCollection intersectionPoints = null;

            try
            {
                IGeometry targetGeometry   = targetFeature.ShapeCopy;
                IGeometry originalGeometry = Feature.Shape;
                IPolyline clippedSource    = OriginalClippedPolyline;

                GeometryUtils.EnsureSpatialReference(targetGeometry,
                                                     clippedSource.SpatialReference);

                crackPointCalculator.SetDataResolution(Feature);

                IGeometry intersectionTarget;
                intersectionPoints = crackPointCalculator.GetIntersectionPoints(
                    clippedSource, targetGeometry, out intersectionTarget);

                // TODO: if the target has a vertex closish (wrt tolerance) to the actual intersection point
                //		 the intersection point is somewhere in between. Consider snapping intersection points
                //		 to target vertices (this might be the start of clustering!) or use minimal tolerance!
                AddIntersectionPoints(intersectionPoints);

                IList <CrackPoint> crackPoints = crackPointCalculator.DetermineCrackPoints(
                    intersectionPoints, originalGeometry, clippedSource, intersectionTarget);

                // TODO: rename to AddNonCrackablePoints / sort out whether drawing can happen straight from List<CrackPoint>
                AddCrackPoints(crackPoints);

                if (intersectionTarget != null && intersectionTarget != targetGeometry)
                {
                    Marshal.ReleaseComObject(intersectionTarget);
                }

                Marshal.ReleaseComObject(targetGeometry);
            }
            catch (Exception e)
            {
                string message =
                    $"Error calculationg crack points with target feature {RowFormat.Format(targetFeature)}: {e.Message}";

                _msg.Debug(message, e);

                if (crackPointCalculator.ContinueOnException)
                {
                    crackPointCalculator.FailedOperations.Add(Feature.OID, message);
                }
                else
                {
                    throw;
                }
            }

            _msg.DebugStopTiming(watch, "Calculated and processed {0} intersection points",
                                 intersectionPoints?.PointCount);
        }