GPS经纬度lat, lon映射到平面坐标x,y公式推导与c代码

概念理解

1、纬度圈、赤道圈、平行圈

2、经度圈、子午圈

3、法线

4、卯酋圈

5、曲率、曲率半径

6、半轴长:
          地球的长半轴上:a = 6378137m
          地球的短半轴上:b = 6356755m
7、扁率
在这里插入图片描述
8、椭圆的第一偏心率
在这里插入图片描述
在这里插入图片描述
9、椭圆的第二偏心率
在这里插入图片描述
10、大地纬度
         B:单位,rad, -pi/2~pi/2

公式推导

在这里插入图片描述

1、卯酋圈曲率半径

在这里插入图片描述

在这里插入图片描述
即卯酋圈曲率半径为
在这里插入图片描述

2、子午圈曲率半径

在这里插入图片描述
即子午圈曲率半径为
在这里插入图片描述

3、平行圈曲率半径

在这里插入图片描述

表现意义

  知道了南北向的子午圈曲率半径,东西向的平行圈曲率半径,地球表面的经纬度为lat、lon(弧度),则转为平面坐标为:
在这里插入图片描述
在这里插入图片描述

代码实现

map_project.h

#ifndef __MAP_PROJECT__
#define	__MAP_PROJECT__

#define		M_PI_F			3.1415926f

#define		R2D(v)			(v/M_PI_F*180.0f)
#define		D2R(v)			(v/180.0f*M_PI_F)

typedef struct{
	unsigned char inited;
	double h_lat;
	double h_lon;
	double dx_mue;
	double dy_lambda;
}coordinate_map_t;

int coordinate_map_ref_init(coordinate_map_t *pref, double lon, double lat, double h);
int coordinate_map_project(const coordinate_map_t *pref, double lon, double lat, float *x, float *y);
int coordinate_map_reproject(const coordinate_map_t *pref, float x, float y, double *lon, double *lat);
int coordinate_map_ref_distance(const coordinate_map_t *pref, double lon, double lat, float *d_x, float *d_y);

#endif

map_project.cpp

/*======================================================================*
*																		*
*	map project,														*
*																		*
*	Author: niu hongfang												*
*	Date:	2019.07.29													*		
*	Addr:	Shen Zhen, Guangdong										*
*																		*
*=======================================================================*/
#include "map_project.h"
#include "math.h"

#define		E_a				6378137.0f		/* 地球纬度圈半径 m */
#define		E_b				6356755.0f		/* 地球经度圈半径 m */

/*
*	note: coordinate ref init.
*
*	@param1	ref
*	@param2 latitude,  rad, -pi/2~pi/2
*	@param3	longitude, rad, -pi~pi
*	@param4	h,		   m,
*	@return	init success/failure
*/
int coordinate_map_ref_init(coordinate_map_t *pref, double lon, double lat, double h)
{
	double e, e_2;
	double f;
	double sin_2_lat;
	double R_lat_circle;
	double R_lon_circle;
	double den_prime_vertical, R_prime_vertical, omiga_2;

	if (lat > M_PI_F / 2 || lat < -M_PI_F / 2){
		return -1;
	}

	f = (E_a - E_b) / E_a;
	e_2 = f * (2.0 - f);
	sin_2_lat = sin(lat);

	omiga_2 = 1 - e_2 * sin_2_lat;
	den_prime_vertical = sqrtf(omiga_2);
	R_prime_vertical = E_a / den_prime_vertical;

	R_lat_circle = (R_prime_vertical + h) * cosf(lat);
	R_lon_circle = R_prime_vertical * (1 - e_2) / omiga_2 + h;

	pref->h_lat = lat;
	pref->h_lon = lon;
	pref->dx_mue = R_lon_circle;
	pref->dy_lambda = R_lat_circle;
	pref->inited = 1;

	return 0;
}

int coordinate_map_project(const coordinate_map_t *pref, double lon, double lat, float *x, float *y)
{
	if (!pref->inited){
		return -1;
	}

	*x = pref->dx_mue * lon;
	*y = pref->dy_lambda * lat;

	return 0;
}

int coordinate_map_reproject(const coordinate_map_t *pref, float x, float y, double *lon, double *lat)
{
	if (!pref->inited){
		return -1;
	}

	*lon = (double)x / pref->dx_mue;
	*lat = (double)y / pref->dy_lambda;

	return 0;
}

int coordinate_map_ref_distance(const coordinate_map_t *pref, double lon, double lat, float *d_x, float *d_y)
{
	if (!pref->inited){
		return -1;
	}

	double d_lon, d_lat;

	d_lon = lon - pref->h_lon;
	d_lat = lat - pref->h_lat;

	*d_x = d_lon*pref->dx_mue;
	*d_y = d_lat*pref->dy_lambda;

	return 0;
}

main.c

#include "stdio.h"
#include "iostream"
#include "map_project.h"

/* 经纬度转为平面坐标xy ----------------------------------- */
coordinate_map_t coordinate_ref = { 0 };

int main()
{
	/* 深圳 */
	double lat = 22.55329;
	double lon = 113.88308;

	/* 广州 */
	double lat_g = 23.15792;
	double lon_g = 113.27324;

	float x_g, y_g, x_s, y_s;

	coordinate_map_ref_init(&coordinate_ref, D2R(lon), D2R(lat), 10);
	printf("R-lat:%.3f, \r\nR-lon:%.3f\n", coordinate_ref.dy_lambda, coordinate_ref.dx_mue);

	coordinate_map_project(&coordinate_ref, D2R(lon_g), D2R(lat_g), &x_g, &y_g);
	printf("g  x:%f,  y:%f\r\n",  x_g, y_g);

	coordinate_map_project(&coordinate_ref, D2R(lon), D2R(lat), &x_s, &y_s);
	printf("g-->s  x:%f,  y:%f\r\n", x_g - x_s, y_g - y_s);

	float d1,d2;
	coordinate_map_ref_distance(&coordinate_ref, D2R(lon_g), D2R(lat_g), &d1, &d2);
	printf("g-->s  x:%f,  y:%f\r\n", d1, d2);
}

可直接下载使用:https://download.csdn.net/download/niu_88/11449955

参考文献:

  1. https://baike.baidu.com/item/卯酉圈/3033623?fr=aladdin
  2. https://baike.baidu.com/item/扁率/8654862?fr=aladdin
  3. https://wenku.baidu.com/view/b9440674dd88d0d232d46a8a.html
  4. https://wenku.baidu.com/view/61d7a12003768e9951e79b89680203d8cf2f6a7f.html
  5. https://download.csdn.net/my
  • 8
    点赞
  • 56
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值