mod aitoff;
mod albers;
mod axis_oriented;
mod azimuthal_equidistant;
mod behrmann;
mod bonne;
mod cassini;
mod central_conic;
mod collignon;
mod craster;
mod cylindrical_equal_area;
mod eckert_i;
mod eckert_ii;
mod eckert_iii;
mod eckert_iv;
mod eckert_v;
mod eckert_vi;
mod equirectangular;
mod equal_earth;
mod euler;
mod fahey;
mod foucaut;
mod gall_peters;
mod gall_stereographic;
mod geographic;
mod geocentric;
mod geostationary;
mod gnomonic;
mod hammer;
mod hatano;
mod hobo_dyer;
mod hotine_oblique_mercator;
mod lagrange;
mod kavrayskiy_v;
mod kavrayskiy_vii;
mod krovak;
mod lambert_azimuthal_equal_area;
mod lambert_conformal_conic;
mod loximuthal;
mod mercator;
mod miller_cylindrical;
mod murdoch_i;
mod murdoch_ii;
mod murdoch_iii;
mod mbt_s;
mod mbt_fps;
mod mbtfpp;
mod mbtfpq;
mod mollweide;
mod natural_earth;
mod natural_earth_ii;
mod nell;
mod nell_hammer;
mod orthographic;
mod patterson;
mod perspective_conic;
mod polar_stereographic;
mod polyconic;
mod putnins_p2;
mod putnins_p3;
mod putnins_p3p;
mod putnins_p4p;
mod putnins_p5;
mod putnins_p5p;
mod putnins_p6;
mod putnins_p6p;
mod putnins_p1;
mod quartic_authalic;
mod robinson;
mod sinusoidal;
mod stereographic;
mod times;
mod tissot;
mod two_point_equidistant;
mod tobler_mercator;
mod transverse_cylindrical_equal_area;
mod transverse_mercator;
mod van_der_grinten;
mod vertical;
mod wagner_i;
mod wagner_ii;
mod wagner_iii;
mod wagner_iv;
mod wagner_v;
mod wagner_vi;
mod werenskiold_i;
mod winkel_i;
mod winkel_ii;
mod winkel_tripel;
mod vitkovsky_i;
use crate::datum::Datum;
use crate::ellipsoid::Ellipsoid;
use crate::error::Result;
use crate::transform::{CoordTransform, Point2D};
#[derive(Debug, Clone, PartialEq)]
pub enum ProjectionKind {
Geographic,
Geocentric,
Geostationary {
satellite_height: f64,
sweep_x: bool,
},
Vertical,
Mercator,
WebMercator,
TransverseMercator,
TransverseMercatorSouthOrientated,
Utm {
zone: u8,
south: bool,
},
LambertConformalConic {
lat1: f64,
lat2: Option<f64>,
},
AlbersEqualAreaConic {
lat1: f64,
lat2: f64,
},
AzimuthalEquidistant,
TwoPointEquidistant {
lon1: f64,
lat1: f64,
lon2: f64,
lat2: f64,
},
LambertAzimuthalEqualArea,
Krovak,
HotineObliqueMercator {
azimuth: f64,
rectified_grid_angle: Option<f64>,
},
CentralConic {
lat1: f64,
},
Lagrange {
lat1: f64,
w: f64,
},
Loximuthal {
lat1: f64,
},
Euler {
lat1: f64,
lat2: f64,
},
Tissot {
lat1: f64,
lat2: f64,
},
MurdochI {
lat1: f64,
lat2: f64,
},
MurdochII {
lat1: f64,
lat2: f64,
},
MurdochIII {
lat1: f64,
lat2: f64,
},
PerspectiveConic {
lat1: f64,
lat2: f64,
},
VitkovskyI {
lat1: f64,
lat2: f64,
},
ToblerMercator,
WinkelII,
KavrayskiyV,
Stereographic,
ObliqueStereographic,
PolarStereographic {
north: bool,
lat_ts: Option<f64>,
},
Orthographic,
Sinusoidal,
Mollweide,
MbtFps,
MbtS,
Mbtfpp,
Mbtfpq,
Nell,
EqualEarth,
CylindricalEqualArea {
lat_ts: f64,
},
Equirectangular {
lat_ts: f64,
},
Robinson,
Gnomonic,
Aitoff,
VanDerGrinten,
WinkelTripel,
Hammer,
Hatano,
EckertI,
EckertII,
EckertIII,
EckertIV,
EckertV,
MillerCylindrical,
GallStereographic,
GallPeters,
Behrmann,
HoboDyer,
WagnerI,
WagnerII,
WagnerIII,
WagnerIV,
WagnerV,
NaturalEarth,
NaturalEarthII,
WagnerVI,
EckertVI,
TransverseCylindricalEqualArea,
Polyconic,
Cassini,
Bonne,
BonneSouthOrientated,
Craster,
PutninsP4p,
Fahey,
Times,
Patterson,
PutninsP3,
PutninsP3p,
PutninsP5,
PutninsP5p,
PutninsP1,
PutninsP2,
PutninsP6,
PutninsP6p,
QuarticAuthalic,
Foucaut,
WinkelI,
WerenskioldI,
Collignon,
NellHammer,
KavrayskiyVII,
}
#[derive(Debug, Clone)]
pub struct ProjectionParams {
pub kind: ProjectionKind,
pub lon0: f64,
pub lat0: f64,
pub false_easting: f64,
pub false_northing: f64,
pub scale: f64,
pub ellipsoid: Ellipsoid,
pub datum: Datum,
}
impl Default for ProjectionParams {
fn default() -> Self {
ProjectionParams {
kind: ProjectionKind::Equirectangular { lat_ts: 0.0 },
lon0: 0.0,
lat0: 0.0,
false_easting: 0.0,
false_northing: 0.0,
scale: 1.0,
ellipsoid: Ellipsoid::WGS84,
datum: Datum::WGS84,
}
}
}
impl ProjectionParams {
pub fn new(kind: ProjectionKind) -> Self {
ProjectionParams {
kind,
..Default::default()
}
}
pub fn utm(zone: u8, south: bool) -> Self {
let lon0 = (zone as f64 - 1.0) * 6.0 - 180.0 + 3.0;
ProjectionParams {
kind: ProjectionKind::Utm { zone, south },
lon0,
lat0: 0.0,
false_easting: 500_000.0,
false_northing: if south { 10_000_000.0 } else { 0.0 },
scale: 0.9996,
ellipsoid: Ellipsoid::WGS84,
datum: Datum::WGS84,
}
}
pub fn web_mercator() -> Self {
ProjectionParams {
kind: ProjectionKind::WebMercator,
lon0: 0.0,
lat0: 0.0,
false_easting: 0.0,
false_northing: 0.0,
scale: 1.0,
ellipsoid: Ellipsoid::SPHERE,
datum: Datum::WGS84,
}
}
pub fn with_lon0(mut self, lon0: f64) -> Self {
self.lon0 = lon0;
self
}
pub fn with_lat0(mut self, lat0: f64) -> Self {
self.lat0 = lat0;
self
}
pub fn with_false_easting(mut self, fe: f64) -> Self {
self.false_easting = fe;
self
}
pub fn with_false_northing(mut self, fn_: f64) -> Self {
self.false_northing = fn_;
self
}
pub fn with_scale(mut self, k: f64) -> Self {
self.scale = k;
self
}
pub fn with_ellipsoid(mut self, ellipsoid: Ellipsoid) -> Self {
self.ellipsoid = ellipsoid.clone();
self.datum = Datum {
name: "Custom",
ellipsoid,
transform: crate::datum::DatumTransform::None,
};
self
}
}
trait ProjectionImpl: Send + Sync {
fn forward(&self, lon_deg: f64, lat_deg: f64) -> Result<(f64, f64)>;
fn inverse(&self, x: f64, y: f64) -> Result<(f64, f64)>;
}
pub struct Projection {
params: ProjectionParams,
inner: Box<dyn ProjectionImpl>,
}
impl std::fmt::Debug for Projection {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Projection")
.field("params", &self.params)
.finish()
}
}
impl Projection {
pub fn new(params: ProjectionParams) -> Result<Self> {
let inner: Box<dyn ProjectionImpl> = match ¶ms.kind {
ProjectionKind::Geographic => Box::new(
geographic::GeographicProj::new(¶ms)?,
),
ProjectionKind::Geocentric => Box::new(
geocentric::GeocentricProj::new(¶ms)?,
),
ProjectionKind::Geostationary {
satellite_height,
sweep_x,
} => Box::new(
geostationary::GeostationaryProj::new(¶ms, *satellite_height, *sweep_x)?,
),
ProjectionKind::Vertical => Box::new(
vertical::VerticalProj::new(¶ms)?,
),
ProjectionKind::Mercator => Box::new(
mercator::MercatorProj::new(¶ms)?,
),
ProjectionKind::WebMercator => Box::new(
mercator::WebMercatorProj::new(¶ms)?,
),
ProjectionKind::TransverseMercator => Box::new(
transverse_mercator::TransverseMercatorProj::new(¶ms)?,
),
ProjectionKind::TransverseMercatorSouthOrientated => Box::new(
axis_oriented::AxisOrientedProj::new(
Box::new(transverse_mercator::TransverseMercatorProj::new(¶ms)?),
params.false_easting,
params.false_northing,
true,
true,
),
),
ProjectionKind::Utm { zone, south } => {
let _ = (zone, south); Box::new(transverse_mercator::TransverseMercatorProj::new(¶ms)?)
}
ProjectionKind::LambertConformalConic { lat1, lat2 } => Box::new(
lambert_conformal_conic::LccProj::new(¶ms, *lat1, *lat2)?,
),
ProjectionKind::AlbersEqualAreaConic { lat1, lat2 } => Box::new(
albers::AlbersProj::new(¶ms, *lat1, *lat2)?,
),
ProjectionKind::AzimuthalEquidistant => Box::new(
azimuthal_equidistant::AzimuthalEquidistantProj::new(¶ms)?,
),
ProjectionKind::TwoPointEquidistant { lon1, lat1, lon2, lat2 } => Box::new(
two_point_equidistant::TwoPointEquidistantProj::new(¶ms, *lon1, *lat1, *lon2, *lat2)?,
),
ProjectionKind::LambertAzimuthalEqualArea => Box::new(
lambert_azimuthal_equal_area::LambertAzimuthalEqualAreaProj::new(¶ms)?,
),
ProjectionKind::Krovak => Box::new(
krovak::KrovakProj::new(¶ms)?,
),
ProjectionKind::HotineObliqueMercator {
azimuth,
rectified_grid_angle,
} => Box::new(
hotine_oblique_mercator::HotineObliqueMercatorProj::new(
¶ms,
*azimuth,
rectified_grid_angle.unwrap_or(*azimuth),
)?,
),
ProjectionKind::CentralConic { lat1 } => Box::new(
central_conic::CentralConicProj::new(¶ms, *lat1)?,
),
ProjectionKind::Lagrange { lat1, w } => Box::new(
lagrange::LagrangeProj::new(¶ms, *lat1, *w)?,
),
ProjectionKind::Loximuthal { lat1 } => Box::new(
loximuthal::LoximuthalProj::new(¶ms, *lat1)?,
),
ProjectionKind::Euler { lat1, lat2 } => Box::new(
euler::EulerProj::new(¶ms, *lat1, *lat2)?,
),
ProjectionKind::Tissot { lat1, lat2 } => Box::new(
tissot::TissotProj::new(¶ms, *lat1, *lat2)?,
),
ProjectionKind::MurdochI { lat1, lat2 } => Box::new(
murdoch_i::MurdochIProj::new(¶ms, *lat1, *lat2)?,
),
ProjectionKind::MurdochII { lat1, lat2 } => Box::new(
murdoch_ii::MurdochIIProj::new(¶ms, *lat1, *lat2)?,
),
ProjectionKind::MurdochIII { lat1, lat2 } => Box::new(
murdoch_iii::MurdochIIIProj::new(¶ms, *lat1, *lat2)?,
),
ProjectionKind::PerspectiveConic { lat1, lat2 } => Box::new(
perspective_conic::PerspectiveConicProj::new(¶ms, *lat1, *lat2)?,
),
ProjectionKind::VitkovskyI { lat1, lat2 } => Box::new(
vitkovsky_i::VitkovskyIProj::new(¶ms, *lat1, *lat2)?,
),
ProjectionKind::ToblerMercator => Box::new(
tobler_mercator::ToblerMercatorProj::new(¶ms)?,
),
ProjectionKind::WinkelII => Box::new(
winkel_ii::WinkelIIProj::new(¶ms)?,
),
ProjectionKind::KavrayskiyV => Box::new(
kavrayskiy_v::KavrayskiyVProj::new(¶ms)?,
),
ProjectionKind::Stereographic => Box::new(
stereographic::StereographicProj::new(¶ms)?,
),
ProjectionKind::PolarStereographic { north, lat_ts } => Box::new(
polar_stereographic::PolarStereographicProj::new(¶ms, *north, *lat_ts)?,
),
ProjectionKind::ObliqueStereographic => Box::new(
stereographic::StereographicProj::new(¶ms)?,
),
ProjectionKind::Orthographic => Box::new(
orthographic::OrthographicProj::new(¶ms)?,
),
ProjectionKind::Sinusoidal => Box::new(
sinusoidal::SinusoidalProj::new(¶ms)?,
),
ProjectionKind::Mollweide => Box::new(
mollweide::MollweideProj::new(¶ms)?,
),
ProjectionKind::MbtFps => Box::new(
mbt_fps::MbtFpsProj::new(¶ms)?,
),
ProjectionKind::MbtS => Box::new(
mbt_s::MbtSProj::new(¶ms)?,
),
ProjectionKind::Mbtfpp => Box::new(
mbtfpp::MbtfppProj::new(¶ms)?,
),
ProjectionKind::Mbtfpq => Box::new(
mbtfpq::MbtfpqProj::new(¶ms)?,
),
ProjectionKind::Nell => Box::new(
nell::NellProj::new(¶ms)?,
),
ProjectionKind::EqualEarth => Box::new(
equal_earth::EqualEarthProj::new(¶ms)?,
),
ProjectionKind::MillerCylindrical => Box::new(
miller_cylindrical::MillerCylindricalProj::new(¶ms)?,
),
ProjectionKind::GallStereographic => Box::new(
gall_stereographic::GallStereographicProj::new(¶ms)?,
),
ProjectionKind::GallPeters => Box::new(
gall_peters::GallPetersProj::new(¶ms)?,
),
ProjectionKind::Behrmann => Box::new(
behrmann::BehrmannProj::new(¶ms)?,
),
ProjectionKind::HoboDyer => Box::new(
hobo_dyer::HoboDyerProj::new(¶ms)?,
),
ProjectionKind::WagnerI => Box::new(
wagner_i::WagnerIProj::new(¶ms)?,
),
ProjectionKind::WagnerII => Box::new(
wagner_ii::WagnerIiProj::new(¶ms)?,
),
ProjectionKind::WagnerIII => Box::new(
wagner_iii::WagnerIiiProj::new(¶ms)?,
),
ProjectionKind::WagnerIV => Box::new(
wagner_iv::WagnerIvProj::new(¶ms)?,
),
ProjectionKind::WagnerV => Box::new(
wagner_v::WagnerVProj::new(¶ms)?,
),
ProjectionKind::NaturalEarth => Box::new(
natural_earth::NaturalEarthProj::new(¶ms)?,
),
ProjectionKind::NaturalEarthII => Box::new(
natural_earth_ii::NaturalEarthIIProj::new(¶ms)?,
),
ProjectionKind::WagnerVI => Box::new(
wagner_vi::WagnerViProj::new(¶ms)?,
),
ProjectionKind::EckertVI => Box::new(
eckert_vi::EckertViProj::new(¶ms)?,
),
ProjectionKind::TransverseCylindricalEqualArea => Box::new(
transverse_cylindrical_equal_area::TransverseCylindricalEqualAreaProj::new(¶ms)?,
),
ProjectionKind::Polyconic => Box::new(
polyconic::PolyconicProj::new(¶ms)?,
),
ProjectionKind::Cassini => Box::new(
cassini::CassiniProj::new(¶ms)?,
),
ProjectionKind::Bonne => Box::new(
bonne::BonneProj::new(¶ms)?,
),
ProjectionKind::BonneSouthOrientated => Box::new(
axis_oriented::AxisOrientedProj::new(
Box::new(bonne::BonneProj::new(¶ms)?),
params.false_easting,
params.false_northing,
true,
true,
),
),
ProjectionKind::Craster => Box::new(
craster::CrasterProj::new(¶ms)?,
),
ProjectionKind::PutninsP4p => Box::new(
putnins_p4p::PutninsP4pProj::new(¶ms)?,
),
ProjectionKind::Fahey => Box::new(
fahey::FaheyProj::new(¶ms)?,
),
ProjectionKind::Times => Box::new(
times::TimesProj::new(¶ms)?,
),
ProjectionKind::Patterson => Box::new(
patterson::PattersonProj::new(¶ms)?,
),
ProjectionKind::PutninsP3 => Box::new(
putnins_p3::PutninsP3Proj::new(¶ms)?,
),
ProjectionKind::PutninsP3p => Box::new(
putnins_p3p::PutninsP3pProj::new(¶ms)?,
),
ProjectionKind::PutninsP5 => Box::new(
putnins_p5::PutninsP5Proj::new(¶ms)?,
),
ProjectionKind::PutninsP5p => Box::new(
putnins_p5p::PutninsP5pProj::new(¶ms)?,
),
ProjectionKind::PutninsP1 => Box::new(
putnins_p1::PutninsP1Proj::new(¶ms)?,
),
ProjectionKind::PutninsP2 => Box::new(
putnins_p2::PutninsP2Proj::new(¶ms)?,
),
ProjectionKind::PutninsP6 => Box::new(
putnins_p6::PutninsP6Proj::new(¶ms)?,
),
ProjectionKind::PutninsP6p => Box::new(
putnins_p6p::PutninsP6pProj::new(¶ms)?,
),
ProjectionKind::QuarticAuthalic => Box::new(
quartic_authalic::QuarticAuthalicProj::new(¶ms)?,
),
ProjectionKind::Foucaut => Box::new(
foucaut::FoucautProj::new(¶ms)?,
),
ProjectionKind::WinkelI => Box::new(
winkel_i::WinkelIProj::new(¶ms)?,
),
ProjectionKind::WerenskioldI => Box::new(
werenskiold_i::WerenskioldIProj::new(¶ms)?,
),
ProjectionKind::CylindricalEqualArea { lat_ts } => Box::new(
cylindrical_equal_area::CylindricalEqualAreaProj::new(¶ms, *lat_ts)?,
),
ProjectionKind::Equirectangular { lat_ts } => Box::new(
equirectangular::EquirectangularProj::new(¶ms, *lat_ts)?,
),
ProjectionKind::Robinson => Box::new(
robinson::RobinsonProj::new(¶ms)?,
),
ProjectionKind::Gnomonic => Box::new(
gnomonic::GnomonicProj::new(¶ms)?,
),
ProjectionKind::Aitoff => Box::new(
aitoff::AitoffProj::new(¶ms)?,
),
ProjectionKind::VanDerGrinten => Box::new(
van_der_grinten::VanDerGrintenProj::new(¶ms)?,
),
ProjectionKind::WinkelTripel => Box::new(
winkel_tripel::WinkelTripelProj::new(¶ms)?,
),
ProjectionKind::Hammer => Box::new(
hammer::HammerProj::new(¶ms)?,
),
ProjectionKind::Hatano => Box::new(
hatano::HatanoProj::new(¶ms)?,
),
ProjectionKind::EckertI => Box::new(
eckert_i::EckertIProj::new(¶ms)?,
),
ProjectionKind::EckertII => Box::new(
eckert_ii::EckertIiProj::new(¶ms)?,
),
ProjectionKind::EckertIII => Box::new(
eckert_iii::EckertIiiProj::new(¶ms)?,
),
ProjectionKind::EckertIV => Box::new(
eckert_iv::EckertIvProj::new(¶ms)?,
),
ProjectionKind::EckertV => Box::new(
eckert_v::EckertVProj::new(¶ms)?,
),
ProjectionKind::Collignon => Box::new(
collignon::CollignonProj::new(¶ms)?,
),
ProjectionKind::NellHammer => Box::new(
nell_hammer::NellHammerProj::new(¶ms)?,
),
ProjectionKind::KavrayskiyVII => Box::new(
kavrayskiy_vii::KavrayskiyViiProj::new(¶ms)?,
),
};
Ok(Projection { params, inner })
}
pub fn forward(&self, lon_deg: f64, lat_deg: f64) -> Result<(f64, f64)> {
self.inner.forward(lon_deg, lat_deg)
}
pub fn inverse(&self, x: f64, y: f64) -> Result<(f64, f64)> {
self.inner.inverse(x, y)
}
pub fn params(&self) -> &ProjectionParams {
&self.params
}
pub fn name(&self) -> &str {
match &self.params.kind {
ProjectionKind::Geographic => "Geographic",
ProjectionKind::Geocentric => "Geocentric",
ProjectionKind::Geostationary { .. } => "Geostationary Satellite View",
ProjectionKind::Vertical => "Vertical",
ProjectionKind::Mercator => "Mercator",
ProjectionKind::WebMercator => "Web Mercator",
ProjectionKind::TransverseMercator => "Transverse Mercator",
ProjectionKind::TransverseMercatorSouthOrientated => "Transverse Mercator South Orientated",
ProjectionKind::Utm { zone, south } => {
let _ = (zone, south);
"UTM"
}
ProjectionKind::LambertConformalConic { .. } => "Lambert Conformal Conic",
ProjectionKind::AlbersEqualAreaConic { .. } => "Albers Equal-Area Conic",
ProjectionKind::AzimuthalEquidistant => "Azimuthal Equidistant",
ProjectionKind::TwoPointEquidistant { .. } => "Two-Point Equidistant",
ProjectionKind::LambertAzimuthalEqualArea => "Lambert Azimuthal Equal-Area",
ProjectionKind::Krovak => "Krovak",
ProjectionKind::HotineObliqueMercator { .. } => "Hotine Oblique Mercator",
ProjectionKind::CentralConic { .. } => "Central Conic",
ProjectionKind::Lagrange { .. } => "Lagrange",
ProjectionKind::Loximuthal { .. } => "Loximuthal",
ProjectionKind::Euler { .. } => "Euler",
ProjectionKind::Tissot { .. } => "Tissot",
ProjectionKind::MurdochI { .. } => "Murdoch I",
ProjectionKind::MurdochII { .. } => "Murdoch II",
ProjectionKind::MurdochIII { .. } => "Murdoch III",
ProjectionKind::PerspectiveConic { .. } => "Perspective Conic",
ProjectionKind::VitkovskyI { .. } => "Vitkovsky I",
ProjectionKind::ToblerMercator => "Tobler-Mercator",
ProjectionKind::WinkelII => "Winkel II",
ProjectionKind::KavrayskiyV => "Kavrayskiy V",
ProjectionKind::Stereographic => "Stereographic",
ProjectionKind::PolarStereographic { north, .. } => {
if *north { "Polar Stereographic (North)" } else { "Polar Stereographic (South)" }
}
ProjectionKind::ObliqueStereographic => "Oblique Stereographic",
ProjectionKind::Orthographic => "Orthographic",
ProjectionKind::Sinusoidal => "Sinusoidal",
ProjectionKind::Mollweide => "Mollweide",
ProjectionKind::MbtFps => "McBryde-Thomas Flat-Pole Sine (No. 2)",
ProjectionKind::MbtS => "McBryde-Thomas Flat-Polar Sine (No. 1)",
ProjectionKind::Mbtfpp => "McBryde-Thomas Flat-Polar Parabolic",
ProjectionKind::Mbtfpq => "McBryde-Thomas Flat-Polar Quartic",
ProjectionKind::Nell => "Nell",
ProjectionKind::EqualEarth => "Equal Earth",
ProjectionKind::CylindricalEqualArea { .. } => "Cylindrical Equal Area",
ProjectionKind::Equirectangular { .. } => "Equirectangular",
ProjectionKind::Robinson => "Robinson",
ProjectionKind::Gnomonic => "Gnomonic",
ProjectionKind::Aitoff => "Aitoff",
ProjectionKind::VanDerGrinten => "Van der Grinten",
ProjectionKind::WinkelTripel => "Winkel Tripel",
ProjectionKind::Hammer => "Hammer",
ProjectionKind::Hatano => "Hatano",
ProjectionKind::EckertI => "Eckert I",
ProjectionKind::EckertII => "Eckert II",
ProjectionKind::EckertIII => "Eckert III",
ProjectionKind::EckertIV => "Eckert IV",
ProjectionKind::EckertV => "Eckert V",
ProjectionKind::MillerCylindrical => "Miller Cylindrical",
ProjectionKind::GallStereographic => "Gall Stereographic",
ProjectionKind::GallPeters => "Gall-Peters",
ProjectionKind::Behrmann => "Behrmann",
ProjectionKind::HoboDyer => "Hobo-Dyer",
ProjectionKind::WagnerI => "Wagner I",
ProjectionKind::WagnerII => "Wagner II",
ProjectionKind::WagnerIII => "Wagner III",
ProjectionKind::WagnerIV => "Wagner IV",
ProjectionKind::WagnerV => "Wagner V",
ProjectionKind::NaturalEarth => "Natural Earth",
ProjectionKind::NaturalEarthII => "Natural Earth II",
ProjectionKind::WagnerVI => "Wagner VI",
ProjectionKind::EckertVI => "Eckert VI",
ProjectionKind::TransverseCylindricalEqualArea => "Transverse Cylindrical Equal Area",
ProjectionKind::Polyconic => "Polyconic",
ProjectionKind::Cassini => "Cassini-Soldner",
ProjectionKind::Bonne => "Bonne",
ProjectionKind::BonneSouthOrientated => "Bonne South Orientated",
ProjectionKind::Craster => "Craster",
ProjectionKind::PutninsP4p => "Putnins P4'",
ProjectionKind::Fahey => "Fahey",
ProjectionKind::Times => "Times",
ProjectionKind::Patterson => "Patterson",
ProjectionKind::PutninsP3 => "Putnins P3",
ProjectionKind::PutninsP3p => "Putnins P3'",
ProjectionKind::PutninsP5 => "Putnins P5",
ProjectionKind::PutninsP5p => "Putnins P5'",
ProjectionKind::PutninsP1 => "Putnins P1",
ProjectionKind::PutninsP2 => "Putnins P2",
ProjectionKind::PutninsP6 => "Putnins P6",
ProjectionKind::PutninsP6p => "Putnins P6'",
ProjectionKind::QuarticAuthalic => "Quartic Authalic",
ProjectionKind::Foucaut => "Foucaut",
ProjectionKind::WinkelI => "Winkel I",
ProjectionKind::WerenskioldI => "Werenskiold I",
ProjectionKind::Collignon => "Collignon",
ProjectionKind::NellHammer => "Nell-Hammer",
ProjectionKind::KavrayskiyVII => "Kavrayskiy VII",
}
}
}
impl CoordTransform for Projection {
fn transform_fwd(&self, point: Point2D) -> Result<Point2D> {
let (x, y) = self.forward(point.x, point.y)?;
Ok(Point2D::new(x, y))
}
fn transform_inv(&self, point: Point2D) -> Result<Point2D> {
let (lon, lat) = self.inverse(point.x, point.y)?;
Ok(Point2D::new(lon, lat))
}
}