From f98459f76cd054a5207a16d209840d7ccedd3816 Mon Sep 17 00:00:00 2001 From: AlexisDrogoul Date: Tue, 4 May 2021 13:26:21 +0700 Subject: [PATCH] Factorisation of some operations in GIS files. Addition of the "dimension" to CoordinateSequences to comply with GeoTools and JTS. --- .../database/geosql/GamaSqlConnection.java | 15 +- .../geometry/GamaCoordinateSequence.java | 42 ++--- .../GamaCoordinateSequenceFactory.java | 28 +-- .../gama/common/geometry/ICoordinates.java | 11 +- .../geometry/UnboundedCoordinateSequence.java | 42 ++--- .../geometry/UniqueCoordinateSequence.java | 28 +-- .../topology/projection/Projection.java | 45 ++--- .../src/msi/gama/util/file/GamaGMLFile.java | 100 +---------- .../msi/gama/util/file/GamaGeoJsonFile.java | 66 +------ .../src/msi/gama/util/file/GamaGisFile.java | 114 +++++++++--- .../src/msi/gama/util/file/GamaGridFile.java | 70 +++----- .../src/msi/gama/util/file/GamaOsmFile.java | 105 +++++------ .../src/msi/gama/util/file/GamaSVGFile.java | 21 +-- .../src/msi/gama/util/file/GamaShapeFile.java | 164 +++++++++--------- 14 files changed, 358 insertions(+), 493 deletions(-) diff --git a/irit.gaml.extensions.database/src/msi/gama/database/geosql/GamaSqlConnection.java b/irit.gaml.extensions.database/src/msi/gama/database/geosql/GamaSqlConnection.java index da6160fb15..ab232df410 100644 --- a/irit.gaml.extensions.database/src/msi/gama/database/geosql/GamaSqlConnection.java +++ b/irit.gaml.extensions.database/src/msi/gama/database/geosql/GamaSqlConnection.java @@ -14,14 +14,13 @@ import org.geotools.filter.text.ecql.ECQL; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.jdbc.JDBCDataStoreFactory; +import org.locationtech.jts.geom.Geometry; import org.opengis.feature.Feature; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.feature.type.GeometryType; import org.opengis.filter.Filter; import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.locationtech.jts.geom.Geometry; - import msi.gama.common.geometry.Envelope3D; import msi.gama.common.util.FileUtils; import msi.gama.metamodel.shape.GamaGisGeometry; @@ -142,7 +141,7 @@ public DataStore Connect(final IScope scope) throws Exception { dStore = DataStoreFinder.getDataStore(connectionParameters); // get // connection // DEBUG.LOG("data store postgress:" + dStore); - if (dStore == null) { throw new IOException("Can't connect to " + database); } + if (dStore == null) throw new IOException("Can't connect to " + database); return dStore; } @@ -152,9 +151,8 @@ public DataStore Connect(final IScope scope) throws Exception { public void close(final IScope scope) throws GamaRuntimeException { if (dataStore != null) { dataStore.dispose(); - } else { + } else throw GamaRuntimeException.error("The connection to " + this.database + " is not opened ", scope); - } } public void setDataStore(final DataStore dataStore) { @@ -208,7 +206,7 @@ private void readTable(final IScope scope, final String tableName, final String */ @Override protected void fillBuffer(final IScope scope) throws GamaRuntimeException { - if (getBuffer() != null) { return; } + if (getBuffer() != null) return; setBuffer(GamaListFactory. create(Types.GEOMETRY)); readTable(scope); } @@ -291,4 +289,9 @@ public SimpleFeatureCollection getRecordSet() { } }// end of class QueryInfo + @Override + protected SimpleFeatureCollection getFeatureCollection(final IScope scope) { + return null; + } + } diff --git a/msi.gama.core/src/msi/gama/common/geometry/GamaCoordinateSequence.java b/msi.gama.core/src/msi/gama/common/geometry/GamaCoordinateSequence.java index 45c999b2a0..0225188eca 100644 --- a/msi.gama.core/src/msi/gama/common/geometry/GamaCoordinateSequence.java +++ b/msi.gama.core/src/msi/gama/common/geometry/GamaCoordinateSequence.java @@ -11,14 +11,13 @@ package msi.gama.common.geometry; import static com.google.common.collect.Iterators.forArray; -import static org.locationtech.jts.algorithm.CGAlgorithms.signedArea; import static msi.gama.common.geometry.GamaGeometryFactory.isRing; +import static org.locationtech.jts.algorithm.CGAlgorithms.signedArea; import java.util.Arrays; import java.util.Iterator; import org.apache.commons.lang.ArrayUtils; - import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Envelope; @@ -35,6 +34,8 @@ public class GamaCoordinateSequence implements ICoordinates { + final int dimension; + /** * The final array of GamaPoint, considered to be internally mutable (i.e. points can be changed inside) */ @@ -48,8 +49,8 @@ public class GamaCoordinateSequence implements ICoordinates { * @param points2 * an array of points */ - GamaCoordinateSequence(final Coordinate... points2) { - this(true, points2); + GamaCoordinateSequence(final int dimension, final Coordinate... points2) { + this(dimension, true, points2); } /** @@ -62,7 +63,8 @@ public class GamaCoordinateSequence implements ICoordinates { * @param points2 * an array of points */ - GamaCoordinateSequence(final boolean copy, final Coordinate... points2) { + GamaCoordinateSequence(final int dimension, final boolean copy, final Coordinate... points2) { + this.dimension = dimension; if (copy) { final int size = points2.length; points = new GamaPoint[size]; @@ -81,7 +83,8 @@ public class GamaCoordinateSequence implements ICoordinates { * @param size * an int > 0 (negative sizes will be treated as 0) */ - GamaCoordinateSequence(final int size) { + GamaCoordinateSequence(final int dimension, final int size) { + this.dimension = dimension; points = new GamaPoint[size < 0 ? 0 : size]; for (int i = 0; i < size; i++) { points[i] = new GamaPoint(0d, 0d, 0d); @@ -95,7 +98,7 @@ public class GamaCoordinateSequence implements ICoordinates { */ @Override public int getDimension() { - return 3; + return dimension; } /** @@ -103,9 +106,10 @@ public int getDimension() { */ @Override public final GamaCoordinateSequence copy() { - return new GamaCoordinateSequence(true, points); + return new GamaCoordinateSequence(dimension, true, points); } - + + @Override @Deprecated public GamaCoordinateSequence clone() { return copy(); @@ -257,7 +261,7 @@ public ICoordinates yNegated() { // CW property is ensured by reversing the resulting array points2[i] = points[size - i - 1].yNegated(); } - return new GamaCoordinateSequence(false, points2); + return new GamaCoordinateSequence(dimension, false, points2); } @Override @@ -314,7 +318,7 @@ public void visit(final PairVisitor v) { @Override public void getNormal(final boolean clockwise, final double factor, final GamaPoint normal) { normal.setLocation(0, 0, 0); - if (points.length < 3) { return; } + if (points.length < 3) return; for (int i = 0; i < points.length - 1; i++) { final GamaPoint v0 = points[i]; final GamaPoint v1 = points[i + 1]; @@ -343,7 +347,7 @@ public Envelope3D getEnvelopeInto(final Envelope3D envelope) { @Override public double averageZ() { double sum = 0d; - if (points.length == 0) { return sum; } + if (points.length == 0) return sum; for (final GamaPoint p : points) { sum += p.z; } @@ -395,7 +399,7 @@ public void applyRotation(final Rotation3D rotation) { @Override public void replaceWith(final int i, final double x, final double y, final double z) { - if (i < 0 || i >= points.length) { return; } + if (i < 0 || i >= points.length) return; points[i].setLocation(x, y, z); } @@ -404,7 +408,7 @@ public void replaceWith(final int i, final double x, final double y, final doubl public boolean isHorizontal() { final double z = points[0].z; for (int i = 1; i < points.length; i++) { - if (points[i].z != z) { return false; } + if (points[i].z != z) return false; } return true; } @@ -429,7 +433,7 @@ public void setAllZ(final double elevation) { @Override public boolean isCoveredBy(final Envelope3D env) { for (final GamaPoint point : points) { - if (!env.covers(point)) { return false; } + if (!env.covers(point)) return false; } return true; } @@ -484,15 +488,13 @@ public void translateBy(final double x, final double y, final double z) { */ @Override public void ensureClockwiseness() { - if (!isRing(points)) { return; } - if (signedArea(points) <= 0) { - ArrayUtils.reverse(points); - } + if (!isRing(points)) return; + if (signedArea(points) <= 0) { ArrayUtils.reverse(points); } } @Override public boolean equals(final Object object) { - if (!(object instanceof GamaCoordinateSequence)) { return false; } + if (!(object instanceof GamaCoordinateSequence)) return false; final GamaCoordinateSequence other = (GamaCoordinateSequence) object; return Arrays.equals(points, other.points); } diff --git a/msi.gama.core/src/msi/gama/common/geometry/GamaCoordinateSequenceFactory.java b/msi.gama.core/src/msi/gama/common/geometry/GamaCoordinateSequenceFactory.java index 325fecaba7..67f4fa9147 100644 --- a/msi.gama.core/src/msi/gama/common/geometry/GamaCoordinateSequenceFactory.java +++ b/msi.gama.core/src/msi/gama/common/geometry/GamaCoordinateSequenceFactory.java @@ -6,7 +6,7 @@ * (c) 2007-2020 UMI 209 UMMISCO IRD/SU & Partners * * Visit https://github.com/gama-platform/gama for license information and contacts. - * + * ********************************************************************************************************/ package msi.gama.common.geometry; @@ -20,41 +20,41 @@ public class GamaCoordinateSequenceFactory implements CoordinateSequenceFactory /** * Method create() - * + * * @see org.locationtech.jts.geom.CoordinateSequenceFactory#create(org.locationtech.jts.geom.Coordinate[]) */ @Override public ICoordinates create(final Coordinate[] coordinates) { - if (coordinates.length == 1) { return new UniqueCoordinateSequence(coordinates[0]); } - return new GamaCoordinateSequence(coordinates); + if (coordinates.length == 1) return new UniqueCoordinateSequence(3, coordinates[0]); + return new GamaCoordinateSequence(3, coordinates); } public ICoordinates create(final GamaPoint[] coordinates, final boolean copy) { - if (coordinates.length == 1) { return new UniqueCoordinateSequence(coordinates[0]); } - return new GamaCoordinateSequence(copy, coordinates); + if (coordinates.length == 1) return new UniqueCoordinateSequence(3, coordinates[0]); + return new GamaCoordinateSequence(3, copy, coordinates); } /** * Method create() - * + * * @see org.locationtech.jts.geom.CoordinateSequenceFactory#create(org.locationtech.jts.geom.CoordinateSequence) */ @Override - public ICoordinates create(final CoordinateSequence coordSeq) { - if (coordSeq.size() == 1) { return new UniqueCoordinateSequence(coordSeq.getCoordinate(0)); } - if (coordSeq instanceof GamaCoordinateSequence) { return ((GamaCoordinateSequence) coordSeq).clone(); } - return new GamaCoordinateSequence(coordSeq.toCoordinateArray()); + public ICoordinates create(final CoordinateSequence cs) { + if (cs.size() == 1) return new UniqueCoordinateSequence(cs.getDimension(), cs.getCoordinate(0)); + if (cs instanceof GamaCoordinateSequence) return ((GamaCoordinateSequence) cs).clone(); + return new GamaCoordinateSequence(cs.getDimension(), cs.toCoordinateArray()); } /** * Method create() - * + * * @see org.locationtech.jts.geom.CoordinateSequenceFactory#create(int, int) */ @Override public ICoordinates create(final int size, final int dimension) { - if (size == 1) { return new UniqueCoordinateSequence(new GamaPoint()); } - return new GamaCoordinateSequence(size); + if (size == 1) return new UniqueCoordinateSequence(dimension, new GamaPoint()); + return new GamaCoordinateSequence(dimension, size); } } \ No newline at end of file diff --git a/msi.gama.core/src/msi/gama/common/geometry/ICoordinates.java b/msi.gama.core/src/msi/gama/common/geometry/ICoordinates.java index fcd581931b..14f40a3226 100644 --- a/msi.gama.core/src/msi/gama/common/geometry/ICoordinates.java +++ b/msi.gama.core/src/msi/gama/common/geometry/ICoordinates.java @@ -45,7 +45,7 @@ public interface VertexVisitor { /** * The empty coordinate sequence */ - ICoordinates EMPTY = new GamaCoordinateSequence(new GamaPoint[] {}); + ICoordinates EMPTY = new GamaCoordinateSequence(3, new GamaPoint[] {}); /** * Returns the geometric center of this sequence of points @@ -62,9 +62,10 @@ default void getCenter(final GamaPoint center) { center.setLocation(0, 0, 0); addCenterTo(center); } - + + @Override @Deprecated - default CoordinateSequence clone() { + default CoordinateSequence clone() { return copy(); } @@ -86,7 +87,7 @@ default CoordinateSequence clone() { * @return a point or null */ default GamaPoint at(final int i) { - if (i > size() || i < 0) { return null; } + if (i > size() || i < 0) return null; return getCoordinate(i); } @@ -175,7 +176,7 @@ default GamaPoint getNormal(final boolean clockwise) { final GamaPoint normal = new GamaPoint(); getNormal(clockwise, 1, normal); return normal; - }; + } /** * Computes the normal to this sequence, multiplying the resulting unit vector by a given factor, and fills the diff --git a/msi.gama.core/src/msi/gama/common/geometry/UnboundedCoordinateSequence.java b/msi.gama.core/src/msi/gama/common/geometry/UnboundedCoordinateSequence.java index 5e582350ef..a8e51b058a 100644 --- a/msi.gama.core/src/msi/gama/common/geometry/UnboundedCoordinateSequence.java +++ b/msi.gama.core/src/msi/gama/common/geometry/UnboundedCoordinateSequence.java @@ -23,6 +23,7 @@ public class UnboundedCoordinateSequence implements ICoordinates { + final int dimension; final static int INITIAL_SIZE = 1000; GamaPoint[] points = null; int nbPoints; @@ -35,6 +36,11 @@ private void fillFrom(final int begin) { } public UnboundedCoordinateSequence() { + this(3); + } + + public UnboundedCoordinateSequence(final int dimension) { + this.dimension = dimension; growTo(INITIAL_SIZE); } @@ -43,7 +49,7 @@ private void growTo(final int size) { if (points == null) { points = new GamaPoint[size]; } else { - if (size <= points.length) { return; } + if (size <= points.length) return; begin = points.length; points = Arrays.copyOf(points, Math.max(size, begin + begin / 2)); } @@ -55,22 +61,22 @@ public int getDimension() { return 3; } - UnboundedCoordinateSequence(final boolean copy, final int size, final GamaPoint[] points2) { + UnboundedCoordinateSequence(final int dimension, final boolean copy, final int size, final GamaPoint[] points2) { + this.dimension = dimension; growTo(size); nbPoints = size; for (int i = 0; i < size; i++) { points[i].setLocation(points2[i]); } - if (copy) { - ensureClockwiseness(); - } + if (copy) { ensureClockwiseness(); } } @Override public final UnboundedCoordinateSequence copy() { - return new UnboundedCoordinateSequence(true, nbPoints, points); + return new UnboundedCoordinateSequence(dimension, true, nbPoints, points); } + @Override @Deprecated public UnboundedCoordinateSequence clone() { return copy(); @@ -156,7 +162,7 @@ public ICoordinates yNegated() { // CW property is ensured by reversing the resulting array points2[i] = points[size - i - 1].yNegated(); } - return new GamaCoordinateSequence(false, points2); + return new GamaCoordinateSequence(dimension, false, points2); } @@ -220,7 +226,7 @@ public void visit(final PairVisitor v) { @Override public void getNormal(final boolean clockwise, final double factor, final GamaPoint normal) { normal.setLocation(0, 0, 0); - if (nbPoints < 3) { return; } + if (nbPoints < 3) return; for (int i = 0; i < nbPoints - 1; i++) { final GamaPoint v0 = points[i]; final GamaPoint v1 = points[i + 1]; @@ -249,7 +255,7 @@ public Envelope3D getEnvelopeInto(final Envelope3D envelope) { @Override public double averageZ() { double sum = 0d; - if (nbPoints == 0) { return sum; } + if (nbPoints == 0) return sum; for (int i = 0; i < nbPoints; i++) { sum += points[i].z; } @@ -279,7 +285,7 @@ public ICoordinates setTo(final double... points2) { @Override public void replaceWith(final int i, final double x, final double y, final double z) { - if (i < 0 || i >= nbPoints) { return; } + if (i < 0 || i >= nbPoints) return; points[i].setLocation(x, y, z); } @@ -308,7 +314,7 @@ public void applyRotation(final Rotation3D rotation) { public boolean isHorizontal() { final double z = points[0].z; for (int i = 1; i < nbPoints; i++) { - if (points[i].z != z) { return false; } + if (points[i].z != z) return false; } return true; } @@ -332,7 +338,7 @@ public void setAllZ(final double elevation) { @Override public boolean isCoveredBy(final Envelope3D envelope3d) { for (int i = 0; i < nbPoints; i++) { - if (!envelope3d.covers(points[i])) { return false; } + if (!envelope3d.covers(points[i])) return false; } return true; } @@ -357,18 +363,16 @@ public void translateBy(final double i, final double j, final double k) { @Override public void ensureClockwiseness() { - if (isRing() && signedArea() <= 0) { - reverse(); - } + if (isRing() && signedArea() <= 0) { reverse(); } } public boolean isRing() { - if (nbPoints < 4) { return false; } + if (nbPoints < 4) return false; return points[0].equals(points[nbPoints - 1]); } public double signedArea() { - if (nbPoints < 3) { return 0.0; } + if (nbPoints < 3) return 0.0; double sum = 0.0; /** * Based on the Shoelace formula. http://en.wikipedia.org/wiki/Shoelace_formula @@ -390,9 +394,7 @@ public void setToYNegated(final ICoordinates other) { for (final GamaPoint p : other) { points[i++].setLocation(p.x, -p.y, p.z); } - if (isRing()) { - reverse(); - } + if (isRing()) { reverse(); } } public void setTo(final ICoordinates other) { diff --git a/msi.gama.core/src/msi/gama/common/geometry/UniqueCoordinateSequence.java b/msi.gama.core/src/msi/gama/common/geometry/UniqueCoordinateSequence.java index df06ba1b2a..9b70945be2 100644 --- a/msi.gama.core/src/msi/gama/common/geometry/UniqueCoordinateSequence.java +++ b/msi.gama.core/src/msi/gama/common/geometry/UniqueCoordinateSequence.java @@ -12,10 +12,11 @@ import java.util.Iterator; -import com.google.common.collect.Iterators; import org.locationtech.jts.geom.Coordinate; import org.locationtech.jts.geom.Envelope; +import com.google.common.collect.Iterators; + import msi.gama.metamodel.shape.GamaPoint; /** @@ -27,18 +28,21 @@ public class UniqueCoordinateSequence implements ICoordinates { final GamaPoint point; + final int dimension; - public UniqueCoordinateSequence(final Coordinate coord) { + public UniqueCoordinateSequence(final int dimension, final Coordinate coord) { + this.dimension = dimension; point = new GamaPoint(coord); } - public UniqueCoordinateSequence(final boolean copy, final GamaPoint gamaPoint) { + public UniqueCoordinateSequence(final int dimension, final boolean copy, final GamaPoint gamaPoint) { + this.dimension = dimension; point = gamaPoint; } @Override public int getDimension() { - return 3; + return dimension; } @Override @@ -103,23 +107,23 @@ public Iterator iterator() { @Override public ICoordinates yNegated() { - return new UniqueCoordinateSequence(false, point.yNegated()); + return new UniqueCoordinateSequence(dimension, false, point.yNegated()); } @Override public final UniqueCoordinateSequence copy() { - return new UniqueCoordinateSequence(new GamaPoint(point)); + return new UniqueCoordinateSequence(dimension, new GamaPoint(point)); } - + + @Override @Deprecated public UniqueCoordinateSequence clone() { return copy(); } - @Override public void visit(final IndexedVisitor v, final int max, final boolean reversed) { - if (max == 0) { return; } + if (max == 0) return; v.process(0, point.x, point.y, point.z); } @@ -140,7 +144,7 @@ public double averageZ() { @Override public ICoordinates setTo(final GamaPoint... points) { - if (points.length == 0) { return this; } + if (points.length == 0) return this; final GamaPoint p = points[0]; point.x = p.x; point.y = p.y; @@ -150,7 +154,7 @@ public ICoordinates setTo(final GamaPoint... points) { @Override public ICoordinates setTo(final double... points) { - if (points.length < 3) { return this; } + if (points.length < 3) return this; point.x = points[0]; point.y = points[1]; point.z = points[2]; @@ -181,7 +185,7 @@ public void applyRotation(final Rotation3D rotation) { @Override public void replaceWith(final int i, final double x, final double y, final double z) { - if (i != 0) { return; } + if (i != 0) return; point.setLocation(x, y, z); } diff --git a/msi.gama.core/src/msi/gama/metamodel/topology/projection/Projection.java b/msi.gama.core/src/msi/gama/metamodel/topology/projection/Projection.java index a15fcc38ed..9d4e0cbc63 100644 --- a/msi.gama.core/src/msi/gama/metamodel/topology/projection/Projection.java +++ b/msi.gama.core/src/msi/gama/metamodel/topology/projection/Projection.java @@ -14,15 +14,14 @@ import org.geotools.geometry.jts.GeometryCoordinateSequenceTransformer; import org.geotools.geometry.jts.JTS; import org.geotools.referencing.CRS; +import org.locationtech.jts.geom.Geometry; +import org.locationtech.jts.geom.GeometryCollection; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.NoninvertibleTransformException; import org.opengis.referencing.operation.TransformException; -import org.locationtech.jts.geom.Geometry; -import org.locationtech.jts.geom.GeometryCollection; - import msi.gama.common.geometry.Envelope3D; import msi.gama.common.geometry.GeometryUtils; import msi.gama.runtime.IScope; @@ -46,7 +45,7 @@ public class Projection implements IProjection { this.referenceProjection = world; initialCRS = crs; if (env != null) { - if (initialCRS != null && ! initialCRS.equals(getTargetCRS(scope))) { + if (initialCRS != null && !initialCRS.equals(getTargetCRS(scope))) { createTransformation(computeProjection(scope)); } // We project the envelope and we use it for initializing the translations @@ -75,25 +74,15 @@ public void createTransformation(final MathTransform t) { @Override public Geometry transform(final Geometry g) { // Remove uselessly complicated multigeometries - if (g instanceof GeometryCollection && g.getNumGeometries() == 1) { return transform(g.getGeometryN(0)); } - Geometry geom = GeometryUtils.GEOMETRY_FACTORY.createGeometry(g); - if (transformer != null) { - try { - geom = transformer.transform(geom); - } catch (final TransformException e) { - e.printStackTrace(); - } - } - translate(geom); - convertUnit(geom); - return geom; + if (g instanceof GeometryCollection && g.getNumGeometries() == 1) return transform(g.getGeometryN(0)); + return transform(g, true); } public Geometry transform(final Geometry g, final boolean translate) { Geometry geom = GeometryUtils.GEOMETRY_FACTORY.createGeometry(g); if (transformer != null) { try { - geom = transformer.transform(g); + geom = transformer.transform(geom); } catch (final TransformException e) { e.printStackTrace(); } @@ -106,7 +95,7 @@ public Geometry transform(final Geometry g, final boolean translate) { } Envelope3D transform(final Envelope3D g) { - if (transformer == null) { return g; } + if (transformer == null) return g; return Envelope3D.of(transform(JTS.toGeometry(g)).getEnvelopeInternal()); } @@ -127,7 +116,7 @@ public Geometry inverseTransform(final Geometry g) { MathTransform computeProjection(final IScope scope) { MathTransform crsTransformation = null; - if (initialCRS == null) { return null; } + if (initialCRS == null) return null; try { crsTransformation = CRS.findMathTransform(initialCRS, getTargetCRS(scope), true); } catch (final FactoryException e) { @@ -154,7 +143,7 @@ public Envelope3D getProjectedEnvelope() { */ @Override public CoordinateReferenceSystem getTargetCRS(final IScope scope) { - if (referenceProjection != null) { return referenceProjection.getTargetCRS(scope); } + if (referenceProjection != null) return referenceProjection.getTargetCRS(scope); return factory.getTargetCRS(scope); } @@ -165,9 +154,7 @@ public CoordinateReferenceSystem getTargetCRS(final IScope scope) { */ @Override public void translate(final Geometry geom) { - if (referenceProjection != null) { - referenceProjection.translate(geom); - } + if (referenceProjection != null) { referenceProjection.translate(geom); } } /** @@ -177,24 +164,18 @@ public void translate(final Geometry geom) { */ @Override public void inverseTranslate(final Geometry geom) { - if (referenceProjection != null) { - referenceProjection.inverseTranslate(geom); - } + if (referenceProjection != null) { referenceProjection.inverseTranslate(geom); } } @Override public void convertUnit(final Geometry geom) { - if (referenceProjection != null) { - referenceProjection.convertUnit(geom); - } + if (referenceProjection != null) { referenceProjection.convertUnit(geom); } } @Override public void inverseConvertUnit(final Geometry geom) { - if (referenceProjection != null) { - referenceProjection.inverseConvertUnit(geom); - } + if (referenceProjection != null) { referenceProjection.inverseConvertUnit(geom); } } diff --git a/msi.gama.core/src/msi/gama/util/file/GamaGMLFile.java b/msi.gama.core/src/msi/gama/util/file/GamaGMLFile.java index 07c2929234..684c4a5c1a 100644 --- a/msi.gama.core/src/msi/gama/util/file/GamaGMLFile.java +++ b/msi.gama.core/src/msi/gama/util/file/GamaGMLFile.java @@ -15,27 +15,21 @@ import javax.xml.parsers.ParserConfigurationException; +import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.wfs.GML; import org.geotools.wfs.GML.Version; -import org.locationtech.jts.geom.Geometry; -import org.opengis.feature.Feature; -import org.opengis.referencing.crs.CoordinateReferenceSystem; import org.xml.sax.SAXException; import msi.gama.common.geometry.Envelope3D; -import msi.gama.metamodel.shape.GamaGisGeometry; -import msi.gama.metamodel.shape.IShape; import msi.gama.precompiler.GamlAnnotations.doc; import msi.gama.precompiler.GamlAnnotations.example; import msi.gama.precompiler.GamlAnnotations.file; import msi.gama.precompiler.IConcept; -import msi.gama.runtime.GAMA; import msi.gama.runtime.IScope; import msi.gama.runtime.exceptions.GamaRuntimeException; import msi.gama.util.GamaListFactory; import msi.gama.util.IList; import msi.gaml.types.IType; -import msi.gaml.types.Types; /** * Written by drogoul Modified on 13 nov. 2011 @@ -54,10 +48,6 @@ @SuppressWarnings ({ "unchecked" }) public class GamaGMLFile extends GamaGisFile { - CoordinateReferenceSystem crs = null; - IList shapes = null; - Envelope3D env = null; - /** * @throws GamaRuntimeException * @param scope @@ -123,97 +113,21 @@ public GamaGMLFile(final IScope scope, final String pathName, final String code, super(scope, pathName, code, with3D); } - /** - * @see msi.gama.util.GamaFile#fillBuffer() - */ - @Override - protected void fillBuffer(final IScope scope) throws GamaRuntimeException { - if (getBuffer() != null) { return; } - setBuffer(GamaListFactory. create(Types.GEOMETRY)); - readShapes(scope); - for (final IShape shape : shapes) { - getBuffer().add(shape); - } - shapes.clear(); - } - @Override public IList getAttributes(final IScope scope) { return GamaListFactory.EMPTY_LIST; } @Override - protected CoordinateReferenceSystem getOwnCRS(final IScope scope) { - // PROBLEM: how to get the crs of the file? - return crs; - } - - protected void readShapes(final IScope scope) { - scope.getGui().getStatus(scope).beginSubStatus("Reading file " + getName(scope)); - final var file = getFile(scope); - shapes = GamaListFactory.create(Types.GEOMETRY); - var size = 0; + protected SimpleFeatureCollection getFeatureCollection(final IScope scope) { + final var gml = new GML(Version.GML3); try { - - final var gml = new GML(Version.GML3); - final var collection = gml.decodeFeatureCollection(new FileInputStream(file)); - crs = collection.getSchema().getCoordinateReferenceSystem(); - env = Envelope3D.of(collection.getBounds()); - size = collection.size(); - var index = 0; - computeProjection(scope, env); - - final var it = collection.features(); - while (it.hasNext()) { - index++; - if (index % 20 == 0) { - scope.getGui().getStatus(scope).setSubStatusCompletion(index / (double) size); - } - final Feature feature = it.next(); - - var g = (Geometry) feature.getDefaultGeometryProperty().getValue(); - if (g != null && !g.isEmpty() /* Fix for Issue 725 && 677 */ ) { - - g = gis.transform(g); - if (!with3D) { - g.apply(ZERO_Z); - g.geometryChanged(); - } - - g = multiPolygonManagement(g); - shapes.add(new GamaGisGeometry(g, feature)); - } else if (g == null) { - // See Issue 725 - GAMA.reportError(scope, - GamaRuntimeException - .warning("GamaShapeFile.fillBuffer; geometry could not be added as it is " - + "nil: " + feature.getIdentifier(), scope), - false); - } - } - - } catch (final IOException e) { - throw GamaRuntimeException.create(e, scope); - } catch (final SAXException e) { - throw GamaRuntimeException.create(e, scope); - } catch (final ParserConfigurationException e) { + SimpleFeatureCollection collection = gml.decodeFeatureCollection(new FileInputStream(getFile(scope))); + computeProjection(scope, Envelope3D.of(collection.getBounds())); + return collection; + } catch (IOException | SAXException | ParserConfigurationException e) { throw GamaRuntimeException.create(e, scope); - } finally { - scope.getGui().getStatus(scope).endSubStatus("Reading file " + getName(scope)); - } - if (size > shapes.size()) { - GAMA.reportError(scope, GamaRuntimeException.warning("Problem with file " + getFile(scope) + ": only " - + shapes.size() + " of the " + size + " geometries could be added", scope), false); - } - - } - - @Override - public Envelope3D computeEnvelope(final IScope scope) { - if (env == null) { - readShapes(scope); } - return env; } } diff --git a/msi.gama.core/src/msi/gama/util/file/GamaGeoJsonFile.java b/msi.gama.core/src/msi/gama/util/file/GamaGeoJsonFile.java index 05edbdfb33..fa390805ec 100644 --- a/msi.gama.core/src/msi/gama/util/file/GamaGeoJsonFile.java +++ b/msi.gama.core/src/msi/gama/util/file/GamaGeoJsonFile.java @@ -15,17 +15,10 @@ import java.util.Map; import org.geotools.data.simple.SimpleFeatureCollection; -import org.geotools.data.simple.SimpleFeatureIterator; import org.geotools.geojson.feature.FeatureJSON; -import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.feature.type.GeometryType; -import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.locationtech.jts.geom.Geometry; - -import msi.gama.common.geometry.Envelope3D; -import msi.gama.metamodel.shape.GamaGisGeometry; import msi.gama.metamodel.shape.IShape; import msi.gama.precompiler.GamlAnnotations.doc; import msi.gama.precompiler.GamlAnnotations.example; @@ -109,7 +102,7 @@ public GamaGeoJsonFile(final IScope scope, final String pathName, final String c @Override protected void fillBuffer(final IScope scope) throws GamaRuntimeException { - if (getBuffer() != null) { return; } + if (getBuffer() != null) return; setBuffer(GamaListFactory. create(Types.GEOMETRY)); readShapes(scope); } @@ -133,11 +126,6 @@ public IList getAttributes(final IScope scope) { } @Override - protected CoordinateReferenceSystem getOwnCRS(final IScope scope) { - final SimpleFeatureCollection store = getFeatureCollection(scope); - return store.getSchema().getCoordinateReferenceSystem(); - } - protected SimpleFeatureCollection getFeatureCollection(final IScope scope) { try (FileReader fileReader = new FileReader(getFile(scope))) { final FeatureJSON fJSON = new FeatureJSON(); @@ -148,56 +136,4 @@ protected SimpleFeatureCollection getFeatureCollection(final IScope scope) { return null; } - public void readShapes(final IScope scope) { - final IList list = getBuffer(); - int size = 0; - final SimpleFeatureCollection fc = getFeatureCollection(scope); - if (fc == null) { return; } - final Envelope3D env = Envelope3D.of(fc.getBounds()); - size = fc.size(); - int index = 0; - computeProjection(scope, env); - try (SimpleFeatureIterator reader = fc.features()) { - while (reader.hasNext()) { - index++; - if (index % 20 == 0) { - scope.getGui().getStatus(scope).setSubStatusCompletion(index / (double) size); - } - final SimpleFeature feature = reader.next(); - Geometry g = (Geometry) feature.getDefaultGeometry(); - if (g != null && !g.isEmpty() /* Fix for Issue 725 && 677 */ ) { - g = gis.transform(g); - if (!with3D) { - g.apply(ZERO_Z); - g.geometryChanged(); - } - list.add(new GamaGisGeometry(g, feature)); - } else if (g == null) { - // See Issue 725 - GAMA.reportError(scope, - GamaRuntimeException - .warning("GamaGeoJsonFile.fillBuffer; geometry could not be added as it is " - + "nil: " + feature.getIdentifier(), scope), - false); - } - } - } - if (size > list.size()) { - GAMA.reportError(scope, GamaRuntimeException.warning("Problem with file " + getFile(scope) + ": only " - + list.size() + " of the " + size + " geometries could be added", scope), false); - } - } - - @Override - public Envelope3D computeEnvelope(final IScope scope) { - if (gis == null) { - final SimpleFeatureCollection store = getFeatureCollection(scope); - if (store == null) { return Envelope3D.EMPTY; } - final Envelope3D env = Envelope3D.of(store.getBounds()); - computeProjection(scope, env); - } - return gis.getProjectedEnvelope(); - - } - } diff --git a/msi.gama.core/src/msi/gama/util/file/GamaGisFile.java b/msi.gama.core/src/msi/gama/util/file/GamaGisFile.java index eab045367c..011baa2b2e 100644 --- a/msi.gama.core/src/msi/gama/util/file/GamaGisFile.java +++ b/msi.gama.core/src/msi/gama/util/file/GamaGisFile.java @@ -12,26 +12,35 @@ import static msi.gama.common.geometry.GeometryUtils.GEOMETRY_FACTORY; -import org.opengis.referencing.crs.CoordinateReferenceSystem; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import org.geotools.data.simple.SimpleFeatureCollection; import org.locationtech.jts.geom.CoordinateFilter; import org.locationtech.jts.geom.Geometry; import org.locationtech.jts.geom.LinearRing; import org.locationtech.jts.geom.MultiPolygon; import org.locationtech.jts.geom.Polygon; +import org.opengis.referencing.crs.CoordinateReferenceSystem; import msi.gama.common.geometry.Envelope3D; import msi.gama.common.geometry.GeometryUtils; import msi.gama.common.geometry.ICoordinates; +import msi.gama.common.util.GISUtils; import msi.gama.kernel.experiment.IExperimentAgent; -import msi.gama.metamodel.shape.GamaPoint; +import msi.gama.metamodel.shape.GamaGisGeometry; +import msi.gama.metamodel.shape.GamaShape; import msi.gama.metamodel.shape.IShape; import msi.gama.metamodel.topology.projection.IProjection; import msi.gama.metamodel.topology.projection.ProjectionFactory; +import msi.gama.runtime.GAMA; import msi.gama.runtime.IScope; import msi.gama.runtime.exceptions.GamaRuntimeException; import msi.gama.util.Collector; +import msi.gama.util.GamaListFactory; import msi.gaml.types.GamaGeometryType; +import msi.gaml.types.Types; /** * Class GamaGisFile. @@ -44,7 +53,7 @@ public abstract class GamaGisFile extends GamaGeometryFile { // The code to force reading the GIS data as already projected public static final int ALREADY_PROJECTED_CODE = 0; - static CoordinateFilter ZERO_Z = coord -> ((GamaPoint) coord).z = 0; + static CoordinateFilter ZERO_Z = coord -> coord.setZ(0); protected IProjection gis; protected Integer initialCRSCode = null; protected String initialCRSCodeStr = null; @@ -53,11 +62,11 @@ public abstract class GamaGisFile extends GamaGeometryFile { // Faire les tests sur ALREADY_PROJECTED ET LE PASSER AUSSI A GIS UTILS ??? /** - * Returns the CRS defined with this file (in a ".prj" file or elsewhere) + * Returns the CRS defined with this file (in a ".prj" file or passed by the user) * * @return */ - protected CoordinateReferenceSystem getExistingCRS(final IScope scope) { + protected final CoordinateReferenceSystem getExistingCRS(final IScope scope) { if (initialCRSCode != null) { try { return scope.getSimulation().getProjectionFactory().getCRS(scope, initialCRSCode); @@ -88,16 +97,65 @@ protected CoordinateReferenceSystem getExistingCRS(final IScope scope) { /** * @return */ - protected abstract CoordinateReferenceSystem getOwnCRS(IScope scope); + protected CoordinateReferenceSystem getOwnCRS(final IScope scope) { + URL url; + try { + url = getFile(scope).toURI().toURL(); + CoordinateReferenceSystem crs = getFeatureCollection(scope).getSchema().getCoordinateReferenceSystem(); + if (crs == null) { crs = GISUtils.manageGoogleCRS(url); } + return crs; + } catch (MalformedURLException e) { + return null; + } - protected void computeProjection(final IScope scope, final Envelope3D env) { - if (scope == null) { - return; + } + + protected abstract SimpleFeatureCollection getFeatureCollection(final IScope scope); + + protected final void readShapes(final IScope scope) { + ProgressCounter counter = new ProgressCounter(scope, "Reading " + getName(scope)); + SimpleFeatureCollection collection = getFeatureCollection(scope); + computeEnvelope(scope); + try { + collection.accepts(feature -> { + Geometry g = (Geometry) feature.getDefaultGeometryProperty().getValue(); + if (g != null && !g.isEmpty() /* Fix for Issue 725 && 677 */ ) { + // if (!with3D && !g.isValid()) { g = GeometryUtils.cleanGeometry(g); } + // g = gis.transform(g); + if (!with3D) { + g.apply(ZERO_Z); + g.geometryChanged(); + } + g = multiPolygonManagement(g); + GamaShape gt = new GamaGisGeometry(g, feature); + if (gt.getInnerGeometry() != null) { getBuffer().add(gt); } + } else if (g == null) { + // See Issue 725 + GAMA.reportError(scope, + GamaRuntimeException.warning( + "geometry could not be added as it is " + "nil: " + feature.getIdentifier(), scope), + false); + } + }, counter); + } catch (final IOException e) { + throw GamaRuntimeException.create(e, scope); } + // finally { + // if (store != null) { store.dispose(); } + // } + // if (size > list.size()) { + // reportError(scope, warning("Problem with file " + getFile(scope) + ": only " + list.size() + " of the " + // + size + " geometries could be added", scope), false); + // } + } + + protected void computeProjection(final IScope scope, final Envelope3D env) { + if (scope == null) return; final CoordinateReferenceSystem crs = getExistingCRS(scope); final ProjectionFactory pf; if (scope.getSimulation().isMicroSimulation()) { - pf=((IExperimentAgent)scope.getExperiment().getPopulation().getHost()).getSimulation().getProjectionFactory(); + pf = ((IExperimentAgent) scope.getExperiment().getPopulation().getHost()).getSimulation() + .getProjectionFactory(); } else { pf = scope.getSimulation() == null ? new ProjectionFactory() : scope.getSimulation().getProjectionFactory(); } @@ -113,10 +171,8 @@ protected Geometry multiPolygonManagement(final Geometry geom) { final LinearRing lr = GEOMETRY_FACTORY.createLinearRing(coords.toCoordinateArray()); try (final Collector.AsList holes = Collector.getList()) { for (int j = 0; j < p.getNumInteriorRing(); j++) { - final LinearRing h = (LinearRing) p.getInteriorRingN(j); - if (!hasNullElements(h.getCoordinates())) { - holes.add(h); - } + final LinearRing h = p.getInteriorRingN(j); + if (!hasNullElements(h.getCoordinates())) { holes.add(h); } } LinearRing[] stockArr = new LinearRing[holes.size()]; stockArr = holes.items().toArray(stockArr); @@ -130,9 +186,7 @@ protected Geometry multiPolygonManagement(final Geometry geom) { protected static boolean hasNullElements(final Object[] array) { for (final Object element : array) { - if (element == null) { - return true; - } + if (element == null) return true; } return false; } @@ -160,9 +214,7 @@ public GamaGisFile(final IScope scope, final String pathName, final String code, } public IProjection getGis(final IScope scope) { - if (gis == null) { - fillBuffer(scope); - } + if (gis == null) { fillBuffer(scope); } return gis; } @@ -171,6 +223,28 @@ protected IShape buildGeometry(final IScope scope) { return GamaGeometryType.geometriesToGeometry(scope, getBuffer()); } + /** + * @see msi.gama.util.GamaFile#fillBuffer() + */ + @Override + protected void fillBuffer(final IScope scope) throws GamaRuntimeException { + if (getBuffer() != null) return; + setBuffer(GamaListFactory. create(Types.GEOMETRY)); + readShapes(scope); + } + + @Override + public Envelope3D computeEnvelope(final IScope scope) { + if (gis == null) { + final SimpleFeatureCollection collection = getFeatureCollection(scope); + if (collection == null) return Envelope3D.EMPTY; + final Envelope3D env = Envelope3D.of(collection.getBounds()); + computeProjection(scope, env); + } + return gis.getProjectedEnvelope(); + + } + @Override public void invalidateContents() { super.invalidateContents(); diff --git a/msi.gama.core/src/msi/gama/util/file/GamaGridFile.java b/msi.gama.core/src/msi/gama/util/file/GamaGridFile.java index d5d6b94294..ec7ddfe1d0 100644 --- a/msi.gama.core/src/msi/gama/util/file/GamaGridFile.java +++ b/msi.gama.core/src/msi/gama/util/file/GamaGridFile.java @@ -18,23 +18,22 @@ // ArcGridReader still requires input streams import java.io.StringBufferInputStream; import java.nio.channels.FileChannel; -import java.util.ArrayList; import java.util.Scanner; import org.geotools.coverage.grid.GridCoverage2D; import org.geotools.coverage.grid.io.AbstractGridCoverage2DReader; import org.geotools.data.DataSourceException; import org.geotools.data.PrjFileReader; +import org.geotools.data.simple.SimpleFeatureCollection; import org.geotools.gce.arcgrid.ArcGridReader; import org.geotools.gce.geotiff.GeoTiffReader; import org.geotools.geometry.DirectPosition2D; import org.geotools.geometry.GeneralEnvelope; import org.geotools.util.factory.Hints; +import org.locationtech.jts.geom.Envelope; import org.opengis.referencing.FactoryException; import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.locationtech.jts.geom.Envelope; - import msi.gama.common.geometry.Envelope3D; import msi.gama.metamodel.shape.GamaPoint; import msi.gama.metamodel.shape.GamaShape; @@ -49,7 +48,6 @@ import msi.gama.runtime.exceptions.GamaRuntimeException; import msi.gama.util.GamaListFactory; import msi.gama.util.IList; -import msi.gaml.operators.Spatial.Projections; import msi.gaml.types.GamaGeometryType; import msi.gaml.types.IType; import msi.gaml.types.Types; @@ -102,14 +100,14 @@ private GamaGridReader createReader(final IScope scope, final boolean fillBuffer "The format of " + getName(scope) + " is incorrect. Attempting to read it anyway.", scope), false); - - reader = fixFileHeader(scope,fillBuffer); + + reader = fixFileHeader(scope, fillBuffer); } } return reader; } - - public GamaGridReader fixFileHeader(IScope scope,final boolean fillBuffer) { + + public GamaGridReader fixFileHeader(final IScope scope, final boolean fillBuffer) { final StringBuilder text = new StringBuilder(); final String NL = System.getProperty("line.separator"); @@ -132,8 +130,8 @@ public GamaGridReader fixFileHeader(IScope scope,final boolean fillBuffer) { // } } } catch (final FileNotFoundException e2) { - final GamaRuntimeException ex = GamaRuntimeException.error( - "The format of " + getName(scope) + " is not correct. Error: " + e2.getMessage(), scope); + final GamaRuntimeException ex = GamaRuntimeException + .error("The format of " + getName(scope) + " is not correct. Error: " + e2.getMessage(), scope); ex.addContext("for file " + getPath(scope)); throw ex; } @@ -154,9 +152,7 @@ class GamaGridReader { setBuffer(GamaListFactory. create(Types.GEOMETRY)); AbstractGridCoverage2DReader store = null; try { - if (fillBuffer) { - scope.getGui().getStatus(scope).beginSubStatus("Reading file " + getName(scope)); - } + if (fillBuffer) { scope.getGui().getStatus(scope).beginSubStatus("Reading file " + getName(scope)); } // Necessary to compute it here, because it needs to be passed // to the Hints final CoordinateReferenceSystem crs = getExistingCRS(scope); @@ -178,7 +174,8 @@ class GamaGridReader { final GeneralEnvelope genv = store.getOriginalEnvelope(); numRows = store.getOriginalGridRange().getHigh(1) + 1; numCols = store.getOriginalGridRange().getHigh(0) + 1; - final Envelope3D env = Envelope3D.of(genv.getMinimum(0), genv.getMaximum(0), genv.getMinimum(1), genv.getMaximum(1), 0, 0); + final Envelope3D env = Envelope3D.of(genv.getMinimum(0), genv.getMaximum(0), genv.getMinimum(1), + genv.getMaximum(1), 0, 0); computeProjection(scope, env); final Envelope envP = gis.getProjectedEnvelope(); final double cellHeight = envP.getHeight() / numRows; @@ -194,7 +191,7 @@ class GamaGridReader { shapes.add(new GamaPoint(originX, maxY)); shapes.add(shapes.get(0)); geom = GamaGeometryType.buildPolygon(shapes); - if (!fillBuffer) { return; } + if (!fillBuffer) return; final GamaPoint p = new GamaPoint(0, 0); coverage = store.read(null); @@ -235,40 +232,30 @@ class GamaGridReader { } if (doubleValues) { final double[] vd = (double[]) vals; - if (i == 0) { - nbBands = vd.length; - } + if (i == 0) { nbBands = vd.length; } rect.setAttribute("grid_value", vd[0]); rect.setAttribute("bands", GamaListFactory.create(scope, Types.FLOAT, vd)); } else if (intValues) { final int[] vi = (int[]) vals; - if (i == 0) { - nbBands = vi.length; - } + if (i == 0) { nbBands = vi.length; } final double v = Double.valueOf(vi[0]); rect.setAttribute("grid_value", v); rect.setAttribute("bands", GamaListFactory.create(scope, Types.FLOAT, vi)); } else if (longValues) { final long[] vi = (long[]) vals; - if (i == 0) { - nbBands = vi.length; - } + if (i == 0) { nbBands = vi.length; } final double v = Double.valueOf(vi[0]); rect.setAttribute("grid_value", v); rect.setAttribute("bands", GamaListFactory.create(scope, Types.FLOAT, vi)); } else if (floatValues) { final float[] vi = (float[]) vals; - if (i == 0) { - nbBands = vi.length; - } + if (i == 0) { nbBands = vi.length; } final double v = Double.valueOf(vi[0]); rect.setAttribute("grid_value", v); rect.setAttribute("bands", GamaListFactory.create(scope, Types.FLOAT, vi)); } else if (byteValues) { final byte[] bv = (byte[]) vals; - if (i == 0) { - nbBands = bv.length; - } + if (i == 0) { nbBands = bv.length; } if (bv.length == 1) { final double v = Double.valueOf(((byte[]) vals)[0]); rect.setAttribute("grid_value", v); @@ -289,9 +276,7 @@ class GamaGridReader { ex.addContext("for file " + getFile(scope).getPath()); throw ex; } finally { - if (store != null) { - store.dispose(); - } + if (store != null) { store.dispose(); } scope.getGui().getStatus(scope).endSubStatus("Opening file " + getName(scope)); } } @@ -333,15 +318,13 @@ public Envelope3D computeEnvelope(final IScope scope) { } public Envelope computeEnvelopeWithoutBuffer(final IScope scope) { - if (gis == null) { - createReader(scope, false); - } + if (gis == null) { createReader(scope, false); } return gis.getProjectedEnvelope(); } @Override protected void fillBuffer(final IScope scope) { - if (getBuffer() != null) { return; } + if (getBuffer() != null) return; createReader(scope, true); } @@ -437,9 +420,7 @@ protected CoordinateReferenceSystem getOwnCRS(final IScope scope) { public void invalidateContents() { super.invalidateContents(); reader = null; - if (coverage != null) { - coverage.dispose(true); - } + if (coverage != null) { coverage.dispose(true); } coverage = null; } @@ -448,9 +429,7 @@ public GridCoverage2D getCoverage() { } public Double valueOf(final IScope scope, final ILocation loc) { - if (getBuffer() == null) { - fillBuffer(scope); - } + if (getBuffer() == null) { fillBuffer(scope); } Object vals = null; try { vals = coverage.evaluate(new DirectPosition2D(loc.getLocation().getX(), loc.getLocation().getY())); @@ -489,4 +468,9 @@ public Double valueOf(final IScope scope, final ILocation loc) { return val; } + @Override + protected SimpleFeatureCollection getFeatureCollection(final IScope scope) { + return null; + } + } diff --git a/msi.gama.core/src/msi/gama/util/file/GamaOsmFile.java b/msi.gama.core/src/msi/gama/util/file/GamaOsmFile.java index 8999267da9..03d4716317 100644 --- a/msi.gama.core/src/msi/gama/util/file/GamaOsmFile.java +++ b/msi.gama.core/src/msi/gama/util/file/GamaOsmFile.java @@ -40,14 +40,13 @@ import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; import org.geotools.referencing.crs.DefaultGeographicCRS; +import org.locationtech.jts.geom.Geometry; import org.opengis.feature.simple.SimpleFeature; import org.opengis.feature.simple.SimpleFeatureType; import org.opengis.referencing.FactoryException; import org.opengis.referencing.NoSuchAuthorityCodeException; import org.opengis.referencing.crs.CoordinateReferenceSystem; -import org.locationtech.jts.geom.Geometry; - import msi.gama.common.geometry.Envelope3D; import msi.gama.ext.osmosis.Bound; import msi.gama.ext.osmosis.Entity; @@ -94,7 +93,7 @@ public class GamaOsmFile extends GamaGisFile { final ReferencedEnvelope env = new ReferencedEnvelope(); - + public static class OSMInfo extends GamaFileMetaData { int itemNumber; @@ -102,7 +101,7 @@ public static class OSMInfo extends GamaFileMetaData { final double width; final double height; final Map attributes = new LinkedHashMap(); - + public OSMInfo(final URL url, final long modificationStamp) { super(modificationStamp); CoordinateReferenceSystem crs = null; @@ -190,9 +189,7 @@ public void appendSuffix(final StringBuilder sb) { return; } sb.append(itemNumber).append(" object"); - if (itemNumber > 1) { - sb.append("s"); - } + if (itemNumber > 1) { sb.append("s"); } sb.append(SUFFIX_DEL); sb.append(Math.round(width)).append("m x "); sb.append(Math.round(height)).append("m"); @@ -278,9 +275,7 @@ public GamaOsmFile(final IScope scope, final String pathName, final IMap arg0) {} }; readFile(scope, sinkImplementation, getFile(scope)); - - if (returnIt) { - setBuffer(buildGeometries(scope, nodes, ways, relations, intersectionNodes, nodesPt)); - } - + + if (returnIt) { setBuffer(buildGeometries(scope, nodes, ways, relations, intersectionNodes, nodesPt)); } + } private void addAttribute(final Map atts, final String nameAt, final Object val) { final String type = atts.get(nameAt); - if (type != null && type.equals("string")) { return; } + if (type != null && type.equals("string")) return; String newType = "int"; try { Integer.parseInt(val.toString()); @@ -370,9 +361,7 @@ private void addAttribute(final Map atts, final String nameAt, f } } - if (type == null || newType.equals("string")) { - atts.put(nameAt, newType); - } + if (type == null || newType.equals("string")) { atts.put(nameAt, newType); } } /** @@ -380,22 +369,23 @@ private void addAttribute(final Map atts, final String nameAt, f */ @Override protected void fillBuffer(final IScope scope) throws GamaRuntimeException { - if (getBuffer() != null) { return; } + if (getBuffer() != null) return; setBuffer(GamaListFactory. create(Types.GEOMETRY)); getFeatureIterator(scope, true); } - public IList buildGeometries(IScope scope, final List nodes, final List ways, final List relations, - final Set intersectionNodes, final Map nodesPt) { - + public IList buildGeometries(final IScope scope, final List nodes, final List ways, + final List relations, final Set intersectionNodes, final Map nodesPt) { + final IList geometries = GamaListFactory.create(Types.GEOMETRY); if (gis == null) { computeProjection(scope, Envelope3D.of(env)); - if (gis != null) + if (gis != null) { for (Long id : nodesPt.keySet()) { GamaShape sp = new GamaShape(gis.transform(nodesPt.get(id).getInnerGeometry())); nodesPt.put(id, sp); - } + } + } } final Map geomMap = new HashMap<>(); for (final Node node : nodes) { @@ -407,13 +397,9 @@ public IList buildGeometries(IScope scope, final List nodes, final for (final Tag tg : node.getTags()) { final String key = tg.getKey().split(":")[0]; final Object val = tg.getValue(); - if (val != null) { - addAttribute(atts, key, val); - } + if (val != null) { addAttribute(atts, key, val); } pt.setAttribute(key, val); - if (key.equals("highway")) { - intersectionNodes.add(node.getId()); - } + if (key.equals("highway")) { intersectionNodes.add(node.getId()); } } if (hasAttributes) { geometries.add(pt); @@ -463,9 +449,7 @@ public IList buildGeometries(IScope scope, final List nodes, final for (final Tag tg : way.getTags()) { final String key = tg.getKey().split(":")[0]; final Object val = tg.getValue(); - if (val != null) { - addAttribute(atts, key, val); - } + if (val != null) { addAttribute(atts, key, val); } values.put(key, tg.getValue()); } values.put("osm_id", way.getId()); @@ -497,20 +481,16 @@ public IList buildGeometries(IScope scope, final List nodes, final final List points = GamaListFactory.create(Types.GEOMETRY); for (final WayNode node : way.getWayNodes()) { final GamaShape pp = nodesPt.get(node.getNodeId()); - if (pp == null) { - continue; - } + if (pp == null) { continue; } points.add(pp); } - if (points.size() < 3) { - continue; - } - + if (points.size() < 3) { continue; } + final IShape geom = GamaGeometryType.buildPolygon(points); - + if (geom != null && geom.getInnerGeometry() != null && !geom.getInnerGeometry().isEmpty() && geom.getInnerGeometry().getArea() > 0) { - + values.forEach((k, v) -> geom.setAttribute(k, v)); geometries.add(geom); // if (geom.getAttributes() != null) {} @@ -607,14 +587,10 @@ public List createSplitRoad(final List wayNodes, final Map 1) { - pointsList.add(points); - } + if (points.size() > 1) { pointsList.add(points); } points = GamaListFactory.create(Types.GEOMETRY); points.add(pt); @@ -625,16 +601,14 @@ public List createSplitRoad(final List wayNodes, final Map tempValues = new HashMap<>(values); tempValues.put("way_order", index++); final IShape g = createRoad(pts, tempValues); - if (g != null) { - geometries.add(g); - } + if (g != null) { geometries.add(g); } } return geometries; } private IShape createRoad(final List points, final Map values) { - if (points.size() < 2) { return null; } + if (points.size() < 2) return null; final IShape geom = GamaGeometryType.buildPolyline(points); if (geom != null && geom.getInnerGeometry() != null && !geom.getInnerGeometry().isEmpty() && geom.getInnerGeometry().isSimple() && geom.getPerimeter() > 0) { @@ -710,12 +684,8 @@ private void readXML(final IScope scope, final Sink sink) throws GamaRuntimeExce @Override public Envelope3D computeEnvelope(final IScope scope) { - if (gis == null) { - getFeatureIterator(scope, false); - } - if (gis == null) { - return Envelope3D.of(env); - } + if (gis == null) { getFeatureIterator(scope, false); } + if (gis == null) return Envelope3D.of(env); return gis.getProjectedEnvelope(); } @@ -747,4 +717,9 @@ public List getFeatureTypes() { return featureTypes; } + @Override + protected SimpleFeatureCollection getFeatureCollection(final IScope scope) { + return null; + } + } diff --git a/msi.gama.core/src/msi/gama/util/file/GamaSVGFile.java b/msi.gama.core/src/msi/gama/util/file/GamaSVGFile.java index cd7b019410..49aa22b36e 100644 --- a/msi.gama.core/src/msi/gama/util/file/GamaSVGFile.java +++ b/msi.gama.core/src/msi/gama/util/file/GamaSVGFile.java @@ -21,8 +21,7 @@ import msi.gama.common.geometry.GeometryUtils; import msi.gama.common.geometry.Scaling3D; -import msi.gama.ext.svgsalamander.SVGCache; -import msi.gama.ext.svgsalamander.SVGDiagram; +import msi.gama.ext.svgsalamander.SVGRoot; import msi.gama.ext.svgsalamander.SVGUniverse; import msi.gama.metamodel.shape.GamaPoint; import msi.gama.metamodel.shape.GamaShape; @@ -91,27 +90,15 @@ public IList getAttributes(final IScope scope) { @Override protected void fillBuffer(final IScope scope) throws GamaRuntimeException { try (BufferedReader in = new BufferedReader(new FileReader(getFile(scope)))) { - final SVGUniverse svg = SVGCache.getSVGUniverse(); + final SVGUniverse svg = SVGUniverse.getInstance(); final URI uri = svg.loadSVG(in, getPath(scope)); - final SVGDiagram diagram = svg.getDiagram(uri); - final Shape shape = diagram.getRoot().getShape(); + final SVGRoot diagram = svg.getRoot(uri); + final Shape shape = diagram.getShape(); final Geometry geom = ShapeReader.read(shape, 1.0, GeometryUtils.GEOMETRY_FACTORY); // flatness - // = - // ?? - // We center and scale the shape in the same operation - // final Envelope env = geom.getEnvelopeInternal(); - // GamaPoint translation = new GamaPoint(-env.getWidth() / 2, - // -env.getHeight() / 2); final IShape gs = new GamaShape(null, geom, null, new GamaPoint(0, 0), size, true); - // gs.setLocation(new GamaPoint(0, 0)); - // gs.setLocation(translation); - // if ( size != null ) { - // gs = Spatial.Transformations.scaled_to(scope, gs, size); - // } setBuffer(GamaListFactory.wrap(Types.GEOMETRY, gs)); } catch (final IOException e) { throw GamaRuntimeException.create(e, scope); - // e.printStackTrace(); } } diff --git a/msi.gama.core/src/msi/gama/util/file/GamaShapeFile.java b/msi.gama.core/src/msi/gama/util/file/GamaShapeFile.java index 9c6af9edde..d86facd090 100644 --- a/msi.gama.core/src/msi/gama/util/file/GamaShapeFile.java +++ b/msi.gama.core/src/msi/gama/util/file/GamaShapeFile.java @@ -10,12 +10,9 @@ ********************************************************************************************************/ package msi.gama.util.file; -import static msi.gama.runtime.GAMA.reportError; -import static msi.gama.runtime.exceptions.GamaRuntimeException.warning; import static org.apache.commons.lang.StringUtils.join; import static org.apache.commons.lang.StringUtils.splitByWholeSeparatorPreserveAllTokens; -import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; @@ -30,15 +27,12 @@ import org.geotools.data.simple.SimpleFeatureSource; import org.geotools.geometry.jts.ReferencedEnvelope; import org.geotools.referencing.CRS; -import org.locationtech.jts.geom.Geometry; import org.opengis.feature.type.AttributeDescriptor; import org.opengis.feature.type.GeometryType; import org.opengis.referencing.crs.CoordinateReferenceSystem; -import msi.gama.common.geometry.Envelope3D; import msi.gama.common.geometry.GeometryUtils; import msi.gama.common.util.GISUtils; -import msi.gama.metamodel.shape.GamaGisGeometry; import msi.gama.metamodel.shape.IShape; import msi.gama.metamodel.topology.projection.ProjectionFactory; import msi.gama.precompiler.GamlAnnotations.doc; @@ -71,6 +65,12 @@ @SuppressWarnings ({ "unchecked", "rawtypes" }) public class GamaShapeFile extends GamaGisFile { + static { + DEBUG.ON(); + } + + FileDataStore store; + public static class ShapeInfo extends GamaFileMetaData { final int itemNumber; @@ -81,7 +81,7 @@ public static class ShapeInfo extends GamaFileMetaData { public ShapeInfo(final IScope scope, final URL url, final long modificationStamp) { super(modificationStamp); - ShapefileDataStore store = null; + FileDataStore store = null; ReferencedEnvelope env = new ReferencedEnvelope(); CoordinateReferenceSystem crs1 = null; int number = 0; @@ -319,94 +319,96 @@ public IList getAttributes(final IScope scope) { return GamaListFactory.wrap(Types.STRING, s.attributes.keySet()); } - @Override - protected CoordinateReferenceSystem getOwnCRS(final IScope scope) { - ShapefileDataStore store = null; + static FileDataStore getDataStore(final URL url) { + FileDataStore fds; try { - final URL url = getFile(scope).toURI().toURL(); - store = getDataStore(url); - CoordinateReferenceSystem crs = store.getFeatureSource().getInfo().getCRS(); - if (crs == null) { crs = GISUtils.manageGoogleCRS(url); } - return crs; - } catch (final IOException e) { + fds = FileDataStoreFinder.getDataStore(url); + } catch (IOException e) { return null; - } finally { - if (store != null) { store.dispose(); } } - } + if (fds instanceof ShapefileDataStore) { + ShapefileDataStore store = (ShapefileDataStore) fds; + store.setGeometryFactory(GeometryUtils.GEOMETRY_FACTORY); + store.setBufferCachingEnabled(true); + store.setMemoryMapped(true); + store.setCharset(Charset.forName("UTF8")); + } + return fds; - static ShapefileDataStore getDataStore(final URL url) { - final ShapefileDataStore store = new ShapefileDataStore(url); - store.setGeometryFactory(GeometryUtils.GEOMETRY_FACTORY); - store.setBufferCachingEnabled(true); - store.setMemoryMapped(true); - store.setCharset(Charset.forName("UTF8")); - return store; } - protected void readShapes(final IScope scope) { - ProgressCounter counter = new ProgressCounter(scope, "Reading file " + getName(scope)); - FileDataStore store = null; - final File file = getFile(scope); - final IList list = getBuffer(); + // @Override + // protected final void readShapes(final IScope scope) { + // ProgressCounter counter = new ProgressCounter(scope, "Reading file " + getName(scope)); + // counter.started(); + // computeEnvelope(scope); + // try (ShapefileReader reader = + // new ShapefileReader(new ShpFiles(getFile(scope)), false, true, GeometryUtils.GEOMETRY_FACTORY)) { + // float size = length(scope); + // int index = 0; + // reader.setFlatGeometry(true); + // DEBUG.LINE(); + // while (reader.hasNext()) { + // index++; + // Geometry g = (Geometry) reader.nextRecord().shape(); + // if (g != null && !g.isEmpty() /* Fix for Issue 725 && 677 */ ) { + // // if (!with3D && !g.isValid()) { g = GeometryUtils.cleanGeometry(g); } + // g = gis.transform(g); + // if (!with3D) { + // g.apply(ZERO_Z); + // g.geometryChanged(); + // } + // g = multiPolygonManagement(g); + // GamaShape gt = new GamaGisGeometry(g, null); + // if (gt.getInnerGeometry() != null) { getBuffer().add(gt); } + // } else if (g == null) { + // // See Issue 725 + // GAMA.reportError(scope, + // GamaRuntimeException.warning("geometry could not be added as it is " + "nil: ", scope), + // false); + // } + // if (index % 100 == 0) { + // DEBUG.OUT(index + "...", false); + // counter.progress(index / size); + // if (index % 5000 == 0) { DEBUG.OUT(""); } + // } + // } + // counter.complete(); + // DEBUG.LINE(); + // } catch (final IOException e) { + // throw GamaRuntimeException.create(e, scope); + // } + // // finally { + // // if (store != null) { store.dispose(); } + // // } + // // if (size > list.size()) { + // // reportError(scope, warning("Problem with file " + getFile(scope) + ": only " + list.size() + " of the " + // // + size + " geometries could be added", scope), false); + // // } + // } + + @Override + protected SimpleFeatureCollection getFeatureCollection(final IScope scope) { try { - store = FileDataStoreFinder.getDataStore(file); + if (store == null) { store = getDataStore(getFile(scope).toURI().toURL()); } final SimpleFeatureSource source = store.getFeatureSource(); - final Envelope3D env = Envelope3D.of(source.getBounds()); - computeProjection(scope, env); - SimpleFeatureCollection collection = source.getFeatures(); - collection.accepts(feature -> { - Geometry g = (Geometry) feature.getDefaultGeometryProperty().getValue(); - System.out.println(g.getCoordinate()); - }, counter); - collection.accepts(feature -> { - Geometry g = (Geometry) feature.getDefaultGeometryProperty().getValue(); - if (g != null && !g.isEmpty() /* Fix for Issue 725 && 677 */ ) { - if (!with3D && !g.isValid()) { g = GeometryUtils.cleanGeometry(g); } - g = gis.transform(g); - if (!with3D) { - g.apply(ZERO_Z); - g.geometryChanged(); - } - g = multiPolygonManagement(g); - GamaGisGeometry gt = new GamaGisGeometry(g, feature); - if (gt.getInnerGeometry() != null) { list.add(gt); } - } else if (g == null) { - // See Issue 725 - reportError(scope, - warning("geometry could not be added as it is " + "nil: " + feature.getIdentifier(), - scope), - false); - } - }, counter); - - } catch (final IOException e) { + return source.getFeatures(); + } catch (IOException e) { throw GamaRuntimeException.create(e, scope); - } finally { - if (store != null) { store.dispose(); } } - // if (size > list.size()) { - // reportError(scope, warning("Problem with file " + getFile(scope) + ": only " + list.size() + " of the " - // + size + " geometries could be added", scope), false); - // } } @Override - public Envelope3D computeEnvelope(final IScope scope) { - if (gis == null) { - ShapefileDataStore store = null; - try { - store = getDataStore(getFile(scope).toURI().toURL()); - final Envelope3D env = Envelope3D.of(store.getFeatureSource().getBounds()); - computeProjection(scope, env); - } catch (final IOException e) { - return Envelope3D.EMPTY; - } finally { - if (store != null) { store.dispose(); } - } - } - return gis.getProjectedEnvelope(); + public int length(final IScope scope) { + if (getBuffer() == null) return getFeatureCollection(scope).size(); + return super.length(scope); + } + @Override + public void invalidateContents() { + super.invalidateContents(); + if (store != null) { store.dispose(); } + store = null; } }