0

I am working in ArcMap. I have a feature class layer (polyline) that has points in it. For each point, I want to cast/convert it to a geometry and place it in a separate layers attribute table; under the shape field column.

I also try and do other calculations on Shape field column in the table (such as a distance between points) and I get an error saying "The operation was attempted on an empty geometry.". This leads me to believe that I am not inserting the value into the table correctly. Furthermore, it leads me to believe I am not casting correctly or creating the IGeometry variable correctly either.

Also, when I try and look at the attribute table, it shows PointZM in the 'Shape' field column, however, when looking at the map, I cant see any points in Arcmap. My code is below.

IFeatureLayer _SelectedLayer = MultiItemList._CapturedFeatureLayer;
IFeatureClass _SelectedFeatClass = _SelectedLayer.FeatureClass;

IDataset _SelectedFeatureDataset = (IDataset)_SelectedFeatClass;
IWorkspace _SelectedWorkspace = (IWorkspace)_SelectedFeatureDataset.Workspace;
string _SelectedPath = _SelectedWorkspace.PathName;

IFeature _mySelectedFeature = _SelectedFeatClass.GetFeature(0);
IGeometry _theGeometry = _mySelectedFeature.Shape as IGeometry;      

IPolyline _PolyLine = (IPolyline)_theGeometry;                
IPointCollection _pointsCollection = (IPointCollection)_PolyLine;

if (_pointsCollection.PointCount>=2)            
{
   IEnumVertex2 _enumVertex = _pointsCollection.EnumVertices as IEnumVertex2;
   IPoint _queryVertex = new PointClass();  
   _enumVertex.Reset();                                                         
   IPoint _outVertex;                                                    
   int partIndex;
   int vertexIndex;
   _enumVertex.Next(out _outVertex, out partIndex, out vertexIndex);

   while (_outVertex != null)
   {
     ITable LeveePointsTable = (ITable)LeveePoints_featureClass;
     int ShapeIndex = LeveePointsTasble.FindField("Shape");
     IRow LeveePointsRow = LeveePointsTable.CreateRow();

     // trying to cast IPoint to IGeometry
     IGeomerty _myPoints = (Igeometry)_outVertex

     LeveePointsRow.set_Value(ShapeIndex, _MyPoints);
   }
}

Any help on this topic would be greatly appreciated. Thanks in advance.

user1898629
  • 329
  • 1
  • 4
  • 22
  • I'm going to assume you set a breakpoint after this line (it won't compile for at least three distinct reasons, but maybe you retyped it): `IGeomerty _myPoints = (Igeometry)_outVertex`. When you did that, was `_myPoints` null? Another point to ponder is whether or not the actual runtime type of _outVertex implements `IGeometry`. You checked that, right? – 15ee8f99-57ff-4f92-890c-b56153 Jul 06 '16 at 18:47
  • Yes, _outVertex (IPoint) does implement IGeometry. With the line: ' IGeomerty _myPoints = (Igeometry)_outVertex ' I can use a MessageBox to ouput the X and Y coordinate of the variable _outVertex and it will display them. Plus I don't get a casting error on this line. I did not initialize the variable '_myPoints' to anything though. Perhaps I should initialize it to null first. – user1898629 Jul 06 '16 at 18:58
  • No, don't initialize `_myPoints` to null; you're already initializing it to `(IGeometry)_outVertex` and that's all you need. – 15ee8f99-57ff-4f92-890c-b56153 Jul 06 '16 at 18:59
  • Apologies as well, but this probably won't compile because I left out a part at the top. [MulitItemList] is a separate class. The class (or really container) is a container (or list) for feature class layers. Also, the above function is under the OnClick() method. My hunch was that I wasn't fully creating the IGeometry variable (if that makes sense). I'm thinking I should be incorporating a spatial reference with this IGeometry variable...perhaps the reason why when I try to insert it into the table, its inserted as an empty geometry. Its a possibility. Again, sorry for the omitted code. – user1898629 Jul 06 '16 at 19:07

2 Answers2

0

I would do the following:

  1. Try to get the geometry directly from the IPointCollection object, something like this:

    for (int i = 0; i < pointCollection.PointCount; i++)
    {
        var p = pointCollection.get_Point(i);
    }
    
  2. Apply the geometry to the shape property using the IFeature interface:

    ((IFeature)row).Shape = p;
    

BTW: If you are creating a feature inside a feature class, why not use the IFeature and IFeatureClass interfaces, instead of ITable and IRow? There are a lot of problems using the "Shape" string directly to get the shape field, due to the name depends on the database type.

Katah
  • 121
  • 4
0

There are a few things in your code that I won´t mention in the comments to make it easier to read them.

First off you should definitly cash the results of searching for a field. Doing this within a loop is not recommended.

However - and this is the second point - you won´t need to search for the shape-field, you can simply take the geometriy-field from the featureclass - no need to cast to ITable.

Third your loop never terminates as your reference to _outVertex is allways the same. I assume you want to get the next vertex within your collection using _enumVertex.Next(out _outVertex, out partIndex, out vertexIndex).

Fourth you don´t need to cast to IGeometry as IPoint should already inherit that interface. Thus everything implementing the latter should also implicitely implement the former interface.

Fifth and last you can directly access and iterate the IPointCollection without casting to IEnumVertex.

So after having said this your code could be simplified to this:

for(int i = 0; i < _pointsCollection.PointCount && _pointsCollection.PointCount >= 2; i++)
{
    IFeature newFeature = LeveePoints_featureClass.CreateFeature();
    // further attributes on the feature

    newFeature.Shape = _pointsCollection.get_Point(i);
}

Anyway I doubt all this will actually solve your issue as updates are not automatically mirrored in the view - in your case ArcMap - because they are internally cached to avoid massivly redrawing the whole screen after every update. To draw those updates from the cash you can use IActiveView.PartialRefresh.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111