From 11dd64c11194dbb0a4c13578e651b64b3476efe5 Mon Sep 17 00:00:00 2001 From: Tim Schaub Date: Sun, 16 Sep 2012 23:06:44 -0600 Subject: [PATCH] Consistent projection handling (closes #26) --- .../org/geoscript/js/feature/Feature.java | 54 +++++++++-------- .../java/org/geoscript/js/feature/Field.java | 4 +- .../java/org/geoscript/js/feature/Schema.java | 11 +++- .../java/org/geoscript/js/geom/Geometry.java | 9 ++- .../org/geoscript/js/proj/Projection.java | 2 +- .../tests/geoscript/feature/test_feature.js | 60 ++++++++++++++++++- .../js/tests/geoscript/geom/test_point.js | 32 ++++++++++ .../js/tests/geoscript/layer/common.js | 23 +++++++ 8 files changed, 163 insertions(+), 32 deletions(-) diff --git a/src/main/java/org/geoscript/js/feature/Feature.java b/src/main/java/org/geoscript/js/feature/Feature.java index 86dcd547..bb8c5584 100644 --- a/src/main/java/org/geoscript/js/feature/Feature.java +++ b/src/main/java/org/geoscript/js/feature/Feature.java @@ -3,7 +3,6 @@ import org.geoscript.js.GeoObject; import org.geoscript.js.geom.Bounds; import org.geoscript.js.geom.Geometry; -import org.geoscript.js.geom.GeometryWrapper; import org.geoscript.js.proj.Projection; import org.geotools.feature.simple.SimpleFeatureBuilder; import org.mozilla.javascript.Context; @@ -23,6 +22,7 @@ import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.feature.type.AttributeDescriptor; +import org.opengis.feature.type.GeometryDescriptor; import org.opengis.referencing.crs.CoordinateReferenceSystem; public class Feature extends GeoObject implements Wrapper { @@ -35,11 +35,6 @@ public class Feature extends GeoObject implements Wrapper { */ private SimpleFeature feature; - /** - * Optional coordinate reference system for the feature. - */ - CoordinateReferenceSystem crs; - /** * Layer from which this feature was accessed. Used to persist * modifications. @@ -158,36 +153,29 @@ public String getGeometryName() { @JSGetter public Geometry getGeometry() { - Geometry jsGeom = null; - com.vividsolutions.jts.geom.Geometry geometry = - (com.vividsolutions.jts.geom.Geometry) feature.getDefaultGeometry(); - if (geometry != null) { - jsGeom = (Geometry) GeometryWrapper.wrap(getParentScope(), geometry); - jsGeom.setProjection(getProjection()); - } - return jsGeom; + String name = getGeometryName(); + return (Geometry) get(name); } @JSSetter public void setGeometry(Geometry geometry) { String name = getGeometryName(); + if (name == null) { + throw ScriptRuntime.constructError("Error", "Feature schema has no geometry field"); + } set(name, geometry); } - @JSSetter - public void setProjection(Projection projection) { - CoordinateReferenceSystem crs = null; - if (projection != null) { - crs = projection.unwrap(); - } - this.crs = crs; - } - @JSGetter public Projection getProjection() { Projection projection = null; - if (crs != null) { - projection = new Projection(getParentScope(), crs); + SimpleFeatureType featureType = feature.getFeatureType(); + GeometryDescriptor descriptor = featureType.getGeometryDescriptor(); + if (descriptor != null) { + CoordinateReferenceSystem crs = descriptor.getCoordinateReferenceSystem(); + if (crs != null) { + projection = new Projection(getParentScope(), crs); + } } return projection; } @@ -219,7 +207,18 @@ public Feature set(String name, Object value) { if (!(value instanceof Geometry)) { throw ScriptRuntime.constructError("Error", "Attempted to set geometry property to a non-geometry object: " + Context.toString(value)); } - setProjection(((Geometry) value).getProjection()); + Projection featureProj = getProjection(); + Geometry geometry = (Geometry) value; + Projection geomProj = geometry.getProjection(); + if (featureProj != null) { + if (geomProj != null) { + if (!featureProj.equals(geometry.getProjection())) { + value = geometry.transform(featureProj); + } + } + } else if (geomProj != null) { + throw ScriptRuntime.constructError("Error", "Cannot add a geometry with a projection to a feature without a projection"); + } } feature.setAttribute(name, jsToJava(value)); if (layer != null) { @@ -244,6 +243,9 @@ public Object get(String name) { value = Context.getUndefinedValue(); } else { value = javaToJS(feature.getAttribute(name), getParentScope()); + if (value instanceof Geometry) { + ((Geometry) value).setProjection(getProjection()); + } } return value; } diff --git a/src/main/java/org/geoscript/js/feature/Field.java b/src/main/java/org/geoscript/js/feature/Field.java index 219cab1f..97633ed2 100644 --- a/src/main/java/org/geoscript/js/feature/Field.java +++ b/src/main/java/org/geoscript/js/feature/Field.java @@ -192,7 +192,9 @@ public Projection getProjection() { Projection projection = null; if (descriptor instanceof GeometryDescriptor) { CoordinateReferenceSystem crs = ((GeometryDescriptor) descriptor).getCoordinateReferenceSystem(); - projection = new Projection(getParentScope(), crs); + if (crs != null) { + projection = new Projection(getParentScope(), crs); + } } return projection; } diff --git a/src/main/java/org/geoscript/js/feature/Schema.java b/src/main/java/org/geoscript/js/feature/Schema.java index 9eba26ed..1c39c3d5 100644 --- a/src/main/java/org/geoscript/js/feature/Schema.java +++ b/src/main/java/org/geoscript/js/feature/Schema.java @@ -3,6 +3,8 @@ import java.util.List; import org.geoscript.js.GeoObject; +import org.geoscript.js.geom.Geometry; +import org.geoscript.js.proj.Projection; import org.geotools.feature.NameImpl; import org.geotools.feature.simple.SimpleFeatureTypeBuilder; import org.mozilla.javascript.Context; @@ -217,7 +219,8 @@ public static Schema fromValues(Scriptable scope, NativeObject values) { Scriptable fields = cx.newArray(scope, names.length); for (int i=0; i