Skip to content

Commit

Permalink
Fix ticket orbisgis#96 add Extent to CRS
Browse files Browse the repository at this point in the history
  • Loading branch information
mukoki committed Dec 28, 2019
1 parent 1bced33 commit ea5d4c6
Show file tree
Hide file tree
Showing 9 changed files with 290 additions and 73 deletions.
43 changes: 24 additions & 19 deletions src/main/java/org/cts/crs/CoordinateReferenceSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import org.cts.Identifiable;
import org.cts.cs.CoordinateSystem;
import org.cts.cs.Extent;
import org.cts.datum.Datum;
import org.cts.op.projection.Projection;

Expand All @@ -47,50 +48,54 @@
*
* @author Michaël Michaud
*/
public interface CoordinateReferenceSystem extends Identifiable {
public interface CoordinateReferenceSystem extends Identifiable, Extent {

/**
* Coordinate Reference System Type.
*/
public enum Type {
enum Type {

GEOCENTRIC, GEOGRAPHIC3D, GEOGRAPHIC2D, PROJECTED, VERTICAL, COMPOUND, ENGINEERING
}

/**
* Returns this CoordinateReferenceSystem Type.
* @return
* Returns this <code>CoordinateReferenceSystem.Type</code>.
*/
public Type getType();
Type getType();

/**
* Returns the {@link CoordinateSystem} used by this
* <code>CoordinateReferenceSystem</code>.
* @return
*/
public CoordinateSystem getCoordinateSystem();
CoordinateSystem getCoordinateSystem();

/**
* Returns the {@link Datum} to which this
* <code>CoordinateReferenceSystem</code> is refering. For compound
* <code>CoordinateReferenceSystem</code>, getDatum returns the the main
* datum, ie the {@link org.cts.datum.GeodeticDatum} (or horizontal Datum).
* @return
* <code>CoordinateReferenceSystem</code> refers.
* For compound <code>CoordinateReferenceSystem</code>, getDatum returns the
* main datum, ie the {@link org.cts.datum.GeodeticDatum} (or horizontal Datum).
*/
public Datum getDatum();
Datum getDatum();

/**
* Returns the {@link Projection} to which this
* <code>CoordinateReferenceSystem</code> is refering. It returns null if no
* <code>CoordinateReferenceSystem</code> refers. It returns null if no
* projection is defined for this CRS.
* @return
* @return the {@link Projection} used by this
* <code>CoordinateReferenceSystem</code> or null.
*/
public Projection getProjection();
Projection getProjection();

/**
* Returns a WKT representation of the CoordinateReferenceSystem.
*
* @return
* Returns a WKT representation of this <code>CoordinateReferenceSystem</code>.
*/
public String toWKT();
String toWKT();

/**
* Returns whether coord is inside this Extent or not. It's up to the user to
* check consistency between coord and extent type.
*/
default boolean isInside(double[] coord) {
return true;
}
}
22 changes: 12 additions & 10 deletions src/main/java/org/cts/crs/GeocentricCRS.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ public class GeocentricCRS extends GeodeticCRS {
/**
* A 3D cartesian {@link CoordinateSystem}.
*/
public static final CoordinateSystem XYZ = new CoordinateSystem(new Axis[]{X, Y, Z}, new Unit[]{METER, METER, METER});
public static final CoordinateSystem XYZ =
new CoordinateSystem(new Axis[]{X, Y, Z}, new Unit[]{METER, METER, METER});

/**
* Returns this CoordinateReferenceSystem Type.
* @return
* @see CoordinateReferenceSystem#getType().
*/
@Override
public Type getType() {
Expand Down Expand Up @@ -92,12 +92,14 @@ public GeocentricCRS(Identifier identifier, GeodeticDatum datum,
}

/**
* @return
* Creates a CoordinateOperation to transform coordinates from this
* <code>GeocentricCRS</code> to the associated <code>Geographic3DCRS</code>.
*
* @see GeodeticCRS#toGeographicCoordinateConverter()
*/
@Override
public CoordinateOperation toGeographicCoordinateConverter() {
List<CoordinateOperation> ops = new ArrayList<CoordinateOperation>();
List<CoordinateOperation> ops = new ArrayList<>();
ops.add(new Geocentric2Geographic(getDatum().getEllipsoid()));
if (!getDatum().getPrimeMeridian().equals(PrimeMeridian.GREENWICH)) {
ops.add(LongitudeRotation.getLongitudeRotationTo(getDatum().getPrimeMeridian()));
Expand All @@ -107,12 +109,14 @@ public CoordinateOperation toGeographicCoordinateConverter() {
}

/**
* @return
* Creates a CoordinateOperation to transform coordinates from the associated
* <code>Geographic3DCRS</code> to this <code>GeocentricCRS</code>.
*
* @see GeodeticCRS#fromGeographicCoordinateConverter()
*/
@Override
public CoordinateOperation fromGeographicCoordinateConverter() {
List<CoordinateOperation> ops = new ArrayList<CoordinateOperation>();
List<CoordinateOperation> ops = new ArrayList<>();
if (!getDatum().getPrimeMeridian().equals(PrimeMeridian.GREENWICH)) {
ops.add(LongitudeRotation.getLongitudeRotationFrom(getDatum().getPrimeMeridian()));
}
Expand All @@ -122,9 +126,7 @@ public CoordinateOperation fromGeographicCoordinateConverter() {
}

/**
* Returns a WKT representation of the geocentric CRS.
*
* @return
* @see CoordinateReferenceSystem#toWKT()
*/
public String toWKT() {
StringBuilder w = new StringBuilder();
Expand Down
76 changes: 55 additions & 21 deletions src/main/java/org/cts/crs/GeodeticCRS.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,14 @@

import org.cts.IdentifiableComponent;
import org.cts.Identifier;
import org.cts.IllegalCoordinateException;
import org.cts.cs.CoordinateSystem;
import org.cts.cs.Extent;
import org.cts.datum.GeodeticDatum;
import org.cts.op.CoordinateOperation;
import org.cts.op.CoordinateOperationException;
import org.cts.op.projection.Projection;
import org.cts.units.Unit;

/**
* A {@link org.cts.crs.CoordinateReferenceSystem} based on a
Expand Down Expand Up @@ -61,6 +64,8 @@ public Projection getProjection() {
*/
protected CoordinateSystem coordinateSystem;

private Extent extent;

/**
* Creates a new GeodeticCRS.
*
Expand Down Expand Up @@ -89,34 +94,64 @@ public CoordinateSystem getCoordinateSystem() {

/**
* Returns the {@link org.cts.datum.Datum} to which this
* <code>CoordinateReferenceSystem</code> is refering.
* <code>CoordinateReferenceSystem</code> refers.
*/
public GeodeticDatum getDatum() {
return geodeticDatum;
}

/**
* Return whether this coord is a valid coord in this
* CoordinateReferenceSystem.
* Return whether the coord is within this CRS's extent or not.
*
* @param coord standard coordinate for this CoordinateReferenceSystem
* datums (ex. decimal degrees for geographic datums and meters for vertical
* datums).
* @param coord coordinates to test
*/
//@TODO Clarify : geodeticDatum.getExtent().isInside does not use coordinates
// expressed with this CoordinateReferenceSystem
// Do we have to convert coord to a decimal degree or radian Geographic CRS first ?
//public boolean isValid(double[] coord) {
// return geodeticDatum.getExtent().isInside(coord);
//}
public boolean isInside(double[] coord) {
return extent == null || extent.isInside(coord);
}

/**
* Set this <code>CoordinateReferenceSystem</code>'s extent from min and max coordinates
* expressed in this CoordinateReferenceSystem.
* @param min min ordinates along each axis
* @param max max ordinates along each axis
*/
public void setExtent(double[] min, double[] max) {
this.extent = new Extent() {
public String getName() { return ""; }
public boolean isInside(double[] coord) {
for (int i = 0 ; i < Math.min(coord.length, min.length) ; i++) {
if (coord[i] < min[i] || coord[i] > max[i]) return false;
}
return true;
}
};
}

/**
* Set this <code>CoordinateReferenceSystem</code>'s extent from min and max
* longitude and latitude in degrees
* @param minLon minimum longitude
* @param minLat minimum latitude
* @param maxLon maximum longitude
* @param maxLat maximum latitude
*/
public void setExtent(double minLon, double minLat, double maxLon, double maxLat)
throws CoordinateOperationException, IllegalCoordinateException {
CoordinateOperation op = fromGeographicCoordinateConverter();
double[] minLocal = op.transform(new double[]{Unit.DEGREE.toBaseUnit(minLat), Unit.DEGREE.toBaseUnit(minLon)});
double[] maxLocal = op.transform(new double[]{Unit.DEGREE.toBaseUnit(maxLat), Unit.DEGREE.toBaseUnit(maxLon)});
setExtent(minLocal, maxLocal);
}

/**
* Creates a CoordinateOperation object to convert coordinates from this
* CoordinateReferenceSystem to a {@link org.cts.crs.Geographic3DCRS} based on
* the same {@link org.cts.datum.GeodeticDatum}, and using normal SI units in the
* following order : latitude (rad), longitude (rad) height (m).
* @return
* @throws org.cts.op.CoordinateOperationException
*
* @throws org.cts.op.CoordinateOperationException if an exception occurs
* during the computation of the <code>CoordinateOperation</code> to be used
* to convert coordinates to the associated <code>Geographic3DCRS</code>
*/
abstract public CoordinateOperation toGeographicCoordinateConverter()
throws CoordinateOperationException;
Expand All @@ -126,20 +161,21 @@ abstract public CoordinateOperation toGeographicCoordinateConverter()
* {@link org.cts.crs.Geographic3DCRS} based on the same {@link org.cts.datum.GeodeticDatum},
* and using normal SI units in the following order : latitude (rad),
* longitude (rad) height (m) to this CoordinateReferenceSystem.
* @return
* @throws org.cts.op.CoordinateOperationException
*
* @throws org.cts.op.CoordinateOperationException if an exception occurs
* during the computation of the <code>CoordinateOperation</code> to be used
* to convert coordinates from the associated <code>Geographic3DCRS</code>
*/
abstract public CoordinateOperation fromGeographicCoordinateConverter()
throws CoordinateOperationException;

/**
* Returns a WKT representation of the geodetic CRS.
* @see CoordinateReferenceSystem#toWKT()
*/
public abstract String toWKT();

/**
* Return a String representation of this Datum.
* @return
* Returns a String representation of this Datum.
*/
@Override
public String toString() {
Expand All @@ -153,7 +189,6 @@ public String toString() {
* the {@link GeodeticDatum}, the {@link CoordinateSystem}.
*
* @param o The object to compare this GeodeticCRS against
* @return
*/
@Override
public boolean equals(Object o) {
Expand All @@ -177,7 +212,6 @@ public boolean equals(Object o) {

/**
* Returns the hash code for this GeodeticCRS.
* @return
*/
@Override
public int hashCode() {
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/org/cts/cs/Extent.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ public interface Extent {
/**
* Return the name of this extent.
*/
public String getName();
String getName();

/**
* Return wether coord is inside this Extent or not. It's up to the user to
* Returns wether coord is inside this Extent or not. It's up to the user to
* check consistency between coord and extent type.
*/
public boolean isInside(double[] coord);
boolean isInside(double[] coord);
}
67 changes: 67 additions & 0 deletions src/main/java/org/cts/op/CheckInExtentCoordinateOperation.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package org.cts.op;

import org.cts.Identifier;
import org.cts.IllegalCoordinateException;
import org.cts.crs.CoordinateReferenceSystem;
import org.cts.cs.Extent;

import java.util.Arrays;


public class CheckInExtentCoordinateOperation extends AbstractCoordinateOperation {

Extent extent;

public CheckInExtentCoordinateOperation(CoordinateReferenceSystem crs) {
super(new Identifier(CoordinateOperation.class, "extent of '" + crs.getName() + "'"));
this.extent = crs;
}

/**
* Check if coord lies in extent. If it is inside, coord is returned as is,
* else, a IllegalCoordinateException is thrown.
*
* @param coord coordinate to check
* @return the same coordinates array
* @throws IllegalCoordinateException if <code>coord</code> does not lie in extent.
* @throws org.cts.op.CoordinateOperationException if this operation
* failed during the transformation process.
*/
public double[] transform(double[] coord) throws IllegalCoordinateException {
if (extent == null || extent.isInside(coord)) return coord;
throw new IllegalCoordinateException("Coord " + Arrays.toString(coord) + " is not within " + getName());
}

/**
* Return the inverse CoordinateOperation, or throw a
* NonInvertibleOperationException. If op.inverse() is not null,
* <pre>
* op.inverse().transform(op.transform(point));
* </pre> should let point unchanged.
*/
public CoordinateOperation inverse() {
return this;
}

///**
// * Returns the maximum precision
// */
//public double getPrecision() {
// return 1E-9;
//}

///**
// * @return true if this operation does not change coordinates.
// */
//public boolean isIdentity() {
// return true;
//}

/**
* Returns whether coord is consistent with source and target CRS.
*/
//public boolean isInside(double[] coord) {
// if (extent == null || extent.isInside(coord)) return true;
// throw new IllegalCoordinateException("Coordinates " + coord + " does not lie in extent");
//}
}
Loading

0 comments on commit ea5d4c6

Please sign in to comment.