In a previous post we discussed methods for providing multiple geometries for a given feature. The options described included ArcSchematics, cartographic representations and use of related feature classes. In this post we take on a similar but different topic of creating an additional geometry definition in an existing feature class that is managed entirely by a custom application.
We all know a feature class has a single geometry type. It’s one of the fundamental characteristics of the ArcGIS data model. One of the properties of a feature class is its ShapeType, defined by an enumeration including esriPoint, esriPolyline, esriPolygon, etc.
But what if we have a custom application that would really benefit from having a single feature class with multiple geometry fields? We recently ran into this case and here’s what we found.
Adding a Second Geometry Field
A geometry, of course, is stored in a field on a feature class with a field type of esriFieldTypeGeometry. In terms of a DBMS such as Oracle the field is a BLOB (Binary Large Object). Staying inside the box within ArcGIS applications such as ArcMap and ArcCatalog know about a single geometry field. But it is possible to add another to the using ArcObjects by creating a new geometry field and using the IFeatureClass::AddField method.
However, in ArcGIS as with life just because you can do some thing it doesn’t mean you should do that thing. In practice we’ve found that ArcMap gets confused with multiple Geometry fields on the same class and can behave in undesirable ways. In sum, we strongly recommend against this approach.
A similar path would be to create a cartographic representation. This basically adds an additional geometry in an OVERRIDE field – defined as a Blob directly on the feature class. While this does create the data structure we’re looking for, we don’t want our custom application competing with core ArcGIS functionality for use of the field’s contents.
Adding a “Geometry” in a non-Geometry Field
This case requires a different approach. In addition, say what you really need is to add a line geometry field to a point feature class or a polygon geometry to a line feature class. Neither of the above approaches (however unappetizing) would accomplish that.
There may be more that one way to skin this cat, but a way we found to work well is to add a TEXT column to the class and populate it with a geometry defined as Well Known Text (WKT). In our case we added a text field of the maximum Oracle VARCHAR column size, 4,000 characters and had our custom app write and read LINESTRING geometries.
There is no native ArcObjects method for converting a WKT line string to an Arc Geometry, but there is an ArcPy function. And parsing the string in C# is pretty straightforward (which is what we did).
In our implementation we represent lines as collections of points. However, if we wanted to get fancy and support parametric curves that might be present in an ArcGIS Polyline geometry we could have used the WKT GEOMETRYCOLLECTION object.
This worked well for 99.9%+ of the cases we encountered. In the remaining less than 1% of the cases the line string definition exceeded our 4,000 character limit. Using 7-digit integer X and Y values we could accommodate lines of about 250 vertices – and a few of our lines had more.
Again, there are multiple cat-skinning strategies to address this issue. The one we implemented was to reduce the size of the string below the 4K limit by eliminating insignificant vertices. By “insignificant” we could have opted for vertices bounding the shortest segments within the line string, but instead chose to remove vertices that introduce the smallest tangent angle.
As illustrated below, the tangent angle of the segment between vertices 2 and 3 is smallest in the line and thus would be first to be removed. Vertices are progressively removed under the overall line string size is less that 4K.
Another way to overcome the 4K TEXT field limit would be to use a CLOB data type – which would hold a virtually unlimited set of characters. In our case we didn’t want to incur the performance overhead in dealing with CLOB’s and found that for geometries of over 250 vertices there are typically many cases where vertices can be removed without noticeably changing the shape of the line.
In application use cases that call for multiple geometries for a given feature we know there are traditional methods including creating a related feature class with the second (or third) geometry, or using representations. But if we really want to streamline access to that additional geometry we found we can accomplish most of our goals by adding a TEXT field holding a geometry in WKT format. Of course, use of this field requires an application that can process WKT geometries. And we found this straightforward within our own custom app.