public static void assertEquals(MultiPolygon p1, MultiPolygon p2) { assert p1.getNumGeometries() == p2.getNumGeometries() : "expected " + p1.getNumGeometries() + " geometries but found " + p2.getNumGeometries(); // TODO: This test do not check all permutations. So the Test fails // if the inner polygons are not ordered the same way in both Multipolygons for (int i = 0; i < p1.getNumGeometries(); i++) { Geometry a = p1.getGeometryN(i); Geometry b = p2.getGeometryN(i); assertEquals(a, b); } }
/** * make sure outer ring is CCW and holes are CW for all the polygons in the Geometry * * @param mp set of polygons to check */ MultiPolygon makeGoodSHAPEMultiPolygon(MultiPolygon mp) { MultiPolygon result; Polygon[] ps = new Polygon[mp.getNumGeometries()]; // check each sub-polygon for (int t = 0; t < mp.getNumGeometries(); t++) { ps[t] = makeGoodSHAPEPolygon((Polygon) mp.getGeometryN(t)); } result = new MultiPolygon(ps, new PrecisionModel(), 0); return result; }
protected Geometry transformMultiPolygon(MultiPolygon geom, Geometry parent) { List transGeomList = new ArrayList(); for (int i = 0; i < geom.getNumGeometries(); i++) { Geometry transformGeom = transformPolygon((Polygon) geom.getGeometryN(i), geom); if (transformGeom == null) continue; if (transformGeom.isEmpty()) continue; transGeomList.add(transformGeom); } return factory.buildGeometry(transGeomList); }
public Geobuf.Data.Geometry multiPolyToGeobuf(MultiPolygon poly) { Geobuf.Data.Geometry.Builder builder = Geobuf.Data.Geometry.newBuilder().setType(Geobuf.Data.Geometry.Type.MULTIPOLYGON); // first we specify the number of polygons builder.addLengths(poly.getNumGeometries()); for (int i = 0; i < poly.getNumGeometries(); i++) { Polygon p = (Polygon) poly.getGeometryN(i); // how many rings there are builder.addLengths(p.getNumInteriorRing() + 1); Stream<LineString> interiorRings = IntStream.range(0, p.getNumInteriorRing()).<LineString>mapToObj(p::getInteriorRingN); Stream.concat(Stream.of(p.getExteriorRing()), interiorRings) .forEach(r -> addRing(r, builder)); } return builder.build(); }
protected static Geometry transformMultiPolygon( CoordinateTransform ct, MultiPolygon multiPolygon) { Polygon[] polygon = new Polygon[multiPolygon.getNumGeometries()]; for (int i = 0; i < polygon.length; ++i) { polygon[i] = multiPolygon .getFactory() .createPolygon( transformCoordinates(ct, multiPolygon.getGeometryN(i).getCoordinates())); } return multiPolygon.getFactory().createMultiPolygon(polygon); }
/** * Filling multipolygons might result in holes where two polygons overlap. In this method we work * around that by drawing each polygon as a separate shape * * @param g * @param shape */ void fillLiteShape(Graphics2D g, LiteShape2 shape) { if (shape.getGeometry() instanceof MultiPolygon && shape.getGeometry().getNumGeometries() > 1) { MultiPolygon mp = (MultiPolygon) shape.getGeometry(); for (int i = 0; i < mp.getNumGeometries(); i++) { Polygon p = (Polygon) mp.getGeometryN(i); try { g.fill(new LiteShape2(p, null, null, false, false)); } catch (Exception e) { // should not really happen, but anyways throw new RuntimeException("Unexpected error occurred while rendering a multipolygon", e); } } } else { g.fill(shape); } }
/** * Writes the body for a <code>MultiPolygon</code> object. MultiPolygons are encoded into SVG path * elements. This function writes the different polygons in one d-attribute of an SVG path * element, separated by an 'M' character. (in other words, it calls the super.writeBody for each * polygon). * * @param o The <code>MultiPolygon</code> to be encoded. */ public void writeObject(Object o, GraphicsDocument document, boolean asChild) throws RenderException { document.writeElement("path", asChild); document.writeAttribute("fill-rule", "evenodd"); document.writeAttributeStart("d"); MultiPolygon mpoly = (MultiPolygon) o; for (int i = 0; i < mpoly.getNumGeometries(); i++) { Polygon poly = (Polygon) mpoly.getGeometryN(i); LineString shell = poly.getExteriorRing(); int nHoles = poly.getNumInteriorRing(); document.writeClosedPathContent(shell.getCoordinates()); for (int j = 0; j < nHoles; j++) { document.writeClosedPathContent(poly.getInteriorRingN(j).getCoordinates()); } } document.writeAttributeEnd(); }
private String transformMultiPolygonToJsonPolygonArray(MultiPolygon multipolygon) { LOGGER.info("Transforming multipolygon to JSON polygon array"); /* * For a multi polygon, we make several simple polygons and put them into an array */ String polygonArray = "["; boolean firstElement = true; for (int i = 0; i < multipolygon.getNumGeometries(); i++) { Polygon polygon = (Polygon) multipolygon.getGeometryN(i); String aPolygon = transformPolygonToJsonPolygon(polygon); if (firstElement) { polygonArray = polygonArray.concat(aPolygon); firstElement = false; } else { polygonArray = polygonArray.concat(", " + aPolygon); } } return polygonArray; }
// Multipolygon private String transformMultiPolygonToJsonPolygon(MultiPolygon multipolygon) { LOGGER.info("Transforming multipolygon to JSON polygon with several rings in it."); /* Lines are like this: {"paths":[[[-122.68,45.53], [-122.58,45.55],[-122.57,45.58],[-122.53,45.6]]], "spatialReference":{"wkid":4326}} * For a multi polygon, we put several paths. * We will assemble it in several parts: * (a) {"paths":[ * (b) several paths, comma separated, each has square brackets: * (b) [ [coords],[coords],[coords] ] <== this is one path, with square brackets! * (b) [ [coords],[coords],[coords] ], <== this is one path, with square brackets! * (b) [ [coords],[coords],[coords] ], <== this is one path, with square brackets! * (c) ], * (d) "spatialReference":{"wkid":4326} * (e) } */ // (1) make paths, and concatenate them, comma separated String allRings = ""; boolean firstElement = true; for (int i = 0; i < multipolygon.getNumGeometries(); i++) { Polygon polygon = (Polygon) multipolygon.getGeometryN(i); String aRing = getPathFromPolygon(polygon); if (firstElement) { allRings = allRings.concat(aRing); firstElement = false; } else { allRings = allRings.concat(", " + aRing); } } // (2) assemble polygon String jsonString = assemblePolygon(allRings, multipolygon); return jsonString; }
/** * Transform a feature to a JSON string * * <p>The feature that is passed to this method is transformed to a JSON string according to this * site (http://help.arcgis.com/en/webapi/javascript/arcgis/help/jsapi_start.htm). * * @param geom * @return * @throws IOException */ private String transformOneFeature(Geometry geom) throws IOException { // Depending on geometry's type, transform to json geometry String jsonString = ""; // simple geometries: if (geom instanceof Point) { jsonString = transformPointToJsonPoint((Point) geom); } else if (geom instanceof LineString) { jsonString = transformLineStringToJsonLineString((LineString) geom); } else if (geom instanceof Polygon) { jsonString = transformPolygonToJsonPolygon((Polygon) geom); } // multipoint else if (geom instanceof MultiPoint) { MultiPoint multipoint = (MultiPoint) geom; // if only one point inside, make normal point out of it if (multipoint.getNumGeometries() == 1) { Point point = (Point) multipoint.getGeometryN(0); jsonString = transformPointToJsonPoint(point); } else { jsonString = transformMultiPointToJsonMultiPoint(multipoint); } // multilinestring } else if (geom instanceof MultiLineString) { MultiLineString multiline = (MultiLineString) geom; // if only one linestring inside, make normal linestring out of it if (multiline.getNumGeometries() == 1) { LineString line = (LineString) multiline.getGeometryN(0); jsonString = transformLineStringToJsonLineString(line); } // real multilinestring else { if (multiGeometriesToArray) { jsonString = transformMultiLineStringToJsonLineStringArray(multiline); } else { jsonString = transformMultiLineStringToJsonLineString(multiline); } } // multipolygon } else if (geom instanceof MultiPolygon) { MultiPolygon multipoly = (MultiPolygon) geom; // if only one polygon inside, make normal polygon out of it if (multipoly.getNumGeometries() == 1) { Polygon poly = (Polygon) multipoly.getGeometryN(0); jsonString = transformPolygonToJsonPolygon(poly); } // real multi polygon else { if (multiGeometriesToArray) { jsonString = transformMultiPolygonToJsonPolygonArray(multipoly); } else { jsonString = transformMultiPolygonToJsonPolygon(multipoly); } } } else { LOGGER.error("Feature has no recognized geometry type"); } return jsonString; }
@Override public void decodeData(boolean autoClosed) throws DecodeException, IOException, TransformException { super.decodeData(autoClosed); polyMultimap = ArrayListMultimap.create(); radialDataBlock = new RadialDataBlock(); radialDataBlock.builder(this.decodeCinradXHeader.getRandomAccessFile(), -1); if (autoClosed) { this.decodeCinradXHeader.getRandomAccessFile().close(); } SimpleFeatureTypeBuilder builder = new SimpleFeatureTypeBuilder(); builder.setCRS(crs); builder.setName("Cinrad-X Radial Data"); builder.add("geom", Geometry.class); builder.add("colorIndex", Float.class); builder.add("value", Float.class); schema = builder.buildFeatureType(); // Reset index counter geoIndex = 0; if (getPlaneFeatures() == null) { planeFeatures = new DefaultFeatureCollection(); } planeFeatures.clear(); double minA = filter.getMinAzimuth(); double maxA = filter.getMaxAzimuth(); if (maxA - minA < 360.0) { while (minA >= 360.0) { minA -= 360.0; maxA -= 360.0; } } for (RadialData data : radialDataBlock.getRadialDatas()) { if (testInAzimuthRange(data, minA, maxA)) { double startAngle = data.getStartAngle(); double endAngle = startAngle + data.getAngleWidth(); // double angle1 = 90.0 - startAngle; // double angle2 = 90.0 - endAngle; if (startAngle < 0) { startAngle += 360; } if (endAngle < 0) { endAngle += 360; } // Add .00000001 to any 0, 90, 180, 270, 360 values to prevent // sin // or cos error if (startAngle == 0.0 || startAngle == 90.0 || startAngle == 180.0 || startAngle == 270.0 || startAngle == 360.0) { startAngle += 0.00001; } if (endAngle == 0.0 || endAngle == 90.0 || endAngle == 180.0 || endAngle == 270.0 || endAngle == 360.0) { endAngle += 0.00001; } startAngle = Math.toRadians(startAngle); endAngle = Math.toRadians(endAngle); int startRange = data.getRadialHeader().getStartRange(); int key; float value; for (Map.Entry<Integer, Float> entry : data.getDataValueArray().entrySet()) { value = entry.getValue(); if (testValueRange(value)) { key = entry.getKey(); // double[] geoXY; double[] albX = new double[4]; double[] albY = new double[4]; int length1 = startRange + key * data.getRadialHeader().getResolution(); albX[0] = length1 * Math.sin(startAngle); albY[0] = length1 * Math.cos(startAngle); albX[1] = length1 * Math.sin(endAngle); albY[1] = length1 * Math.cos(endAngle); int length2 = length1 + data.getRadialHeader().getResolution(); albX[2] = length2 * Math.sin(endAngle); albY[2] = length2 * Math.cos(endAngle); albX[3] = length2 * Math.sin(startAngle); albY[3] = length2 * Math.cos(startAngle); Coordinate[] cArray = new Coordinate[5]; // Add the first point double[] srcPts0 = {albX[0], albY[0]}; double[] dstPts0 = new double[2]; cinradTransform.transform(srcPts0, 0, dstPts0, 0, 1); cArray[0] = new Coordinate(dstPts0[0], dstPts0[1]); for (int nr = 1; nr < albX.length; nr++) { double[] srcPts = {albX[nr], albY[nr]}; double[] dstPts = new double[2]; cinradTransform.transform(srcPts, 0, dstPts, 0, 1); cArray[nr] = new Coordinate(dstPts[0], dstPts[1]); } // Add the first point again to close polygon cArray[4] = new Coordinate(dstPts0[0], dstPts0[1]); LinearRing lr = geoFactory.createLinearRing(cArray); Polygon poly = JTSUtilities.makeGoodShapePolygon(geoFactory.createPolygon(lr, null)); // System.out.println("value:" + entry.getValue()); if (configuration.getBoolean(COLOR_MODE, true)) { polyMultimap.put(CinradXUtils.getRadialColorIndex(entry.getValue()) * 1.0f, poly); } else { polyMultimap.put(entry.getValue(), poly); } } } } } Set<Float> valueSet = polyMultimap.keySet(); // System.out.println(valueSet.size()); if (valueSet.size() > 0) { for (Float v : valueSet) { Float color = new Float(v); Float value = color; if (configuration.getBoolean(COLOR_MODE, true)) { value = color * 5; } if (configuration.getBoolean(REDUCE_POLYGONS, true)) { logger.debug("REDUCING POLYGONS!"); if (polyMultimap.get(v).size() > 0) { Polygon[] polyArray = new Polygon[polyMultimap.get(v).size()]; GeometryCollection polyCollection = geoFactory.createGeometryCollection(polyMultimap.get(v).toArray(polyArray)); Geometry union = polyCollection.buffer(geometryBuffer); union = TopologyPreservingSimplifier.simplify(union, geometrySimplify); logger.debug("Geometry Type:" + union.getGeometryType()); // polyMultimap.get(v).clear(); if (union.getGeometryType().equalsIgnoreCase("MultiPolygon")) { // logger.debug(union.toString()); if (configuration.getBoolean(MULTIPOLYGON_MODE, true)) { SimpleFeature feature = SimpleFeatureBuilder.build( schema, new Object[] {union, color, value}, new Integer(geoIndex++).toString()); planeFeatures.add(feature); } else { MultiPolygon multiPolygon = (MultiPolygon) union; for (int j = 0; j < multiPolygon.getNumGeometries(); j++) { // create the feature SimpleFeature feature = SimpleFeatureBuilder.build( schema, new Object[] {(Geometry) multiPolygon.getGeometryN(j), color, value}, new Integer(geoIndex++).toString()); planeFeatures.add(feature); // logger.debug(feature.toString()); } } } else if (union.getGeometryType().equalsIgnoreCase("Polygon")) { if (configuration.getBoolean(MULTIPOLYGON_MODE, true)) { // create the feature Polygon[] pa = {(Polygon) union}; SimpleFeature feature = SimpleFeatureBuilder.build( schema, new Object[] {(Geometry) new MultiPolygon(pa, geoFactory), color, value}, new Integer(geoIndex++).toString()); planeFeatures.add(feature); } else { // create the feature SimpleFeature feature = SimpleFeatureBuilder.build( schema, new Object[] {(Geometry) union, color, value}, new Integer(geoIndex++).toString()); planeFeatures.add(feature); } // logger.debug(feature.toString()); } } } else { for (Polygon poly : polyMultimap.get(v)) { SimpleFeature feature = SimpleFeatureBuilder.build( schema, new Object[] {poly, color, value}, new Integer(geoIndex++).toString()); planeFeatures.add(feature); // logger.debug(feature.toString()); } } } } }
public static IGlobeFeatureCollection< IVector2, ? extends IBoundedGeometry2D<? extends IFinite2DBounds<?>>> readFeatures(final DataStore dataStore, final String layerName, final GProjection projection) throws Exception { final SimpleFeatureSource featureSource = dataStore.getFeatureSource(layerName); final SimpleFeatureCollection featuresCollection = featureSource.getFeatures(); final GIntHolder validCounter = new GIntHolder(0); // final GIntHolder polygonsWithHolesCounter = new GIntHolder(0); final GIntHolder invalidCounter = new GIntHolder(0); // final GIntHolder validVerticesCounter = new GIntHolder(0); final GIntHolder polygonsCounter = new GIntHolder(0); final GIntHolder linesCounter = new GIntHolder(0); final GIntHolder pointsCounter = new GIntHolder(0); final int featuresCount = featuresCollection.size(); final ArrayList<IGlobeFeature<IVector2, IBoundedGeometry2D<? extends IFinite2DBounds<?>>>> euclidFeatures = new ArrayList< IGlobeFeature<IVector2, IBoundedGeometry2D<? extends IFinite2DBounds<?>>>>( featuresCount); final GProgress progress = new GProgress(featuresCount) { @Override public void informProgress( final double percent, final long elapsed, final long estimatedMsToFinish) { // System.out.println("Loading \"" + fileName.buildPath() + "\" " // + progressString(percent, elapsed, // estimatedMsToFinish)); System.out.println( "Loading data from data storage: " + layerName + " " + progressString(percent, elapsed, estimatedMsToFinish)); } }; final FeatureIterator<SimpleFeature> iterator = featuresCollection.features(); while (iterator.hasNext()) { final SimpleFeature feature = iterator.next(); final GeometryAttribute geometryAttribute = feature.getDefaultGeometryProperty(); final GeometryType type = geometryAttribute.getType(); if (type.getBinding() == com.vividsolutions.jts.geom.MultiPolygon.class) { polygonsCounter.increment(); final com.vividsolutions.jts.geom.MultiPolygon multipolygon = (com.vividsolutions.jts.geom.MultiPolygon) geometryAttribute.getValue(); final int geometriesCount = multipolygon.getNumGeometries(); final List<IPolygon2D> polygons = new ArrayList<IPolygon2D>(geometriesCount); for (int i = 0; i < geometriesCount; i++) { final com.vividsolutions.jts.geom.Polygon jtsPolygon = (com.vividsolutions.jts.geom.Polygon) multipolygon.getGeometryN(i); try { final IPolygon2D euclidPolygon = createEuclidPolygon(projection, jtsPolygon); if (euclidPolygon != null) { // euclidFeatures.add(createFeature(euclidPolygon, feature)); polygons.add(euclidPolygon); validCounter.increment(); } } catch (final IllegalArgumentException e) { // System.err.println(e.getMessage()); } } if (!polygons.isEmpty()) { if (polygons.size() == 1) { euclidFeatures.add(createFeature(polygons.get(0), feature)); } else { euclidFeatures.add(createFeature(new GMultiGeometry2D<IPolygon2D>(polygons), feature)); } } } else if (type.getBinding() == com.vividsolutions.jts.geom.MultiLineString.class) { linesCounter.increment(); final com.vividsolutions.jts.geom.MultiLineString multiline = (com.vividsolutions.jts.geom.MultiLineString) geometryAttribute.getValue(); final int geometriesCount = multiline.getNumGeometries(); final List<IPolygonalChain2D> lines = new ArrayList<IPolygonalChain2D>(geometriesCount); for (int i = 0; i < geometriesCount; i++) { final com.vividsolutions.jts.geom.LineString jtsLine = (com.vividsolutions.jts.geom.LineString) multiline.getGeometryN(i); try { final IPolygonalChain2D euclidLine = createLine(jtsLine.getCoordinates(), projection); // euclidFeatures.add(createFeature(euclidLines, feature)); lines.add(euclidLine); } catch (final IllegalArgumentException e) { // System.err.println(e.getMessage()); } } if (!lines.isEmpty()) { if (lines.size() == 1) { euclidFeatures.add(createFeature(lines.get(0), feature)); } else { euclidFeatures.add( createFeature(new GMultiGeometry2D<IPolygonalChain2D>(lines), feature)); } } validCounter.increment(); } else if (type.getBinding() == com.vividsolutions.jts.geom.Point.class) { pointsCounter.increment(); final IVector2 euclidPoint = createPoint( ((com.vividsolutions.jts.geom.Point) geometryAttribute.getValue()).getCoordinate(), projection); euclidFeatures.add(createFeature(euclidPoint, feature)); validCounter.increment(); } else if (type.getBinding() == com.vividsolutions.jts.geom.MultiPoint.class) { final IBoundedGeometry2D<? extends IFinite2DBounds<?>> euclidMultipoint = createEuclidMultiPoint(geometryAttribute, projection); euclidFeatures.add(createFeature(euclidMultipoint, feature)); validCounter.increment(); } else { invalidCounter.increment(); System.out.println("invalid type: " + type); } progress.stepDone(); } dataStore.dispose(); euclidFeatures.trimToSize(); System.out.println(); System.out.println("Features: " + featuresCount); System.out.println(); System.out.println("Read " + validCounter.get() + " valid geometries"); System.out.println(" => " + polygonsCounter.get() + " valid polygons"); System.out.println(" => " + linesCounter.get() + " valid lines"); System.out.println(" => " + pointsCounter.get() + " valid points"); System.out.println(); if (invalidCounter.get() > 0) { System.out.println("Ignored " + invalidCounter.get() + " invalid geometries"); } System.out.println(); final SimpleFeatureType schema = featureSource.getSchema(); final int fieldsCount = schema.getAttributeCount(); final List<GField> fields = new ArrayList<GField>(fieldsCount); System.out.println("Fields count: " + fieldsCount); for (int i = 0; i < fieldsCount; i++) { final String fieldName = schema.getType(i).getName().getLocalPart(); System.out.println("Fieldname: " + fieldName); final Class<?> fieldType = schema.getType(i).getBinding(); fields.add(new GField(fieldName, fieldType)); } return new GListFeatureCollection<IVector2, IBoundedGeometry2D<? extends IFinite2DBounds<?>>>( GProjection.EPSG_4326, fields, euclidFeatures, "uniqueId_000"); }