package jeql.io.shapefile; import com.vividsolutions.jts.algorithm.CGAlgorithms; import com.vividsolutions.jts.geom.Coordinate; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import com.vividsolutions.jts.geom.PrecisionModel; public class ShapeGeometryBuilder { /** * reverses the order of points in lr (is CW -> CCW or CCW->CW) */ static LinearRing reverseRing(LinearRing lr) { int numPoints = lr.getNumPoints(); Coordinate[] newCoords = new Coordinate[numPoints]; for (int t = 0; t < numPoints; t++) { newCoords[t] = lr.getCoordinateN(numPoints - t - 1); } return new LinearRing(newCoords, new PrecisionModel(), 0); } /** * make sure outer ring is CCW and holes are CW * * @param p * polygon to check */ static Polygon createShpPolygon(Polygon p) { LinearRing outer; LinearRing[] holes = new LinearRing[p.getNumInteriorRing()]; Coordinate[] coords; if (p.isEmpty()) return p; coords = p.getExteriorRing().getCoordinates(); if (CGAlgorithms.isCCW(coords)) { outer = reverseRing((LinearRing) p.getExteriorRing()); } else { outer = (LinearRing) p.getExteriorRing(); } for (int t = 0; t < p.getNumInteriorRing(); t++) { coords = p.getInteriorRingN(t).getCoordinates(); if (!(CGAlgorithms.isCCW(coords))) { holes[t] = reverseRing((LinearRing) p.getInteriorRingN(t)); } else { holes[t] = (LinearRing) p.getInteriorRingN(t); } } return new Polygon(outer, holes, new PrecisionModel(), 0); } /** * make sure outer ring is CCW and holes are CW for all the polygons in the * Geometry * * @param mp * set of polygons to check */ static MultiPolygon createShpMultiPolygon(MultiPolygon mp) { MultiPolygon result; Polygon[] ps = new Polygon[mp.getNumGeometries()]; // check each sub-polygon for (int t = 0; t < mp.getNumGeometries(); t++) { ps[t] = createShpPolygon((Polygon) mp.getGeometryN(t)); } result = new MultiPolygon(ps, new PrecisionModel(), 0); return result; } static Geometry buildGeometry(Geometry geom, int geomtype) { switch (geomtype) { case Shapefile.POINT: if ((geom instanceof Point)) { return geom; } else { // create empty Point return new Point(null, new PrecisionModel(), 0); } case Shapefile.MULTIPOINT: if ((geom instanceof Point)) { // good! Point[] p = new Point[1]; p[0] = (Point) geom; return new MultiPoint(p, new PrecisionModel(), 0); } else if (geom instanceof MultiPoint) { return geom; } else { return new MultiPoint(null, new PrecisionModel(), 0); } case Shapefile.ARC: // line if ((geom instanceof LineString)) { LineString[] l = new LineString[1]; l[0] = (LineString) geom; return new MultiLineString(l, new PrecisionModel(), 0); } else if (geom instanceof MultiLineString) { return geom; } else { return new MultiLineString(null, new PrecisionModel(), 0); } case Shapefile.POLYGON: // polygon if (geom instanceof Polygon) { // good! Polygon[] p = new Polygon[1]; p[0] = (Polygon) geom; return createShpMultiPolygon(new MultiPolygon(p, new PrecisionModel(), 0)); } else if (geom instanceof MultiPolygon) { return createShpMultiPolygon((MultiPolygon) geom); } else { return new MultiPolygon(null, new PrecisionModel(), 0); } } // should never reach here throw new IllegalStateException("Unhandled geometry type: " + geom.getGeometryType()); } }