mirror of
https://github.com/meteoinfo/MeteoInfo.git
synced 2025-12-08 20:36:05 +00:00
support output GeoJSON file from Layer
This commit is contained in:
parent
cac71057b7
commit
b02bda02f5
@ -33,7 +33,8 @@ public class PointD implements Cloneable{
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contructor
|
* Constructor
|
||||||
|
*
|
||||||
* @param x
|
* @param x
|
||||||
* @param y
|
* @param y
|
||||||
*/
|
*/
|
||||||
@ -46,6 +47,22 @@ public class PointD implements Cloneable{
|
|||||||
// </editor-fold>
|
// </editor-fold>
|
||||||
// <editor-fold desc="Methods">
|
// <editor-fold desc="Methods">
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To double array
|
||||||
|
* @return Double array
|
||||||
|
*/
|
||||||
|
public double[] toArray() {
|
||||||
|
return new double[]{X, Y};
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To float array
|
||||||
|
* @return Float array
|
||||||
|
*/
|
||||||
|
public float[] toFloatArray() {
|
||||||
|
return new float[]{(float) X, (float) Y};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equals of two pointDs
|
* Equals of two pointDs
|
||||||
* @param p PointD
|
* @param p PointD
|
||||||
|
|||||||
@ -137,6 +137,15 @@ public class ColorUtil {
|
|||||||
// </editor-fold>
|
// </editor-fold>
|
||||||
// <editor-fold desc="Methods">
|
// <editor-fold desc="Methods">
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert color r,g,b to hex string
|
||||||
|
* @param color The color
|
||||||
|
* @return Hex string
|
||||||
|
*/
|
||||||
|
public static String toHex(Color color) {
|
||||||
|
return String.format("#%02X%02X%02X", color.getRed(), color.getGreen(), color.getBlue());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a color to hex string
|
* Convert a color to hex string
|
||||||
*
|
*
|
||||||
|
|||||||
@ -67,7 +67,7 @@ import java.util.zip.ZipInputStream;
|
|||||||
public static String getVersion(){
|
public static String getVersion(){
|
||||||
String version = GlobalUtil.class.getPackage().getImplementationVersion();
|
String version = GlobalUtil.class.getPackage().getImplementationVersion();
|
||||||
if (version == null || version.equals("")) {
|
if (version == null || version.equals("")) {
|
||||||
version = "3.7.8";
|
version = "3.7.9";
|
||||||
}
|
}
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,77 @@
|
|||||||
|
package org.meteoinfo.geo.io;
|
||||||
|
|
||||||
|
import org.meteoinfo.common.colors.ColorUtil;
|
||||||
|
import org.meteoinfo.geo.layer.VectorLayer;
|
||||||
|
import org.meteoinfo.geometry.io.geojson.*;
|
||||||
|
import org.meteoinfo.geometry.legend.ColorBreak;
|
||||||
|
import org.meteoinfo.geometry.legend.LegendScheme;
|
||||||
|
import org.meteoinfo.geometry.legend.LegendType;
|
||||||
|
import org.meteoinfo.geometry.legend.PolygonBreak;
|
||||||
|
import org.meteoinfo.geometry.shape.Shape;
|
||||||
|
import org.meteoinfo.geometry.shape.ShapeTypes;
|
||||||
|
import org.meteoinfo.ndarray.DataType;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class GeoJSONReader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a VectorLayer from GeoJSON feature collection
|
||||||
|
* @param features The feature collection
|
||||||
|
* @return VectorLayer object
|
||||||
|
*/
|
||||||
|
public static VectorLayer read(FeatureCollection features) {
|
||||||
|
Shape shape = GeoJSONUtil.toShape(features.getFeature(0).getGeometry());
|
||||||
|
VectorLayer layer = new VectorLayer(shape.getShapeType());
|
||||||
|
String fieldName = "title";
|
||||||
|
layer.editAddField(fieldName, DataType.STRING);
|
||||||
|
LegendScheme ls = new LegendScheme(shape.getShapeType());
|
||||||
|
ls.setLegendType(LegendType.UNIQUE_VALUE);
|
||||||
|
ls.setFieldName(fieldName);
|
||||||
|
for (int i = 0; i < features.getNumFeatures(); i++) {
|
||||||
|
Feature feature = features.getFeature(i);
|
||||||
|
Map<String, Object> properties = feature.getProperties();
|
||||||
|
String titleValue = (String) properties.get("title");
|
||||||
|
PolygonBreak cb = new PolygonBreak();
|
||||||
|
cb.setStartValue(titleValue);
|
||||||
|
cb.setCaption(titleValue);
|
||||||
|
Color color = ColorUtil.parseToColor((String) properties.get("fill"));
|
||||||
|
float alpha = Float.parseFloat(properties.get("fill-opacity").toString());
|
||||||
|
color = ColorUtil.getColor(color, alpha);
|
||||||
|
cb.setColor(color);
|
||||||
|
color = ColorUtil.parseToColor((String) properties.get("stroke"));
|
||||||
|
alpha = Float.parseFloat(properties.get("stroke-opacity").toString());
|
||||||
|
color = ColorUtil.getColor(color, alpha);
|
||||||
|
cb.setOutlineColor(color);
|
||||||
|
float lineWidth = Float.parseFloat(properties.get("stroke-width").toString());
|
||||||
|
cb.setOutlineSize(lineWidth);
|
||||||
|
ls.addLegendBreak(cb);
|
||||||
|
Geometry geometry = feature.getGeometry();
|
||||||
|
if (geometry != null) {
|
||||||
|
try {
|
||||||
|
int idx = layer.getShapeNum();
|
||||||
|
layer.editInsertShape(GeoJSONUtil.toShape(geometry), idx);
|
||||||
|
layer.editCellValue(fieldName, idx, titleValue);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
layer.setLegendScheme(ls);
|
||||||
|
|
||||||
|
return layer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a VectorLayer from GeoJSON string
|
||||||
|
* @param json The GeoJSON string
|
||||||
|
* @return VectorLayer object
|
||||||
|
*/
|
||||||
|
public static VectorLayer read(String json) {
|
||||||
|
FeatureCollection features = (FeatureCollection) GeoJSONFactory.create(json);
|
||||||
|
|
||||||
|
return read(features);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,63 @@
|
|||||||
|
package org.meteoinfo.geo.io;
|
||||||
|
|
||||||
|
import org.meteoinfo.common.colors.ColorUtil;
|
||||||
|
import org.meteoinfo.geo.layer.VectorLayer;
|
||||||
|
import org.meteoinfo.geometry.io.geojson.Feature;
|
||||||
|
import org.meteoinfo.geometry.io.geojson.FeatureCollection;
|
||||||
|
import org.meteoinfo.geometry.io.geojson.GeoJSONUtil;
|
||||||
|
import org.meteoinfo.geometry.io.geojson.Geometry;
|
||||||
|
import org.meteoinfo.geometry.legend.*;
|
||||||
|
import org.meteoinfo.geometry.shape.Shape;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class GeoJSONWriter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a vector layer to GeoJSON feature collection
|
||||||
|
*
|
||||||
|
* @param layer The vector layer
|
||||||
|
* @return GeoJSON feature collection
|
||||||
|
*/
|
||||||
|
public static FeatureCollection write(VectorLayer layer) {
|
||||||
|
Feature[] features = new Feature[layer.getShapeNum()];
|
||||||
|
LegendScheme ls = layer.getLegendScheme();
|
||||||
|
for (int i = 0; i < layer.getShapeNum(); i++) {
|
||||||
|
Shape shape = layer.getShape(i);
|
||||||
|
Geometry geometry = GeoJSONUtil.fromShape(shape);
|
||||||
|
Map<String, Object> properties = new HashMap<>();
|
||||||
|
ColorBreak cb = ls.getLegendBreak(shape.getLegendIndex());
|
||||||
|
switch (cb.getBreakType()) {
|
||||||
|
case POINT_BREAK:
|
||||||
|
PointBreak pointBreak = (PointBreak) cb;
|
||||||
|
properties.put("marker-size", "medium");
|
||||||
|
properties.put("marker-color", ColorUtil.toHex(pointBreak.getColor()));
|
||||||
|
break;
|
||||||
|
case POLYLINE_BREAK:
|
||||||
|
PolylineBreak polylineBreak = (PolylineBreak) cb;
|
||||||
|
properties.put("stroke", ColorUtil.toHex(polylineBreak.getColor()));
|
||||||
|
properties.put("stroke-opacity", polylineBreak.getColor().getAlpha() / 255.f);
|
||||||
|
properties.put("stroke-width", polylineBreak.getWidth());
|
||||||
|
break;
|
||||||
|
case POLYGON_BREAK:
|
||||||
|
PolygonBreak polygonBreak = (PolygonBreak) cb;
|
||||||
|
properties.put("fill", ColorUtil.toHex(cb.getColor()));
|
||||||
|
properties.put("fill-opacity", cb.getColor().getAlpha() / 255.f);
|
||||||
|
if (polygonBreak.isDrawOutline()) {
|
||||||
|
properties.put("stroke", ColorUtil.toHex(polygonBreak.getOutlineColor()));
|
||||||
|
properties.put("stroke-opacity", polygonBreak.getOutlineColor().getAlpha() / 255.f);
|
||||||
|
properties.put("stroke-width", polygonBreak.getOutlineSize());
|
||||||
|
} else {
|
||||||
|
properties.put("stroke-opacity", 0);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
properties.put("title", cb.getCaption());
|
||||||
|
features[i] = new Feature(geometry, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new FeatureCollection(features);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1412,6 +1412,17 @@ public class VectorLayer extends MapLayer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit: Remove a shape by index
|
||||||
|
* @param idx The index
|
||||||
|
*/
|
||||||
|
public void editRemoveShape(int idx) {
|
||||||
|
if (idx >= 0 && idx < this.getShapeNum() - 1) {
|
||||||
|
this._shapeList.remove(idx);
|
||||||
|
this._attributeTable.getTable().removeRow(idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateLayerExtent(Shape aShape) {
|
private void updateLayerExtent(Shape aShape) {
|
||||||
if (this.getShapeNum() == 1) {
|
if (this.getShapeNum() == 1) {
|
||||||
this.setExtent((Extent) aShape.getExtent().clone());
|
this.setExtent((Extent) aShape.getExtent().clone());
|
||||||
|
|||||||
@ -37,6 +37,16 @@
|
|||||||
<artifactId>jts-core</artifactId>
|
<artifactId>jts-core</artifactId>
|
||||||
<version>1.19.0</version>
|
<version>1.19.0</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-databind</artifactId>
|
||||||
|
<version>2.13.4.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.fasterxml.jackson.core</groupId>
|
||||||
|
<artifactId>jackson-annotations</artifactId>
|
||||||
|
<version>2.13.4</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
|
||||||
|
@JsonPropertyOrder({"type", "id", "geometry", "properties"})
|
||||||
|
public class Feature extends GeoJSON {
|
||||||
|
@JsonInclude(Include.NON_EMPTY)
|
||||||
|
private final Object id;
|
||||||
|
private final Geometry geometry;
|
||||||
|
private final Map<String, Object> properties;
|
||||||
|
|
||||||
|
public Feature(
|
||||||
|
@JsonProperty("geometry") Geometry geometry,
|
||||||
|
@JsonProperty("properties") Map<String,Object> properties) {
|
||||||
|
this(null, geometry, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public Feature(
|
||||||
|
@JsonProperty("id") Object id,
|
||||||
|
@JsonProperty("geometry") Geometry geometry,
|
||||||
|
@JsonProperty("properties") Map<String,Object> properties) {
|
||||||
|
super();
|
||||||
|
this.id = id;
|
||||||
|
this.geometry = geometry;
|
||||||
|
this.properties = properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Geometry getGeometry() {
|
||||||
|
return geometry;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, Object> getProperties() {
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,41 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||||
|
|
||||||
|
@JsonPropertyOrder({"type", "features"})
|
||||||
|
public class FeatureCollection extends GeoJSON {
|
||||||
|
private final Feature[] features;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public FeatureCollection(@JsonProperty("features") Feature[] features) {
|
||||||
|
super();
|
||||||
|
this.features = features;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get features
|
||||||
|
* @return Features
|
||||||
|
*/
|
||||||
|
public Feature[] getFeatures() {
|
||||||
|
return features;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get number of features
|
||||||
|
* @return Number of features
|
||||||
|
*/
|
||||||
|
public int getNumFeatures() {
|
||||||
|
return features.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a feature by index
|
||||||
|
* @param index The index
|
||||||
|
* @return The feature
|
||||||
|
*/
|
||||||
|
public Feature getFeature(int index) {
|
||||||
|
return features[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,58 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
|
import com.fasterxml.jackson.core.JsonGenerationException;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
@JsonTypeInfo(
|
||||||
|
use = JsonTypeInfo.Id.NAME,
|
||||||
|
include = JsonTypeInfo.As.EXISTING_PROPERTY,
|
||||||
|
property = "type"
|
||||||
|
)
|
||||||
|
@JsonSubTypes( {
|
||||||
|
@JsonSubTypes.Type(value=Point.class, name="Point" ),
|
||||||
|
@JsonSubTypes.Type(value=LineString.class, name="LineString" ),
|
||||||
|
@JsonSubTypes.Type(value=Polygon.class, name="Polygon" ),
|
||||||
|
@JsonSubTypes.Type(value=MultiPoint.class, name="MultiPoint" ),
|
||||||
|
@JsonSubTypes.Type(value=MultiLineString.class, name="MultiLineString" ),
|
||||||
|
@JsonSubTypes.Type(value=MultiPolygon.class, name="MultiPolygon" ),
|
||||||
|
@JsonSubTypes.Type(value=Feature.class, name="Feature" ),
|
||||||
|
@JsonSubTypes.Type(value=FeatureCollection.class, name="FeatureCollection" ),
|
||||||
|
@JsonSubTypes.Type(value=GeometryCollection.class, name="GeometryCollection" )
|
||||||
|
})
|
||||||
|
public abstract class GeoJSON {
|
||||||
|
private static final ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
@JsonProperty("type")
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public GeoJSON() {
|
||||||
|
setType(getClass().getSimpleName());
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
try {
|
||||||
|
return mapper.writeValueAsString(this);
|
||||||
|
} catch (JsonGenerationException e) {
|
||||||
|
return "Unhandled exception occured when serializing this instance";
|
||||||
|
} catch (JsonMappingException e) {
|
||||||
|
return "Unhandled exception occured when serializing this instance";
|
||||||
|
} catch (IOException e) {
|
||||||
|
return "Unhandled exception occured when serializing this instance";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,65 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonParseException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonMappingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.type.MapType;
|
||||||
|
|
||||||
|
public class GeoJSONFactory {
|
||||||
|
private static final ObjectMapper mapper = new ObjectMapper();
|
||||||
|
|
||||||
|
public static GeoJSON create(String json) {
|
||||||
|
try {
|
||||||
|
JsonNode node = mapper.readTree(json);
|
||||||
|
String type = node.get("type").asText();
|
||||||
|
if (type.equals("FeatureCollection"))
|
||||||
|
return readFeatureCollection(node);
|
||||||
|
else if (type.equals("Feature"))
|
||||||
|
return readFeature(node);
|
||||||
|
else
|
||||||
|
return readGeometry(node, type);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static FeatureCollection readFeatureCollection(JsonNode node)
|
||||||
|
throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
|
||||||
|
Iterator<JsonNode> it = node.get("features").iterator();
|
||||||
|
List<Feature> features = new ArrayList<>();
|
||||||
|
while (it.hasNext())
|
||||||
|
features.add(readFeature(it.next()));
|
||||||
|
return new FeatureCollection(features.toArray(new Feature[features.size()]));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Feature readFeature(JsonNode node)
|
||||||
|
throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
|
||||||
|
JsonNode geometryNode = node.get("geometry");
|
||||||
|
MapType javaType = mapper.getTypeFactory().constructMapType(Map.class, String.class, Object.class);
|
||||||
|
JsonNode id = node.get("id");
|
||||||
|
Map<String, Object> properties = mapper.readValue(node.get("properties").traverse(), javaType);
|
||||||
|
Geometry geometry = readGeometry(geometryNode);
|
||||||
|
return new Feature(id, geometry, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Geometry readGeometry(JsonNode node)
|
||||||
|
throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
|
||||||
|
if (node != null && !node.isNull())
|
||||||
|
return readGeometry(node, node.get("type").asText());
|
||||||
|
else
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Geometry readGeometry(JsonNode node, String type)
|
||||||
|
throws JsonParseException, JsonMappingException, IOException, ClassNotFoundException {
|
||||||
|
return (Geometry) mapper.readValue(node.traverse(), Class.forName("org.meteoinfo.geometry.io.geojson." + type));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,341 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import org.meteoinfo.common.PointD;
|
||||||
|
import org.meteoinfo.geometry.shape.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GeoJSONUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert GeoJSON geometry to shape
|
||||||
|
*
|
||||||
|
* @param geometry The geometry
|
||||||
|
* @return Shape
|
||||||
|
*/
|
||||||
|
public static Shape toShape(Geometry geometry) {
|
||||||
|
if (geometry instanceof Point) {
|
||||||
|
return toShape((Point) geometry);
|
||||||
|
} else if (geometry instanceof LineString) {
|
||||||
|
return toShape((LineString) geometry);
|
||||||
|
} else if (geometry instanceof MultiLineString) {
|
||||||
|
return toShape((MultiLineString) geometry);
|
||||||
|
} else if (geometry instanceof Polygon) {
|
||||||
|
return toShape((Polygon) geometry);
|
||||||
|
} else if (geometry instanceof MultiPolygon) {
|
||||||
|
return toShape((MultiPolygon) geometry);
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert shape to GeoJSON geometry
|
||||||
|
*
|
||||||
|
* @param shape The shape
|
||||||
|
* @return Geometry
|
||||||
|
*/
|
||||||
|
public static Geometry fromShape(Shape shape) {
|
||||||
|
if (shape instanceof PointShape) {
|
||||||
|
return fromShape((PointShape) shape);
|
||||||
|
} else if (shape instanceof PolylineShape) {
|
||||||
|
return fromShape((PolylineShape) shape);
|
||||||
|
} else if (shape instanceof PolygonShape) {
|
||||||
|
return fromShape((PolygonShape) shape);
|
||||||
|
} else {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert PointShape to GeoJSON Point
|
||||||
|
*
|
||||||
|
* @param pointShape The PointShape object
|
||||||
|
* @return GeoJSON Point object
|
||||||
|
*/
|
||||||
|
public static Point fromShape(PointShape pointShape) {
|
||||||
|
PointD p = pointShape.getPoint();
|
||||||
|
|
||||||
|
return new Point(p.toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert GeoJSON Point to PointShape
|
||||||
|
*
|
||||||
|
* @param point The GeoJSON Point object
|
||||||
|
* @return PointShape object
|
||||||
|
*/
|
||||||
|
public static PointShape toShape(Point point) {
|
||||||
|
double[] coordinates = point.getCoordinates();
|
||||||
|
if (coordinates.length == 2) {
|
||||||
|
return new PointShape(new PointD(coordinates[0], coordinates[1]));
|
||||||
|
} else {
|
||||||
|
return new PointZShape(new PointZ(coordinates[0], coordinates[1], coordinates[2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert PolylineShape to GeoJSON LineString or MultiLineString
|
||||||
|
*
|
||||||
|
* @param polylineShape The PolylineShape object
|
||||||
|
* @return GeoJSON LineString or MultiLineString object
|
||||||
|
*/
|
||||||
|
public static Geometry fromShape(PolylineShape polylineShape) {
|
||||||
|
if (polylineShape.isMultiLine()) {
|
||||||
|
int lineNum = polylineShape.getPartNum();
|
||||||
|
double[][][] coordinates = new double[lineNum][][];
|
||||||
|
int cNum = polylineShape.getShapeType() == ShapeTypes.POLYLINE ? 2 : 3;
|
||||||
|
for (int j = 0; j < lineNum; j++) {
|
||||||
|
Polyline polyline = polylineShape.getPolylines().get(j);
|
||||||
|
int pNum = polyline.getPointList().size();
|
||||||
|
double[][] matrix = new double[pNum][cNum];
|
||||||
|
for (int i = 0; i < pNum; i++) {
|
||||||
|
matrix[i] = polyline.getPointList().get(i).toArray();
|
||||||
|
}
|
||||||
|
coordinates[j] = matrix;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MultiLineString(coordinates);
|
||||||
|
} else {
|
||||||
|
int cNum = polylineShape.getShapeType() == ShapeTypes.POLYLINE ? 2 : 3;
|
||||||
|
double[][] coordinates = new double[polylineShape.getPointNum()][cNum];
|
||||||
|
for (int i = 0; i < polylineShape.getPointNum(); i++) {
|
||||||
|
coordinates[i] = polylineShape.getPoints().get(i).toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
return new LineString(coordinates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert GeoJSON LineString to PolylineShape
|
||||||
|
*
|
||||||
|
* @param lineString The GeoJSON LineString object
|
||||||
|
* @return PolylineShape object
|
||||||
|
*/
|
||||||
|
public static PolylineShape toShape(LineString lineString) {
|
||||||
|
double[][] coordinates = lineString.getCoordinates();
|
||||||
|
int pNum = coordinates.length;
|
||||||
|
if (coordinates[0].length == 2) {
|
||||||
|
List<PointD> points = new ArrayList<>();
|
||||||
|
for (int i = 0; i < pNum; i++) {
|
||||||
|
points.add(new PointD(coordinates[i][0], coordinates[i][1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PolylineShape(points);
|
||||||
|
} else {
|
||||||
|
List<PointZ> points = new ArrayList<>();
|
||||||
|
for (int i = 0; i < pNum; i++) {
|
||||||
|
points.add(new PointZ(coordinates[i][0], coordinates[i][1], coordinates[i][2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PolylineZShape(points);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert GeoJSON LineString to PolylineShape
|
||||||
|
*
|
||||||
|
* @param lineString The GeoJSON LineString object
|
||||||
|
* @return PolylineShape object
|
||||||
|
*/
|
||||||
|
public static PolylineShape toShape(MultiLineString lineString) {
|
||||||
|
double[][][] coordinates = lineString.getCoordinates();
|
||||||
|
int lineNum = coordinates.length;
|
||||||
|
int cNum = coordinates[0][0].length;
|
||||||
|
if (cNum == 2) {
|
||||||
|
PolylineShape polylineShape = new PolylineShape();
|
||||||
|
polylineShape.setPartNum(lineNum);
|
||||||
|
polylineShape.parts = new int[lineNum];
|
||||||
|
List<PointD> points = new ArrayList<>();
|
||||||
|
for (int j = 0; j < lineNum; j++) {
|
||||||
|
int pNum = coordinates[j].length;
|
||||||
|
polylineShape.parts[j] = pNum;
|
||||||
|
for (int i = 0; i < pNum; i++) {
|
||||||
|
points.add(new PointD(coordinates[j][i][0], coordinates[j][i][1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
polylineShape.setPoints(points);
|
||||||
|
|
||||||
|
return polylineShape;
|
||||||
|
} else {
|
||||||
|
PolylineZShape polylineZShape = new PolylineZShape();
|
||||||
|
polylineZShape.setPartNum(lineNum);
|
||||||
|
polylineZShape.parts = new int[lineNum];
|
||||||
|
List<PointZ> points = new ArrayList<>();
|
||||||
|
for (int j = 0; j < lineNum; j++) {
|
||||||
|
int pNum = coordinates[j].length;
|
||||||
|
polylineZShape.parts[j] = pNum;
|
||||||
|
for (int i = 0; i < pNum; i++) {
|
||||||
|
points.add(new PointZ(coordinates[j][i][0], coordinates[j][i][1], coordinates[j][i][2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
polylineZShape.setPoints(points);
|
||||||
|
|
||||||
|
return polylineZShape;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert PolygonShape to GeoJSON Polygon or MultiPolygon
|
||||||
|
*
|
||||||
|
* @param polygonShape The PolygonShape object
|
||||||
|
* @return GeoJSON Polygon or MultiPolygon object
|
||||||
|
*/
|
||||||
|
public static Geometry fromShape(PolygonShape polygonShape) {
|
||||||
|
int cNum = polygonShape.getShapeType() == ShapeTypes.POLYGON ? 2 : 3;
|
||||||
|
if (polygonShape.isMultiPolygon()) {
|
||||||
|
int polygonNum = polygonShape.getPolygons().size();
|
||||||
|
double[][][][] coordinates = new double[polygonNum][][][];
|
||||||
|
for (int k = 0; k < polygonNum; k++) {
|
||||||
|
org.meteoinfo.geometry.shape.Polygon sPolygon = polygonShape.getPolygon(k);
|
||||||
|
int ringNumber = sPolygon.getRingNumber();
|
||||||
|
double[][][] a3d = new double[ringNumber][][];
|
||||||
|
int pNum = sPolygon.getOutLine().size();
|
||||||
|
double[][] matrix = new double[pNum][cNum];
|
||||||
|
for (int i = 0; i < pNum; i++) {
|
||||||
|
matrix[i] = sPolygon.getOutLine().get(i).toArray();
|
||||||
|
}
|
||||||
|
a3d[0] = matrix;
|
||||||
|
if (sPolygon.hasHole()) {
|
||||||
|
for (int j = 0; j < sPolygon.getHoleLineNumber(); j++) {
|
||||||
|
pNum = sPolygon.getHoleLine(j).size();
|
||||||
|
matrix = new double[pNum][cNum];
|
||||||
|
for (int i = 0; i < sPolygon.getHoleLine(j).size(); i++) {
|
||||||
|
matrix[i] = sPolygon.getHoleLine(j).get(i).toArray();
|
||||||
|
}
|
||||||
|
a3d[j + 1] = matrix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
coordinates[k] = a3d;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new MultiPolygon(coordinates);
|
||||||
|
} else {
|
||||||
|
org.meteoinfo.geometry.shape.Polygon sPolygon = polygonShape.getPolygon(0);
|
||||||
|
int ringNum = sPolygon.getRingNumber();
|
||||||
|
double[][][] coordinates = new double[ringNum][][];
|
||||||
|
int pNum = sPolygon.getOutLine().size();
|
||||||
|
double[][] matrix = new double[pNum][cNum];
|
||||||
|
for (int i = 0; i < pNum; i++) {
|
||||||
|
matrix[i] = sPolygon.getOutLine().get(i).toArray();
|
||||||
|
}
|
||||||
|
coordinates[0] = matrix;
|
||||||
|
if (sPolygon.hasHole()) {
|
||||||
|
for (int j = 0; j < sPolygon.getHoleLineNumber(); j++) {
|
||||||
|
pNum = sPolygon.getHoleLine(j).size();
|
||||||
|
matrix = new double[pNum][cNum];
|
||||||
|
for (int i = 0; i < sPolygon.getHoleLine(j).size(); i++) {
|
||||||
|
matrix[i] = sPolygon.getHoleLine(j).get(i).toArray();
|
||||||
|
}
|
||||||
|
coordinates[j + 1] = matrix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Polygon(coordinates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert GeoJSON Polygon to PolygonShape
|
||||||
|
*
|
||||||
|
* @param polygon The GeoJSON Polygon object
|
||||||
|
* @return PolygonShape object
|
||||||
|
*/
|
||||||
|
public static PolygonShape toShape(Polygon polygon) {
|
||||||
|
double[][][] coordinates = polygon.getCoordinates();
|
||||||
|
int ringNum = coordinates.length;
|
||||||
|
int cNum = coordinates[0][0].length;
|
||||||
|
if (cNum == 2) {
|
||||||
|
PolygonShape polygonShape = new PolygonShape();
|
||||||
|
polygonShape.setPartNum(ringNum);
|
||||||
|
polygonShape.parts = new int[ringNum];
|
||||||
|
List<PointD> points = new ArrayList<>();
|
||||||
|
for (int j = 0; j < ringNum; j++) {
|
||||||
|
int pNum = coordinates[j].length;
|
||||||
|
polygonShape.parts[j] = pNum;
|
||||||
|
for (int i = 0; i < pNum; i++) {
|
||||||
|
points.add(new PointD(coordinates[j][i][0], coordinates[j][i][1]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
polygonShape.setPoints(points);
|
||||||
|
|
||||||
|
return polygonShape;
|
||||||
|
} else {
|
||||||
|
PolygonZShape polygonZShape = new PolygonZShape();
|
||||||
|
polygonZShape.setPartNum(ringNum);
|
||||||
|
polygonZShape.parts = new int[ringNum];
|
||||||
|
List<PointZ> points = new ArrayList<>();
|
||||||
|
for (int j = 0; j < ringNum; j++) {
|
||||||
|
int pNum = coordinates[j].length;
|
||||||
|
polygonZShape.parts[j] = pNum;
|
||||||
|
for (int i = 0; i < pNum; i++) {
|
||||||
|
points.add(new PointZ(coordinates[j][i][0], coordinates[j][i][1], coordinates[j][i][2]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
polygonZShape.setPoints(points);
|
||||||
|
|
||||||
|
return polygonZShape;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert GeoJSON MultiPolygon to PolygonShape
|
||||||
|
*
|
||||||
|
* @param multiPolygon The GeoJSON MultiPolygon object
|
||||||
|
* @return PolygonShape object
|
||||||
|
*/
|
||||||
|
public static PolygonShape toShape(MultiPolygon multiPolygon) {
|
||||||
|
double[][][][] coordinates = multiPolygon.getCoordinates();
|
||||||
|
int polygonNum = coordinates.length;
|
||||||
|
int cNum = coordinates[0][0][0].length;
|
||||||
|
if (cNum == 2) {
|
||||||
|
List<org.meteoinfo.geometry.shape.Polygon> polygons = new ArrayList<>();
|
||||||
|
for (int k = 0; k < polygonNum; k++) {
|
||||||
|
int ringNum = coordinates[k].length;
|
||||||
|
org.meteoinfo.geometry.shape.Polygon polygon = new org.meteoinfo.geometry.shape.Polygon();
|
||||||
|
for (int j = 0; j < ringNum; j++) {
|
||||||
|
List<PointD> points = new ArrayList<>();
|
||||||
|
int pNum = coordinates[k][j].length;
|
||||||
|
for (int i = 0; i < pNum; i++) {
|
||||||
|
points.add(new PointD(coordinates[k][j][i][0], coordinates[k][j][i][1]));
|
||||||
|
}
|
||||||
|
if (j == 0) {
|
||||||
|
polygon.setOutLine(points);
|
||||||
|
} else {
|
||||||
|
polygon.addHole(points);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
polygons.add(polygon);
|
||||||
|
}
|
||||||
|
PolygonShape polygonShape = new PolygonShape();
|
||||||
|
polygonShape.setPolygons(polygons);
|
||||||
|
|
||||||
|
return polygonShape;
|
||||||
|
} else {
|
||||||
|
List<org.meteoinfo.geometry.shape.Polygon> polygons = new ArrayList<>();
|
||||||
|
for (int k = 0; k < polygonNum; k++) {
|
||||||
|
int ringNum = coordinates[k].length;
|
||||||
|
org.meteoinfo.geometry.shape.Polygon polygon = new org.meteoinfo.geometry.shape.Polygon();
|
||||||
|
for (int j = 0; j < ringNum; j++) {
|
||||||
|
List<PointZ> points = new ArrayList<>();
|
||||||
|
int pNum = coordinates[k][j].length;
|
||||||
|
for (int i = 0; i < pNum; i++) {
|
||||||
|
points.add(new PointZ(coordinates[k][j][i][0], coordinates[k][j][i][1],
|
||||||
|
coordinates[k][j][i][2]));
|
||||||
|
}
|
||||||
|
if (j == 0) {
|
||||||
|
polygon.setOutLine(points);
|
||||||
|
} else {
|
||||||
|
polygon.addHole(points);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
polygons.add(polygon);
|
||||||
|
}
|
||||||
|
PolygonZShape polygonZShape = new PolygonZShape();
|
||||||
|
polygonZShape.setPolygons(polygons);
|
||||||
|
|
||||||
|
return polygonZShape;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,33 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonSubTypes;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonTypeInfo;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||||
|
|
||||||
|
@JsonTypeInfo(
|
||||||
|
use = JsonTypeInfo.Id.NAME,
|
||||||
|
include = JsonTypeInfo.As.EXISTING_PROPERTY,
|
||||||
|
property = "type"
|
||||||
|
)
|
||||||
|
@JsonSubTypes( {
|
||||||
|
@JsonSubTypes.Type(value=Point.class, name="Point" ),
|
||||||
|
@JsonSubTypes.Type(value=LineString.class, name="LineString" ),
|
||||||
|
@JsonSubTypes.Type(value=Polygon.class, name="Polygon" ),
|
||||||
|
@JsonSubTypes.Type(value=MultiPoint.class, name="MultiPoint" ),
|
||||||
|
@JsonSubTypes.Type(value=MultiLineString.class, name="MultiLineString" ),
|
||||||
|
@JsonSubTypes.Type(value=MultiPolygon.class, name="MultiPolygon" ),
|
||||||
|
@JsonSubTypes.Type(value=Feature.class, name="Feature" ),
|
||||||
|
@JsonSubTypes.Type(value=FeatureCollection.class, name="FeatureCollection" ),
|
||||||
|
@JsonSubTypes.Type(value=GeometryCollection.class, name="GeometryCollection" )
|
||||||
|
} )
|
||||||
|
|
||||||
|
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||||
|
@JsonPropertyOrder({"type", "coordinates", "bbox"})
|
||||||
|
public abstract class Geometry extends GeoJSON {
|
||||||
|
@JsonCreator
|
||||||
|
public Geometry() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||||
|
|
||||||
|
@JsonPropertyOrder({"type", "geometries"})
|
||||||
|
public class GeometryCollection extends Geometry {
|
||||||
|
private final Geometry[] geometries;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public GeometryCollection(@JsonProperty("geometries") Geometry[] geometries) {
|
||||||
|
super();
|
||||||
|
this.geometries = geometries;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Geometry[] getGeometries() {
|
||||||
|
return geometries;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
|
public class LineString extends Geometry {
|
||||||
|
private final double[][] coordinates;
|
||||||
|
private final double[] bbox;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public LineString(@JsonProperty("coordinates") double [][] coordinates) {
|
||||||
|
super();
|
||||||
|
this.coordinates = coordinates;
|
||||||
|
this.bbox = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[][] getCoordinates() {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] getBbox() {
|
||||||
|
return bbox;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
|
public class MultiLineString extends Geometry {
|
||||||
|
private final double[][][] coordinates;
|
||||||
|
private final double[] bbox;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public MultiLineString(@JsonProperty("coordinates") double [][][] coordinates) {
|
||||||
|
super();
|
||||||
|
this.coordinates = coordinates;
|
||||||
|
this.bbox = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[][][] getCoordinates() {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] getBbox() {
|
||||||
|
return bbox;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
|
public class MultiPoint extends Geometry {
|
||||||
|
private final double[][] coordinates;
|
||||||
|
private final double[] bbox;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public MultiPoint(@JsonProperty("coordinates") double [][] coordinates) {
|
||||||
|
super();
|
||||||
|
this.coordinates = coordinates;
|
||||||
|
this.bbox = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[][] getCoordinates() {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] getBbox() {
|
||||||
|
return bbox;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
|
public class MultiPolygon extends Geometry {
|
||||||
|
private final double[][][][] coordinates;
|
||||||
|
private final double[] bbox;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public MultiPolygon(@JsonProperty("coordinates") double [][][][] coordinates) {
|
||||||
|
super();
|
||||||
|
this.coordinates = coordinates;
|
||||||
|
this.bbox = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[][][][] getCoordinates() {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] getBbox() {
|
||||||
|
return bbox;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
|
public class Point extends Geometry {
|
||||||
|
private final double[] coordinates;
|
||||||
|
private final double[] bbox;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public Point(@JsonProperty("coordinates") double [] coordinates) {
|
||||||
|
super();
|
||||||
|
this.coordinates = coordinates;
|
||||||
|
this.bbox = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] getCoordinates() {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] getBbox() {
|
||||||
|
return bbox;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,27 @@
|
|||||||
|
package org.meteoinfo.geometry.io.geojson;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude.Include;
|
||||||
|
|
||||||
|
@JsonInclude(Include.NON_NULL)
|
||||||
|
public class Polygon extends Geometry {
|
||||||
|
private final double[][][] coordinates;
|
||||||
|
private final double[] bbox;
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public Polygon(@JsonProperty("coordinates") double [][][] coordinates) {
|
||||||
|
super();
|
||||||
|
this.coordinates = coordinates;
|
||||||
|
this.bbox = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[][][] getCoordinates() {
|
||||||
|
return coordinates;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double[] getBbox() {
|
||||||
|
return bbox;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -94,6 +94,7 @@ public class PointZ extends PointD implements Cloneable{
|
|||||||
* To double array
|
* To double array
|
||||||
* @return Double array
|
* @return Double array
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public double[] toArray() {
|
public double[] toArray() {
|
||||||
return new double[]{X, Y, Z};
|
return new double[]{X, Y, Z};
|
||||||
}
|
}
|
||||||
@ -102,6 +103,7 @@ public class PointZ extends PointD implements Cloneable{
|
|||||||
* To float array
|
* To float array
|
||||||
* @return Float array
|
* @return Float array
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public float[] toFloatArray() {
|
public float[] toFloatArray() {
|
||||||
return new float[]{(float) X, (float) Y, (float) Z};
|
return new float[]{(float) X, (float) Y, (float) Z};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -38,6 +38,15 @@ public class PointZShape extends PointShape {
|
|||||||
this.point = new PointZ();
|
this.point = new PointZ();
|
||||||
this.updateExtent((PointZ)this.point);
|
this.updateExtent((PointZ)this.point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param pointZ The PointZ object
|
||||||
|
*/
|
||||||
|
public PointZShape(PointZ pointZ) {
|
||||||
|
this.point = pointZ;
|
||||||
|
this.updateExtent(pointZ);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
|||||||
@ -77,19 +77,6 @@ public class Polygon {
|
|||||||
return this._holeLines;
|
return this._holeLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get hole lines
|
|
||||||
*
|
|
||||||
* @return hole lines
|
|
||||||
*/
|
|
||||||
public List<List<? extends PointD>> getHoleLines_bak() {
|
|
||||||
List<List<? extends PointD>> hlines = new ArrayList<>();
|
|
||||||
for (List<? extends PointD> hline : _holeLines){
|
|
||||||
hlines.add((List<PointD>)hline);
|
|
||||||
}
|
|
||||||
return hlines;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a hole line
|
* Get a hole line
|
||||||
* @param idx Index
|
* @param idx Index
|
||||||
|
|||||||
@ -150,6 +150,14 @@ public class PolygonShape extends Shape implements Cloneable {
|
|||||||
return ShapeTypes.POLYGON;
|
return ShapeTypes.POLYGON;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get is multi polygon or not
|
||||||
|
* @return Multi polygon or not
|
||||||
|
*/
|
||||||
|
public boolean isMultiPolygon() {
|
||||||
|
return this._numParts > 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To geometry method
|
* To geometry method
|
||||||
*
|
*
|
||||||
@ -279,6 +287,15 @@ public class PolygonShape extends Shape implements Cloneable {
|
|||||||
return _polygons;
|
return _polygons;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a polygon
|
||||||
|
* @param index The polygon index
|
||||||
|
* @return The polygon
|
||||||
|
*/
|
||||||
|
public Polygon getPolygon(int index) {
|
||||||
|
return _polygons.get(index);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set polygons
|
* Set polygons
|
||||||
*
|
*
|
||||||
|
|||||||
@ -58,6 +58,14 @@ public class PolylineShape extends Shape implements Cloneable {
|
|||||||
_polylines = new ArrayList<>();
|
_polylines = new ArrayList<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param points Point list
|
||||||
|
*/
|
||||||
|
public PolylineShape(List<PointD> points) {
|
||||||
|
this.setPoints(points);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
*
|
*
|
||||||
@ -109,6 +117,14 @@ public class PolylineShape extends Shape implements Cloneable {
|
|||||||
return ShapeTypes.POLYLINE;
|
return ShapeTypes.POLYLINE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get is multi line or not
|
||||||
|
* @return Multi line or not
|
||||||
|
*/
|
||||||
|
public boolean isMultiLine() {
|
||||||
|
return this._numParts > 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* To geometry method
|
* To geometry method
|
||||||
*
|
*
|
||||||
|
|||||||
@ -41,6 +41,14 @@ public class PolylineZShape extends PolylineShape {
|
|||||||
public PolylineZShape() {
|
public PolylineZShape() {
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor
|
||||||
|
* @param points Points
|
||||||
|
*/
|
||||||
|
public PolylineZShape(List<PointZ> points) {
|
||||||
|
this.setPoints(points);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor
|
* Constructor
|
||||||
|
|||||||
@ -1,32 +1,32 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<MeteoInfo File="milconfig.xml" Type="configurefile">
|
<MeteoInfo File="milconfig.xml" Type="configurefile">
|
||||||
<Path OpenPath="D:\Working\MIScript\Jython\mis\meteo\wrf">
|
<Path OpenPath="D:\Working\MIScript\Jython\mis\io\json">
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\traj"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\jogl"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\3d_earth"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\chart"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\chart\legend"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\wind"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\map\webmap"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\netcdf"/>
|
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\netcdf"/>
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
|
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\meteo"/>
|
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\meteo"/>
|
||||||
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\meteo\wrf"/>
|
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\meteo\wrf"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\ascii"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\plot_types\3d\3d_earth"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript\Jython"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript\cuace_dust"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript\cuace_dust\py"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript\Jython\mis"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\traj"/>
|
||||||
|
<RecentFolder Folder="D:\Working\MIScript\Jython\mis\io\json"/>
|
||||||
</Path>
|
</Path>
|
||||||
<File>
|
<File>
|
||||||
<OpenedFiles>
|
<OpenedFiles>
|
||||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\wind\streamplot_cdata_map_1.py"/>
|
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\json\test_geojson_file_read_write.py"/>
|
||||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\3d_earth\plot_cuace_earth_isosurface_streamline.py"/>
|
<OpenedFile File="D:\Working\MIScript\Jython\mis\traj\hy_conc_geojson.py"/>
|
||||||
<OpenedFile File="D:\Working\MIScript\Jython\mis\meteo\wrf\wrf_destagger_uv_webmap.py"/>
|
<OpenedFile File="D:\Working\MIScript\Jython\mis\io\json\hy_conc_nuclear_geojson.py"/>
|
||||||
</OpenedFiles>
|
</OpenedFiles>
|
||||||
<RecentFiles>
|
<RecentFiles>
|
||||||
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\wind\streamplot_cdata_map_1.py"/>
|
<RecentFile File="D:\Working\MIScript\Jython\mis\io\json\test_geojson_file_read_write.py"/>
|
||||||
<RecentFile File="D:\Working\MIScript\Jython\mis\plot_types\3d\3d_earth\plot_cuace_earth_isosurface_streamline.py"/>
|
<RecentFile File="D:\Working\MIScript\Jython\mis\traj\hy_conc_geojson.py"/>
|
||||||
<RecentFile File="D:\Working\MIScript\Jython\mis\meteo\wrf\wrf_destagger_uv_webmap.py"/>
|
<RecentFile File="D:\Working\MIScript\Jython\mis\io\json\hy_conc_nuclear_geojson.py"/>
|
||||||
</RecentFiles>
|
</RecentFiles>
|
||||||
</File>
|
</File>
|
||||||
<Font>
|
<Font>
|
||||||
@ -34,5 +34,5 @@
|
|||||||
</Font>
|
</Font>
|
||||||
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
|
<LookFeel DockWindowDecorated="true" LafDecorated="true" Name="FlatDarkLaf"/>
|
||||||
<Figure DoubleBuffering="true"/>
|
<Figure DoubleBuffering="true"/>
|
||||||
<Startup MainFormLocation="-7,0" MainFormSize="1383,794"/>
|
<Startup MainFormLocation="-7,0" MainFormSize="1330,805"/>
|
||||||
</MeteoInfo>
|
</MeteoInfo>
|
||||||
|
|||||||
Binary file not shown.
@ -17,6 +17,7 @@ from org.meteoinfo.projection import ProjectionUtil, KnownCoordinateSystems
|
|||||||
from org.meteoinfo.geometry.shape import PolygonShape, ShapeTypes
|
from org.meteoinfo.geometry.shape import PolygonShape, ShapeTypes
|
||||||
from org.meteoinfo.geo.analysis import GeometryUtil
|
from org.meteoinfo.geo.analysis import GeometryUtil
|
||||||
from org.meteoinfo.geo.util import GeoProjectionUtil
|
from org.meteoinfo.geo.util import GeoProjectionUtil
|
||||||
|
from org.meteoinfo.geo.io import GeoJSONReader, GeoJSONWriter
|
||||||
|
|
||||||
|
|
||||||
class MILayer(object):
|
class MILayer(object):
|
||||||
@ -277,6 +278,14 @@ class MILayer(object):
|
|||||||
for shape, field in zip(shapes, fields):
|
for shape, field in zip(shapes, fields):
|
||||||
self._layer.editAddShape(shape, field)
|
self._layer.editAddShape(shape, field)
|
||||||
|
|
||||||
|
def del_shape(self, shape):
|
||||||
|
"""
|
||||||
|
Delete a shape.
|
||||||
|
|
||||||
|
:param shape: (*Shape or int*) The shape or shape index to be deleted.
|
||||||
|
"""
|
||||||
|
self._layer.editRemoveShape(shape)
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
"""
|
"""
|
||||||
Copy the layer.
|
Copy the layer.
|
||||||
@ -547,7 +556,7 @@ class MILayer(object):
|
|||||||
else:
|
else:
|
||||||
self._layer.saveFile(fn, encoding)
|
self._layer.saveFile(fn, encoding)
|
||||||
|
|
||||||
def savekml(self, fn):
|
def save_kml(self, fn):
|
||||||
"""
|
"""
|
||||||
Save layer as KML file.
|
Save layer as KML file.
|
||||||
|
|
||||||
@ -555,7 +564,7 @@ class MILayer(object):
|
|||||||
"""
|
"""
|
||||||
self._layer.saveAsKMLFile(fn)
|
self._layer.saveAsKMLFile(fn)
|
||||||
|
|
||||||
def savebil(self, fn, proj=None):
|
def save_bil(self, fn, proj=None):
|
||||||
"""
|
"""
|
||||||
Save layer as bil file.
|
Save layer as bil file.
|
||||||
|
|
||||||
@ -567,6 +576,27 @@ class MILayer(object):
|
|||||||
else:
|
else:
|
||||||
self._layer.saveFile(fn, proj)
|
self._layer.saveFile(fn, proj)
|
||||||
|
|
||||||
|
def save_geojson(self, fn):
|
||||||
|
"""
|
||||||
|
Save layer as GeoJSON file.
|
||||||
|
|
||||||
|
:param fn: (*str*) GeoJSON file name.
|
||||||
|
"""
|
||||||
|
features = GeoJSONWriter.write(self._layer)
|
||||||
|
with open(fn, 'w') as f:
|
||||||
|
f.write("{\n")
|
||||||
|
f.write(""""type": "FeatureCollection",\n""")
|
||||||
|
f.write(""""features": [\n""")
|
||||||
|
for i in range(features.getNumFeatures()):
|
||||||
|
feature = features.getFeature(i)
|
||||||
|
f.write(feature.toString())
|
||||||
|
if i < features.getNumFeatures() - 1:
|
||||||
|
f.write(",\n")
|
||||||
|
else:
|
||||||
|
f.write("\n")
|
||||||
|
f.write("]\n")
|
||||||
|
f.write("}")
|
||||||
|
|
||||||
|
|
||||||
class MIXYListData():
|
class MIXYListData():
|
||||||
def __init__(self, data=None):
|
def __init__(self, data=None):
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@ -34,7 +34,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<java.version>1.8</java.version>
|
<java.version>1.8</java.version>
|
||||||
<revision>3.7.8</revision>
|
<revision>3.7.9</revision>
|
||||||
<maven.compiler.source>8</maven.compiler.source>
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
<maven.compiler.target>8</maven.compiler.target>
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
<maven.compiler.release>8</maven.compiler.release>
|
<maven.compiler.release>8</maven.compiler.release>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user