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); }
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); } }
/// <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())); } } }
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); }
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); }
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); }