garybroyd

Getting featureCount within a polygon doesn't always work if items close to edges

Discussion created by garybroyd on Apr 11, 2011
Latest reply on Apr 13, 2011 by garybroyd
Hi everybody,

I'm in the process of moving our VB6 code over to .Net and have hit a problem with one of our ArcMap tools.

The tool is a fairly crude density analysis tool where by we have points on the map and the user specifies a rectangular region analyse.  It then divides the region into series of smaller squares (each of type "esriGeometry.Polygon") and for each of these squares we look to see how many items are contained within the square.  The items within the squares are of type "ersiGeometry.Point"

The problem we are finding is that if some of the features are close to the edges of the square we are looking in, then it doesn't report them as being contained within.  I have even double-checked the coordinates of the points and the square to make sure it's actually within it.

The code all worked fine in VB 6 and it's pretty much as is so I can't work out what is wrong.

Is there some sort of threshold as to how close to the edge an item can be to be considered as "contained" or is there a default size attribute to the points contained within it (e.g. a radius on the point which implies it has area which means that it won't be fully contained within the square)?  I'm just wondering if I'm missing some important factor.

Here is some sample code:

IPointCollection pointCollection = (IPointCollection)mObjectFactory.Create( "esriGeometry.Polygon" );
IPolygon firstPolygon = (IPolygon)pointCollection;

//gridSpacing is the size of each square

//Lower left
AddPointToCollection( pointCollection, mSelectedRegion.LowerLeft.X, mSelectedRegion.LowerLeft.Y );
//Lower right
AddPointToCollection( pointCollection, mSelectedRegion.LowerLeft.X + gridSpacing, mSelectedRegion.LowerLeft.Y );
//Upper right
AddPointToCollection( pointCollection, mSelectedRegion.LowerLeft.X + gridSpacing, mSelectedRegion.LowerLeft.Y + gridSpacing );
//Upper left
AddPointToCollection( pointCollection, mSelectedRegion.LowerLeft.X, mSelectedRegion.LowerLeft.Y + gridSpacing );
firstPolygon.Close();

IFeatureCursor insertFeatureCursor = featureClass.Insert( true );
IFeatureBuffer insertFeatureBuffer = featureClass.CreateFeatureBuffer();

int colRowFieldIndex = featureClass.FindField( "Col_Row" );
int currentFeatureCount = 0;

//For each row and column of the selected region, create a clone of the square, move it to the appropriate position
//so we end up with a rectangle divided into a large number of smaller squares
for ( int x = 0; x < iterationsX; x++ )
{
 double deltaX = x * gridSpacing;

 for ( int y = 0; y < iterationsY; y++ )
 {
  double deltaY = y * gridSpacing;
  IPolygon polygon = (IPolygon)( (IClone)firstPolygon ).Clone();
  ITransform2D transform2D = (ITransform2D)polygon;

  transform2D.Move( deltaX, deltaY );
  insertFeatureBuffer.Shape = polygon;

  insertFeatureBuffer.set_Value( colRowFieldIndex, currentFeatureCount );
  insertFeatureCursor.InsertFeature( insertFeatureBuffer );
 }
}

//Now look for points within every square using a query
IFeatureCursor featureCursor = featureClass.Search( null, false );
IFeature gridFeature = featureCursor.NextFeature();

while ( gridFeature != null )
{

 //Query each FID and produce a selection
 int OID = gridFeature.OID;

 IQueryFilter queryFilter = mObjectFactory.Create( "esriGeoDatabase.QueryFilter" ) as IQueryFilter;
 queryFilter.WhereClause = string.Format( CultureInfo.InvariantCulture, "FID = {0}", OID );
 IFeatureSelection featureSelection = (IFeatureSelection)gridLayer;


 //Select just the square with the specified FID 
 featureSelection.SelectFeatures( queryFilter, esriSelectionResultEnum.esriSelectionResultNew, false );
 ISpatialFilter spatialFilter = (ISpatialFilter)mObjectFactory.Create( "esriGeoDatabase.SpatialFilter" );

 spatialFilter.Geometry = gridFeature.Shape;
 spatialFilter.GeometryField = gridLayer.FeatureClass.ShapeFieldName;
 spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelContains;

 //Find out how many features are within the square    
 int numberOfFeaturesInGrid = selectedFeatureLayer.FeatureClass.FeatureCount( spatialFilter );

 //Store the amount in a "Count" field and store it
 gridFeature.set_Value( countFieldIndex, numberOfFeaturesInGrid );
 gridFeature.Store();

 //Move to the next square
 gridFeature = featureCursor.NextFeature();
}

private void AddPointToCollection( IPointCollection pointCollection, double x, double y )
{
 object missing1 = Type.Missing;
 object missing2 = Type.Missing;
 //Debug.Print( string.Format( "Adding point: {0}, {1}", x, y ) ); 
 pointCollection.AddPoint( CreatePoint( x, y), ref missing1, ref missing2 );
}

Outcomes