2017-05-10 3 views
1

私は次のような場所でマップの例を持っています:
1)ピッチ角60度のビューを設定します
2)キャンバスのコーナーポイントを写像して台形として俯瞰錐を
3)台形を30度変えて台形を再び描画する
4)台形を見るためにズームアウト
5)手動で台形を30度回転させる
6)回転した台形を描く
7)ピッチをゼロに変更する画像を見下ろす
これを行うと、手動で回転した台形(画像の赤色)がsetBearing()呼び出し(画像の紫色)を使って生成された台形と一致しません。それは不適切に歪曲されているように見えます。私はマニュアルの回転コードを8時間見ていて、理由を理解できません。私は地球の曲がりを扱っているのですか?誰かがこれを整理することはできますか?ありがとう!マップボックス内の回転した点が歪んでいる

mapboxgl.accessToken = 'pk.eyJ1IjoiZm1hY2RlZSIsImEiOiJjajJlNWMxenowNXU2MzNudmkzMndwaGI3In0.ALOYWlvpYXnlcH6sCR9MJg'; 
 

 
var map; 
 

 
function addLayerToMap(name, points, color, width) { 
 
    map.addLayer({ 
 
     "id": name, 
 
     "type": "line", 
 
     "source": { 
 
      "type": "geojson", 
 
      "data": { 
 
       "type": "Feature", 
 
       "properties": {}, 
 
       "geometry": { 
 
        "type": "LineString", 
 
        "coordinates": points 
 
       } 
 
      } 
 
     }, 
 
     "layout": { 
 
      "line-join": "round", 
 
      "line-cap": "round" 
 
     }, 
 
     "paint": { 
 
      "line-color": color, 
 
      "line-width": width 
 
     } 
 
    }); 
 
} 
 

 
function pointsRotate(points, cx, cy, angle){ 
 
    var radians = (Math.PI/180) * angle; 
 
    var cos = Math.cos(radians); 
 
    var sin = Math.sin(radians); 
 
    var newpoints = []; 
 

 
    function rotate(x, y) { 
 
     nx = (cos * (x - cx)) + (sin * (y - cy)) + cx, 
 
     ny = (cos * (y - cy)) + (-sin * (x - cx)) + cy; 
 
     return [nx, ny]; 
 
    } 
 
    for(var i=0;i<points.length;i++) { 
 
     newpoints[i] = rotate(points[i][0],points[i][1]); 
 
    } 
 
    return(newpoints); 
 
} 
 

 
function convertTrapezoidToPath(trap) { 
 
    return([ 
 
     [trap.Tl.lng, trap.Tl.lat], [trap.Tr.lng, trap.Tr.lat], 
 
     [trap.Br.lng, trap.Br.lat], [trap.Bl.lng, trap.Bl.lat], 
 
     [trap.Tl.lng, trap.Tl.lat] ]); 
 
} 
 

 
function getViewTrapezoid() { 
 
    var canvas = map.getCanvas(); 
 
    var trap = {}; 
 

 
    trap.Tl = map.unproject([0,0]); 
 
    trap.Tr = map.unproject([canvas.offsetWidth,0]); 
 
    trap.Br = map.unproject([canvas.offsetWidth,canvas.offsetHeight]); 
 
    trap.Bl = map.unproject([0,canvas.offsetHeight]); 
 

 
    return(trap); 
 
} 
 

 
map = new mapboxgl.Map({ 
 
    container: 'map', 
 
    style: 'mapbox://styles/mapbox/streets-v9', 
 
    center: [-122.48610019683838, 37.82880236636284], 
 
    zoom: 17, 
 
    pitch: 60 
 
}); 
 

 
map.on('load', function() { 
 

 
    // get the center and trapezoid of the zoomed in view 
 
    var center = map.getCenter(); 
 
    var trapezoid = getViewTrapezoid(); 
 
    
 
    // convert the view trapezoid to a path and add it to the view 
 
    var trapezoid_path = convertTrapezoidToPath(trapezoid); 
 
    addLayerToMap("viewTrapezoid",trapezoid_path,'#888',4); 
 

 
    // now rotate the bearing by 30 degrees to get a second view trapezoid 
 
    map.setBearing(30); 
 
    setTimeout(function() { 
 
    var trapezoid2 = getViewTrapezoid(); 
 
    var trapezoid2_path = convertTrapezoidToPath(trapezoid2); 
 
    addLayerToMap("viewTrapezoid2",trapezoid2_path,'#f0f',2); 
 
    
 
    // return to a "top down" view and zoom out to show the trapezoids 
 
    map.setBearing(0); 
 
    map.setZoom(13.5); 
 
     setTimeout(function() { 
 
     map.flyTo({ pitch: 0 }); 
 
     
 
     // rotate the original view trapezoid by 30 degrees and add it to the map 
 
     var newpath = pointsRotate(trapezoid_path,center.lng,center.lat,30); 
 
     addLayerToMap("rotatedTrapezoid",newpath,'#f00',2); 
 
    }, 500); 
 
    }, 500); 
 
    
 
    
 
    
 
});
body { margin:0; padding:0; } 
 
#map { position:absolute; top:0; bottom:0; width:100%; }
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.js'></script> 
 
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.css' rel='stylesheet' /> 
 

 
<div id='map'></div>

+0

うーんは - それは経度距離が極近い小さな取得する際に問題があるように見えます。私の計算はこのポストに従って赤道付近でしか動作しません:https://gis.stackexchange.com/questions/206698/rotating-a-set-of-coordinates-around-a-point
私は彼らのコードの提案を試みます。 update ... – fmacdee

+0

これで、緯度の度合いに基づいて経度の長さを計算するアルゴリズムが見つかりました。私はそれを試してみましょう... https://gis.stackexchange.com/questions/75528/understanding-terms-in-length-of-degree-formula/75535#75535 – fmacdee

答えて

0

[OK]を、ので、それはので、あなたが極に近づくにつれて、より薄くなっ経度の、あなたが最初に必要メルカトルコに(緯度と長い)すべての度座標を変換することが判明地球の非球面性を考慮した縦座標です。私は、ここで2つの関数を追加しました。これは、lat lonからmercatorへ、そしてその逆の変換を行い、それらをコードに入れ、結果はsetBearing()メソッドを使って提供される台形の上に直接置かれます。問題が解決しました!

mapboxgl.accessToken = 'pk.eyJ1IjoiZm1hY2RlZSIsImEiOiJjajJlNWMxenowNXU2MzNudmkzMndwaGI3In0.ALOYWlvpYXnlcH6sCR9MJg'; 
 

 
var map; 
 

 
function addLayerToMap(name, points, color, width) { 
 
    map.addLayer({ 
 
     "id": name, 
 
     "type": "line", 
 
     "source": { 
 
      "type": "geojson", 
 
      "data": { 
 
       "type": "Feature", 
 
       "properties": {}, 
 
       "geometry": { 
 
        "type": "LineString", 
 
        "coordinates": points 
 
       } 
 
      } 
 
     }, 
 
     "layout": { 
 
      "line-join": "round", 
 
      "line-cap": "round" 
 
     }, 
 
     "paint": { 
 
      "line-color": color, 
 
      "line-width": width 
 
     } 
 
    }); 
 
} 
 

 
function pointsRotate(points, cx, cy, angle){ 
 
    var radians = (Math.PI/180) * angle; 
 
    var cos = Math.cos(radians); 
 
    var sin = Math.sin(radians); 
 
    var newpoints = []; 
 

 
    function rotate(x, y) { 
 
     nx = (cos * (x - cx)) + (sin * (y - cy)) + cx, 
 
     ny = (cos * (y - cy)) + (-sin * (x - cx)) + cy; 
 
     return [nx, ny]; 
 
    } 
 
    for(var i=0;i<points.length;i++) { 
 
     newpoints[i] = rotate(points[i][0],points[i][1]); 
 
    } 
 
    return(newpoints); 
 
} 
 

 
function convertTrapezoidToPath(trap) { 
 
    return([ 
 
     [trap.Tl.lng, trap.Tl.lat], [trap.Tr.lng, trap.Tr.lat], 
 
     [trap.Br.lng, trap.Br.lat], [trap.Bl.lng, trap.Bl.lat], 
 
     [trap.Tl.lng, trap.Tl.lat] ]); 
 
} 
 

 
function getViewTrapezoid() { 
 
    var canvas = map.getCanvas(); 
 
    var trap = {}; 
 

 
    trap.Tl = map.unproject([0,0]); 
 
    trap.Tr = map.unproject([canvas.offsetWidth,0]); 
 
    trap.Br = map.unproject([canvas.offsetWidth,canvas.offsetHeight]); 
 
    trap.Bl = map.unproject([0,canvas.offsetHeight]); 
 

 
    return(trap); 
 
} 
 

 
function Mercator2ll(mercX, mercY) { 
 
    var rMajor = 6378137; //Equatorial Radius, WGS84 
 
    var shift = Math.PI * rMajor; 
 
    var lon = mercX/shift * 180.0; 
 
    var lat = mercY/shift * 180.0; 
 
    lat = 180/Math.PI * (2 * Math.atan(Math.exp(lat * Math.PI/180.0)) - Math.PI/2.0); 
 

 
    return [ lon, lat ]; 
 
} 
 
function ll2Mercator(lon, lat) { 
 
    var rMajor = 6378137; //Equatorial Radius, WGS84 
 
    var shift = Math.PI * rMajor; 
 
    var x  = lon * shift/180; 
 
    var y  = Math.log(Math.tan((90 + lat) * Math.PI/360))/(Math.PI/180); 
 
    y = y * shift/180; 
 

 
    return [ x, y ]; 
 
} 
 

 
function convertDegrees2Meters(points) { 
 
    var newpoints = []; 
 

 
    for(var i=0;i<points.length;i++) { 
 
     newpoints[i] = ll2Mercator(points[i][0], points[i][1]); 
 
    } 
 
    return newpoints; 
 
} 
 
function convertMeters2Degrees(points) { 
 
    var newpoints = []; 
 

 
    for(var i=0;i<points.length;i++) { 
 
     newpoints[i] = Mercator2ll(points[i][0], points[i][1]);; 
 
    } 
 
    return newpoints; 
 
} 
 

 
map = new mapboxgl.Map({ 
 
    container: 'map', 
 
    style: 'mapbox://styles/mapbox/streets-v9', 
 
    center: [-122.48610019683838, 37.82880236636284], 
 
    zoom: 17, 
 
    pitch: 60 
 
}); 
 

 
map.on('load', function() { 
 

 
    // get the center and trapezoid of the zoomed in view 
 
    var center = map.getCenter(); 
 
    var trapezoid = getViewTrapezoid(); 
 
    var center_meters = ll2Mercator(center.lng,center.lat); 
 
    // convert the view trapezoid to a path and add it to the view 
 
    var trapezoid_path = convertTrapezoidToPath(trapezoid); 
 
    addLayerToMap("viewTrapezoid",trapezoid_path,'#888',4); 
 

 
    // now rotate the bearing by 30 degrees to get a second view trapezoid 
 
    map.setBearing(30); 
 
    setTimeout(function() { 
 
    var trapezoid2 = getViewTrapezoid(); 
 
    var trapezoid2_path = convertTrapezoidToPath(trapezoid2); 
 
    addLayerToMap("viewTrapezoid2",trapezoid2_path,'#f0f',2); 
 
    
 
    // return to a "top down" view and zoom out to show the trapezoids 
 
    map.setBearing(0); 
 
    map.setZoom(13.5); 
 
     setTimeout(function() { 
 
     map.flyTo({ pitch: 0 }); 
 
     
 
     // rotate the original view trapezoid by 30 degrees and add it to the map 
 
     var tpath_meters = convertDegrees2Meters(trapezoid_path); 
 
     var newpath_meters = pointsRotate(tpath_meters,center_meters[0],center_meters[1],30); 
 
     var newpath = convertMeters2Degrees(newpath_meters); 
 
     addLayerToMap("rotatedTrapezoid",newpath,'#f00',2); 
 
    }, 500); 
 
    }, 500); 
 
});
body { margin:0; padding:0; } 
 
#map { position:absolute; top:0; bottom:0; width:100%; }
<script src='https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.js'></script> 
 
<link href='https://api.tiles.mapbox.com/mapbox-gl-js/v0.37.0/mapbox-gl.css' rel='stylesheet' /> 
 

 
<div id='map'></div>

関連する問題