3

I'm working with ArcObjects, C# and ArcMap. I have an attribute table that has several rows of data including a "shape" field that holds a point geometry. I also have a random point. How can I iterate through each point in the table to see if it matches my random point?

I thought using something like ISpatialFilter would work, but I'm not sure if I'm using it right. My code is below:

IPoint _point = new PointClass();
_point.PutCoords(3605857.580, 516199.563);
ISpatialFilter _filter = new SpatialFilterClass();
_filter.Geometry = _point;
_filter.GeometryField = _featureClass.ShapeFieldName;
_filter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;
//_filter.WhereClause = "Shape = "+ _point+"";    // DONT KNOW WHAT TO PUT
//_filter.SubFields = "Shape";

IFeatureCursor _featureCursor = _featureClass.Search(_filter, false);

while ((_featureCursor.NextFeature()) != null)
     {
        if (_point == _featureCursor)
            {
               MessageBox.Show("FOUND");
            }
     }

As you can see, I do have some code edited out as I'm not sure what to put in certain areas.

9
  • 1
    Did you try setting the point's spatial reference to match that of the featureclass you are searching? Also try using esriSpatialRelIntersects. Often people choose to create a search envelope centered on the search point with a width and height based on a search tolerance. Otherwise your point will have to exactly intersect a point in the featureclass. Commented Apr 15, 2016 at 19:11
  • Also, don't forget to call ReleaseCOMObject on your cursor, otherwise you get strange bugs that are hard to diagnose. Commented Apr 15, 2016 at 19:13
  • I tried using esriSpatialRelIntersects but no luck Commented Apr 15, 2016 at 19:32
  • If you want to iterate through all points, don't use any spatialfilter (or queryfilter). Just pass null. But then you'll have to see if the geometry of each feature returned intersects that of your point. Commented Apr 15, 2016 at 19:38
  • I suppose you're right. I've also realized I may have to use a brute force approach to figuring this out. I have been able to search the attribute table for my "Shape" field and output each value under that column. However, I was getting a System._ComObject error. To combat this, I needed to cast/convert it to/as a geometry (IGeometry) and then cast/convert it to/as a point (IPoint). From there I can do an if else comparison. I'll update my code in a little while to demonstrate these changes. Commented Apr 15, 2016 at 20:06

1 Answer 1

1

Point on point isn't going to work, even if the coordinates are exact match, it's a 50/50 whether the feature class point will be selected by the query point. To overcome this I always buffer the point by a very small amount - this depends on your spatial reference, 1 metre (or foot) usually isn't very much but 1 degree usually is a very large number, you'll have to decide this yourself.

// new spatial filter class
ISpatialFilter pSpatialFilter = new SpatialFilterClass();
pSpatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

// buffer the point
ITopologicalOperator pTopOp = gSelectionPoint as ITopologicalOperator;
gSelectionGeom = pTopOp.Buffer(gSelectionDist); // gSelectionDist is a small number

// assign the buffer to the spatial filter
pSpatialFilter.Geometry = gSelectionGeom;

// check to see if this query matches *any* point in the table
if (_featureClass.FeatureCount(pSpatialFilter) > 0)
{
    // get the matching row(s)
    IFeatureCursor _featureCursor = _featureClass.Search(_filter, false);
}

Before you try to get any rows using a query filter you should get the feature count using IFeatureClass.FeatureCount, this is much quicker than actually grabbing the row(s) onto a cursor which can be of benefit if you want to do this lots of times.

As an aside, you're starting your variables with an underscore, I would encourage you not to do this as many system variables start with an underscore and you could get a name clash.. I use the pVariable, gVariable, cConstant syntax which immediately reveals the variables' scope p for local, g for global (try not to use many globals) and c for constant.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.