Select to view content in your preferred language

Extent not updated when editing a empty shapefile with ShapefileFeatureTable

382
10
Jump to solution
3 weeks ago
Labels (2)
TaroShibata
Emerging Contributor

Hello, I edited an empty shapefile using ShapefileFeatureTable.

However, when I checked the shapefile in QGIS, no geometry was displayed, even though the shapefile actually contains a polygon.

It looks like ShapefileFeatureTable does not update the extent of the shapefile, is that correct?

Here is the output of ogrinfo:

$ ogrinfo -al -so test.shp
INFO: Open of `test.shp'
using driver `ESRI Shapefile' successful.

Layer name: test
Metadata:
DBF_DATE_LAST_UPDATE=2025-12-17
Geometry: Polygon
Feature Count: 1
Extent: (0.000000, 0.000000) - (0.000000, 0.000000)
...

$ ogrinfo -al test.shp
INFO: Open of `test.shp'
using driver `ESRI Shapefile' successful.

Layer name: test
Metadata:
DBF_DATE_LAST_UPDATE=2025-12-17
Geometry: Polygon
Feature Count: 1
Extent: (0.000000, 0.000000) - (0.000000, 0.000000)
...

OGRFeature(test):0
level (Integer64) = 3
POLYGON ((139.757125 35.671236,139.757125 35.691236,
139.777125 35.691236,139.777125 35.671236,
139.757125 35.671236))

 

0 Kudos
1 Solution

Accepted Solutions
RossMcguyer
Esri Contributor

It appears that some tools, including ArcGIS Pro and Google Earth, are able to read a shapefile with an incorrect extent, whereas QGIS fails to do so.


I would be hesitant to conclude that Google Earth Pro and ArcGIS Pro are working despite reading an incorrect extent. Examining your shapefile in both applications indicates that the extent is being updated to the expected values, and the polygon is rendering. I can also see (after setting some breakpoints in your code using Visual Studio), that the extent of the table is updated after calling AddFeatureAsync. I have also verified that running the program again and reading from the modified shapefile that the table that is created has the expected extent.


Is this a QGIS-side issue?

Given that your code works in 3 separate instances (including one non-Esri application), I have to conclude that this is an issue with QGIS, or perhaps OGR, as that is the "provider" for QGIS. Other shapefiles seem to work fine with QGIS, so at a glance it seems as though QGIS, or OGR, is incapable of reading the updated extent of the shapefile table. This is unfortunately the limit of my expertise, as I am not in a position to know how QGIS reads and interprets shapefiles.

View solution in original post

10 Replies
RossMcguyer
Esri Contributor

Hi there! This was determined to be a bug in the ArcGIS Maps SDK. This issue will be fixed with the release of the next major version of ArcGIS Maps SDK. In the meantime, the following workarounds exist that will resolve the issue:

1) After creating a feature layer from the shapefile feature table, adding it to a map, and rendering that map, updating features will correctly adjust the extent.

2) If there is no intention or ability to render the data, then copying the existing feature into a new feature, changing the new feature's geometry, deleting the old feature, then finally adding the new feature to the table, (essentially a roundabout way to update a feature) will correctly adjust the extent of the table.

TaroShibata
Emerging Contributor

@RossMcguyer 

Thank you for the reply.

I'll go with approach 2) ,as I am writing a command line tool to export a shapefile.

If I want to create a shafile containing two polygons , is the following procedure correct?

(1)Read empty shapefile with openasync

(2)Add the first polygon with CreateFeature

(3)Copy the polygon with CreateFeature ,edit it with UpdateFeatureAsync, and delete the original with DeleteFeatureAsync

(4)Add the second polygon with CreateFeature

0 Kudos
RossMcguyer
Esri Contributor

CreateFeature is a synchronous method that creates a new feature in memory, and will not write to the shapefile's table. In order to write a feature to the shapefile, you will need to call AddFeatureAsync. So for your use case, it sounds like the following would be sufficient:

1) Read in the empty shapefile
2) Create a Feature using the overload of CreateFeature, with the polygon as the Geometry
3) Add the new Feature to the Shapefile with AddFeatureAsync
4) Repeat for each Polygon

Alternatively, instead of calling AddFeatureAsync after you create each new feature, you could add all the newly created features to a collection, and then add them all at once by calling AddFeaturesAsync.

The bug I mentioned in my first response is specific to UpdateFeatureAsync, AddFeatureAsync will correctly adjust the extent of the table if the added feature's geometry exceeds the extent of the table.

If you find that you need to change the geometry of a Feature that already exists in the table, and you are concerned that the change to the geometry will exceed the table's extent, then you will need to use the workaround I described for the time being.
      

0 Kudos
TaroShibata
Emerging Contributor

Thank you for your quick reply.

I tried using AddFeatureAsync , but the extent wasn't updated. 

$ ogrinfo -al  -geom=YES empty_polygon.shp
INFO: Open of `empty_polygon.shp'
      using driver `ESRI Shapefile' successful.

Layer name: empty_polygon
Metadata:
  DBF_DATE_LAST_UPDATE=2026-01-01
Geometry: Polygon
Feature Count: 1
Extent: (0.000000, 0.000000) - (0.000000, 0.000000)
Layer SRS WKT:
GEOGCRS["WGS 84",
    DATUM["World Geodetic System 1984",
        ELLIPSOID["WGS 84",6378137,298.257223563,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["latitude",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["longitude",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    ID["EPSG",4326]]
Data axis to CRS axis mapping: 2,1
level: Real (21.6)
OGRFeature(empty_polygon):0
  level (Real) = 3.000000
  POLYGON ((139.757125 35.671236,139.757125 35.691236,139.777125 35.691236,139.777125 35.671236,139.757125 35.671236))

 

My code was below.  (I also pushed the full code to github )

Any ideas what I might be doing wrong?

 

 class Program
 {
     static async Task Main()

     {
         var baseDir = AppContext.BaseDirectory;
         var shpPath = Path.Combine(baseDir, "data", "empty_polygon.shp");
         var sr = SpatialReferences.Wgs84;
         //near tokyo station
         double centerLon = 139.767125;
         double centerLat = 35.681236;

         double offset1 = 0.01; // ~1.1 km
         var points = new PointCollection(sr)
         {
             new MapPoint(centerLon - offset1, centerLat - offset1, sr),
             new MapPoint(centerLon + offset1, centerLat - offset1, sr),
             new MapPoint(centerLon + offset1, centerLat + offset1, sr),
             new MapPoint(centerLon - offset1, centerLat + offset1, sr),
             new MapPoint(centerLon - offset1, centerLat - offset1, sr)
         };
         var poly1 = new Polygon(points);
         //
         var attrs = new Dictionary<string, object>
         {
             ["level"] = (float)3
         };
         await ShapeHandler.AddPolygonFeatureAsync(shpPath, poly1, attrs);

         
     }
  public static async Task AddPolygonFeatureAsync(string shapefilePath, Polygon polygon, IDictionary<string, object>? attributes = null)
  {
      if (string.IsNullOrWhiteSpace(shapefilePath))
          throw new ArgumentException("shapefilePath is required", nameof(shapefilePath));

      var table = new ShapefileFeatureTable(shapefilePath);
      Console.WriteLine(table);
      await table.LoadAsync().ConfigureAwait(false);

      var feature = table.CreateFeature();

      //SpatialReference sr = table.SpatialReference ?? SpatialReferences.Wgs84;
      feature.Geometry = polygon;

      if (attributes != null)
      {
          foreach (var kv in attributes)
          {
              if (feature.Attributes.ContainsKey(kv.Key))
              {
                  Console.WriteLine(kv);
                  feature.Attributes[kv.Key] = kv.Value;
              }
          }
      }

      await table.AddFeatureAsync(feature).ConfigureAwait(false);
      Console.WriteLine("add feature");
      Console.WriteLine(table.GetField("level").FieldType);

      table.Close();
}

 

0 Kudos
RossMcguyer
Esri Contributor

I ran the program you uploaded to GitHub. It appears to be working as expected. I was able to see a polygon over Tokyo and the extent was updated to match (this was observed using ArcGIS Pro, see image below). I noticed your Hello.csproj file included these lines

<!-- Copy shapefile components from the data folder to output and publish directories -->
<ItemGroup>
<None Include="data\**\*.shp" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
<None Include="data\**\*.dbf" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
<None Include="data\**\*.shx" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
<None Include="data\**\*.prj" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
<None Include="data\**\*.cpg" CopyToOutputDirectory="PreserveNewest" CopyToPublishDirectory="PreserveNewest" />
</ItemGroup>



It would be good to confirm you are inspecting the correct files.  The original shapefiles you included inside your Data folder are not actually the ones being modified by your program. I was only able to see shapefile updates after looking at the path contained within shpPath. For me, the file path looked like \MyArcSample-master\bin\Debug\net9.0\data\empty_polygon.shp, not MyArcSample-master\data\empty_polygon.shp.

Hope this helps!


RossMcguyer_0-1767397108624.png

 

0 Kudos
TaroShibata
Emerging Contributor

@RossMcguyerI appreciate you checking my code.

I also checked the file at \bin\Debug\net9.0\data\empty_polygon.shp.

The polygon itself was saved correctly, but the extent was not updated, as shown below.

ogrinfo -al  -geom=YES empty_polygon.shp
INFO: Open of `empty_polygon.shp'
      using driver `ESRI Shapefile' successful.
Layer name: empty_polygon
Metadata:
  DBF_DATE_LAST_UPDATE=2026-01-01
Geometry: Polygon
Feature Count: 1
Extent: (0.000000, 0.000000) - (0.000000, 0.000000)

(****************some lines omitted**********************************)

OGRFeature(empty_polygon):0
  level (Real) = 3.000000
  POLYGON ((139.757125 35.671236,139.757125 35.691236,139.777125 35.691236,139.777125 35.671236,139.757125 35.671236))

It appears that some tools, including ArcGIS Pro and Google Earth, are able to read a shapefile with an incorrect extent, whereas QGIS fails to do so.

 

Is this a QGIS-side issue?

 

TaroShibata_0-1767453469274.png

TaroShibata_2-1767454217414.png

 

0 Kudos
RossMcguyer
Esri Contributor

It appears that some tools, including ArcGIS Pro and Google Earth, are able to read a shapefile with an incorrect extent, whereas QGIS fails to do so.


I would be hesitant to conclude that Google Earth Pro and ArcGIS Pro are working despite reading an incorrect extent. Examining your shapefile in both applications indicates that the extent is being updated to the expected values, and the polygon is rendering. I can also see (after setting some breakpoints in your code using Visual Studio), that the extent of the table is updated after calling AddFeatureAsync. I have also verified that running the program again and reading from the modified shapefile that the table that is created has the expected extent.


Is this a QGIS-side issue?

Given that your code works in 3 separate instances (including one non-Esri application), I have to conclude that this is an issue with QGIS, or perhaps OGR, as that is the "provider" for QGIS. Other shapefiles seem to work fine with QGIS, so at a glance it seems as though QGIS, or OGR, is incapable of reading the updated extent of the shapefile table. This is unfortunately the limit of my expertise, as I am not in a position to know how QGIS reads and interprets shapefiles.

TaroShibata
Emerging Contributor

@RossMcguyer 

It seems that OGR-based libraries are unable to read the extent of a shapefile updated by ArcGIS Runtime as pyshp and goshp  can also read it .

Anyway thanks for taking the time to answer my question.

 

 

0 Kudos
AndreaGiudiceandrea
Emerging Contributor

The issue is due to the fact that the .shx index sidecar file of the provided zipped ESRI Shapefile layer is malformed, according to the ESRI Shapefile Technical Description; in fact, the extent stored in its header section is 0,0 - 0,0:

Offset(d) 00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
00000032              00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00      ............................
00000064  00 00 00 00                                                                                      

ogrinfo reports the extent information contained in the header section of the .shx file.

See a more detailed answer at https://gis.stackexchange.com/a/499601/107272.