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);
}

參考文獻:

  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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章