Take the 2-minute tour ×
Geographic Information Systems Stack Exchange is a question and answer site for cartographers, geographers and GIS professionals. It's 100% free, no registration required.

I come from the Java world and go straight to C# and ArcGis 10 (I have to make a simple task for the university). So this means I don't really know much of C# but I can live with it and don't know ArcGis API at all. All I have is an example from the classes. It is about how to filter the cities by coordinates X and Y and a Buffer. So we have layers City(Point) and States(Polygon). My task is to make other functionality, and by functionality I mean method, that takes the name of 1 state and get all the cities from state's area.
In the example code that we have some ISpatialFilter that we use with the buffer like this:

public List<City> SearchCities(...)
{
    IFeatureClass citiesClass = MyHelper.GetLayer(Layers.CITIES);

    ISpatialFilter spatialFilter = getSpatialFilter(centerX, centerY, distance);

    IFeatureCursor citiesCursor = citiesClass.Search((QueryFilter)spatialFilter, true);
    .....
    .....
}

private static ISpatialFilter getSpatialFilter(double centerX, double centerY, double distance)
{
    IPoint center = getCenter(centerX, centerY);
    IGeometry buffer = getBuffer(distance, center);

    ISpatialFilter spatialFilter = new SpatialFilterClass();
    spatialFilter.Geometry = buffer;
    spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

    return spatialFilter;
}


private static IGeometry getBuffer(double distance, IPoint center)
{
    return (center as ITopologicalOperator).Buffer(distance);
}

private static IPoint getCenter(double centerX, double centerY)
{
    IPoint center = new Point();
    center.PutCoords(centerX, centerY);
    return center;
}

So I decided to reuse some of the code and only change the way the data is filtered. So, I came up with something like this:

private IQueryFilter GetQueryFilter(string stateAbbr)
{
    IGeometry stateGeometry = getGeometry(stateAbbr);

    ISpatialFilter spatialFilter = new SpatialFilterClass();
    spatialFilter.Geometry = stateGeometry;
    spatialFilter.SpatialRel = esriSpatialRelEnum.esriSpatialRelIntersects;

    return (QueryFilter)spatialFilter;
}

// TODO fix it
private IGeometry getGeometry(string stateAbbr)
{
    IFeature state = GetStateByAbbr(stateAbbr);

    return (state as ITopologicalOperator).Boundary;
}

private IFeature GetStateByAbbr(string stateAbbr)
{
    IFeatureClass statesClass = MyHelper.GetLayer(Layers.STATES);
    IQueryFilter queryFilter = GetStateQueryFilter(stateAbbr);
    IFeatureCursor stateCursor = statesClass.Search(queryFilter, false);

    return stateCursor.NextFeature();
}

private IQueryFilter GetStateQueryFilter(string stateAbbr)
{
    ISpatialFilter spatialFilter = new SpatialFilterClass();
    spatialFilter.WhereClause = StatesWhereBuilder(stateAbbr);

    return (QueryFilter)spatialFilter;
}

private string StatesWhereBuilder(string stateAbbr)
{
    return (MyHelper.isEmpty(stateAbbr)) ? "" : MyHelper.CreateEqualStatement(StateConst.STATE_ABBR, stateAbbr, true);
}

I know it is probably very amusing for some of you, but this is all I came up with :] The problem is that I get NullReferenceException after calling (state as ITopologicalOperator).Boundary but the debug shows that state is not null. So after the as something happens. I might be wrong with the ITopologicalOperator. If so, what should I use instead? Thanks in advance.

EDIT: Please tell me what do you think about this question (how it is exposed, etc.)

I changed the GetGeometry() method to:

private IGeometry getGeometry(string stateAbbr)
{
    IFeature state = GetStateByAbbr(stateAbbr);
    IPolygon statePolygon = state.Shape as IPolygon;

    return (statePolygon as ITopologicalOperator).Boundary;
}

and now I don't have NullPointerException, but I don't get any result.

share|improve this question

1 Answer 1

up vote 2 down vote accepted

IToplogicalOperator.Boundary returns a polyline if the input geometry is a polygon. You probably don't want that (selecting cities by the boundary/perimeter as opposed to the the interior/area of a state makes no sense), so just return the feature's Shape or ShapeCopy.

Also it's good to know the difference between these, and between a recycling and non-recycling cursor.

A recycling cursor reuses internal resources used by the previous row as soon as the next row is accessed (and so should not be used if modifying the row), while a non-recycling cursor does not, at the cost of memory and speed. See the "Recycling" section under How to use cursors in the geodatabase for more info.

Shape returns the feature's geometry directly, if you are using a recycling cursor, you have to be sure you don't need that reference for longer than one row iteration if you are using a recycling cursor. ShapeCopy creates a clone of the feature's geometry that you can then hold on to (and are responsible for releasing in a timely manner if you don't want to wait for the GC to do it when it feels like it).

In this case since you are only accessing one feature, it doesn't matter too much, but I would use a recycling cursor and ShapeCopy. Release the cursor immediately after you've gotten your shape copy, and release the shape copy as soon as you are done querying with it.

share|improve this answer
    
Perfect :) My dummy workaround was to use Buffer(0), which I suppose is something like Shape. –  Maistora May 31 '12 at 7:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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