private IList <Feature> GetOverlappingFeatures(
            [NotNull] ICollection <Feature> selectedFeatures,
            [CanBeNull] CancelableProgressor cancellabelProgressor)
        {
            Dictionary <MapMember, List <long> > selection = ActiveMapView.Map.GetSelection();

            Envelope inExtent = ActiveMapView.Extent;

            TargetFeatureSelection targetFeatureSelection = TargetFeatureSelection.VisibleFeatures;

            IEnumerable <KeyValuePair <FeatureClass, List <Feature> > > foundOidsByClass =
                MapUtils.FindFeatures(ActiveMapView, selection, targetFeatureSelection,
                                      CanOverlapLayer, inExtent, cancellabelProgressor);

            if (cancellabelProgressor != null &&
                !cancellabelProgressor.CancellationToken.IsCancellationRequested)
            {
                return(new List <Feature>());
            }

            var foundFeatures = new List <Feature>();

            foreach (var keyValuePair in foundOidsByClass)
            {
                foundFeatures.AddRange(keyValuePair.Value);
            }

            // Remove the selected features from the set of overlapping features.
            // This is also important to make sure the geometries don't get mixed up / reset
            // by inserting target vertices
            foundFeatures.RemoveAll(
                f => selectedFeatures.Any(s => GdbObjectUtils.IsSameFeature(f, s)));

            return(foundFeatures);
        }
Esempio n. 2
0
        public static IEnumerable <KeyValuePair <FeatureClass, List <Feature> > > FindFeatures(
            [NotNull] MapView mapView,
            [NotNull] Dictionary <MapMember, List <long> > intersectingSelectedFeatures,
            TargetFeatureSelection targetSelectionType,
            [CanBeNull] Predicate <FeatureLayer> layerPredicate = null,
            [CanBeNull] Envelope extent = null,
            [CanBeNull] CancelableProgressor cancelableProgressor = null)
        {
            Assert.ArgumentCondition(
                targetSelectionType != TargetFeatureSelection.SelectedFeatures &&
                targetSelectionType != TargetFeatureSelection.Undefined,
                "Unsupported target selection type");

            var selectedFeatures = GetFeatures(intersectingSelectedFeatures).ToList();

            var searchGeometry = GetSearchGeometry(selectedFeatures, extent);

            if (searchGeometry == null)
            {
                yield break;
            }

            foreach (var keyValuePair in FindFeatures(
                         mapView, searchGeometry, targetSelectionType, layerPredicate,
                         selectedFeatures, cancelableProgressor))
            {
                yield return(keyValuePair);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Finds the features in the map by the specified criteria, grouped by feature class
        /// </summary>
        /// <param name="mapView">The map view containing the layers to search</param>
        /// <param name="searchGeometry">The search geometry</param>
        /// <param name="spatialRelationship">The spatial relationship between the found features
        /// and the search geometry.</param>
        /// <param name="targetSelectionType">The target selection type that determines which layers
        /// are searched.</param>
        /// <param name="layerPredicate">An extra layer predicate that allows for a more
        /// fine-granular determination of the layers to be searched.</param>
        /// <param name="featurePredicate">An extra feature predicate that allows to determine
        /// criteria on the feature level.</param>
        /// <param name="selectedFeatures">The selected features, relevant only for
        /// <see cref="targetSelectionType"/> with value <see cref="TargetFeatureSelection.SameClass"/>. </param>
        /// <param name="cancelableProgressor"></param>
        /// <returns></returns>
        public static IEnumerable <KeyValuePair <FeatureClass, List <Feature> > > FindFeatures(
            [NotNull] MapView mapView,
            [NotNull] ArcGIS.Core.Geometry.Geometry searchGeometry,
            SpatialRelationship spatialRelationship,
            TargetFeatureSelection targetSelectionType,
            [CanBeNull] Predicate <FeatureLayer> layerPredicate,
            [CanBeNull] Predicate <Feature> featurePredicate,
            List <Feature> selectedFeatures,
            CancelableProgressor cancelableProgressor = null)
        {
            // NOTE: FeatureLayer.Search is quite useless, as we cannot control recyclability and as soon as the cursor
            //       is disposed, the feature's geometry is wrong!

            // -> Get the distinct feature classes (TODO: include layer definition queries)

            IEnumerable <FeatureLayer> featureLayers =
                GetLayers <FeatureLayer>(
                    mapView, fl => IsLayerApplicable(fl, targetSelectionType, layerPredicate,
                                                     selectedFeatures));

            IEnumerable <IGrouping <IntPtr, FeatureLayer> > layersGroupedByClass =
                featureLayers.GroupBy(fl => fl.GetFeatureClass().Handle);

            foreach (var layersInClass in layersGroupedByClass)
            {
                // One query per distinct definition query, then make OIDs distinct

                FeatureClass   featureClass = null;
                List <Feature> features     = new List <Feature>();
                foreach (IGrouping <string, FeatureLayer> layers in layersInClass.GroupBy(
                             fl => fl.DefinitionQuery))
                {
                    if (cancelableProgressor != null &&
                        cancelableProgressor.CancellationToken.IsCancellationRequested)
                    {
                        yield break;
                    }

                    featureClass = layers.First().GetFeatureClass();

                    QueryFilter filter =
                        GdbQueryUtils.CreateSpatialFilter(searchGeometry, spatialRelationship);
                    filter.WhereClause = layers.Key;

                    IEnumerable <Feature> foundFeatures = GdbQueryUtils
                                                          .GetFeatures(featureClass, filter, false)
                                                          .Where(f => featurePredicate == null ||
                                                                 featurePredicate(f));
                    features.AddRange(foundFeatures);
                }

                if (featureClass != null && features.Count > 0)
                {
                    yield return(new KeyValuePair <FeatureClass, List <Feature> >(
                                     featureClass, features.DistinctBy(f => f.GetObjectID()).ToList()));
                }
            }
        }
Esempio n. 4
0
        private static bool IsLayerApplicable(
            [CanBeNull] FeatureLayer featureLayer,
            TargetFeatureSelection targetSelectionType,
            [CanBeNull] Predicate <FeatureLayer> layerPredicate,
            [NotNull] ICollection <Feature> selectedFeatures)
        {
            if (featureLayer?.GetFeatureClass() == null)
            {
                return(false);
            }

            if (layerPredicate != null && !layerPredicate(featureLayer))
            {
                return(false);
            }

            if ((targetSelectionType == TargetFeatureSelection.VisibleEditableFeatures ||
                 targetSelectionType == TargetFeatureSelection.VisibleSelectableEditableFeatures) &&
                !featureLayer.IsEditable)
            {
                return(false);
            }

            if ((targetSelectionType == TargetFeatureSelection.VisibleSelectableFeatures ||
                 targetSelectionType == TargetFeatureSelection.VisibleSelectableEditableFeatures) &&
                !featureLayer.IsSelectable)
            {
                return(false);
            }

            if (!featureLayer.IsVisible)
            {
                return(false);
            }

            if (targetSelectionType == TargetFeatureSelection.SameClass &&
                !selectedFeatures.Any(
                    f => DatasetUtils.IsSameClass(f.GetTable(), featureLayer.GetTable())))
            {
                return(false);
            }

            return(true);
        }
Esempio n. 5
0
        private bool SelectTargets(List <Feature> selectedFeatures, Geometry sketch,
                                   CancelableProgressor progressor)
        {
            const TargetFeatureSelection targetFeatureSelection =
                TargetFeatureSelection.VisibleFeatures;

            sketch = ToolUtils.SketchToSearchGeometry(sketch, GetSelectionTolerancePixels(),
                                                      out bool _);

            Predicate <Feature> canUseAsTargetFeature =
                t => CanUseAsTargetFeature(selectedFeatures, t);

            SpatialRelationship spatialRel =
                SketchType == SketchGeometryType.Polygon
                                        ? SpatialRelationship.Contains
                                        : SpatialRelationship.Intersects;

            var foundOidsByLayer =
                MapUtils.FindFeatures(ActiveMapView, sketch, spatialRel,
                                      targetFeatureSelection, CanUseAsTargetLayer,
                                      canUseAsTargetFeature, selectedFeatures, progressor);

            // TODO: Picker if single click and several found

            if (progressor != null && progressor.CancellationToken.IsCancellationRequested)
            {
                _msg.Warn("Calculation of reshape lines was cancelled.");
                return(false);
            }

            IList <Feature> allTargetFeatures =
                GetDistinctSelectedFeatures(foundOidsByLayer, _changeAlongCurves?.TargetFeatures,
                                            KeyboardUtils.IsModifierPressed(Keys.Shift));

            _changeAlongCurves =
                allTargetFeatures.Count > 0
                                        ? CalculateReshapeCurves(selectedFeatures, allTargetFeatures, progressor)
                                        : new ChangeAlongCurves(new List <CutSubcurve>(),
                                                                ReshapeAlongCurveUsability.NoTarget);

            _feedback.Update(_changeAlongCurves);

            return(true);
        }
Esempio n. 6
0
        private IList <Feature> GetAdjacentFeatures(
            [NotNull] ICollection <Feature> selectedFeatures,
            [CanBeNull] CancelableProgressor cancellabelProgressor)
        {
            Dictionary <MapMember, List <long> > selection = ActiveMapView.Map.GetSelection();

            if (!selection.Keys.Any(mm => mm is FeatureLayer fl &&
                                    fl.ShapeType == esriGeometryType.esriGeometryPolyline))
            {
                return(null);
            }

            Envelope inExtent = ActiveMapView.Extent;

            // TODO: Use linear network classes as defined in reshape options
            TargetFeatureSelection targetFeatureSelection = TargetFeatureSelection.SameClass;

            IEnumerable <KeyValuePair <FeatureClass, List <Feature> > > foundOidsByClass =
                MapUtils.FindFeatures(
                    ActiveMapView, selection, targetFeatureSelection,
                    layer => layer.ShapeType == esriGeometryType.esriGeometryPolyline,
                    inExtent, cancellabelProgressor);

            if (cancellabelProgressor != null &&
                !cancellabelProgressor.CancellationToken.IsCancellationRequested)
            {
                return(new List <Feature>());
            }

            var foundFeatures = new List <Feature>();

            foreach (var keyValuePair in foundOidsByClass)
            {
                foundFeatures.AddRange(keyValuePair.Value);
            }

            foundFeatures.RemoveAll(
                f => selectedFeatures.Any(s => GdbObjectUtils.IsSameFeature(f, s)));

            return(foundFeatures);
        }