public void CanCreateSpatialFilterWithNonZSimpleGeometry() { IFeatureWorkspace ws = OpenTestWorkspace(); IFeatureClass fc = ws.OpenFeatureClass("TOPGIS_TLM.TLM_STRASSE"); IEnvelope nonZSimpleEnvelope = GeometryFactory.CreateEnvelope(2600000, 1200000, 2700000, 1300000); GeometryUtils.MakeZAware(nonZSimpleEnvelope); Assert.False(((IZAware)nonZSimpleEnvelope).ZSimple, "Must be non-Z-simple"); ISpatialReference spatialReference = Assert.NotNull(DatasetUtils.GetSpatialReference(fc)); IGeometry validGeometry; string message; Assert.False(GdbQueryUtils.IsValidFilterGeometry( nonZSimpleEnvelope, SpatialReferenceUtils.GetXyResolution(spatialReference), out validGeometry, out message), "Search geometry should not be valid"); Assert.NotNull(validGeometry); IQueryFilter filter = GdbQueryUtils.CreateSpatialFilter(fc, nonZSimpleEnvelope); Assert.True(GdbQueryUtils.GetFeatures(fc, filter, true).Any(), "No features found"); }
public void CanCreateSpatialFilterWithSubResolutionPolygon() { IFeatureWorkspace ws = OpenTestWorkspace(); IFeatureClass fc = ws.OpenFeatureClass("TOPGIS_TLM.TLM_STRASSE"); IPolygon subResolutionPoly = GeometryFactory.CreatePolygon(2600000, 1200000, 2600000.0001, 1200000.0001); subResolutionPoly.SpatialReference = ((IGeoDataset)fc).SpatialReference; IQueryFilter filter = GdbQueryUtils.CreateSpatialFilter( fc, subResolutionPoly, esriSpatialRelEnum.esriSpatialRelIntersects, false, null); IFeatureCursor cursor = fc.Search(filter, true); Marshal.ReleaseComObject(cursor); IPolygon linearPoly = GeometryFactory.CreatePolygon(2600000, 1200000, 2600000.0001, 1200010); linearPoly.SpatialReference = ((IGeoDataset)fc).SpatialReference; filter = GdbQueryUtils.CreateSpatialFilter( fc, linearPoly, esriSpatialRelEnum.esriSpatialRelIntersects, true, null); cursor = fc.Search(filter, true); Marshal.ReleaseComObject(cursor); }
/// <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())); } } }
public void CanGetRasterFileFromMosaicDatasetUsingSpatialQuery() { IWorkspace workspace = TestUtils.OpenUserWorkspaceOracle(); IMosaicDataset mosaicDataset = DatasetUtils.OpenMosaicDataset(workspace, "TOPGIS_TLM.TLM_DTM_MOSAIC"); IFeatureClass rasterCatalog = mosaicDataset.Catalog; IEnvelope winterthur = GeometryFactory.CreateEnvelope( 2690000, 1254000, 2707500, 1266000, SpatialReferenceUtils.CreateSpatialReference(WellKnownHorizontalCS.LV95)); winterthur.Expand(-0.1, -0.1, false); IQueryFilter spatialFilter = GdbQueryUtils.CreateSpatialFilter(rasterCatalog, winterthur); IStringArray stringArray; Stopwatch watch = Stopwatch.StartNew(); int count = 0; foreach (IFeature catalogFeature in GdbQueryUtils.GetFeatures( rasterCatalog, spatialFilter, false)) { // Method 1 (slow): var rasterCatalogItem = (IRasterCatalogItem)catalogFeature; IRasterDataset rasterDataset = rasterCatalogItem.RasterDataset; var itemPaths = (IItemPaths)rasterDataset; stringArray = itemPaths.GetPaths(); Marshal.ReleaseComObject(rasterDataset); Assert.AreEqual(1, stringArray.Count); string resultPathViaRasterDataset = stringArray.Element[0]; // Method 2 (fast): var itemPathsQuery = (IItemPathsQuery)mosaicDataset; if (itemPathsQuery.QueryPathsParameters == null) { itemPathsQuery.QueryPathsParameters = new QueryPathsParametersClass(); } stringArray = itemPathsQuery.GetItemPaths(catalogFeature); Assert.AreEqual(1, stringArray.Count); string resultPathViaItemPathsQuery = stringArray.Element[0]; Assert.AreEqual(resultPathViaRasterDataset, resultPathViaItemPathsQuery); count++; } Console.WriteLine("Successfully extracted {0} raster paths in {1}s", count, watch.Elapsed.TotalSeconds); }
public void Measure_performance_query_items_from_GDB() { Polygon polygon = PolygonConstruction .StartPolygon(0, 0) .LineTo(0, 20) .LineTo(20, 20) .LineTo(20, 0) .ClosePolygon(); Polygon areaOfInterest = PolygonConstruction .StartPolygon(0, 0) .LineTo(0, 100) .LineTo(100, 100) .LineTo(100, 0) .ClosePolygon(); var rowCount = 10000; TestUtils.InsertRows(_emptyIssuesGdb, _featureClassName, polygon, rowCount); try { var uri = new Uri(_emptyIssuesGdb, UriKind.Absolute); var geodatabase = new Geodatabase(new FileGeodatabaseConnectionPath(uri)); var table = geodatabase.OpenDataset <Table>(_featureClassName); Dictionary <Geodatabase, List <Table> > tablesByGeodatabase = new Dictionary <Geodatabase, List <Table> > { { geodatabase, new List <Table> { table } } }; IRepository stateRepository = new XmlWorkItemStateRepository(@"C:\temp\states.xml", null, null); IWorkItemRepository repository = new IssueItemRepository(tablesByGeodatabase, stateRepository); IWorkList workList = new GdbQueryWorkList(repository, "work list"); workList.AreaOfInterest = areaOfInterest; var filter = GdbQueryUtils.CreateSpatialFilter(areaOfInterest); var watch = new Stopwatch(); watch.Start(); IEnumerable <IWorkItem> items = workList.GetItems(filter); watch.Stop(); Console.WriteLine($"{watch.ElapsedMilliseconds} ms"); Assert.AreEqual(rowCount, items.Count()); } finally { TestUtils.DeleteAllRows(_emptyIssuesGdb, _featureClassName); } }
public void CanCreateSpatialFilterWithSubResolutionEnvelope() { IFeatureWorkspace ws = OpenTestWorkspace(); IFeatureClass fc = ws.OpenFeatureClass("TOPGIS_TLM.TLM_STRASSE"); IEnvelope subResolutionEnv = GeometryFactory.CreateEnvelope(2600000, 1200000, 2600000.0001, 1200000.0001); ISpatialReference spatialReference = DatasetUtils.GetSpatialReference(fc); subResolutionEnv.SpatialReference = spatialReference; double xyResolution = SpatialReferenceUtils.GetXyResolution(Assert.NotNull(spatialReference)); IGeometry validGeometry; string message; Assert.False(GdbQueryUtils.IsValidFilterGeometry( subResolutionEnv, xyResolution, out validGeometry, out message), "Sub-resolution polygon should not be valid"); Assert.NotNull(validGeometry); Assert.False(subResolutionEnv == validGeometry, "Corrected geometry must be different to input"); Assert.True(GdbQueryUtils.IsValidFilterGeometry( validGeometry, xyResolution, out validGeometry, out message), "Corrected geometry should be valid"); IQueryFilter filter = GdbQueryUtils.CreateSpatialFilter( fc, subResolutionEnv, esriSpatialRelEnum.esriSpatialRelIntersects, false, spatialReference); IFeatureCursor cursor = fc.Search(filter, true); Marshal.ReleaseComObject(cursor); IEnvelope linearEnv = GeometryFactory.CreateEnvelope(2600000, 1200000, 2600000.0001, 1201010); linearEnv.SpatialReference = ((IGeoDataset)fc).SpatialReference; filter = GdbQueryUtils.CreateSpatialFilter( fc, linearEnv, esriSpatialRelEnum.esriSpatialRelIntersects, true, null); cursor = fc.Search(filter, true); Marshal.ReleaseComObject(cursor); }
public void CanCreateSpatialFilterWithEmptyPolygon() { IFeatureWorkspace ws = OpenTestWorkspace(); IFeatureClass fc = ws.OpenFeatureClass("TOPGIS_TLM.TLM_STRASSE"); IPolygon emptyPoly = new PolygonClass(); emptyPoly.SpatialReference = ((IGeoDataset)fc).SpatialReference; IGeometry validGeometry; string message; Assert.False(GdbQueryUtils.IsValidFilterGeometry( emptyPoly, 0.001, out validGeometry, out message), "Empty polygon should not be valid"); Assert.Null(validGeometry); if (RuntimeUtils.Is10_4orHigher) { NUnit.Framework.Assert.Catch <Exception>( () => GdbQueryUtils.CreateSpatialFilter(fc, emptyPoly)); } ISpatialFilter spatialFilter = new SpatialFilterClass(); spatialFilter.GeometryField = fc.ShapeFieldName; spatialFilter.set_GeometryEx(emptyPoly, true); spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects; IFeatureCursor cursor = null; if (RuntimeUtils.Is10_1 || RuntimeUtils.Is10_2 || RuntimeUtils.Is10_3 || RuntimeUtils.Is10_4orHigher) { NUnit.Framework.Assert.Throws <NullReferenceException>( () => cursor = fc.Search(spatialFilter, true)); } else { cursor = fc.Search(spatialFilter, true); } if (cursor != null) { Marshal.ReleaseComObject(cursor); } }
public void CanCreateSpatialFilterWithMultipatch() { IFeatureWorkspace ws = OpenTestWorkspace(); IFeatureClass fc = ws.OpenFeatureClass("TOPGIS_TLM.TLM_STRASSE"); ISpatialReference spatialReference = DatasetUtils.GetSpatialReference(fc); IEnvelope largeEnvelope = GeometryFactory.CreateEnvelope(2600000, 1200000, 2601000, 1201000, 445, spatialReference); IMultiPatch multiPatch = GeometryFactory.CreateMultiPatch(GeometryFactory.CreatePolygon(largeEnvelope)); double xyResolution = SpatialReferenceUtils.GetXyResolution(Assert.NotNull(spatialReference)); // NOTE: Multipatch implements IRelationalOperator since a while! IGeometry validGeometry; string message; Assert.True(GdbQueryUtils.IsValidFilterGeometry( multiPatch, xyResolution, out validGeometry, out message), "Multipatch should be valid"); Assert.NotNull(validGeometry); Assert.True(multiPatch == validGeometry, "Multipatch should be valid"); Assert.True(GdbQueryUtils.IsValidFilterGeometry( validGeometry, xyResolution, out validGeometry, out message), "Corrected geometry should be valid"); IQueryFilter filter = GdbQueryUtils.CreateSpatialFilter( fc, multiPatch, esriSpatialRelEnum.esriSpatialRelIntersects, false, spatialReference); Assert.True(GdbQueryUtils.GetFeatures(fc, filter, true).Any(), "No features found."); }
protected static List <IFeature> SearchFeatureClasses( [NotNull] IEnumerable <LinearNetworkClassDef> linearNetworkClasses, [NotNull] IGeometry searchGeometry, [NotNull] ICollection <esriGeometryType> geometryTypes, [CanBeNull] IWorkspace alternateVersion = null) { var foundFeatures = new List <IFeature>(); foreach (LinearNetworkClassDef networkClassDef in linearNetworkClasses) { IFeatureClass featureClass = networkClassDef.FeatureClass; if (alternateVersion != null && !WorkspaceUtils.IsSameVersion(alternateVersion, DatasetUtils.GetWorkspace(featureClass))) { featureClass = DatasetUtils.OpenFeatureClass(alternateVersion, DatasetUtils.GetName(featureClass)); } if (!geometryTypes.Contains(featureClass.ShapeType)) { continue; } IQueryFilter filter = GdbQueryUtils.CreateSpatialFilter(featureClass, searchGeometry); filter.WhereClause = networkClassDef.WhereClause; foundFeatures.AddRange(GdbQueryUtils.GetFeatures(featureClass, filter, false)); } return(foundFeatures); }
public void CanOpenRasterFileFromMosaicDatasetUsingSpatialQueryGdal_Learning() { // TODO: Corrext GDAL native reference. Work-around: copy the x64 directory to the output dir IWorkspace workspace = TestUtils.OpenUserWorkspaceOracle(); IMosaicDataset mosaicDataset = DatasetUtils.OpenMosaicDataset(workspace, "TOPGIS_TLM.TLM_DTM_MOSAIC"); IFeatureClass rasterCatalog = mosaicDataset.Catalog; IPoint winterthurLL = GeometryFactory.CreatePoint( 2690021, 1254011, SpatialReferenceUtils.CreateSpatialReference(WellKnownHorizontalCS.LV95)); IQueryFilter spatialFilter = GdbQueryUtils.CreateSpatialFilter(rasterCatalog, winterthurLL); Gdal.AllRegister(); IStringArray stringArray; Stopwatch watch = Stopwatch.StartNew(); List <IFeature> features = GdbQueryUtils.GetFeatures( rasterCatalog, spatialFilter, false).ToList(); Assert.True(features.Count > 0); var itemPathsQuery = (IItemPathsQuery)mosaicDataset; itemPathsQuery.QueryPathsParameters = new QueryPathsParametersClass(); stringArray = itemPathsQuery.GetItemPaths(features[0]); string rasterPath = stringArray.Element[0]; Dataset ds = Gdal.Open(rasterPath, Access.GA_ReadOnly); if (ds == null) { Console.WriteLine("Can't open " + rasterPath); return; } Console.WriteLine("Raster dataset parameters:"); Console.WriteLine(" Projection: " + ds.GetProjectionRef()); Console.WriteLine(" RasterCount: " + ds.RasterCount); Console.WriteLine(" RasterSize (" + ds.RasterXSize + "," + ds.RasterYSize + ")"); double[] adfGeoTransform = new double[6]; ds.GetGeoTransform(adfGeoTransform); double originX = adfGeoTransform[0]; double originY = adfGeoTransform[3]; Console.WriteLine($"Origin: {originX} | {originY}"); double pixelSizeX = adfGeoTransform[1]; double pixelSizeY = adfGeoTransform[5]; Console.WriteLine($"Pixel Size: {pixelSizeX} | {pixelSizeY}"); /* -------------------------------------------------------------------- */ /* Get driver */ /* -------------------------------------------------------------------- */ Driver drv = ds.GetDriver(); if (drv == null) { Console.WriteLine("Can't get driver."); Environment.Exit(-1); } Console.WriteLine("Using driver " + drv.LongName); /* -------------------------------------------------------------------- */ /* Get raster band */ /* -------------------------------------------------------------------- */ for (int iBand = 1; iBand <= ds.RasterCount; iBand++) { Band band = ds.GetRasterBand(iBand); Console.WriteLine("Band " + iBand + " :"); Console.WriteLine(" DataType: " + band.DataType); Console.WriteLine(" Size (" + band.XSize + "," + band.YSize + ")"); Console.WriteLine(" PaletteInterp: " + band.GetRasterColorInterpretation().ToString()); band.GetBlockSize(out int blockSizeX, out int blockSizeY); Console.WriteLine(" Block Size (" + blockSizeX + "," + blockSizeY + ")"); for (int iOver = 0; iOver < band.GetOverviewCount(); iOver++) { Band over = band.GetOverview(iOver); Console.WriteLine(" OverView " + iOver + " :"); Console.WriteLine(" DataType: " + over.DataType); Console.WriteLine(" Size (" + over.XSize + "," + over.YSize + ")"); Console.WriteLine(" PaletteInterp: " + over.GetRasterColorInterpretation()); } // Get the value at winterthurLL: int pxlOffsetX = (int)Math.Floor((winterthurLL.X - originX) / pixelSizeX); int pxlOffsetY = (int)Math.Floor((winterthurLL.Y - originY) / pixelSizeY); double[] buffer = new double[1]; band.ReadRaster(pxlOffsetX, pxlOffsetY, 1, 1, buffer, 1, 1, 0, 0); double z = buffer[0]; // TODO: Theoretically there is an underlying block cache which would make subsequent // reads in a similar area very fast (TEST!) - probably the same as IRaster behaviour. // TODO: Bilinear interpolation if it's not the middle of a pixel! Console.WriteLine("Z value at {0}, {1}: {2}", winterthurLL.X, winterthurLL.Y, z); } }
private IList <IWorkItem> GetWorkItemsForInnermostContext([NotNull] Polygon[] perimeters, VisitedSearchOption visitedSearch, int startIndex) { Assert.ArgumentNotNull(perimeters, nameof(perimeters)); if (_msg.IsVerboseDebugEnabled) { _msg.DebugFormat("Getting work items for innermost context ({0} perimeters)", perimeters.Length); } const CurrentSearchOption currentSearch = CurrentSearchOption.ExcludeCurrent; for (var index = 0; index < perimeters.Length; index++) { Polygon intersection = GetIntersection(perimeters, index); if (intersection.IsEmpty) { // continue with next perimeter } else { // Possible optimization: do one search, // and qualify each candidate with "intersects" / "within" // --> filter result // todo daro: old implementation // search the items fully within the search extent //IList<WorkItem> workItems = GetItems(statusSearch, currentSearch, // visitedSearch, startIndex, // intersection, // SpatialSearchOption.Within, // match); SpatialQueryFilter filter = GdbQueryUtils.CreateSpatialFilter(intersection, SpatialRelationship.Within); List <IWorkItem> workItems = GetItems(filter, startIndex, currentSearch, visitedSearch).ToList(); if (workItems.Count == 0) { if (_msg.IsVerboseDebugEnabled) { _msg.Debug("No work items fully within the intersection, searching partially contained items"); } // todo daro: old implementation // search also intersecting items //workItems = GetItems(statusSearch, currentSearch, // visitedSearch, startIndex, // intersection, SpatialSearchOption.Intersect, // match); filter = GdbQueryUtils.CreateSpatialFilter(intersection); workItems = GetItems(filter, startIndex, currentSearch, visitedSearch).ToList(); } if (_msg.IsVerboseDebugEnabled) { _msg.DebugFormat("{0} work item(s) found", workItems.Count); } if (workItems.Count > 0) { return(workItems); } // else: continue with next perimeter } } // nothing found so far. Search entire work list // todo daro: old implementation //return GetItems(statusSearch, currentSearch, visitedSearch, startIndex, match); return(GetItems(null, startIndex, currentSearch, visitedSearch).ToList()); }
public void CanCreateSpatialFilterWithSubResolutionPolyline() { IFeatureWorkspace ws = OpenTestWorkspace(); IFeatureClass fc = ws.OpenFeatureClass("TOPGIS_TLM.TLM_STRASSE"); IPolyline subResolutionPolyline = GeometryFactory.CreatePolyline(2600000, 1200000, 2600000.0001, 1200000.0001); subResolutionPolyline.SpatialReference = ((IGeoDataset)fc).SpatialReference; Exception expectedEx = null; try { ISpatialFilter standardFilter = new SpatialFilterClass(); standardFilter.Geometry = subResolutionPolyline; standardFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIndexIntersects; // ReSharper disable once UnusedVariable IFeatureCursor failingCursor = fc.Search(standardFilter, true); } catch (Exception ex) { expectedEx = ex; } if (RuntimeUtils.Is10_2 || RuntimeUtils.Is10_3 || RuntimeUtils.Is10_4orHigher) { Assert.Null(expectedEx); } else { Assert.NotNull(expectedEx); } IQueryFilter filter = GdbQueryUtils.CreateSpatialFilter( fc, subResolutionPolyline, esriSpatialRelEnum.esriSpatialRelIntersects, false, null); Assert.True(((ISpatialFilter)filter).FilterOwnsGeometry, "Filter should own geometry due to cloned geometry in GetValidSearchGeometry."); Assert.AreEqual(((ISpatialFilter)filter).SearchOrder, esriSearchOrder.esriSearchOrderSpatial, "Default should be spatial."); Assert.AreEqual(((ISpatialFilter)filter).SpatialRel, esriSpatialRelEnum.esriSpatialRelIntersects, "Default should be spatial."); IFeatureCursor cursor = fc.Search(filter, true); Marshal.ReleaseComObject(cursor); // test the exact half of the resolution - which is the limit double resolution = GeometryUtils.GetXyResolution(fc); subResolutionPolyline = GeometryFactory.CreatePolyline(2600000 - 0.00001, 1200000 - 0.00001, 2600000 + resolution - 0.00001, 1200000 + resolution - 0.00001); filter = GdbQueryUtils.CreateSpatialFilter( fc, subResolutionPolyline, esriSpatialRelEnum.esriSpatialRelIntersects, false, null); cursor = fc.Search(filter, true); Marshal.ReleaseComObject(cursor); }