Polygon importing incorrectly

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Polygon importing incorrectly

Grant, Tyler J [NREM]

Hi All,

 

I’m new to Repast.  Following publication of a paper by Dr. Zalucki and Dr. Hazel Perry on modeling of Monarch Butterfly movement with Repast, I and my group at Iowa State University have decided that an individual-based model (agent-based model) was the best way to answer questions about spatial arrangement of habitat for Monarch Butterflies.  We’ve been in touch with Dr. Perry but she is very busy and we are making some effort to develop some code as well.  While working on a simple prototype model, I’ve had trouble with a polygon importing correctly.  The first photo shows the bad polygon in Repast.  The second photo shows the original polygon with vertices in ArcMap. 

 

 

I ran “Repair Geometry” on the shapefile but that didn’t fix the problem.  Any ideas?

 

Thanks,

Tyler

 

Dr. Tyler J. Grant

Postdoctoral Associate

Department of Natural Resource Ecology and Management

Iowa State University

339 Science II

Ames, IA 50011

 

 


------------------------------------------------------------------------------

_______________________________________________
Repast-interest mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/repast-interest
Reply | Threaded
Open this post in threaded view
|

Re: Polygon importing incorrectly

Tatara, Eric R.

The problem is arising from the internal holes in the polygon which is causing errors in the display.   Your shapefile contains polygons defined by an exterior ring and by multiple interior rings that define the hole perimeters.  There are a few approaches to correct this.  First, it may be possible to rearrange the ordering of vertex coordinates in the polygon so that the internal hole borders are only connected at the closest to the exterior ring vertices.  Some GIS applications allow you to export the shapefile like this which will still have some display artifacts, but would look much better.  One upside to this approach, or just leaving things as-is, is that the geography queries (eg intersect, union, contains) will work correctly if the holes in the polygon are significant to your model.

 

A second approach is to split the polygon up into pieces when loading the shapefile into Repast.   For example, you can read the geometry and the just use the exterior ring to create a new polygon that is matched to the corresponding agent:

 

GeometryFactory fac = new GeometryFactory();

Geometry geom = (Geometry)feature.getDefaultGeometry();

Polygon poly = (Polygon)mp.getGeometryN(0);

Polygon poly2 = fac.createPolygon(poly.getExteriorRing().getCoordinates());

geography.move(agent, poly2);

 

This will discard the holes in the original polygon.   If you’d like to keep the interior ring polygons, you can also go through them one at a time, and add them as separate agent/geometry types to your model to track when other agents intersect with them, and/or to visualized them, eg:

 

int numRings = poly.getNumInteriorRing();

for (int i=0; i<numRings; i++){

     LineString ls = poly.getInteriorRingN(i);

 

     Polygon p = fac.createPolygon(ls.getCoordinates());

     Geography.move(otherAgent, p);

    

}

 

Both of these approaches however won’t let you visualize the original polygon with holes in the display, although the second way of adding the interior ring polygons will at least let you visualize the interior rings differently.  If the interior rings of the polygon are not relevant to the model behavior and you’d like the best visualization, there’s a workaround you can try.  This involves assigning the exterior ring polygon to the agent as I first described, and iterating through the interior ring polygons, but handling them differently.  Instead of passing the interior ring geometries to the Geography via move(…) you store them in the agent and then use them in the style class.  This is usually not recommended as this approach won’t track changes in the geometry shape or position, but is safe if you have a non-moving object represented by the polygon.  Your agent needs to store the interior rings in a list:

 

private List<Coordinate[]> interiorRings = new ArrayList<Coordinate[]>();

 

Then, instead of creating polygons and assigning to the geography as above, simply store the interior ring coordinate arrays in the agent:

 

for (int i=0; i<numRings; i++){

     LineString ls = poly.getInteriorRingN(i);

     agent.getInteriorRings().add(ls.getCoordinates());

}

 

At this point, the Repast Geography projection is only tracking the exterior boundary (and any queries are based only on that shape), but the agent is holding a list of the interior rings that can be used by the style class.  The style class needs to track both the SurfacePolygon instance and an initializer Boolean:

 

private SurfacePolygon poly;

private boolean initialized = false;

    

@Override

public SurfaceShape getSurfaceShape(MyAgent agent, SurfaceShape shape) {

poly =  new SurfacePolygon();

     return poly;

}

 

Then, in any of the other style class methods, except for the construction, we need to assign the interior ring coordinates to the SurfacePolygon from the agent, eg:

 

@Override

public Color getLineColor(MyAgent agent) {

                    

     if (!initialized){

           for (Coordinate[] coords : agent.getInteriorRings()){

                List<LatLon> pts = WWUtils.CoordToLatLon(coords);

                poly.addInnerBoundary(pts);

           }

 

           initialized = true;

     }

          

     return Color.blue;

}

 

In the above example, the assignment simply occurs in the getLineColor(…) method.  We need to use an initialized check because the inner boundary points should only be assigned one time, however the getLineColor() method is called any time the display is updated.

 

 

eric

 

From: Grant, Tyler J [NREM] [mailto:[hidden email]]
Sent: Friday, October 23, 2015 3:20 PM
To: [hidden email]
Subject: [Repast-interest] Polygon importing incorrectly

 

Hi All,

 

I’m new to Repast.  Following publication of a paper by Dr. Zalucki and Dr. Hazel Perry on modeling of Monarch Butterfly movement with Repast, I and my group at Iowa State University have decided that an individual-based model (agent-based model) was the best way to answer questions about spatial arrangement of habitat for Monarch Butterflies.  We’ve been in touch with Dr. Perry but she is very busy and we are making some effort to develop some code as well.  While working on a simple prototype model, I’ve had trouble with a polygon importing correctly.  The first photo shows the bad polygon in Repast.  The second photo shows the original polygon with vertices in ArcMap. 

 

 

I ran “Repair Geometry” on the shapefile but that didn’t fix the problem.  Any ideas?

 

Thanks,

Tyler

 

Dr. Tyler J. Grant

Postdoctoral Associate

Department of Natural Resource Ecology and Management

Iowa State University

339 Science II

Ames, IA 50011

 

 


------------------------------------------------------------------------------

_______________________________________________
Repast-interest mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/repast-interest
Reply | Threaded
Open this post in threaded view
|

Re: Polygon importing incorrectly

Grant, Tyler J [NREM]

Eric,

The area in question is not actually a “donut hole,” it’s a separate polygon.  There are no underlying polygons either.  It just seems to me that it is connecting the wrong vertices for some reason.  It’s only one polygon out of 724, so it probably will not substantially affect the results, but if I can fix it I would like to.  Does the shapefile have to have a particular projection?  I used the projection that was used in the GIS demo project. 

 

As background, I took the Crop Data Layer (from CropScape) for Story County, Iowa, reclassed it to the categories I needed, and converted the raster to a shapefile.  I’ve added some other habitat features on top of that (like 50x50m segments of dirt roads that we have milkweed data for) and did some other processing but most of the polygons come from the CDL. 

 

Tyler

 

Dr. Tyler J. Grant

Postdoctoral Associate

Department of Natural Resource Ecology and Management

Iowa State University

339 Science II

Ames, IA 50011

 

From: Tatara, Eric R. [mailto:[hidden email]]
Sent: Monday, October 26, 2015 5:48 PM
To: Grant, Tyler J [NREM] <[hidden email]>; [hidden email]
Subject: RE: Polygon importing incorrectly

 

The problem is arising from the internal holes in the polygon which is causing errors in the display.   Your shapefile contains polygons defined by an exterior ring and by multiple interior rings that define the hole perimeters.  There are a few approaches to correct this.  First, it may be possible to rearrange the ordering of vertex coordinates in the polygon so that the internal hole borders are only connected at the closest to the exterior ring vertices.  Some GIS applications allow you to export the shapefile like this which will still have some display artifacts, but would look much better.  One upside to this approach, or just leaving things as-is, is that the geography queries (eg intersect, union, contains) will work correctly if the holes in the polygon are significant to your model.

 

A second approach is to split the polygon up into pieces when loading the shapefile into Repast.   For example, you can read the geometry and the just use the exterior ring to create a new polygon that is matched to the corresponding agent:

 

GeometryFactory fac = new GeometryFactory();

Geometry geom = (Geometry)feature.getDefaultGeometry();

Polygon poly = (Polygon)mp.getGeometryN(0);

Polygon poly2 = fac.createPolygon(poly.getExteriorRing().getCoordinates());

geography.move(agent, poly2);

 

This will discard the holes in the original polygon.   If you’d like to keep the interior ring polygons, you can also go through them one at a time, and add them as separate agent/geometry types to your model to track when other agents intersect with them, and/or to visualized them, eg:

 

int numRings = poly.getNumInteriorRing();

for (int i=0; i<numRings; i++){

     LineString ls = poly.getInteriorRingN(i);

 

     Polygon p = fac.createPolygon(ls.getCoordinates());

     Geography.move(otherAgent, p);

    

}

 

Both of these approaches however won’t let you visualize the original polygon with holes in the display, although the second way of adding the interior ring polygons will at least let you visualize the interior rings differently.  If the interior rings of the polygon are not relevant to the model behavior and you’d like the best visualization, there’s a workaround you can try.  This involves assigning the exterior ring polygon to the agent as I first described, and iterating through the interior ring polygons, but handling them differently.  Instead of passing the interior ring geometries to the Geography via move(…) you store them in the agent and then use them in the style class.  This is usually not recommended as this approach won’t track changes in the geometry shape or position, but is safe if you have a non-moving object represented by the polygon.  Your agent needs to store the interior rings in a list:

 

private List<Coordinate[]> interiorRings = new ArrayList<Coordinate[]>();

 

Then, instead of creating polygons and assigning to the geography as above, simply store the interior ring coordinate arrays in the agent:

 

for (int i=0; i<numRings; i++){

     LineString ls = poly.getInteriorRingN(i);

     agent.getInteriorRings().add(ls.getCoordinates());

}

 

At this point, the Repast Geography projection is only tracking the exterior boundary (and any queries are based only on that shape), but the agent is holding a list of the interior rings that can be used by the style class.  The style class needs to track both the SurfacePolygon instance and an initializer Boolean:

 

private SurfacePolygon poly;

private boolean initialized = false;

    

@Override

public SurfaceShape getSurfaceShape(MyAgent agent, SurfaceShape shape) {

poly =  new SurfacePolygon();

     return poly;

}

 

Then, in any of the other style class methods, except for the construction, we need to assign the interior ring coordinates to the SurfacePolygon from the agent, eg:

 

@Override

public Color getLineColor(MyAgent agent) {

                    

     if (!initialized){

           for (Coordinate[] coords : agent.getInteriorRings()){

                List<LatLon> pts = WWUtils.CoordToLatLon(coords);

                poly.addInnerBoundary(pts);

           }

 

           initialized = true;

     }

          

     return Color.blue;

}

 

In the above example, the assignment simply occurs in the getLineColor(…) method.  We need to use an initialized check because the inner boundary points should only be assigned one time, however the getLineColor() method is called any time the display is updated.

 

 

eric

 

From: Grant, Tyler J [NREM] [[hidden email]]
Sent: Friday, October 23, 2015 3:20 PM
To: [hidden email]
Subject: [Repast-interest] Polygon importing incorrectly

 

Hi All,

 

I’m new to Repast.  Following publication of a paper by Dr. Zalucki and Dr. Hazel Perry on modeling of Monarch Butterfly movement with Repast, I and my group at Iowa State University have decided that an individual-based model (agent-based model) was the best way to answer questions about spatial arrangement of habitat for Monarch Butterflies.  We’ve been in touch with Dr. Perry but she is very busy and we are making some effort to develop some code as well.  While working on a simple prototype model, I’ve had trouble with a polygon importing correctly.  The first photo shows the bad polygon in Repast.  The second photo shows the original polygon with vertices in ArcMap. 

 

 

I ran “Repair Geometry” on the shapefile but that didn’t fix the problem.  Any ideas?

 

Thanks,

Tyler

 

Dr. Tyler J. Grant

Postdoctoral Associate

Department of Natural Resource Ecology and Management

Iowa State University

339 Science II

Ames, IA 50011

 

 


------------------------------------------------------------------------------

_______________________________________________
Repast-interest mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/repast-interest