/*
* Geotoolkit - An Open Source Java GIS Toolkit
* http://www.geotoolkit.org
*
* (C) 2004-2008, Open Source Geospatial Foundation (OSGeo)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package org.geotoolkit.geometry.isoonjts;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.measure.UnitConverter;
import javax.measure.Unit;
import org.geotoolkit.geometry.isoonjts.spatialschema.geometry.geometry.JTSGeometryFactory;
import org.geotoolkit.geometry.isoonjts.spatialschema.geometry.primitive.JTSPrimitiveFactory;
import org.apache.sis.referencing.CRS;
import org.apache.sis.referencing.CommonCRS;
import org.apache.sis.util.logging.Logging;
import org.apache.sis.measure.Units;
import org.opengis.util.FactoryException;
import org.opengis.referencing.crs.CoordinateReferenceSystem;
import org.opengis.referencing.crs.GeographicCRS;
import org.opengis.referencing.crs.ProjectedCRS;
import org.opengis.referencing.cs.AxisDirection;
import org.opengis.referencing.cs.CoordinateSystem;
import org.opengis.referencing.cs.CoordinateSystemAxis;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.opengis.geometry.DirectPosition;
import org.opengis.geometry.Envelope;
import org.opengis.geometry.MismatchedDimensionException;
import org.opengis.geometry.complex.CompositeCurve;
import org.opengis.geometry.coordinate.GeometryFactory;
import org.opengis.geometry.coordinate.LineString;
import org.opengis.geometry.coordinate.PointArray;
import org.opengis.geometry.coordinate.Polygon;
import org.opengis.geometry.coordinate.PolyhedralSurface;
import org.opengis.geometry.primitive.Curve;
import org.opengis.geometry.primitive.CurveSegment;
import org.opengis.geometry.primitive.PrimitiveFactory;
import org.opengis.geometry.primitive.Ring;
import org.opengis.geometry.primitive.SurfaceBoundary;
import org.apache.sis.geometry.Envelopes;
/**
* @author crossley
*
* TODO To change the template for this generated type comment go to
* Window - Preferences - Java - Code Style - Code Templates
* @module
*/
public final class GeometryUtils {
private static final Logger LOGGER = Logging.getLogger("org.geotoolkit.geometry.isoonjts");
private static final Envelope WHOLE_WORLD;
static{
CoordinateReferenceSystem crs = CommonCRS.WGS84.geographic();
final GeometryFactory geometryFactory = new JTSGeometryFactory(crs);
final DirectPosition lowerCorner = geometryFactory.createDirectPosition(new double[] {-90,-180});
final DirectPosition upperCorner = geometryFactory.createDirectPosition(new double[] {90,180});
WHOLE_WORLD = geometryFactory.createEnvelope(lowerCorner, upperCorner);
}
/**
* Prevents creating a new {@code GeometryUtils}.
*/
private GeometryUtils() { }
public static Envelope getWholeWorld() {
return WHOLE_WORLD;
}
public static CoordinateReferenceSystem getCRS(final Envelope envelope) {
return envelope.getLowerCorner().getCoordinateReferenceSystem();
}
// PENDING(jdc): need to respect a given Unit for the return array.
/**
* Converts an {@code Envelope} to a "minx, miny, maxx, maxy" array.
* @param envelope
* @param unit
* @return double[]
*/
public static double[] getBBox(Envelope envelope, final Unit unit) {
if (unit.equals(Units.DEGREE)) {
try {
envelope = Envelopes.transform(envelope, CommonCRS.WGS84.normalizedGeographic());
} catch (TransformException ex) {
LOGGER.severe("unable to reproject the envelope:" + ex.getMessage());
}
}
final double[] returnable = new double[4];
final DirectPosition lowerCorner = envelope.getLowerCorner();
final DirectPosition upperCorner = envelope.getUpperCorner();
final CoordinateSystem cs = getCRS(envelope).getCoordinateSystem();
final int xIndex = getDirectedAxisIndex(cs, AxisDirection.EAST);
final Unit xUnit = getDirectedAxisUnit(cs, AxisDirection.EAST);
final int yIndex = getDirectedAxisIndex(cs, AxisDirection.NORTH);
final Unit yUnit = getDirectedAxisUnit(cs, AxisDirection.NORTH);
//edited to use javax.measure.unit.Convertor
UnitConverter xConverter = xUnit.getConverterTo(unit);
UnitConverter yConverter = yUnit.getConverterTo(unit);
returnable[0] = xConverter.convert(lowerCorner.getOrdinate(xIndex));
returnable[1] = yConverter.convert(lowerCorner.getOrdinate(yIndex));
returnable[2] = xConverter.convert(upperCorner.getOrdinate(xIndex));
returnable[3] = yConverter.convert(upperCorner.getOrdinate(yIndex));
return returnable;
}
public static Envelope createCRSEnvelope(
final CoordinateReferenceSystem crs,
final double minx,
final double miny,
final double maxx,
final double maxy) {
final GeometryFactory geometryFactory = new JTSGeometryFactory(crs);
final DirectPosition lowerCorner = geometryFactory.createDirectPosition();
lowerCorner.setOrdinate(0, minx);
lowerCorner.setOrdinate(1, miny);
final DirectPosition upperCorner = geometryFactory.createDirectPosition();
upperCorner.setOrdinate(0, maxx);
upperCorner.setOrdinate(1, maxy);
return geometryFactory.createEnvelope(lowerCorner, upperCorner);
}
/**
* DOCUMENT ME.
* @param crs
* @param minx
* @param miny
* @param maxx
* @param maxy
* @param unit
* @return Envelope
*/
public static Envelope createEnvelope(
final CoordinateReferenceSystem crs,
final double minx,
final double miny,
final double maxx,
final double maxy,
final Unit unit) {
final GeometryFactory geometryFactory = new JTSGeometryFactory(crs);
final CoordinateSystem cs = crs.getCoordinateSystem();
final int xIndex = getDirectedAxisIndex(cs, AxisDirection.EAST);
final Unit xUnit = getDirectedAxisUnit(cs, AxisDirection.EAST);
final int yIndex = getDirectedAxisIndex(cs, AxisDirection.NORTH);
final Unit yUnit = getDirectedAxisUnit(cs, AxisDirection.NORTH);
// HACK(jdc): need to determine the order of the axes...
/*int[] indices = CSUtils.getDirectedAxisIndices(
crs.getCoordinateSystem(),
new AxisDirection[] { AxisDirection.EAST, AxisDirection.NORTH });*/
//edited to use javax.measure.unit.Convertor
UnitConverter xConverter = xUnit.getConverterTo(unit);
UnitConverter yConverter = yUnit.getConverterTo(unit);
double[] lowerOrdinates = new double[crs.getCoordinateSystem().getDimension()];
lowerOrdinates[xIndex] = xConverter.convert(minx);
lowerOrdinates[yIndex] = yConverter.convert(miny);
/*for (int i = 0; i < lowerOrdinates.length; i++) {
// the east or x ordinate
if (i == indices[0]) {
lowerOrdinates[i] = minx;
// the north or y ordinate
} else if (i == indices[1]) {
lowerOrdinates[i] = miny;
} else {
lowerOrdinates[i] = 0;
}
}*/
double[] upperOrdinates = new double[crs.getCoordinateSystem().getDimension()];
upperOrdinates[xIndex] = xConverter.convert(maxx);
upperOrdinates[yIndex] = yConverter.convert(maxy);
/*for (int i = 0; i < upperOrdinates.length; i++) {
// the east or x ordinate
if (i == indices[0]) {
upperOrdinates[i] = maxx;
// the north or y ordinate
} else if (i == indices[1]) {
upperOrdinates[i] = maxy;
} else {
upperOrdinates[i] = 0;
}
}*/
final DirectPosition lowerCorner = geometryFactory.createDirectPosition(lowerOrdinates);
final DirectPosition upperCorner = geometryFactory.createDirectPosition(upperOrdinates);
return geometryFactory.createEnvelope(lowerCorner, upperCorner);
}
/**
* DOCUMENT ME.
* @param envelope
* @param crs
* @param minx
* @param miny
* @param maxx
* @param maxy
* @return boolean
*/
public static boolean within(
final Envelope envelope,
final CoordinateReferenceSystem crs,
final double minx,
final double miny,
final double maxx,
final double maxy) {
final CoordinateSystem cs = crs.getCoordinateSystem();
final int xIndex = getDirectedAxisIndex(cs, AxisDirection.EAST);
final int yIndex = getDirectedAxisIndex(cs, AxisDirection.NORTH);
return ( (minx <= envelope.getMinimum(xIndex)) && (maxx >= envelope.getMaximum(xIndex)) &&
(miny <= envelope.getMinimum(yIndex)) && (maxy >= envelope.getMaximum(yIndex)) );
}
/*public static boolean overlaps(
final Envelope envelope,
final CoordinateReferenceSystem crs,
final double minx,
final double miny,
final double maxx,
final double maxy) {
final CoordinateSystem cs = crs.getCoordinateSystem();
final int xIndex = CSUtils.getDirectedAxisIndex(cs, AxisDirection.EAST);
final int yIndex = CSUtils.getDirectedAxisIndex(cs, AxisDirection.NORTH);
return ( (minx <= envelope.getMinimum(xIndex)) || (maxx >= envelope.getMaximum(xIndex)) ||
(miny <= envelope.getMinimum(yIndex)) || (maxy >= envelope.getMaximum(yIndex)) );
}*/
/**
* DOCUMENT ME.
* @param envelope1
* @param envelope2
* @return boolean
*/
public static boolean equals(final Envelope envelope1, final Envelope envelope2) {
//getLog().debug("PENDING(jdc): implement the method instead of returning false...");
if (envelope1 == null || envelope2 == null) {
return false;
}
final double[] bbox1 = getBBox(envelope1, Units.DEGREE);
final double[] bbox2 = getBBox(envelope2, Units.DEGREE);
return
bbox1[0] == bbox2[0] &&
bbox1[1] == bbox2[1] &&
bbox1[2] == bbox2[2] &&
bbox1[3] == bbox2[3];
}
/**
* Determines whether or not the two specified Envelopes intersect.
* Currently this method requires that the defining corners of the two Envelopes
* must all have the same CRS, otherwise an Exception is thrown.
* @param envelope1
* @param envelope2
* @return True if the Envelopes overlap
*/
public static boolean intersects(final Envelope envelope1, final Envelope envelope2) {
DirectPosition top1 = envelope1.getUpperCorner();
DirectPosition bot1 = envelope1.getLowerCorner();
DirectPosition top2 = envelope2.getUpperCorner();
DirectPosition bot2 = envelope2.getLowerCorner();
CoordinateReferenceSystem crs = top1.getCoordinateReferenceSystem();
if (!crs.equals(bot1.getCoordinateReferenceSystem())
|| !crs.equals(top2.getCoordinateReferenceSystem())
|| !crs.equals(bot2.getCoordinateReferenceSystem())) {
throw new IllegalArgumentException(
"Current implementation of GeoemtryUtils.intersect requires that the corners of both Envelopes have the same CRS");
}
double minx1 = bot1.getOrdinate(0);
double maxx1 = top1.getOrdinate(0);
double miny1 = bot1.getOrdinate(1);
double maxy1 = top1.getOrdinate(1);
double minx2 = bot2.getOrdinate(0);
double maxx2 = top2.getOrdinate(0);
double miny2 = bot2.getOrdinate(1);
double maxy2 = top2.getOrdinate(1);
boolean xoverlap = minx2 < maxx1 && maxx2 > minx1;
return xoverlap && (miny2 < maxy1 && maxy2 > miny1);
}
/**
* Converts a double array to an array of {@code DirectPosition}s.
* @param points the source data
* @param sourceDirections the source data's axes' directions
* @param sourceUnits the source data's axes' units
* @param crs the target {@code CoordinateReferenceSystem}. the {@code crs}'s
* dimension must match the 'dimension' in the source double array.
* @return an array of DirectPositions
*/
public static DirectPosition[] getDirectPositions(
final double[] points,
final AxisDirection[] sourceDirections,
final Unit[] sourceUnits,
final CoordinateReferenceSystem crs) {
int dimension = crs.getCoordinateSystem().getDimension();
int length = points.length / dimension;
DirectPosition[] returnable = new DirectPosition[length];
for (int i = 0; i < length; i++) {
LOGGER.fine("need to make a DirectPosition");
// umm, how am i gonna make a DirectPosition here?
//FactoryManager.getCommonFactory().getGeometryFactory(crs).createDirectPosition
}
return returnable;
}
/**
* Converts an array of {@code DirectPosition}s to a double array.
* @param positions the source data
* @param targetDirections the target data's axes' directions
* @param targetUnits the target data's axes' units
* @return an array of doubles
*/
public static double[] getPoints(
final DirectPosition[] positions,
final AxisDirection[] targetDirections,
final Unit[] targetUnits) {
// make our returnable array of doubles
int length = positions.length * targetDirections.length;
double[] returnable = new double[length];
// just get the first CRS from the first position
// these should be homogenous DirectPositions
CoordinateReferenceSystem crs = positions[0].getCoordinateReferenceSystem();
CoordinateSystem cs = crs.getCoordinateSystem();
int dimension = cs.getDimension();
// find the indices for the axes we want
int[] axisIndices = new int[targetDirections.length];
// also need the unit converters
UnitConverter[] converters = new UnitConverter[targetUnits.length];
// loop through the directions that were passed in
for (int i = 0; i < targetDirections.length; i++) {
// loop through the cs' axes, checking their direction.
// store the index once we've found it
boolean notfound = true;
for (int j = 0; notfound && j < dimension; j++) {
// if we match, store the axis' index and the converter
if (cs.getAxis(j).getDirection().equals(targetDirections[i])) {
axisIndices[i] = j;
converters[i] = cs.getAxis(j).getUnit().getConverterTo(targetUnits[i]);
notfound = false;
}
}
}
// now loop through the given directpositions
for (int i = 0; i < positions.length; i++) {
// loop through the position by dimension and store the converted ordinate
for (int j = 0; j < axisIndices.length; j++) {
returnable[(i * dimension) + j] = converters[j].convert(positions[i].getOrdinate(axisIndices[j]));
}
}
// return our fancy, new array of doubles
return returnable;
}
/**
* Verifies the CRS of the specified {@code DirectPosition} is
* WGS84, and returns it unmodified if it is.
* If not, transforms the input into a new DirectPosition
* with a WGS84 CRS. Returns it as a LatLonAlt if input was LatLonAlt.
* @param dp The DirectPosition to examine and transform if necessary
* @return The original DirectPosition if it was already WGS84,
* or the transformed DirectPosition.
*/
public static DirectPosition ensureWGS84(DirectPosition dp) {
CoordinateReferenceSystem crs = dp.getCoordinateReferenceSystem();
int dim = crs.getCoordinateSystem().getDimension();
CoordinateReferenceSystem bcrs = crs instanceof ProjectedCRS
? ((ProjectedCRS) crs).getBaseCRS() : crs;
GeographicCRS wgs84crs = CommonCRS.WGS84.geographic3D();
//have doubts about following line, was the commented out 2nd clause to condition doing anything - colin
if (bcrs.equals(wgs84crs)) { // || bcrs.equals(CRSUtils.WGS84_PROJ)) {
return dp;
}
//again, what does the follllowing achieve? - colin
if (bcrs.toWKT().indexOf("WGS84") > -1) {
return dp;
}
if (bcrs instanceof GeographicCRS) {
if (((GeographicCRS) bcrs).getDatum().equals(wgs84crs.getDatum())) {
return dp;
}
}
//not going to need CommonFactory.getCoordinateOperationFactory(),
//can use transform util in org.geotoolkit.referencing.CRS instaed
//CoordinateReferenceSystem crs2 = dim == 2 ? wgs84crs : CRSUtils.WGS84_PROJ;
//same equality issues as above
DirectPosition dp2 = new JTSGeometryFactory(wgs84crs).createDirectPosition();
try{
MathTransform transform = CRS.findOperation(crs, wgs84crs, null).getMathTransform();
transform.transform(dp, dp2);
} catch (FactoryException fe) {
LOGGER.log(Level.WARNING,"Could not create CoordinateOperation to convert DirectPosition CRS "
+ crs.getName() + " to WGS84, using original ordinates", fe);
//throw new IllegalArgumentException("Unconvertible coordinate CRS");
} catch (TransformException e) {
LOGGER.log(Level.WARNING,"Could not transform DirectPosition CRS "
+ crs.getName() + " to WGS84, using original ordinates", e);
//throw new IllegalArgumentException("Unconvertible coordinate CRS");
} catch (MismatchedDimensionException e) {
// PENDING(NL): There's probably something better we can do here
// than just throw an exception. Normally we only care about lat and lon,
// and if one has altitude and the other doesn't that shouldn't
// be a showstopper.
LOGGER.log(Level.WARNING,"Dimension mismatch prevented conversion of DirectPosition CRS "
+ crs.getName() + " to WGS84, using original ordinates", e);
//throw new IllegalArgumentException("Unconvertible coordinate CRS");
}
return dp2;
//hmm, not sure about following line,
//think the LatLongAlt class was specific to how the polexis code works
//and is not needed here
//boolean wasLatLonAlt = dp instanceof LatLongAlt;
/*
if (wasLatLonAlt) {
dp = commonFactory.getGeometryFactory(crs).createDirectPosition();
}
*/
/*
CommonFactory commonFactory = FactoryManager.getCommonFactory();
CoordinateOperationFactory coopFactory = commonFactory.getCoordinateOperationFactory();
try {
CoordinateReferenceSystem crs2 = dim == 2 ? wgs84crs : CRSUtils.WGS84_PROJ;
CoordinateOperation coOp = coopFactory.createOperation(crs, crs2);
DirectPosition dp2 = commonFactory.getGeometryFactory(crs2).createDirectPosition();
dp2 = coOp.getMathTransform().transform(dp, dp2);
if (dp2.getCoordinateReferenceSystem() != null) {
if (wasLatLonAlt) {
dp2 = new LatLonAlt(dp2);
}
return dp2;
} else {
getLog().warn(
"Attempted to convert coordinate CRS, transform method returned DirectPosition with null CRS, using original ordinates",
new IllegalArgumentException("Unconvertible coordinate CRS"));
}
} catch (FactoryException fe) {
getLog().warn("Could not create CoordinateOperation to convert DirectPosition CRS "
+ crs.getName() + " to WGS84, using original ordinates", fe);
//throw new IllegalArgumentException("Unconvertible coordinate CRS");
} catch (TransformException e) {
getLog().warn("Could not transform DirectPosition CRS "
+ crs.getName() + " to WGS84, using original ordinates", e);
//throw new IllegalArgumentException("Unconvertible coordinate CRS");
} catch (MismatchedDimensionException e) {
// PENDING(NL): There's probably something better we can do here
// than just throw an exception. Normally we only care about lat and lon,
// and if one has altitude and the other doesn't that shouldn't
// be a showstopper.
getLog().warn("Dimension mismatch prevented conversion of DirectPosition CRS "
+ crs.getName() + " to WGS84, using original ordinates", e);
//throw new IllegalArgumentException("Unconvertible coordinate CRS");
} catch (RuntimeException e) {
getLog().warn("Could not convert DirectPosition CRS "
+ crs.getName() + " to WGS84, using original ordinates", e);
//throw e;
}
return dp;*/
}
/**
* Populates the specified PointArray with the specified points. Any and all preexisting
* points in the PointArray will be overwritten.
* @param pointArray The PointArray to be populated. This must not be null.
* @param newPts The list of new points
* /
public static void populatePointArray(PointArray pointArray, List newPts) {
List pts = pointArray.positions();
pts.clear();
// PENDING(NL): Verify points are really DirectPositions --
// convert from Positions if not
// Probably should save this method for when we can use 1.5
pts.addAll(newPts);
}
*/
/**
* Populates the specified PointArray with the specified points. Any and all preexisting
* points in the PointArray will be overwritten.
* @param pointArray The PointArray to be populated. This must not be null.
* @param dps The new array of points
*/
public static void populatePointArray(final PointArray pointArray, final DirectPosition[] dps) {
List pts = pointArray.positions();
pts.clear();
int count = dps.length;
for (int i = 0; i < count; i++) {
pts.add(dps[i]);
}
}
/**
* Populates the specified PointArray with the specified points, starting at
* the specified index. Overwrites points with the specified index or higher.
* @param pointArray The PointArray to be populated. This must not be null.
* @param dps The array of points to be added
* @param startIndex The first position in the PointArray to overwrite
* @throws ArrayIndexOutOfBoundsException if the start index is negative or
* exceeds the number of points initially in the PointArray
* /
public static void populatePointArray(PointArray pointArray, DirectPosition[] dps,
int startIndex) {
if (startIndex < 0 || startIndex > pointArray.length()) {
throw new ArrayIndexOutOfBoundsException("Specified start index was "
+ startIndex + ", PointArray size was " + pointArray.length());
}
List pts = pointArray.positions();
pts.clear();
int count = dps.length;
for (int i = 0; i < count; i++) {
pointArray.set(i, dps[i]);
}
}
*/
/**
* Returns an array of LineCharSequences corresponding
* to the primitive elements of the specified CompositeCurve.
* This will be empty if the CompositeCurve is empty.
* Throws an exception if any element of the CompositeCurve cannot be converted
* to a LineString.
* @param cc The CompositeCurve of interest
* @return an array of LineCharSequences
* @throws IllegalArgumentException if any element cannot be converted.
* For the present version, only Curves that wrap only LineCharSequences are convertible.
*/
public static LineString[] getLineCharSequences(final CompositeCurve cc) {
ArrayList lsList = getLineCharSequences(cc, new ArrayList());
if (lsList == null) {
throw new IllegalArgumentException(
"Unable to convert all elements of CompositeCurve to LineString");
}
return (LineString[]) lsList.toArray(new LineString[lsList.size()]);
}
/**
* Recursively populates the specified List with LineCharSequences corresponding
* to the primitive elements of the specified CompositeCurve.
* Returns null if any element of the CompositeCurve cannot be converted
* to a LineString.
* @param cc The CompositeCurve of interest
* @param lsList The ArrayList to be populated
* @return The populated List, or null if not valid
*/
private static ArrayList getLineCharSequences(final CompositeCurve cc, final ArrayList lsList) {
// Cast below can be removed when Types will be allowed to abandon Java 1.4 support.
List elements = (List) cc.getGenerators();
boolean valid = true;
if (!elements.isEmpty()) {
Iterator it = elements.iterator();
LineString ls = null;
while (it.hasNext() && valid) {
Object element = it.next();
if (element instanceof CompositeCurve) {
valid = getLineCharSequences((CompositeCurve) element, lsList) != null;
} else if (element instanceof Curve) {
// PENDING(NL): When we have arc geometries implemented,
// make provision to pass in real parameters for spacing and offset.
// What we have below essentially just returns start and end points
// if it's not a LineString
ls = ((Curve) element).asLineString(Double.MAX_VALUE, Double.MAX_VALUE);
if (ls != null) {
lsList.add(ls);
} else {
valid = false;
}
} else {
valid = false;
}
}
}
if (valid) {
return null;
}
return lsList;
}
public static DirectPosition[] getDirectPositions(final LineString lineString) {
final PointArray controlPoints = lineString.getControlPoints();
final DirectPosition[] returnable = new DirectPosition[controlPoints.length()];
for (int i = 0; i < controlPoints.length(); i++) {
returnable[i] = controlPoints.getDirectPosition(i, null);
}
return returnable;
}
public static DirectPosition[] getDirectPositions(final Ring ring) {
final List directPositionList = new ArrayList();
// Cast below can be removed when Types will be allowed to abandon Java 1.4 support.
final List/*<Curve>*/ generators = (List) ring.getGenerators();
for (int i = 0; i < generators.size(); i++) {
final Curve curve = (Curve) generators.get(i);
final List/*<CurveSegments>*/ segments = curve.getSegments();
for (int j = 0; j < segments.size(); j++) {
final CurveSegment curveSegment = (CurveSegment) segments.get(j);
if (curveSegment instanceof LineString) {
final LineString lineString = (LineString) curveSegment;
final DirectPosition[] positions = getDirectPositions(lineString);
directPositionList.addAll(Arrays.asList(positions));
/*final List<Position> positions = lineString.getControlPoints().positions();
for (int k = 0; k < positions.size(); k++) {
Position position = (Position) positions.get(k);
directPositionList.add(position.getPosition());
}*/
}
}
}
if (directPositionList.size() > 0) {
return (DirectPosition[]) directPositionList.toArray(new DirectPosition[directPositionList.size()]);
}
return new DirectPosition[0];
}
public static DirectPosition[] getExteriorDirectPositions(final Polygon polygon) {
final SurfaceBoundary surfaceBoundary = polygon.getBoundary();
final Ring exteriorRing = surfaceBoundary.getExterior();
return GeometryUtils.getDirectPositions(exteriorRing);
}
public static DirectPosition[][] getInteriorDirectPositions(final Polygon polygon) {
final SurfaceBoundary surfaceBoundary = polygon.getBoundary();
final List interiorRings = surfaceBoundary.getInteriors();
final DirectPosition[][] returnable = new DirectPosition[interiorRings.size()][];
for (int i = 0; i < interiorRings.size(); i++) {
returnable[i] = getDirectPositions((Ring)interiorRings.get(i));
}
return returnable;
}
public static PolyhedralSurface createPolyhedralSurface(final DirectPosition[][] patchPoints) {
// get the crs and factories
final CoordinateReferenceSystem crs = patchPoints[0][0].getCoordinateReferenceSystem();
final GeometryFactory geometryFactory = new JTSGeometryFactory(crs);
// create polygons from each of the arrays of directPositions
final List polygons = new ArrayList(patchPoints.length);
for (int i = 0; i < patchPoints.length; i++) {
final Polygon polygon = createPolygon(patchPoints[i]);
polygons.add(polygon);
}
return geometryFactory.createPolyhedralSurface(polygons);
}
public static Polygon createPolygon(
final DirectPosition[] exteriorRing) {
return createPolygon(exteriorRing, new DirectPosition[0][0]);
}
public static Polygon createPolygon(
final DirectPosition[] exteriorRingPoints,
final DirectPosition[][] interiorRingsPoints) {
final CoordinateReferenceSystem crs = exteriorRingPoints[0].getCoordinateReferenceSystem();
final GeometryFactory geometryFactory = new JTSGeometryFactory(crs);
final PrimitiveFactory primitiveFactory = new JTSPrimitiveFactory(crs);
final Ring exteriorRing = createRing(primitiveFactory, exteriorRingPoints);
List interiorRingList = interiorRingsPoints.length == 0 ?
Collections.EMPTY_LIST :
new ArrayList(interiorRingsPoints.length);
for (int i = 0; i < interiorRingsPoints.length; i++) {
final DirectPosition[] interiorRingPoints = interiorRingsPoints[i];
interiorRingList.add(createRing(primitiveFactory,interiorRingPoints));
}
final SurfaceBoundary surfaceBoundary =
primitiveFactory.createSurfaceBoundary(exteriorRing, interiorRingList);
return geometryFactory.createPolygon(surfaceBoundary);
}
public static SurfaceBoundary createSurfaceBoundary(
final DirectPosition[] exteriorRingPoints,
final DirectPosition[][] interiorRingsPoints) {
final CoordinateReferenceSystem crs = exteriorRingPoints[0].getCoordinateReferenceSystem();
final PrimitiveFactory primitiveFactory = new JTSPrimitiveFactory(crs);
return createSurfaceBoundary(primitiveFactory, exteriorRingPoints, interiorRingsPoints);
}
private static SurfaceBoundary createSurfaceBoundary(
final PrimitiveFactory primitiveFactory,
final DirectPosition[] exteriorRingPoints,
final DirectPosition[][] interiorRingsPoints) {
final Ring exteriorRing = createRing(primitiveFactory, exteriorRingPoints);
final List interiorRingList = interiorRingsPoints.length == 0 ?
Collections.EMPTY_LIST :
new ArrayList();
for (int i = 0; i < interiorRingsPoints.length; i++) {
interiorRingList.add(createRing(primitiveFactory, interiorRingsPoints[i]));
}
final SurfaceBoundary surfaceBoundary =
primitiveFactory.createSurfaceBoundary(exteriorRing, interiorRingList);
return surfaceBoundary;
}
public static Ring createRing(final DirectPosition[] points) {
final CoordinateReferenceSystem crs = points[0].getCoordinateReferenceSystem();
final PrimitiveFactory primitiveFactory = new JTSPrimitiveFactory(crs);
return createRing(primitiveFactory, points);
}
private static Ring createRing(
final PrimitiveFactory primitiveFactory,
final DirectPosition[] points) {
final List curveList = Collections.singletonList(createCurve(primitiveFactory, points));
final Ring ring = primitiveFactory.createRing(curveList);
return ring;
}
public static Curve createCurve(final DirectPosition[] points) {
final CoordinateReferenceSystem crs = points[0].getCoordinateReferenceSystem();
final PrimitiveFactory primitiveFactory = new JTSPrimitiveFactory(crs);
return createCurve(primitiveFactory, points);
}
private static Curve createCurve(
final PrimitiveFactory primitiveFactory,
final DirectPosition[] points) {
final GeometryFactory geometryFactory = new JTSGeometryFactory(primitiveFactory.getCoordinateReferenceSystem());
final List curveSegmentList = Collections.singletonList(createLineString(geometryFactory, points));
final Curve curve = primitiveFactory.createCurve(curveSegmentList);
return curve;
}
public static LineString createLineString(final DirectPosition[] points) {
final CoordinateReferenceSystem crs = points[0].getCoordinateReferenceSystem();
final GeometryFactory geometryFactory = new JTSGeometryFactory(crs);
return createLineString(geometryFactory, points);
}
private static LineString createLineString(
final GeometryFactory geometryFactory,
final DirectPosition[] points) {
final LineString lineString = geometryFactory.createLineString(new ArrayList(Arrays.asList(points)));
return lineString;
}
/**
* Check if a reference coordinate system has the expected number of dimensions.
* - code lifted from com.polexis.referencing.CRSUtils - thanks Jesse!
* - not sure i see the need for both this method and CRS.ensureDimensionMatch()
*
* @param name The argument name.
* @param crs The coordinate reference system to check.
* @param expected The expected number of dimensions.
*/
public static void checkDimension(
final String name,
final CoordinateReferenceSystem crs,
final int expected) {
if (crs != null) {
final int actual = crs.getCoordinateSystem().getDimension();
if (actual != expected) {
throw new IllegalArgumentException(/*Resources.format(
ResourceKeys.ERROR_MISMATCHED_DIMENSION_3,
name, new Integer(actual), new Integer(expected))*/"");
}
}
}
/**
* Convenience method for checking object dimension validity.
* This method is usually invoked for argument checking.
*- code lifted from com.polexis.referencing.CRSUtils - thanks Jesse!
*
* @param name The name of the argument to check.
* @param dimension The object dimension.
* @param expectedDimension The Expected dimension for the object.
* @throws MismatchedDimensionException if the object doesn't have the expected dimension.
*/
public static void ensureDimensionMatch(
final String name,
final int dimension,
final int expectedDimension) throws MismatchedDimensionException {
if (dimension != expectedDimension) {
throw new MismatchedDimensionException(name + " does not have " + dimension + "dimension(s)"
/*
* Resources.format(
* ResourceKeys.ERROR_MISMATCHED_DIMENSION_3,
* name, new
* Integer(dimension), new
* Integer(expectedDimension))
*/);
}
}
/**
* Returns the {@code CoordinateSystemAxis} with the given {@code AxisDirection}.
* @param cs the {@code CoordinateSystem} to check
* @param direction the {@code AxisDirection} to check for
* @return CoordinateSystemAxis
*/
public static CoordinateSystemAxis getDirectedAxis(
final CoordinateSystem cs,
final AxisDirection direction) {
int dimension = cs.getDimension();
for (int i = 0; i < dimension; i++) {
if (cs.getAxis(i).getDirection().equals(direction)) {
return cs.getAxis(i);
}
}
return null;
}
/*
* reurns the index of an axis in a given coordinate system,
* axes are specified using org.opengis.referencing.cs.AxisDirection
* used by JTS geometry wrappers
* - code from com.polexis.referencing.cs.CSUtils
* - is AbstractCS a more appropriate place for this?
*/
public static int getDirectedAxisIndex(
final CoordinateSystem cs,
final AxisDirection direction) {
int dimension = cs.getDimension();
for (int i = 0; i < dimension; i++) {
if (cs.getAxis(i).getDirection().equals(direction)) {
return i;
}
}
return -1;
}
/*
* reurns the index of an axis in a given coordinate system,
* axes are specified using org.opengis.referencing.cs.AxisDirection
* used by JTS geometry wrappers
* - code from com.polexis.referencing.cs.CSUtils
* - is AbstractCS a more appropriate place for this?
*/
public static Unit getDirectedAxisUnit(
final CoordinateSystem cs,
final AxisDirection direction) {
CoordinateSystemAxis axis = getDirectedAxis(cs, direction);
if (axis != null) {
return axis.getUnit();
}
return null;
}
}