package org.osm2world.core.map_data.creation;
import static org.osm2world.core.map_data.creation.MercatorProjection.*;
import org.osm2world.core.math.VectorXZ;
/**
* Map projection that is intended to use the "dense" space
* of floating point values by making all coordinates relative to
* the origin. 1 meter distance is roughly represented by 1 internal unit.
*/
public class MetricMapProjection extends OriginMapProjection {
private double originX;
private double originY;
private double scaleFactor;
public VectorXZ calcPos(double lat, double lon) {
double x = lonToX(lon) * scaleFactor - originX;
double y = latToY(lat) * scaleFactor - originY;
/* snap to som cm precision, seems to reduce geometry exceptions */
x = Math.round(x * 1000) / 1000.0d;
y = Math.round(y * 1000) / 1000.0d;
return new VectorXZ(x, y); // x and z(!) are 2d here
}
@Override
public VectorXZ calcPos(LatLon latlon) {
return calcPos(latlon.lat, latlon.lon);
}
@Override
public double calcLat(VectorXZ pos) {
return yToLat((pos.z + originY) / scaleFactor);
}
@Override
public double calcLon(VectorXZ pos) {
return xToLon((pos.x + originX) / scaleFactor);
}
@Override
public VectorXZ getNorthUnit() {
return VectorXZ.Z_UNIT;
}
@Override
public void setOrigin(LatLon origin) {
super.setOrigin(origin);
this.scaleFactor = earthCircumference(origin.lat);
this.originY = latToY(origin.lat) * scaleFactor;
this.originX = lonToX(origin.lon) * scaleFactor;
}
}