/* (c) 2015 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.wms.geojson;
import static org.geoserver.wms.geojson.GeoJsonBuilderFactory.MIME_TYPE;
import java.awt.Rectangle;
import java.io.File;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.util.Map;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import org.apache.commons.io.output.DeferredFileOutputStream;
import org.geoserver.wms.WMSMapContent;
import org.geoserver.wms.map.RawMap;
import org.geoserver.wms.vector.DeferredFileOutputStreamWebMap;
import org.geoserver.wms.vector.VectorTileBuilder;
import org.geotools.geometry.jts.ReferencedEnvelope;
import org.geotools.referencing.CRS;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import com.google.common.base.Charsets;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.PrecisionModel;
import com.vividsolutions.jts.precision.CoordinatePrecisionReducerFilter;
public class GeoJsonWMSBuilder implements VectorTileBuilder {
private Writer writer;
private CoordinatePrecisionReducerFilter precisionReducerFilter;
private DeferredFileOutputStream out;
private org.geoserver.wfs.json.GeoJSONBuilder jsonWriter;
public GeoJsonWMSBuilder(Rectangle mapSize, ReferencedEnvelope mapArea) {
final int memotyBufferThreshold = 8096;
out = new DeferredFileOutputStream(memotyBufferThreshold, "geojson", ".geojson", null);
writer = new OutputStreamWriter(out, Charsets.UTF_8);
jsonWriter = new org.geoserver.wfs.json.GeoJSONBuilder(writer);
jsonWriter.object();// start root object
jsonWriter.key("type").value("FeatureCollection");
jsonWriter.key("totalFeatures").value("unknown");
jsonWriter.key("features");
jsonWriter.array();
CoordinateReferenceSystem mapCrs = mapArea.getCoordinateReferenceSystem();
jsonWriter.setAxisOrder(CRS.getAxisOrder(mapCrs));
Unit<?> unit = mapCrs.getCoordinateSystem().getAxis(0).getUnit();
Unit<?> standardUnit = unit.getStandardUnit();
PrecisionModel pm = null;
if (SI.RADIAN.equals(standardUnit)) {
pm = new PrecisionModel(1e6);// truncate coords at 6 decimals
} else if (SI.METRE.equals(standardUnit)) {
pm = new PrecisionModel(100);// truncate coords at 2 decimals
}
if (pm != null) {
precisionReducerFilter = new CoordinatePrecisionReducerFilter(pm);
}
}
@Override
public void addFeature(String layerName, String featureId, String geometryName, Geometry aGeom,
Map<String, Object> properties) {
if (precisionReducerFilter != null) {
aGeom.apply(precisionReducerFilter);
}
jsonWriter.object();
jsonWriter.key("type").value("Feature");
jsonWriter.key("id").value(featureId);
jsonWriter.key("geometry");
// Write the geometry, whether it is a null or not
jsonWriter.writeGeom(aGeom);
jsonWriter.key("geometry_name").value(geometryName);
jsonWriter.key("properties");
jsonWriter.object();
for (Map.Entry<String, Object> e : properties.entrySet()) {
String attributeName = e.getKey();
Object value = e.getValue();
jsonWriter.key(attributeName);
if (value == null) {
jsonWriter.value(null);
} else {
jsonWriter.value(value);
}
}
jsonWriter.endObject(); // end the properties
jsonWriter.endObject(); // end the feature
}
@Override
public RawMap build(WMSMapContent mapContent) throws IOException {
jsonWriter.endArray(); // end features
jsonWriter.endObject();// end root object
writer.flush();
writer.close();
out.close();
long length;
RawMap map;
if (out.isInMemory()) {
byte[] data = out.getData();
length = data.length;
map = new RawMap(mapContent, data, MIME_TYPE);
} else {
File f = out.getFile();
length = f.length();
map = new DeferredFileOutputStreamWebMap(mapContent, out, MIME_TYPE);
}
map.setResponseHeader("Content-Length", String.valueOf(length));
return map;
}
}