2024-02-23 01:22:22 +01:00
|
|
|
#include "proj.h"
|
|
|
|
|
|
|
|
|
|
#include "common/geodetic/wgs84.h"
|
|
|
|
|
|
|
|
|
|
// All projections
|
|
|
|
|
#include "equirect.h"
|
|
|
|
|
#include "stereo.h"
|
|
|
|
|
#include "tmerc.h"
|
|
|
|
|
#include "geos.h"
|
2024-02-27 16:11:15 +01:00
|
|
|
#include "tpers.h"
|
2024-02-29 14:50:00 +01:00
|
|
|
#include "webmerc.h"
|
2024-02-24 11:19:46 +01:00
|
|
|
// #include "lamcc.h"
|
2024-02-23 01:22:22 +01:00
|
|
|
|
|
|
|
|
namespace proj
|
|
|
|
|
{
|
|
|
|
|
bool projection_setup(projection_t *proj)
|
|
|
|
|
{
|
|
|
|
|
// Set ellipsoid
|
|
|
|
|
proj->a = geodetic::WGS84::a * 1e3; // To Meters!
|
|
|
|
|
proj->e = geodetic::WGS84::e;
|
|
|
|
|
proj->es = geodetic::WGS84::es;
|
|
|
|
|
proj->n = geodetic::WGS84::n;
|
|
|
|
|
proj->one_es = geodetic::WGS84::one_es;
|
|
|
|
|
proj->rone_es = 1.0 / geodetic::WGS84::one_es;
|
|
|
|
|
|
|
|
|
|
bool proj_ret = false;
|
|
|
|
|
if (proj->type == ProjType_Equirectangular)
|
|
|
|
|
proj_ret = projection_equirect_setup(proj);
|
|
|
|
|
else if (proj->type == ProjType_Stereographic)
|
|
|
|
|
proj_ret = projection_stereo_setup(proj);
|
|
|
|
|
else if (proj->type == ProjType_UniversalTransverseMercator)
|
|
|
|
|
proj_ret = projection_tmerc_setup(proj, proj->params.zone, proj->params.south);
|
|
|
|
|
else if (proj->type == ProjType_Geos)
|
2024-02-23 15:19:39 +01:00
|
|
|
proj_ret = projection_geos_setup(proj, proj->params.altitude, proj->params.sweep_x);
|
2024-02-27 16:11:15 +01:00
|
|
|
else if (proj->type == ProjType_Tpers)
|
|
|
|
|
proj_ret = projection_tpers_setup(proj, proj->params.altitude, proj->params.tilt * DEG2RAD, proj->params.azimuth * DEG2RAD);
|
2024-02-29 14:50:00 +01:00
|
|
|
else if (proj->type == ProjType_WebMerc)
|
|
|
|
|
proj_ret = projection_webmerc_setup(proj);
|
2024-02-23 01:22:22 +01:00
|
|
|
else
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (proj_ret) // Exit on error!
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-23 15:19:39 +01:00
|
|
|
void projection_free(projection_t *proj)
|
|
|
|
|
{
|
|
|
|
|
if (proj->proj_dat != nullptr)
|
|
|
|
|
free(proj->proj_dat);
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-12 20:25:45 +01:00
|
|
|
bool projection_perform_fwd(const projection_t *proj, double lon, double lat, double *x, double *y)
|
2024-02-23 01:22:22 +01:00
|
|
|
{
|
|
|
|
|
/* Convert to radians */
|
|
|
|
|
lon *= DEG2RAD;
|
|
|
|
|
lat *= DEG2RAD;
|
|
|
|
|
|
|
|
|
|
lon -= proj->lam0; // Lon Shift
|
|
|
|
|
|
|
|
|
|
/* Call projection function */
|
|
|
|
|
bool proj_ret = false;
|
|
|
|
|
switch (proj->type)
|
|
|
|
|
{
|
|
|
|
|
case ProjType_Equirectangular:
|
|
|
|
|
proj_ret = projection_equirect_fwd(proj, lon, lat, x, y);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ProjType_Stereographic:
|
|
|
|
|
proj_ret = projection_stereo_fwd(proj, lon, lat, x, y);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ProjType_UniversalTransverseMercator:
|
|
|
|
|
proj_ret = projection_tmerc_fwd(proj, lon, lat, x, y);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ProjType_Geos:
|
|
|
|
|
proj_ret = projection_geos_fwd(proj, lon, lat, x, y);
|
|
|
|
|
break;
|
|
|
|
|
|
2024-02-27 16:11:15 +01:00
|
|
|
case ProjType_Tpers:
|
|
|
|
|
proj_ret = projection_tpers_fwd(proj, lon, lat, x, y);
|
|
|
|
|
break;
|
|
|
|
|
|
2024-02-29 14:50:00 +01:00
|
|
|
case ProjType_WebMerc:
|
|
|
|
|
proj_ret = projection_webmerc_fwd(proj, lon, lat, x, y);
|
|
|
|
|
break;
|
|
|
|
|
|
2024-02-23 01:22:22 +01:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (proj_ret) // Exit on error!
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
/* Apply scalars & offsets */
|
|
|
|
|
if (proj->type != ProjType_Equirectangular)
|
|
|
|
|
{
|
|
|
|
|
*x *= proj->a;
|
|
|
|
|
*y *= proj->a;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*x += proj->x0;
|
|
|
|
|
*y += proj->y0;
|
|
|
|
|
|
|
|
|
|
*x = (*x - proj->proj_offset_x) / proj->proj_scalar_x;
|
2024-02-26 12:55:42 +01:00
|
|
|
*y = (*y - proj->proj_offset_y) / proj->proj_scalar_y;
|
2024-02-23 01:22:22 +01:00
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2025-01-12 20:25:45 +01:00
|
|
|
bool projection_perform_inv(const projection_t *proj, double x, double y, double *lon, double *lat)
|
2024-02-23 01:22:22 +01:00
|
|
|
{
|
|
|
|
|
/* Apply scalars & offsets */
|
|
|
|
|
x = x * proj->proj_scalar_x + proj->proj_offset_x;
|
2024-02-26 12:55:42 +01:00
|
|
|
y = y * proj->proj_scalar_y + proj->proj_offset_y;
|
2024-02-23 01:22:22 +01:00
|
|
|
|
|
|
|
|
x -= proj->x0;
|
|
|
|
|
y -= proj->y0;
|
|
|
|
|
|
|
|
|
|
if (proj->type != ProjType_Equirectangular)
|
|
|
|
|
{
|
|
|
|
|
x *= (1.0 / proj->a);
|
|
|
|
|
y *= (1.0 / proj->a);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Call projection function */
|
|
|
|
|
bool proj_ret = false;
|
|
|
|
|
switch (proj->type)
|
|
|
|
|
{
|
|
|
|
|
case ProjType_Equirectangular:
|
|
|
|
|
proj_ret = projection_equirect_inv(proj, x, y, lon, lat);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ProjType_Stereographic:
|
|
|
|
|
proj_ret = projection_stereo_inv(proj, x, y, lon, lat);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ProjType_UniversalTransverseMercator:
|
|
|
|
|
proj_ret = projection_tmerc_inv(proj, x, y, lon, lat);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case ProjType_Geos:
|
|
|
|
|
proj_ret = projection_geos_inv(proj, x, y, lon, lat);
|
|
|
|
|
break;
|
|
|
|
|
|
2024-02-27 16:11:15 +01:00
|
|
|
case ProjType_Tpers:
|
|
|
|
|
proj_ret = projection_tpers_inv(proj, x, y, lon, lat);
|
|
|
|
|
break;
|
|
|
|
|
|
2024-02-29 14:50:00 +01:00
|
|
|
case ProjType_WebMerc:
|
|
|
|
|
proj_ret = projection_webmerc_inv(proj, x, y, lon, lat);
|
|
|
|
|
break;
|
|
|
|
|
|
2024-02-23 01:22:22 +01:00
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (proj_ret) // Exit on error!
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
/* Convert to degrees */
|
|
|
|
|
*lon += proj->lam0; // Lon Shift
|
|
|
|
|
|
2024-02-26 15:21:04 +01:00
|
|
|
while (*lon < -M_PI)
|
|
|
|
|
*lon += M_PI * 2;
|
|
|
|
|
while (*lon > M_PI)
|
|
|
|
|
*lon -= M_PI * 2;
|
2024-02-23 01:22:22 +01:00
|
|
|
|
|
|
|
|
*lon *= RAD2DEG;
|
|
|
|
|
*lat *= RAD2DEG;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|