use of org.apache.sis.referencing.GeodeticCalculator in project geotoolkit by Geomatys.
the class JTS method orthodromicDistance.
/**
* Computes the orthodromic distance between two points. This method: <p>
* <ol> <li>Transforms both points to geographic coordinates
* (<var>latitude</var>,<var>longitude</var>).</li> <li>Computes the
* orthodromic distance between the two points using ellipsoidal
* calculations.</li> </ol> <p> The real work is performed by
* {@link GeodeticCalculator}. This convenience method simply manages a pool
* of pre-defined geodetic calculators for the given coordinate reference
* system in order to avoid repetitive object creation. If a large amount of
* orthodromic distances need to be computed, direct use of
* {@link GeodeticCalculator} provides better performance than this
* convenience method.
*
* @param p1 First point
* @param p2 Second point
* @param crs Reference system the two points are in.
* @return Orthodromic distance between the two points, in meters.
* @throws TransformException if the coordinates can't be transformed from
* the specified CRS to a
* {@linkplain org.opengis.referencing.crs.GeographicCRS geographic CRS}.
*/
public static synchronized double orthodromicDistance(final Coordinate p1, final Coordinate p2, final CoordinateReferenceSystem crs) throws TransformException {
ensureNonNull("p1", p1);
ensureNonNull("p2", p2);
ensureNonNull("crs", crs);
/*
* Need to synchronize because we use a single instance of a Map (CALCULATORS) as well as
* shared instances of GeodeticCalculator and GeneralDirectPosition (POSITIONS). None of
* them are thread-safe.
*/
GeodeticCalculator gc = CALCULATORS.get(crs);
if (gc == null) {
gc = GeodeticCalculator.create(crs);
CALCULATORS.put(crs, gc);
}
assert crs.equals(gc.getPositionCRS()) : crs;
final GeneralDirectPosition pos = POSITIONS[Math.min(POSITIONS.length - 1, crs.getCoordinateSystem().getDimension())];
pos.setCoordinateReferenceSystem(crs);
copy(p1, pos.coordinates);
gc.setStartPoint(pos);
copy(p2, pos.coordinates);
gc.setEndPoint(pos);
return gc.getGeodesicDistance();
}
use of org.apache.sis.referencing.GeodeticCalculator in project geotoolkit by Geomatys.
the class GeometryTransformer method drawArc.
/**
* Draw a succession of segments representing an arc or a circle.
* @implNote
* This method checks given angles to ensure that a full circle is drawn using
* the strict necessary amount of points.
*
* @param center The center point of the arc to draw. The unit of measure MUST
* be consistent with the unit of given radius.
* @param radius The Radius of the arc to draw. Unit must be the same as the
* one of input center point.
* @param startAzimuth Start of the drawn line relative to the geographic north (clockwise order).
* @param endAzimuth End of the drawn line relative to the geographic north (clockwise order). If
* it's inferior to start angle, the arc is drawn on counter-clockwise order. If superior, the arc is
* drawn on clockwise order.
* @param angularStep The step to apply on the trigonometric circle to find
* next point of the arc. its sign will be adapted to match draw order (clockwise
* or counter clockwise).
* @return An arc, as a discrete succession of points of configured precision.
*/
private static Coordinate[] drawArc(final DirectPosition center, final Measure radius, final Measure startAzimuth, final Measure endAzimuth, final Measure angularStep) throws TransformException {
ArgumentChecks.ensureNonNull("Center point", center);
final CoordinateReferenceSystem sourceCrs = center.getCoordinateReferenceSystem();
ArgumentChecks.ensureNonNull("coordinate reference system", sourceCrs);
final SingleCRS hCrs = CRS.getHorizontalComponent(sourceCrs);
if (hCrs == null) {
throw new UnconvertibleObjectException("Cannot extract geometries without projected part.");
}
final int xAxis = AxisDirections.indexOfColinear(sourceCrs.getCoordinateSystem(), hCrs.getCoordinateSystem());
final int yAxis = xAxis + 1;
final GeodeticCalculator gc = GeodeticCalculator.create(sourceCrs);
gc.setStartPoint(center);
final Unit<Length> radiusUnit = gc.getDistanceUnit();
final double r = radius.getUnit(Length.class).getConverterTo(radiusUnit).convert(radius.value);
double theta = startAzimuth.getUnit(Angle.class).getConverterTo(Units.DEGREE).convert(startAzimuth.value);
double end = endAzimuth.getUnit(Angle.class).getConverterTo(Units.DEGREE).convert(endAzimuth.value);
double phi = end - theta;
// Draw a circle. We don"t bother preserving iteration order
double positivePhi = Math.abs(phi);
final boolean isCircle = positivePhi - 1e-8 <= 0 || positivePhi >= 360.0;
if (isCircle) {
phi = 360.0;
}
double step = (phi < 0 ? -1 : 1) * angularStep.getUnit(Angle.class).getConverterTo(Units.DEGREE).convert(angularStep.value);
if ((phi / step) < 3) {
step = phi / 3;
}
final Coordinate[] arcPerimeter = new Coordinate[(int) Math.ceil(phi / step) + 1];
final DoubleFunction<Coordinate> pointOnCircle = azimuth -> {
azimuth = ((azimuth + 180) % 360) - 180;
gc.setStartingAzimuth(azimuth);
gc.setGeodesicDistance(r);
final DirectPosition pt = gc.getEndPoint();
return new Coordinate(pt.getOrdinate(xAxis), pt.getOrdinate(yAxis));
};
/* Don't entirely fill array. Last point will be computed in a sepcial case,
* to ensure it's closed properly if it's a circle.
*/
for (int i = 0; i < arcPerimeter.length - 1; i++, theta += step) {
arcPerimeter[i] = pointOnCircle.apply(theta);
}
if (isCircle) {
// Ensure last point is the start point
arcPerimeter[arcPerimeter.length - 1] = arcPerimeter[0];
} else {
arcPerimeter[arcPerimeter.length - 1] = pointOnCircle.apply(end);
}
return arcPerimeter;
}
use of org.apache.sis.referencing.GeodeticCalculator in project geotoolkit by Geomatys.
the class MeasureUtilities method calculateLenght.
public static double calculateLenght(final Geometry geom, final CoordinateReferenceSystem geomCRS, final Unit<Length> unit) {
if (geom == null || !(geom instanceof LineString))
return 0;
final LineString line = (LineString) geom;
Coordinate[] coords = line.getCoordinates();
try {
final GeodeticCalculator calculator = GeodeticCalculator.create(geomCRS);
final GeneralDirectPosition pos = new GeneralDirectPosition(geomCRS);
double length = 0;
for (int i = 0, n = coords.length - 1; i < n; i++) {
Coordinate coord1 = coords[i];
Coordinate coord2 = coords[i + 1];
pos.coordinates[0] = coord1.x;
pos.coordinates[1] = coord1.y;
calculator.setStartPoint(pos);
pos.coordinates[0] = coord2.x;
pos.coordinates[1] = coord2.y;
calculator.setEndPoint(pos);
length += calculator.getGeodesicDistance();
}
if (!Units.METRE.equals(unit)) {
UnitConverter converter = Units.METRE.getConverterTo(unit);
length = converter.convert(length);
}
return length;
} catch (MismatchedDimensionException ex) {
LOGGER.log(Level.WARNING, null, ex);
}
return 0;
}
use of org.apache.sis.referencing.GeodeticCalculator in project geotoolkit by Geomatys.
the class CanvasUtilities method getGeographicScale.
/**
* Returns the geographic scale, in a ground unit manner, relation between map display size
* and real ground unit meters.
*
* @throws IllegalStateException If the affine transform used for conversion is in illegal state.
*/
public static double getGeographicScale(Point2D center, AffineTransform2D objToDisp, CoordinateReferenceSystem crs) throws TransformException {
final double[] P1 = new double[] { center.getX(), center.getY() };
final double[] P2 = new double[] { P1[0], P1[1] + 1 };
final AffineTransform trs;
try {
trs = objToDisp.createInverse();
} catch (NoninvertibleTransformException ex) {
throw new TransformException(ex.getLocalizedMessage(), ex);
}
trs.transform(P1, 0, P1, 0, 1);
trs.transform(P2, 0, P2, 0, 1);
final Unit unit = crs.getCoordinateSystem().getAxis(0).getUnit();
final double distance;
if (unit.isCompatible(Units.METRE)) {
final Point2D p1 = new Point2D.Double(P1[0], P1[1]);
final Point2D p2 = new Point2D.Double(P2[0], P2[1]);
final UnitConverter conv = unit.getConverterTo(Units.METRE);
distance = conv.convert(p1.distance(p2));
} else {
/*
* If the latitude coordinates (for example) are outside the +/-90°
* range, translate the points in order to bring them back in the
* domain of validity.
*/
final CoordinateSystem cs = crs.getCoordinateSystem();
for (int i = cs.getDimension(); --i >= 0; ) {
final CoordinateSystemAxis axis = cs.getAxis(i);
double delta = P1[i] - axis.getMaximumValue();
if (delta > 0) {
P1[i] -= delta;
P2[i] -= delta;
}
delta = P2[i] - axis.getMaximumValue();
if (delta > 0) {
P1[i] -= delta;
P2[i] -= delta;
}
delta = axis.getMinimumValue() - P1[i];
if (delta > 0) {
P1[i] += delta;
P2[i] += delta;
}
delta = axis.getMinimumValue() - P2[i];
if (delta > 0) {
P1[i] += delta;
P2[i] += delta;
}
}
final GeodeticCalculator gc = GeodeticCalculator.create(crs);
final GeneralDirectPosition pos1 = new GeneralDirectPosition(crs);
pos1.setOrdinate(0, P1[0]);
pos1.setOrdinate(1, P1[1]);
final GeneralDirectPosition pos2 = new GeneralDirectPosition(crs);
pos2.setOrdinate(0, P2[0]);
pos2.setOrdinate(1, P2[1]);
try {
gc.setStartPoint(pos1);
gc.setEndPoint(pos2);
} catch (IllegalArgumentException ex) {
// the coordinate can be out of the crs area, which causes this exception
throw new TransformException(ex.getLocalizedMessage(), ex);
}
distance = gc.getGeodesicDistance();
}
final double displayToDevice = 1f / DEFAULT_DPI * 0.0254f;
return distance / displayToDevice;
}
Aggregations