use of org.apache.sis.geometry.GeneralEnvelope in project sis by apache.
the class Java2D method tryGetEnvelope.
/**
* If the given object is a Java2D geometry and its envelope is non-empty, returns
* that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
*
* @param geometry the geometry from which to get the envelope, or {@code null}.
* @return the envelope of the given object, or {@code null} if the object is not
* a recognized geometry or its envelope is empty.
*/
@Override
final GeneralEnvelope tryGetEnvelope(final Object geometry) {
if (geometry instanceof Shape) {
final Rectangle2D bounds = ((Shape) geometry).getBounds2D();
if (!bounds.isEmpty()) {
// Test if there is NaN values.
final GeneralEnvelope env = new GeneralEnvelope(2);
env.setRange(0, bounds.getMinX(), bounds.getMaxX());
env.setRange(1, bounds.getMinY(), bounds.getMaxY());
return env;
}
}
return null;
}
use of org.apache.sis.geometry.GeneralEnvelope in project sis by apache.
the class EnvelopeOperationTest method run.
/**
* Implementation of the test methods.
*/
private static void run(final AbstractFeature feature) {
assertNull("Before a geometry is set", feature.getPropertyValue("bounds"));
GeneralEnvelope expected;
// Set one geometry
Polygon classes = new Polygon();
classes.startPath(10, 20);
classes.lineTo(10, 30);
classes.lineTo(15, 30);
classes.lineTo(15, 20);
feature.setPropertyValue("classes", classes);
expected = new GeneralEnvelope(HardCodedCRS.WGS84_φλ);
expected.setRange(0, 10, 15);
expected.setRange(1, 20, 30);
assertEnvelopeEquals(expected, (Envelope) feature.getPropertyValue("bounds"));
// Set second geometry
Point wall = new Point(18, 40);
feature.setPropertyValue("climbing wall", wall);
expected = new GeneralEnvelope(HardCodedCRS.WGS84_φλ);
expected.setRange(0, 10, 18);
expected.setRange(1, 20, 40);
assertEnvelopeEquals(expected, (Envelope) feature.getPropertyValue("bounds"));
// Set third geometry. This geometry has CRS axis order reversed.
Polygon gymnasium = new Polygon();
gymnasium.startPath(-5, -30);
gymnasium.lineTo(-6, -30);
gymnasium.lineTo(-6, -31);
gymnasium.lineTo(-5, -31);
feature.setPropertyValue("gymnasium", gymnasium);
expected = new GeneralEnvelope(HardCodedCRS.WGS84_φλ);
expected.setRange(0, -31, 18);
expected.setRange(1, -6, 40);
assertEnvelopeEquals(expected, (Envelope) feature.getPropertyValue("bounds"));
}
use of org.apache.sis.geometry.GeneralEnvelope in project sis by apache.
the class LinearTransformBuilder method getSourceEnvelope.
/**
* Returns the envelope of source points. The lower and upper values are inclusive.
*
* @return the envelope of source points.
* @throws IllegalStateException if the source points are not yet known.
*
* @since 1.0
*/
public Envelope getSourceEnvelope() {
if (gridSize != null) {
final int dim = gridSize.length;
final GeneralEnvelope envelope = new GeneralEnvelope(dim);
for (int i = 0; i < dim; i++) {
envelope.setRange(i, 0, gridSize[i] - 1);
}
return envelope;
} else {
return envelope(sources);
}
}
use of org.apache.sis.geometry.GeneralEnvelope in project sis by apache.
the class Store method parseEnvelope.
/**
* Parses the envelope described by the header line starting with {@code @stboundedby}.
* The envelope returned by this method will be stored in the {@link #envelope} field.
*
* <p>Example:</p>
* {@preformat text
* @stboundedby, urn:ogc:def:crs:CRS:1.3:84, 2D, 50.23 9.23, 50.31 9.27, 2012-01-17T12:33:41Z, 2012-01-17T12:37:00Z, sec
* }
*
* This method sets {@link #timeEncoding} and {@link #spatialDimensionCount} as a side-effect.
*
* @param elements the line elements. The first elements should be {@code "@stboundedby"}.
* @return the envelope, or {@code null} if the given list does not contain enough elements.
*/
@SuppressWarnings("fallthrough")
private GeneralEnvelope parseEnvelope(final List<String> elements) throws DataStoreException, FactoryException {
CoordinateReferenceSystem crs = null;
int spatialDimensionCount = 2;
boolean isDimExplicit = false;
double[] lowerCorner = ArraysExt.EMPTY_DOUBLE;
double[] upperCorner = ArraysExt.EMPTY_DOUBLE;
Instant startTime = null;
Instant endTime = null;
Unit<Time> timeUnit = Units.SECOND;
boolean isTimeAbsolute = false;
int ordinal = -1;
for (final String element : elements) {
ordinal++;
if (!element.isEmpty()) {
switch(ordinal) {
// The "@stboundedby" header.
case 0:
continue;
case 1:
crs = CRS.forCode(element);
continue;
case 2:
if (element.length() == 2 && Character.toUpperCase(element.charAt(1)) == 'D') {
isDimExplicit = true;
spatialDimensionCount = element.charAt(0) - '0';
if (spatialDimensionCount < 1 || spatialDimensionCount > 3) {
throw new DataStoreReferencingException(errors().getString(Errors.Keys.IllegalCoordinateSystem_1, element));
}
continue;
}
/*
* According the Moving Feature specification, the [dim] element is optional.
* If we did not recognized the dimension, assume that we have the next element
* (i.e. the lower corner). Fall-through so we can process it.
*/
// Fall through
ordinal++;
case 3:
lowerCorner = CharSequences.parseDoubles(element, ORDINATE_SEPARATOR);
continue;
case 4:
upperCorner = CharSequences.parseDoubles(element, ORDINATE_SEPARATOR);
continue;
case 5:
startTime = Instant.parse(element);
continue;
case 6:
endTime = Instant.parse(element);
continue;
case 7:
switch(element.toLowerCase(Locale.US)) {
case "sec":
case "second":
/* Already SECOND. */
continue;
case "minute":
timeUnit = Units.MINUTE;
continue;
case "hour":
timeUnit = Units.HOUR;
continue;
case "day":
timeUnit = Units.DAY;
continue;
case "absolute":
isTimeAbsolute = true;
continue;
default:
throw new DataStoreReferencingException(errors().getString(Errors.Keys.UnknownUnit_1, element));
}
}
// If we reach this point, there is some remaining unknown elements. Ignore them.
break;
}
}
/*
* Complete the CRS by adding a vertical component if needed, then a temporal component.
* Only after the CRS has been completed we can create the envelope.
*
* Vertical component:
* Ideally, should be part of the CRS created from the authority code. But if the authority
* code is only for a two-dimensional CRS, we default to an arbitrary height component.
*
* Temporal component:
* Assumed never part of the authority code. We need to build the temporal component ourselves
* in order to set the origin to the start time.
*/
final GeneralEnvelope envelope;
if (crs != null) {
int count = 0;
final CoordinateReferenceSystem[] components = new CoordinateReferenceSystem[3];
components[count++] = crs;
/*
* If the coordinates are three-dimensional but the CRS is 2D, add a vertical axis.
* The vertical axis shall be the third one, however we do not enforce that rule
* since Apache SIS should work correctly even if the vertical axis is elsewhere.
*/
int dimension = crs.getCoordinateSystem().getDimension();
if (isDimExplicit) {
if (spatialDimensionCount > dimension) {
components[count++] = CommonCRS.Vertical.MEAN_SEA_LEVEL.crs();
dimension++;
}
if (dimension != spatialDimensionCount) {
throw new DataStoreReferencingException(errors().getString(Errors.Keys.MismatchedDimension_3, "@stboundedby(CRS)", spatialDimensionCount, dimension));
}
}
if (dimension > Short.MAX_VALUE) {
throw new DataStoreReferencingException(errors().getString(Errors.Keys.ExcessiveNumberOfDimensions_1, dimension));
}
spatialDimensionCount = dimension;
/*
* Add a temporal axis if we have a start time (no need for end time).
* This block presumes that the CRS does not already have a time axis.
* If a time axis was already present, an exception will be thrown at
* builder.createCompoundCRS(…) invocation time.
*/
final GeodeticObjectBuilder builder = new GeodeticObjectBuilder();
String name = crs.getName().getCode();
if (startTime != null) {
final TemporalCRS temporal;
if (isTimeAbsolute) {
temporal = TimeEncoding.DEFAULT.crs();
timeEncoding = TimeEncoding.ABSOLUTE;
} else {
temporal = builder.createTemporalCRS(Date.from(startTime), timeUnit);
timeEncoding = new TimeEncoding(temporal.getDatum(), timeUnit);
}
components[count++] = temporal;
name = name + " + " + temporal.getName().getCode();
}
crs = builder.addName(name).createCompoundCRS(ArraysExt.resize(components, count));
envelope = new GeneralEnvelope(crs);
} else {
/*
* While illegal in principle, Apache SIS accepts missing CRS.
* In such case, use only the number of dimensions.
*/
int dim = spatialDimensionCount;
// Same criterion than in above block.
if (startTime != null)
dim++;
envelope = new GeneralEnvelope(dim);
}
/*
* At this point we got the three- or four-dimensional spatio-temporal CRS.
* We can now set the envelope coordinate values, including temporal values.
*/
int dim;
if ((dim = lowerCorner.length) != spatialDimensionCount || (dim = upperCorner.length) != spatialDimensionCount) {
throw new DataStoreReferencingException(errors().getString(Errors.Keys.MismatchedDimension_3, "@stboundedby(BBOX)", spatialDimensionCount, dim));
}
for (int i = 0; i < spatialDimensionCount; i++) {
envelope.setRange(i, lowerCorner[i], upperCorner[i]);
}
if (startTime != null) {
envelope.setRange(spatialDimensionCount, timeEncoding.toCRS(startTime.toEpochMilli()), (endTime == null) ? Double.NaN : timeEncoding.toCRS(endTime.toEpochMilli()));
}
this.spatialDimensionCount = (short) spatialDimensionCount;
return envelope;
}
use of org.apache.sis.geometry.GeneralEnvelope in project sis by apache.
the class ESRI method tryGetEnvelope.
/**
* If the given object is an ESRI geometry and its envelope is non-empty, returns
* that envelope as an Apache SIS implementation. Otherwise returns {@code null}.
*
* @param geometry the geometry from which to get the envelope, or {@code null}.
* @return the envelope of the given object, or {@code null} if the object is not
* a recognized geometry or its envelope is empty.
*/
@Override
final GeneralEnvelope tryGetEnvelope(final Object geometry) {
if (geometry instanceof Geometry) {
final Envelope2D bounds = new Envelope2D();
((Geometry) geometry).queryEnvelope2D(bounds);
if (!bounds.isEmpty()) {
// Test if there is NaN values.
final GeneralEnvelope env = new GeneralEnvelope(2);
env.setRange(0, bounds.xmin, bounds.xmax);
env.setRange(1, bounds.ymin, bounds.ymax);
return env;
}
}
return null;
}
Aggregations