google-maps - 计算谷歌地图的昼夜叠加

标签 google-maps

我正在尝试找到一种方法来为 Google Maps API V3 创建一个显示世界阳光照射区域的叠加层。这是我正在寻找的基本结果:

http://www.daylightmap.com/index.php

但是想要更多地控制外观(理想情况下只有 10% 的黑色覆盖层,没有城市灯光)。我可以在 Canvas 元素中绘制形状,但不知道如何根据地球的倾斜和旋转等计算形状。

任何帮助,将不胜感激。

编辑:Javascript

我仍然不知道在哪里实现下面的 y-offset 变量。我还需要弄清楚如何调整/拉伸(stretch)从这个(等远纬线)到墨卡托(靠近两极)的 y 偏移量。

// Get the canvas element
var ctx = document.getElementById('canvas').getContext('2d');
ctx.clearRect( 0, 0, 800, 620 );

// Current time
var map_width = $("#canvas").width();
var map_height = $("#canvas").height();
var now = new Date();
var cur_hour = now.getHours();
var cur_min = now.getMinutes();
var cur_sec = now.getSeconds();
var cur_jul = now.julianDate() - 1;
var equinox_jul = new Date(now.getFullYear(),2,20,24,-now.getTimezoneOffset(),0,0).julianDate() - 1;

var offset_x = Math.round(((cur_hour*3600 + cur_min*60 + cur_sec)/86400) * map_width); // Resulting offset X
var offset_sin = ((365.25 - equinox_jul + cur_jul)%365.25)/365.25; // Day offset, mapped on the equinox offset
var offset_sin_factor = Math.sin(offset_sin * 2 * Math.PI); // Sine wave offset
var offset_y = offset_sin_factor * 23.44; // Map onto angle. Maximum angle is 23.44° in both directions

var degrees_per_radian = 180.0 / Math.PI;
var offset_y_mercator = Math.atan( offset_y.sinh() ) * degrees_per_radian;


// Global wave variables
var period = 1 / 6.28291;   // Original value 2Pi: 6.28291
var amplitude = (map_height/2);

// Draw vertical lines: One for each horizontal pixel on the map
for( var x = 0; x <= map_width; x++ ) {
    ctx.beginPath();

    // Start at the bottom of the map
    ctx.moveTo(x,map_height);

    // Get the y value for the x pixel on the sine wave
    var y = (map_height/2) - (Math.sin( (offset_x / map_width) / period ) * amplitude);

    offset_x++;

    // Draw the line up to the point on the sine wave
    ctx.lineTo(x,y);
    ctx.stroke();
}

最佳答案

如果您希望它在物理上准确,您实际上需要考虑两个偏移量:垂直(取决于当前日期)和水平(取决于当前时间)。

可以通过查看地球上某个固定地理位置的当前时间来计算水平偏移 X。阴影偏移量将在午夜为 0,并在午夜后每秒钟增加 1/86400。所以公式是

offsetX = (curHour*3600 + curMinute*60 + curSeconds)/86400

垂直偏移将在 Solstices 之间变化在 6 月 21 日和 12 月 22 日(如果不是闰年,至日在 6 月 20 日和 12 月 21 日)。两个方向的最大角度为 23.44°。我们每个半球有 90°,两个至日之间有 365/2 = 182.5 天,我们正在处理圆周运动的映射,因此必须使用 sin() 函数。正弦波的波长是 2pi,所以我们需要 pi 为一年垂直偏移 Y 的一半。

请注意,我没有考虑闰秒,所以在遥远的过去/ future 计算可能有点偏离。
// current time
$curHour = date("H");
$curMin  = date("i");
$curSec  = date("s");

// resulting offset X
$offsetX = ($curHour*3600 + $curMin*60 + $curSec)/86400;


echo "======== OFFSET X ==========\n";
echo "curHour:      $curHour\n";
echo "curMin:       $curMin\n";
echo "curSec:       $curSec\n";
echo "offsetX:      $offsetX\n\n";


// spring equinox date as day of year
$equinox = date("z", mktime(0, 0, 0, 3, 20));

// current day of year
    // first line is for testing purposes
//$curDay = date("z", mktime(0, 0, 0, 6, 21));
    $curDay = date("z");

// Day offset, mapped on the equinox offset
$offsetSin = ((365.25 - $equinox + $curDay)%365.25)/365.25;

// sinus wave offset
$offsetSinFactor = sin($offsetSin * 2 * pi());

// map onto angle
$offsetY = $offsetSinFactor * 23.44;

// optional: Mercator projection
$degreesPerRadian = 180.0 / pi();
$offsetYmercator = atan(sinh($offsetY)) * $degreesPerRadian;

// missing: mapping onto canvas height (it's currently
// mapped on $offsetY = 90 as the total height of the
// canvas.


echo "========= OFFSET Y =========\n";
echo "equinox day:  $equinox\n";
echo "curDay:       $curDay\n";
echo "offsetSin:    $offsetSin\n";
echo "offsetSinFac: $offsetSinFactor\n";
echo "offsetY:      $offsetY\n";
echo "offsetYmerc:  $offsetYmercator\n";

您应该能够将此计算移植到您想要的任何语言。

关于google-maps - 计算谷歌地图的昼夜叠加,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7100718/

相关文章:

javascript - 谷歌地图未捕获类型错误 : Cannot read property 'firstChild' of null in vue js html?

java - 如何更改谷歌地图标记上方标题和 fragment 的设计

java - 使用谷歌地图计算实时行进距离

javascript - 什么是自动确定用户位置的好javascript

javascript - 为 Google MAPS API v3 放置来自 JSON 数据的标记

reactjs - react 映射错误 :"Did you wrap <GoogleMap> component with withGoogleMap() HOC?"

c# - 如何获取放置在 Google map 上的 JSON 结果?

xcode - swift 3 : Google Maps Api not changing camera view

javascript - 将 infoWindow 包含到 gmaps markclusterer 中时出现问题

r - 如何在R中的 map 中的特定位置绘制数据点