Hello,
First of all, I'm not sure if the mailing list is the proper place to post a bug report. If it is not, someone please kindly inform me.
I am new to MASON, and I was playing around with using GeoMason to import an ESRI shapefile to use as a base map. The shapefile displays country administrative boundaries for the entire globe (from Natural Earth Data http://www.naturalearthdata.com/downloads/10m-cultural-vectors/). I noticed that the UI Portrayal was failing to display the polygons of certain countries at all, notably South Africa and Kazakhstan. On closer inspection, it was in fact displaying part (a very small part) of the country's polygon, like a small island off the coast. I also noticed that the un-displayed countries all had shapefile polygons which had "holes" in them. Digging through the code, I found what I believe to be the error in the class ShapeFileImporter.java, from the latest GeoMason source code. (sim.io.geo.ShapeFileImporter.java)
In the createPolygon(LinearRing[] parts) method, starting on line 154 is a conditional block dealing with creating polygons with holes in them. The source code reads:
if (holes.size() > 0)
{
// Create a polygon with holes
LinearRing[] holesArray = new LinearRing[holes.size()];
holes.toArray(holesArray);
return geomFactory.createPolygon(shells.get(0), holesArray);
}
The bug is that the the code assumes that the polygon being created is a simple polygon with holes, rather than a multi-polygon in which one or more of the constituent polygons have holes in them. So, to use my Kazakhstan polygon as an example, the shapefile I am using has one elliptical hole in the administrative territory of Kazakhstan, where Russia has leased land from Kazakhstan for the Baikonur Cosmodrome. Furthermore, the Kazakhstan polygon in the shapefile is actually a multi-polygon, including the main territory plus numerous small islands in the Caspian Sea owned by the country. GeoMason was only displaying one of these small islands in the Caspian, but not the main territory, because the small island polygon was the first element in the "shells" ArrayList, and so was being the only polygon being displayed by the shells.get(0) call.
I believe that the correct code should read as follows:
if (holes.size() > 0)
{
// Create a polygon with holes
LinearRing[] holesArray = new LinearRing[holes.size()];
holes.toArray(holesArray);
if (shells.size() == 1)
{
return geomFactory.createPolygon(shells.get(0), holesArray);
}
Polygon[] poly = new Polygon[shells.size()];
for (int i = 0; i < shells.size(); i++)
{
poly[i] = geomFactory.createPolygon(shells.get(i), holesArray);
}
return geomFactory.createMultiPolygon(poly);
}
This code attempts to "subtract" the holes from each of the constituent polygons in the multi-polygon. When implemented, the MASON UI properly displays my shapefile. I will append the caveat that I am very out of practice with Java (and not a great programmer anyway) so my analysis and fix might be wrong/dumb/inefficient in many ways. Please let me know if I need to provide anything else to clear up the issue, or, again, if the mailing list is the wrong place to report a bug fix.
Cheers,
George
|