2

Преамбула: есть issue logged с API Карт Google, с просьбой исправить угол наклона улиц, чтобы компенсировать холмы. Я придумал обходное решение на стороне клиента с участием колдовства css на контейнере плитки. Вот моя функция поворота:Вычислить угол поворота для Карт Google Просмотр улиц

rotate: function() { 
    var tilesLoaded = setInterval(function() { 
     var tiles = $('map-canvas').getElementsByTagName('img'); 
     for (var i=0; i<tiles.length; i++) { 
      if (tiles[i].src.indexOf(maps.panorama.getPano()) > -1) { 
       if (typeof maps.panorama.getPhotographerPov != 'undefined') { 
        var pov = maps.panorama.getPhotographerPov(), 
        pitch = pov.pitch, 
        cameraHeading = pov.heading; 

        /************************** 
        // I need help with my logic here. 
        **************************/ 
        var yaw = pov.heading - 90; 
        if (yaw < 0) yaw += 360; 
        var scale = ((Math.abs(maps.heading - yaw)/90) - 1) * -1; 
        pitch = pov.pitch * scale; 


        tiles[i].parentNode.parentNode.style.transform = 'rotate(' + pitch + 'deg)'; 
        clearInterval(tilesLoaded); 
        return; 
       } 
      } 
     } 
    }, 20); 
} 

Полный (более подробно комментировал) проверка концепции находится на this JSFiddle. Как ни странно, горизонт почти идеальный, если я вообще не делаю вычисления на примере в JSFiddle, но этот результат не согласован для каждого Lat/Lng. Это просто совпадение.

Итак, мне нужно вычислить рулон в заголовке клиента, учитывая заголовок клиента, заголовок фотографа и шаг фотографа. Предположим, что фотограф либо смотрит вверх, либо в гору, и pov.pitch является превосходным (с минимальным или максимальным пределом). Как я могу рассчитать желаемый шаг, обращенный к стороне в определенной степени?

Редактировать: Я нашел уравнение, которое, кажется, работает очень хорошо. Я обновил код и скрипку. Хотя это, кажется, довольно близко к ответу, мой алгоритм является линейным. Я считаю, что правильное уравнение должно быть логарифмическим, что приводит к более тонким настройкам ближе к заголовку камеры и наоборот, в то время как регулировки слева и справа камеры больше.

ответ

1

Я нашел ответ, который я искал. Расчет включает в себя сферическую тригонометрию, о которой я даже не знал, прежде чем исследовать эту проблему. Если кто-нибудь замечает какие-либо проблемы, прокомментируйте. Если у вас есть лучшее решение, чем тот, который я нашел, не стесняйтесь добавлять свой ответ, и я, вероятно, соглашусь с ним, если он более надежный или значительно более эффективный, чем мой собственный.

В любом случае, если холст плитки является сферой, 0 шаг (горизонт) - это плоскость, а шаг камеры - другая плоскость, пересекающаяся с фотографом, две плоскости создают на холсте spherical lune. Это луночка может быть использована для вычисления spherical triangle где:

  1. полярного угла = Math.abs (шаг камеры)
  2. = базовой камера заголовок - клиент заголовка
  3. один угол = 90 ° (для плоского горизонта)

С двумя углами и доступной стороной другие свойства сферического треугольника можно рассчитать, используя spherical law of sines. Весь треугольник не нужен - только сторона, противоположная полярному углу. Поскольку это математика за пределами моих навыков, мне пришлось заимствовать логику от this spherical triangle calculator. Особая благодарность emfril!

The jsfiddle был обновлен. Моя продукция рулет геттер обновлена ​​следующим образом:

function $(what) { return document.getElementById(what); } 

var maps = { 

    get roll() { 
     function acos(what) { 
      return (Math.abs(Math.abs(what) - 1) < 0.0000000001) 
      ? Math.round(Math.acos(what)) : Math.acos(what); 
     } 
     function sin(what) { return Math.sin(what); } 
     function cos(what) { return Math.cos(what); } 
     function abs(what) { return Math.abs(what); } 
     function deg2rad(what) { return what * Math.PI/180; } 
     function rad2deg(what) { return what * 180/Math.PI; } 
     var roll=0; 

     if (typeof maps.panorama.getPhotographerPov() != 'undefined') { 
      var pov = maps.panorama.getPhotographerPov(), 
      clientHeading = maps.panorama.getPov().heading; 
      while (clientHeading < 0) clientHeading += 360; 
      while (clientHeading > 360) clientHeading -= 360; 

      // Spherical trigonometry method 
      a1 = deg2rad(abs(pov.pitch)); 
      a2 = deg2rad(90); 
      yaw = deg2rad((pov.heading < 0 ? pov.heading + 360 : pov.heading) - clientHeading); 
      b1 = acos((cos(a1) * cos(a2)) + (sin(a1) * sin(a2) * cos(yaw))); 

      if (sin(a1) * sin(a2) * sin(b1) !== 0) { 

       roll = acos((cos(a1) - (cos(a2) * cos(b1)))/(sin(a2) * sin(b1))); 
       direction = pov.heading - clientHeading; 
       if (direction < 0) direction += 360; 
       if (pov.pitch < 0) 
        roll = (direction < 180) ? rad2deg(roll) * -1 : rad2deg(roll); 
       else 
        roll = (direction > 180) ? rad2deg(roll) * -1 : rad2deg(roll); 

      } else { 

       // Fall back to algebraic estimate to avoid divide-by-zero 
       var yaw = pov.heading - 90; 
       if (yaw < 0) yaw += 360; 
       var scale = ((abs(clientHeading - yaw)/90) - 1) * -1; 
       roll = pov.pitch * scale; 
       if (abs(roll) > abs(pov.pitch)) { 
        var diff = (abs(roll) - abs(pov.pitch)) * 2; 
        roll = (roll < 0) ? roll + diff : roll - diff; 
       } 

      } 
     } 
     return roll;   
    }, // end maps.roll getter 

    // ... rest of maps object... 

} // end maps{} 

После поворота плитки контейнер панорамы, контейнер также должен быть расширен, чтобы скрыть пустые углы. Первоначально я использовал 2D-закон синусов, но я нашел more efficient shortcut. Спасибо, мистер Тан!

function deg2rad(what) { return what * Math.PI/180; } 
function cos(what) { return Math.cos(deg2rad(what)); } 
function sin(what) { return Math.sin(deg2rad(what)); } 

var W = $('map-canvas').clientWidth, 
H = $('map-canvas').clientHeight, 
Rot = Math.abs(maps.originPitch); 

// pixels per side 
maps.growX = Math.round(((W * cos(Rot) + H * cos(90 - Rot)) - W)/2); 
maps.growY = Math.round(((W * sin(Rot) + H * sin(90 - Rot)) - H)/2); 

Там не будет никаких правок в этот ответ, так как я не хочу, чтобы он конвертируется в вики ответ сообщества еще. Поскольку обновления происходят со мной, они будут применяться к fiddle.

+0

Следует отметить, что, хотя я продолжаю вычислять 'maps.growX' способом, показанным в примере выше, я перешел к вычислению' maps.growY' как пропорции. Таким образом, соотношение сторон не изменяется. См. Скрипт для обновления. – rojo

Смежные вопросы