It appears there's a bug in the fgdapi when inserting polygons with arcs. It doesn't calculate the area correctly. It only calculates the straight sides and does not include the area the arc is creating. Once you run it through repair geometry, it fixes the calculation.
Anyone else run across this? Vince Angelo
Solved! Go to Solution.
I'v already sent ESRI support a code sample. Just waiting to see what they find.
I'll update this thread when I find out.
Tech Support generally doesn't support the File Geodatabase API. This GeoNet place is the closest thing available to a support mechanism. The people who maintain the FGDBAPI monitor this place, so if you want timely response, I would suggest you post the code here.
- V
So I finally got a chance to get back to this problem.
Code that creates 1 feature with an arc in it. When you look at that feature in ArcMap it doesn't have the correct area or length.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Esri.FileGDB; using System.IO; namespace GeoDBTest { class Program { static void Main(string[] args) { CPoint[] arrPoints = { new CPoint(280216.393,336991.323), new CPoint(280218.563,336609.378), new CPoint(280116.567,336609.378), new CPoint(280116.567,336993.493), new CPoint(280216.393,336991.323) }; // arc lies between point 1 & 2 CArc arc = new CArc(new CPoint(280116.567, 336993.493), new CPoint(280116.567, 336609.378), new CPoint(279953.806, 336801.436)); Geodatabase geodatabase = null; string geoPath = "geoTest.gdb"; geodatabase = OpenGeoDB(geoPath); Table tblTestArea = null; if(geodatabase != null) { ClearTable(geodatabase); tblTestArea = OpenGDBTable(geodatabase); if(tblTestArea != null) { int iMultipart = 1, iPoints = 5, iArcs = 1; uint iSize = (uint)(4 * sizeof(int) + iMultipart * sizeof(int) + 4 * sizeof(double) + (2 * sizeof(double) * iPoints) + ((sizeof(int) * 3 + sizeof(double) * 2) * iArcs)); int offset = 0; Byte[] shapeBuffer = new Byte[iSize]; // type int type = (int)Esri.FileGDB.ShapeType.GeneralPolyline; type = 536870963; //Byte 29,28 ON and Byte 0 is 51 Buffer.BlockCopy(BitConverter.GetBytes(type), 0, shapeBuffer, offset, sizeof(int)); offset += sizeof(int); // Extent // 280116.567 336609.378 // 280220.013 336607.577 // minimum X Buffer.BlockCopy(BitConverter.GetBytes(arc.pMidPoint.dX), 0, shapeBuffer, offset, sizeof(double)); offset += sizeof(double); // minimum Y Buffer.BlockCopy(BitConverter.GetBytes(arrPoints[2].dY), 0, shapeBuffer, offset, sizeof(double)); offset += sizeof(double); // 280218.563 336991.323 // 279945.499 336995.913 // maximum X Buffer.BlockCopy(BitConverter.GetBytes(arrPoints[0].dX), 0, shapeBuffer, offset, sizeof(double)); offset += sizeof(double); // maximum Y Buffer.BlockCopy(BitConverter.GetBytes(arrPoints[0].dY), 0, shapeBuffer, offset, sizeof(double)); offset += sizeof(double); // number of parts Buffer.BlockCopy(BitConverter.GetBytes(iMultipart), 0, shapeBuffer, offset, sizeof(int)); offset += sizeof(int); // number of points Buffer.BlockCopy(BitConverter.GetBytes(iPoints), 0, shapeBuffer, offset, sizeof(int)); offset += sizeof(int); // load number of parts Buffer.BlockCopy(BitConverter.GetBytes(0), 0, shapeBuffer, offset, sizeof(int)); offset += sizeof(int); // Load all points for (int pt = 0; pt < arrPoints.Count(); pt++) { Buffer.BlockCopy(BitConverter.GetBytes(arrPoints[pt].dX), 0, shapeBuffer, offset, sizeof(double)); offset += sizeof(double); Buffer.BlockCopy(BitConverter.GetBytes(arrPoints[pt].dY), 0, shapeBuffer, offset, sizeof(double)); offset += sizeof(double); } // number of Arcs int numCurves = 1; Buffer.BlockCopy(BitConverter.GetBytes(numCurves), 0, shapeBuffer, offset, sizeof(int)); offset += sizeof(int); // Load ARC //segment point index - arc is starting from point 2 Buffer.BlockCopy(BitConverter.GetBytes(2), 0, shapeBuffer, offset, sizeof(int)); offset += sizeof(int); //segment type 1- circular arc Buffer.BlockCopy(BitConverter.GetBytes(1), 0, shapeBuffer, offset, sizeof(int)); offset += sizeof(int); // ESRI expecting the center point of the 2 cord not the center of the circle (curve) CPoint arcMidPoint = arc.pMidPoint; // Center point Buffer.BlockCopy(BitConverter.GetBytes(arcMidPoint.dX), 0, shapeBuffer, offset, sizeof(double)); offset += sizeof(double); Buffer.BlockCopy(BitConverter.GetBytes(arcMidPoint.dY), 0, shapeBuffer, offset, sizeof(double)); offset += sizeof(double); // It doesn't matter it calculates the arc based on the mid point int minor = 16; int bits = 256 | 128 | 0 | 0 | minor | 0 | 4 | 2 | 0; // copy bits Buffer.BlockCopy(BitConverter.GetBytes(bits), 0, shapeBuffer, offset, sizeof(int)); offset += sizeof(int); // Loading to the Geo Table Row polyRow = tblTestArea.CreateRowObject(); ShapeBuffer polylinesGeometry = new ShapeBuffer(iSize); polylinesGeometry.Allocate(iSize); polylinesGeometry.shapeBuffer = shapeBuffer; polylinesGeometry.inUseLength = iSize; //MultiPartShapeBuffer multiGeometry = polylinesGeometry; polyRow.SetGeometry(polylinesGeometry); tblTestArea.Insert(polyRow); tblTestArea.Close(); tblTestArea.Dispose(); geodatabase.Close(); geodatabase.Dispose(); } } } static Geodatabase OpenGeoDB(string geoDbPath) { Geodatabase geodb = null; try { try { geodb = Geodatabase.Open(geoDbPath); } catch (Exception ex) { //ignore if file is not present } try { if (geodb == null) { geodb = Geodatabase.Create(geoDbPath); } } catch (Exception ex) { } } finally { } return geodb; } static Table OpenGDBTable(Geodatabase geodatabase) { Table geodbTbl = null; string catPath = ""; string tblName = ""; string templatePath = @"PARCELS_TEMPLATE.xml"; try { string featureClassDef = ""; using (StreamReader sr = new StreamReader(templatePath)) { while (sr.Peek() >= 0) { featureClassDef += sr.ReadLine() + "\n"; } sr.Close(); } catPath = @"/FD=CAD2GIS/FC=" + "AreaTest"; tblName = "AreaTest"; featureClassDef = featureClassDef.Replace("_CATLOGPATH_", catPath); featureClassDef = featureClassDef.Replace("_TABLENAME_", tblName); geodbTbl = geodatabase.CreateTable(featureClassDef, ""); } catch (Exception ex) { } finally { } return geodbTbl; } static Table ClearTable(Geodatabase geodatabase) { string tblName = ""; Table tblData = null; tblName = "AreaTest"; try { geodatabase.Delete(tblName, "Table"); } catch (Exception ex) { } finally { } return tblData; } } // end class class CPoint { public double dX; public double dY; public CPoint(double x, double y) { dX = x; dY = y; } } class CArc { public CPoint pStartPoint; public CPoint pEndPoint; public CPoint pMidPoint; public CArc(CPoint SPoint, CPoint EPoint, CPoint MPoint) { pStartPoint = new CPoint(SPoint.dX, SPoint.dY); pEndPoint = new CPoint(EPoint.dX, EPoint.dY); pMidPoint = new CPoint(MPoint.dX, MPoint.dY); } } }
Please include your code in the post, as not everyone would be willing to download a zipfile from some other location (as part of computer security policy, I won't even download zipfiles from GeoNet)
- V
Code is posted.
Area calculation in the file geodatabase API does not include curves in the calculation. We will consider it in a later release.
Yes I think people would want a feature that properly calculates the area in a gis library.
The work-around is to populate vertices in the shape buffer which approximate the curve, instead of relying on ArcGIS to use CAD curves to hide the blocky shapes which are being populated in the shape buffer (which are used to calculate area via Simpson's Rule, as stated back in January).
- V
I guess this is never getting fixed?
Also, what version of the API are you using? The current version is 1.4.