谷歌地球API开发者指南(高级)
2016-08-24 23:05
169 查看
谷歌地球API开发者指南(高级)
作者感慨:Google Earth真是一个好东东,而其爱好者更是天才啊。我们与老美在科技上的差距,不是我们以环境、资源为代价的粗放式快速增长的GDP所能掩盖的
Google Earth API开发者指南(高级)
此例中,Google的logo被叠放在加州总部山景城的位置。
地面覆盖的特点是始终吸附在地表,无论图像放在山脉还是河谷,如下图所示:
效果如下图所示:
下例代码中,地标在普通状态时,图案为三角形,当鼠标在地标上方经过时,其图案变为矩形。
显示建筑三维模型
ge.getLayerRoot().enableLayerById(ge.LAYER_BUILDINGS, true);
隐藏建筑三维模型
ge.getLayerRoot().enableLayerById(ge.LAYER_BUILDINGS, false);
显示边界
ge.getLayerRoot().enableLayerById(ge.LAYER_BORDERS, true);
隐藏边界
ge.getLayerRoot().enableLayerById(ge.LAYER_BORDERS, false);
显示地形
ge.getLayerRoot().enableLayerById(ge.LAYER_TERRAIN, true);
隐藏地形
ge.getLayerRoot().enableLayerById(ge.LAYER_TERRAIN, false);
KML分析
如果您手上有一段KML代码,那么就可以让Google Earth插件对其进行分析——用ge.parseKml对象把KML转换成JavaScript。示例代码如下:
上述代码效果如下图所示:
下列代码将加载一个Collada模型,并将其显示出来。(注:COLLADA的全名是“COLLAborative Design Activity”,是用来建立3D互动程序的一个文件格式,而此格式就叫做“dae”,全名是“digital asset exchange”。COLLADA主要定义一个开放式的XML Schema标准。也就是说,你在3D软件所建好的模型,只要透过COLLADA的外挂软件就可以输出成「dae」的档案,而这个档案所包含的内容就是以XML文字数据的形式来描述的。)
赤经:从春分点沿着天赤道向东到天体时圈与天赤道的交点所夹的角度,成为该天体的赤经。赤经与时角不同,时角是由天子午圈向西量,而赤经是由春分点向东量,两者方向相反。赤经(Right ascension, RA; 符号:希腊字母α),天文学名词。指赤道坐标系的经向坐标,过天球上一点的赤经圈与过春分点的二分圈所交的球面角。天球上相当于地球经线的线,通过天球两极并与天赤道垂直。以时、分、秒表示。
赤纬:从天赤道沿着天体的时圈至天体的角度称为该天体的赤纬。以天赤道为赤纬0°,向北为正,向南为负,分别从0°到90°。日赤纬的变化范围在-23°27 ~+23°27 之间,而月赤纬的最大变化范围为-28°36 ~+-28°36 .赤纬常用δ表示。在第二赤道坐标系中,天体的位置根据规定用经纬度来表示,称作赤经(α)、赤纬(δ)。赤纬就是天体的位置与天赤道位置的差,在天赤道以北多少度就为正多少度,反之,在天赤道以南多少度为负多少度。赤纬的取值为-90度到+90度,南天极的赤纬为-90度,北天极的赤纬为+90度,天赤道的赤纬为0度。天球赤道坐标系的纬度规定与地球纬度类似。只是不称作“南纬”和“北纬”,天球赤纬以北纬为正,以南为负。
用set方法把地球界面切换至天空:
ge.getOptions().setMapType(ge.MAP_TYPE_SKY);
反之,把界面从天空切换回地球:
ge.getOptions().setMapType(ge.MAP_TYPE_EARTH);
计算LookAt对象里的Range值
当您使用LookAt对象来处理星空数据时,必须用下列公式计算出r的距离。
r = R*(k*sin(β/2) - cos(β/2) + 1)
公式中各参数说明如下:
r:即range的值,由<LookAt>标签指定。
R:为假设星空球体的半径。在这里,星空球面为地球内表面,“ Center of Earth”为地球核心,因此R值实为地球半径6.378×106。
k:等于1 / tan ( 2 / α),或者用近似数替代:1.1917536
α:是一个角度范围(β<α<180°)。当观察点向地球原点移动时所形成的夹角。
β:用户所需星空图像两边与地球原点的夹角(单位:秒)。
下例中,网页中的Google Map新增了一个“Earth”按钮,可以随时在Map与Earth之间切换。
Google Earth谷歌地球API开发者指南(高级)
当您点击“Earth”按钮时,窗口切换至Google Earth,地点未变。
Google Earth谷歌地球API开发者指南(高级)
示例代码如下:
大家从以上代码可以看出,在已有地图中添加新类型,只需调用gMap.addMapType(G_SATELLITE_3D_MAP)。如果您的地图上有按钮条,那么上述代码就会在按钮条中新增一项“Earth”,当用户点击它,地球窗口就会显示出来,各种标记、图形、文本等提示框,均能在地球窗口内正常显示。
除了addMapType,您还可以用gMap.setMapType(G_SATELLITE_3D_MAP)直接把地图切换至Google Earth。同样,调用gMapType.setMapType()可以隐藏Google Earth窗口,地图切换到其他类型。
转自
http://www.d3dweb.com/Documents/201203/17-17562793368.html
using System.Collections.Generic;
using System.Linq;
using System.Text;
public static class GEHelper
{
#region
// Keep an angle(角度) in [-180,180]
/**
* Keep an angle in the [-180, 180] range
* @param {number} a Angle in degrees
* @return {number} The angle in the [-180, 180] degree range
*/
private static Double fixAngle(double a)
{
while (a < -180)
a += 360;
while (a > 180)
a -= 360;
return a;
}
/**
* Converts degrees(角度) to radians(弧度)
* @param {number} d Degrees
* @return {number} Radians
*/
private static decimal deg2rad(decimal d)
{
return d * Convert.ToDecimal(Math.PI) / Convert.ToDecimal(180.0);
}
/**
* Converts radians(弧度) to degrees(角度)
* @param {number} r Radians
* @return {number} Degrees
*/
private static double rad2deg(double r)
{
return r * 180.0 / Math.PI;
}
/** 计算两点之间的方位
* Calculates the heading/bearing between two locations. Taken from the formula
* provided at http://mathforum.org/library/drmath/view/55417.html * @param {google.maps.LatLng} loc1 The start location
* @param {google.maps.LatLng} loc2 The destination location
* @return {number} The heading from loc1 to loc2, in degrees
*/
public static double getHeading(GeMode ge1, GeMode ge2)
{
decimal lat1; decimal lon1; decimal lat2; decimal lon2;
lat1 = deg2rad(ge1.lat);
lon1 = deg2rad(ge1.lng);
lat2 = deg2rad(ge2.lat);
lon2 = deg2rad(ge2.lng);
var heading = fixAngle(rad2deg(Math.Atan2(
Math.Sin(Convert.ToDouble(lon2 - lon1)) * Math.Cos(Convert.ToDouble(lat2)),
Math.Cos(Convert.ToDouble(lat1)) * Math.Sin(Convert.ToDouble(lat2)) - Math.Sin(Convert.ToDouble(lat1)) * Math.Cos(Convert.ToDouble(lat2)) *
Math.Cos(Convert.ToDouble(lon2 - lon1)))));
return heading;
}
/// <summary>
/// //找到两点之间的中间
/**
* Calculates an intermediate lat/lon, (100 * f)% between loc1 and loc2
* @param {google.maps.LatLng} loc1 The start location
* @param {google.maps.LatLng} loc2 The end location
* @return {google.maps.LatLng} An intermediate location between loc1 and loc2
*/
/// </summary>
/// <param name="ge1"></param>
/// <param name="ge2"></param>
/// <param name="f"></param>
/// <returns></returns>
public static GeMode interpolateLoc(GeMode ge1, GeMode ge2, decimal f)
{
//decimal d = Convert.ToDecimal(getHeading(ge1, ge2));
decimal lat = ge1.lat + f * (ge2.lat - ge1.lat);
decimal lng = ge2.lng + f * (ge2.lng - ge1.lng);
GeMode ge = new GeMode(lat, lng);
return ge;
}
#endregion
#region
/**
* 经线方向长度转化成纬度
* @param {leng} 经线向量长度(米)
* @return 返回纬度差
*/
private static decimal lenToLat(decimal leng)
{
var L = 10002150; // 半个经线长度(经线圈的1/4),对应90°纬度
var angle = 90 * leng / L; return angle;
}
/**
* 纬线方向长度转化成经度
* @param {lat} 纬度值
* @param {leng} 纬线向量长度(米)
* @return 返回精度差
*/
private static decimal lenToLng(decimal lat, decimal leng)
{
var L = 20037508; // 赤道一半长度(半圈,对应180°经度)
var latL = Convert.ToDecimal(L * Math.Cos(Math.PI / 180 * Convert.ToDouble(lat))); // 指定纬度对应的纬线长度(半圈)
var angle = 180 * leng / latL;
return angle;
}
/// <summary>
/// 根据已知相邻3点,求中点的等距平行点经纬度
/// </summary>
/// <param name="p0">@param {p0, p1, p2} 相邻三个LatLng点</param>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="t">@return {t} 待求平行点到线段的垂直距离</param>
/// <returns></returns>
public static GeMode getParallelPoint(GeMode p0, GeMode p1, GeMode p2, double t)
{
// 经纬度分别转换成长度单位
decimal y12 = p2.lat - p1.lat;
decimal x12 = p2.lng - p1.lng;
decimal y01 = p1.lat - p0.lat;
decimal x01 = p1.lng - p0.lng;
double a, b;
if (x12 == 0)
{
a = Math.PI / 2;
if (y12 < 0)
a = -a;
}
else
{
a = Math.Atan(Convert.ToDouble(y12 / x12));
}
if (x01 == 0)
{
b = Math.PI / 2;
if (y01 < 0)
b = -b;
}
else
{
b = Math.Atan(Convert.ToDouble(y01 / x01));
}
//alert(b);
// 关键核心处
if (p2.lng < p1.lng)
{
a += Math.PI;
}
if (p1.lng < p0.lng)
{
b += Math.PI;
}
var k = (b - a - Math.PI) / 2;
var r = a + k;
var d = t / Math.Sin(k);
var sinr = Math.Sin(r);
var cosr = Math.Cos(r);
// alert(d * sinr);
var d_lat = lenToLat(Convert.ToDecimal(d * sinr));
var d_lng = lenToLng(p1.lat, Convert.ToDecimal(d * cosr));
d_lat = p1.lat + d_lat;
d_lng = p1.lng + d_lng;
GeMode g = new GeMode(d_lat, d_lng);
return g;
// addMark(obj);
}
#endregion
public class GeMode
{
/// <summary>
///
/// </summary>
/// <param name="lat">纬度</param>
/// <param name="lng">进度</param>
public GeMode(decimal lat, decimal lng)
{
_lat = lat;//
_lng = lng;//
}
private decimal _lat;
private decimal _lng;
public decimal lat
{
set { _lat = value; }
get { return _lat; }
}
public decimal lng
{
set { _lng = value; }
get { return _lng; }
}
}
}
作者感慨:Google Earth真是一个好东东,而其爱好者更是天才啊。我们与老美在科技上的差距,不是我们以环境、资源为代价的粗放式快速增长的GDP所能掩盖的
Google Earth API开发者指南(高级)
创建地面覆盖
地面覆盖,允许您在Google Earth的地表上放置图像。其中,图像源自网络,图片的URL包含在“Icon”对象内。var groundOverlay = ge.createGroundOverlay( ); groundOverlay.setIcon(ge.createIcon( )) groundOverlay.getIcon(). setHref("http://www.google.com/intl/en_ALL/images/logo.gif"); groundOverlay.setLatLonBox(ge.createLatLonBox( )); var center = ge.getView().copyAsLookAt(ge.ALTITUDE_RELATIVE_TO_GROUND); var north = center.getLatitude() + .85; var south = center.getLatitude() - .85; var east = center.getLongitude() + .55; var west = center.getLongitude() - .55; var rotation = 0; var latLonBox = groundOverlay.getLatLonBox(); latLonBox.setBox(north, south, east, west, rotation); ge.getFeatures().appendChild(groundOverlay);
此例中,Google的logo被叠放在加州总部山景城的位置。
地面覆盖的特点是始终吸附在地表,无论图像放在山脉还是河谷,如下图所示:
创建屏幕覆盖
屏幕覆盖是指图片固定在屏幕上,不像地面覆盖那样跟随地表起伏而变化。屏幕覆盖通常用来做logo、商标、图例等,其长宽尺寸由size属性决定。图像位置(screenXY属性)由图中的安置点(overlayXY属性)控制,其旋转角度由rotationXY属性决定。下列代码将用Google标志图来创建一个屏幕覆盖,并倾斜一定角度。var screenOverlay = ge.createScreenOverlay( ); screenOverlay.setIcon(ge.createIcon( )); screenOverlay.getIcon(). setHref("http://www.google.com/intl/en_ALL/images/logo.gif"); // Set screen position in pixels screenOverlay.getOverlayXY().setXUnits(ge.UNITS_PIXELS); screenOverlay.getOverlayXY().setYUnits(ge.UNITS_PIXELS); screenOverlay.getOverlayXY().setX(400); screenOverlay.getOverlayXY().setY(200); // Rotate around object s center point screenOverlay.getRotationXY().setXUnits(ge.UNITS_FRACTION); screenOverlay.getRotationXY().setYUnits(ge.UNITS_FRACTION); screenOverlay.getRotationXY().setX(0.5); screenOverlay.getRotationXY().setY(0.5); // Set object s size in pixels screenOverlay.getSize().setXUnits(ge.UNITS_PIXELS); screenOverlay.getSize().setYUnits(ge.UNITS_PIXELS); screenOverlay.getSize().setX(300); screenOverlay.getSize().setY(75); // Rotate 45 degrees screenOverlay.setRotation(45); ge.getFeatures().appendChild(screenOverlay);
效果如下图所示:
样式地图
样式地图在一般情况为地标下提供两种状态:普通状态和高亮状态,分别由两种图标来表示,当用户在Google Earth中用鼠标在地标图案上经过时,图案会自动切换至高亮状态。下例代码中,地标在普通状态时,图案为三角形,当鼠标在地标上方经过时,其图案变为矩形。
map = ge.createStyleMap( styleMap + counter); // Create icon normal for style map normal = ge.createIcon( ); normal.setHref( http://maps.google.com/mapfiles/kml/shapes/triangle.png ); iconNormal = ge.createStyle( styleIconNormal + counter); iconNormal.getIconStyle().setIcon(normal); ? // Create icon highlight for style map highlight = ge.createIcon( ); highlight.setHref( http://maps.google.com/mapfiles/kml/shapes/square.png ); iconHighlight = ge.createStyle( styleIconHighlight + counter); iconHighlight.getIconStyle().setIcon(highlight); // Set normal and highlight for stylemap map.setNormalStyleUrl( #styleIconNormal + counter); map.setHighlightStyleUrl( #styleIconHighlight + counter); // Apply to placemark placemark.setStyleUrl( #styleMap + counter); }
管理地形、道路、边界
当浏览器窗口加载Google Earth插件时,地形特征将被作为默认选项被显示,无需手动干预。并不是所有Google Earth图层特性被显示出来,如果要在浏览器内显示,那么下列JavaScript代码将教您怎么做:显示建筑三维模型
ge.getLayerRoot().enableLayerById(ge.LAYER_BUILDINGS, true);
隐藏建筑三维模型
ge.getLayerRoot().enableLayerById(ge.LAYER_BUILDINGS, false);
显示边界
ge.getLayerRoot().enableLayerById(ge.LAYER_BORDERS, true);
隐藏边界
ge.getLayerRoot().enableLayerById(ge.LAYER_BORDERS, false);
显示地形
ge.getLayerRoot().enableLayerById(ge.LAYER_TERRAIN, true);
隐藏地形
ge.getLayerRoot().enableLayerById(ge.LAYER_TERRAIN, false);
KML分析
如果您手上有一段KML代码,那么就可以让Google Earth插件对其进行分析——用ge.parseKml对象把KML转换成JavaScript。示例代码如下:
var pentagon = ge.parseKml(<?xml version="1.0" encoding="UTF-8"?> + <kml xmlns="http://earth.google.com/kml/2.1"> + <Placemark> + <name>The Pentagon</name> + <Polygon> + <extrude>1</extrude> + <altitudeMode>relativeToGround</altitudeMode> + <outerBoundaryIs> + <LinearRing> + <coordinates> + -77.05788457660967,38.87253259892824,100 + -77.05465973756702,38.87291016281703,100 + -77.05315536854791,38.87053267794386,100 + -77.05552622493516,38.868757801256,100 + -77.05844056290393,38.86996206506943,100 + -77.05788457660967,38.87253259892824,100 + </coordinates> + </LinearRing> + </outerBoundaryIs> + <innerBoundaryIs> + <LinearRing> + <coordinates> + -77.05668055019126,38.87154239798456,100 + -77.05542625960818,38.87167890344077,100 + -77.05485125901024,38.87076535397792,100 + -77.05577677433152,38.87008686581446,100 + -77.05691162017543,38.87054446963351,100 + -77.05668055019126,38.87154239798456,100 + </coordinates> + </LinearRing> + </innerBoundaryIs> + </Polygon> + </Placemark> + </kml> ); ge.getFeatures().appendChild(pentagon); var la = ge.createLookAt( ); la.set(38.867, -77.0565, 500, ge.ALTITUDE_RELATIVE_TO_GROUND, 0, 45, 900); ge.getView().setAbstractView(la);
上述代码效果如下图所示:
察看模型
Google Earth插件支持立体模型(三维场景)。把三维模型导入Google Earth后,会自动转换格式、旋转角度、伸缩大小,以适应Google Earth的坐标系统。下列代码将加载一个Collada模型,并将其显示出来。(注:COLLADA的全名是“COLLAborative Design Activity”,是用来建立3D互动程序的一个文件格式,而此格式就叫做“dae”,全名是“digital asset exchange”。COLLADA主要定义一个开放式的XML Schema标准。也就是说,你在3D软件所建好的模型,只要透过COLLADA的外挂软件就可以输出成「dae」的档案,而这个档案所包含的内容就是以XML文字数据的形式来描述的。)
placemark = ge.createPlacemark( ); placemark.setName( model ); model = ge.createModel( ); ge.getFeatures().appendChild(placemark); loc = ge.createLocation( ); model.setLocation(loc); link = ge.createLink( ); // A textured model created in Sketchup and exported as Collada. var href = window.location.href; var pagePath = href.substring(0, href.lastIndexOf( / )) + / ; link.setHref(pagePath + splotchy_box.dae ); model.setLink(link); la = ge.getView().copyAsLookAt(ge.ALTITUDE_RELATIVE_TO_GROUND); loc.setLatitude(la.getLatitude()); loc.setLongitude(la.getLongitude()); placemark.setGeometry(model); la.setRange(300); la.setTilt(80); ge.getView().setAbstractView(la);
察看太空
您可以创建程序来观察天空——星星、月亮、星座、星系……就像Google Earth里的Sky功能一样。当程序切换到天空模式时,界面也会自动切换。所有星空数据均被放置在虚拟圆形地球的内部,我们的视角切换到球形核心,抬头仰望便可一览苍穹。坐标
星空坐标由赤经和赤纬组成。赤经:从春分点沿着天赤道向东到天体时圈与天赤道的交点所夹的角度,成为该天体的赤经。赤经与时角不同,时角是由天子午圈向西量,而赤经是由春分点向东量,两者方向相反。赤经(Right ascension, RA; 符号:希腊字母α),天文学名词。指赤道坐标系的经向坐标,过天球上一点的赤经圈与过春分点的二分圈所交的球面角。天球上相当于地球经线的线,通过天球两极并与天赤道垂直。以时、分、秒表示。
赤纬:从天赤道沿着天体的时圈至天体的角度称为该天体的赤纬。以天赤道为赤纬0°,向北为正,向南为负,分别从0°到90°。日赤纬的变化范围在-23°27 ~+23°27 之间,而月赤纬的最大变化范围为-28°36 ~+-28°36 .赤纬常用δ表示。在第二赤道坐标系中,天体的位置根据规定用经纬度来表示,称作赤经(α)、赤纬(δ)。赤纬就是天体的位置与天赤道位置的差,在天赤道以北多少度就为正多少度,反之,在天赤道以南多少度为负多少度。赤纬的取值为-90度到+90度,南天极的赤纬为-90度,北天极的赤纬为+90度,天赤道的赤纬为0度。天球赤道坐标系的纬度规定与地球纬度类似。只是不称作“南纬”和“北纬”,天球赤纬以北纬为正,以南为负。
用set方法把地球界面切换至天空:
ge.getOptions().setMapType(ge.MAP_TYPE_SKY);
反之,把界面从天空切换回地球:
ge.getOptions().setMapType(ge.MAP_TYPE_EARTH);
计算LookAt对象里的Range值
当您使用LookAt对象来处理星空数据时,必须用下列公式计算出r的距离。
r = R*(k*sin(β/2) - cos(β/2) + 1)
公式中各参数说明如下:
r:即range的值,由<LookAt>标签指定。
R:为假设星空球体的半径。在这里,星空球面为地球内表面,“ Center of Earth”为地球核心,因此R值实为地球半径6.378×106。
k:等于1 / tan ( 2 / α),或者用近似数替代:1.1917536
α:是一个角度范围(β<α<180°)。当观察点向地球原点移动时所形成的夹角。
β:用户所需星空图像两边与地球原点的夹角(单位:秒)。
与Google Maps相结合
如果您是一位Google Maps开发者,想把网络地图移植到Google Earth插件里以增强互动效果,现在变得轻而易举。Google Maps API为Gmap2类增加了一个新方法,为Gmap类型增加了一个新常量,允许你在已有的网络地图中增加Google Earth三维功能。下例中,网页中的Google Map新增了一个“Earth”按钮,可以随时在Map与Earth之间切换。
Google Earth谷歌地球API开发者指南(高级)
当您点击“Earth”按钮时,窗口切换至Google Earth,地点未变。
Google Earth谷歌地球API开发者指南(高级)
示例代码如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"xmlns:v="urn:schemas-microsoft-com:vml"> <head> <title>Using Google Earth API with the Maps API</title> <script src="http://maps.google.com/maps?file=api&v=2.x&key=abcdefg" type="text/javascript"></script> function initialize() { var map = new GMap2(document.getElementById("map")); map.setCenter(new GLatLng(37.4419, -122.1419), 13); map.addMapType(G_SATELLITE_3D_MAP); map.addControl(new GHierarchicalMapTypeControl()); // Uncomment the following line to start the map with 3D enabled. // map.setMapType(G_SATELLITE_3D_MAP); // Obtain a pointer to the Google Earth instance attached to // your map. map.getEarthInstance(getEarthInstanceCB); } var ge; function getEarthInstanceCB(object) { ge = object; // You can now manipulate ge using the full Google Earth API. } </script> </head> <body onload="initialize()" onunlaod="GUnload"> <div id="map" class="map" style="width:500px;height:350px"></div> </body> </html>
大家从以上代码可以看出,在已有地图中添加新类型,只需调用gMap.addMapType(G_SATELLITE_3D_MAP)。如果您的地图上有按钮条,那么上述代码就会在按钮条中新增一项“Earth”,当用户点击它,地球窗口就会显示出来,各种标记、图形、文本等提示框,均能在地球窗口内正常显示。
除了addMapType,您还可以用gMap.setMapType(G_SATELLITE_3D_MAP)直接把地图切换至Google Earth。同样,调用gMapType.setMapType()可以隐藏Google Earth窗口,地图切换到其他类型。
转自
http://www.d3dweb.com/Documents/201203/17-17562793368.html
GEHelper.cs
using System;using System.Collections.Generic;
using System.Linq;
using System.Text;
public static class GEHelper
{
#region
// Keep an angle(角度) in [-180,180]
/**
* Keep an angle in the [-180, 180] range
* @param {number} a Angle in degrees
* @return {number} The angle in the [-180, 180] degree range
*/
private static Double fixAngle(double a)
{
while (a < -180)
a += 360;
while (a > 180)
a -= 360;
return a;
}
/**
* Converts degrees(角度) to radians(弧度)
* @param {number} d Degrees
* @return {number} Radians
*/
private static decimal deg2rad(decimal d)
{
return d * Convert.ToDecimal(Math.PI) / Convert.ToDecimal(180.0);
}
/**
* Converts radians(弧度) to degrees(角度)
* @param {number} r Radians
* @return {number} Degrees
*/
private static double rad2deg(double r)
{
return r * 180.0 / Math.PI;
}
/** 计算两点之间的方位
* Calculates the heading/bearing between two locations. Taken from the formula
* provided at http://mathforum.org/library/drmath/view/55417.html * @param {google.maps.LatLng} loc1 The start location
* @param {google.maps.LatLng} loc2 The destination location
* @return {number} The heading from loc1 to loc2, in degrees
*/
public static double getHeading(GeMode ge1, GeMode ge2)
{
decimal lat1; decimal lon1; decimal lat2; decimal lon2;
lat1 = deg2rad(ge1.lat);
lon1 = deg2rad(ge1.lng);
lat2 = deg2rad(ge2.lat);
lon2 = deg2rad(ge2.lng);
var heading = fixAngle(rad2deg(Math.Atan2(
Math.Sin(Convert.ToDouble(lon2 - lon1)) * Math.Cos(Convert.ToDouble(lat2)),
Math.Cos(Convert.ToDouble(lat1)) * Math.Sin(Convert.ToDouble(lat2)) - Math.Sin(Convert.ToDouble(lat1)) * Math.Cos(Convert.ToDouble(lat2)) *
Math.Cos(Convert.ToDouble(lon2 - lon1)))));
return heading;
}
/// <summary>
/// //找到两点之间的中间
/**
* Calculates an intermediate lat/lon, (100 * f)% between loc1 and loc2
* @param {google.maps.LatLng} loc1 The start location
* @param {google.maps.LatLng} loc2 The end location
* @return {google.maps.LatLng} An intermediate location between loc1 and loc2
*/
/// </summary>
/// <param name="ge1"></param>
/// <param name="ge2"></param>
/// <param name="f"></param>
/// <returns></returns>
public static GeMode interpolateLoc(GeMode ge1, GeMode ge2, decimal f)
{
//decimal d = Convert.ToDecimal(getHeading(ge1, ge2));
decimal lat = ge1.lat + f * (ge2.lat - ge1.lat);
decimal lng = ge2.lng + f * (ge2.lng - ge1.lng);
GeMode ge = new GeMode(lat, lng);
return ge;
}
#endregion
#region
/**
* 经线方向长度转化成纬度
* @param {leng} 经线向量长度(米)
* @return 返回纬度差
*/
private static decimal lenToLat(decimal leng)
{
var L = 10002150; // 半个经线长度(经线圈的1/4),对应90°纬度
var angle = 90 * leng / L; return angle;
}
/**
* 纬线方向长度转化成经度
* @param {lat} 纬度值
* @param {leng} 纬线向量长度(米)
* @return 返回精度差
*/
private static decimal lenToLng(decimal lat, decimal leng)
{
var L = 20037508; // 赤道一半长度(半圈,对应180°经度)
var latL = Convert.ToDecimal(L * Math.Cos(Math.PI / 180 * Convert.ToDouble(lat))); // 指定纬度对应的纬线长度(半圈)
var angle = 180 * leng / latL;
return angle;
}
/// <summary>
/// 根据已知相邻3点,求中点的等距平行点经纬度
/// </summary>
/// <param name="p0">@param {p0, p1, p2} 相邻三个LatLng点</param>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="t">@return {t} 待求平行点到线段的垂直距离</param>
/// <returns></returns>
public static GeMode getParallelPoint(GeMode p0, GeMode p1, GeMode p2, double t)
{
// 经纬度分别转换成长度单位
decimal y12 = p2.lat - p1.lat;
decimal x12 = p2.lng - p1.lng;
decimal y01 = p1.lat - p0.lat;
decimal x01 = p1.lng - p0.lng;
double a, b;
if (x12 == 0)
{
a = Math.PI / 2;
if (y12 < 0)
a = -a;
}
else
{
a = Math.Atan(Convert.ToDouble(y12 / x12));
}
if (x01 == 0)
{
b = Math.PI / 2;
if (y01 < 0)
b = -b;
}
else
{
b = Math.Atan(Convert.ToDouble(y01 / x01));
}
//alert(b);
// 关键核心处
if (p2.lng < p1.lng)
{
a += Math.PI;
}
if (p1.lng < p0.lng)
{
b += Math.PI;
}
var k = (b - a - Math.PI) / 2;
var r = a + k;
var d = t / Math.Sin(k);
var sinr = Math.Sin(r);
var cosr = Math.Cos(r);
// alert(d * sinr);
var d_lat = lenToLat(Convert.ToDecimal(d * sinr));
var d_lng = lenToLng(p1.lat, Convert.ToDecimal(d * cosr));
d_lat = p1.lat + d_lat;
d_lng = p1.lng + d_lng;
GeMode g = new GeMode(d_lat, d_lng);
return g;
// addMark(obj);
}
#endregion
public class GeMode
{
/// <summary>
///
/// </summary>
/// <param name="lat">纬度</param>
/// <param name="lng">进度</param>
public GeMode(decimal lat, decimal lng)
{
_lat = lat;//
_lng = lng;//
}
private decimal _lat;
private decimal _lng;
public decimal lat
{
set { _lat = value; }
get { return _lat; }
}
public decimal lng
{
set { _lng = value; }
get { return _lng; }
}
}
}
相关文章推荐
- VR系列——Oculus Rift 开发者指南:四、高级渲染配置(二)
- VR系列——Oculus Rift 开发者指南:四、高级渲染配置(四)
- BlackBerry 应用程序开发者指南 第二卷:高级--第7章 与BlackBerry应用程序通信
- BlackBerry 应用程序开发者指南 第二卷:高级--第3章 集成PIM功能
- VR系列——Oculus Rift 开发者指南:四、高级渲染配置(一)
- MySQL核心编程:高级开发者指南
- firefox附加组件开发者指南(四)——使用XPCOM:实现高级处理
- VR系列——Oculus Rift 开发者指南:四、高级渲染配置(五)
- VR系列——Oculus Rift 开发者指南:四、高级渲染配置(三)
- libusb开发者指南
- google chrome 使用指南 -- 对于我这个PHP WEB开发者
- Chrome开发者工具不完全指南(四、性能进阶篇)
- Spark性能优化指南——高级篇
- MFC程序员的WTL指南: Part V - 高级对话框用户界面类
- Wine完全使用指南――从基本到高级
- Spark性能优化指南-高级篇
- liferay 新开发者指南
- Android开发者指南-String资源[原创译文]
- Android开发者指南-Action Bar[原创译文]
- Android开发者指南-View 动画-View Animation[原创译文]