Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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