2016-12-06 3 views
2

Hinweis: Das Problem ist nicht spezifisch für Leaflet, sondern allgemein für GIS.So konvertieren Sie Meter in Längen- oder Breitengrade beim Zeichnen eines Kreises

Ich versuche, einen Bogen auf einer Karte zu zeichnen. Ich habe eine Funktion, um die Polygonpunkte zu erzeugen, und es funktioniert zum Beispiel auf einer Leinwand, aber nicht auf Lng, Lat Karte.

Das Problem ist, dass ich nicht herausfinden kann, wie man den inneren/äußeren Radius von Metern in Grad umwandelt (wie in lng/lat), was ich bisher versucht habe, sieht elliptischer als kreisförmig aus.

Wie kann man Meter an jedem Punkt der Erde (mit Ausnahme der Pole) in Längen- oder Breitengrade umrechnen?

Hier ist, was ich versucht (funktioniert) auf Leinwand.

$(document).ready(function() { 
 
    var d_canvas = document.getElementById('canvas'); 
 
    var c2 = d_canvas.getContext('2d'); 
 
    c2.fillStyle = '#f00'; 
 
    c2.beginPath(); 
 
    
 
    var fromDeg = 0; 
 
    var toDeg = 90; 
 
    var fromRad = getAngle(fromDeg); 
 
    var toRad = getAngle(toDeg); 
 
    var segments = 100; 
 
    var step = getAngle(toDeg-fromDeg)/segments; 
 
    var x = 250; 
 
    var y = 250; 
 
    var outR = 250; 
 
    var inR = 230; 
 
    c2.moveTo(x+(Math.sin(fromRad)*inR),y-(Math.cos(fromRad)*inR)); 
 
    //c2.moveTo(x,y); 
 
    for (var i = fromRad; i<=toRad; i=i+step){ 
 
    \t c2.lineTo(x+(Math.sin(i)*inR),y-(Math.cos(i)*inR)); 
 
    } 
 
    //c2.closePath(); 
 
    for (var i = toRad; i>=fromRad; i=i-step){ 
 
    \t c2.lineTo(x+(Math.sin(i)*outR),y-(Math.cos(i)*outR)); 
 
    } 
 
    c2.lineTo(x+(Math.sin(fromRad)*inR),y-(Math.cos(fromRad)*inR)); 
 
    //c2.closePath(); 
 
    c2.stroke(); 
 
}); 
 

 
function getAngle(deg){ 
 
\t var val = 2*(deg/360); 
 
    \t return Math.PI*val; 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<canvas id="canvas" width="500" height="500"></canvas>

Und hier ist, was ich versucht (dosn't Arbeit gut) auf der Karte Prospekt.

\t \t var osmUrl = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png', 
 
\t \t osmAttrib = '&copy; <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors', 
 
\t \t osm = L.tileLayer(osmUrl, { 
 
\t \t  maxZoom: 18, 
 
\t \t  attribution: osmAttrib 
 
\t \t }); 
 

 
\t \t // initialize the map on the "map" div with a given center and zoom 
 
\t \t var map = L.map('map').setView([59.56667, 150.80000], 12).addLayer(osm); 
 

 
\t \t // Script for adding marker on map click 
 
\t \t L.polygon(getPolygon()).addTo(map); 
 

 
\t \t function getPolygon() { 
 
\t \t var fromDeg = 0; 
 
\t \t var toDeg = 90; 
 
\t \t var fromRad = getAngle(fromDeg); 
 
\t \t var toRad = getAngle(toDeg); 
 
\t \t var segments = 100; 
 
\t \t var step = getAngle(toDeg - fromDeg)/segments; 
 
\t \t var y = 150.84229; 
 
\t \t var x = 59.55416; 
 
\t \t var outR = 0.05; // <------ should be dynamic? 
 
\t \t var inR = 0.025; // <------ this also? 
 
\t \t var polygon = []; 
 
\t \t polygon.push([x + (Math.sin(fromRad) * inR), y + (Math.cos(fromRad) * inR)]); 
 
\t \t for (var i = fromRad; i <= toRad; i = i + step) { 
 
\t \t  polygon.push([x + (Math.sin(i) * inR), y + (Math.cos(i) * inR)]); 
 
\t \t } 
 
\t \t //c2.closePath(); 
 
\t \t for (var i = toRad; i >= fromRad; i = i - step) { 
 
\t \t  polygon.push([x + (Math.sin(i) * outR), y + (Math.cos(i) * outR)]); 
 
\t \t } 
 
\t \t polygon.push([x + (Math.sin(fromRad) * inR), y + (Math.cos(fromRad) * inR)]); 
 
\t \t return polygon; 
 
\t \t } 
 

 
\t \t function getAngle(deg) { 
 
\t \t var val = 2 * (deg/360); 
 
\t \t return Math.PI * val; 
 
\t \t }
#map { 
 
    height: 500px; 
 
    width: 80%; 
 
}
<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script> 
 
<link href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" rel="stylesheet" /> 
 
<script src="http://unpkg.com/leaflet-arc/bin/leaflet-arc.min.js"></script> 
 
<div id="map"></div>

Antwort

4

So Ihre ursprüngliche Frage ist

Wie genau Meter an jedem beliebigen Punkt auf der Erde Länge oder Breite zu konvertieren (mit Ausnahme des Pols)?

Aber mein Gehirn liest, dass als

einen [lat, lng] Punkt und eine Entfernung d in Metern angegeben, wie ein zweiten [lat2, lng2] Punkt, der von dem ersten Punkt d Meter entfernt berechnen?

Welche, wenn Sie einige GIS Jargon wissen, ist die gleiche wie die Frage

Wie löse ich das direct geodesic problem?

Die Antwort bezieht sich auf mathematische Konzepte wie Ellipsoide und Großkreise.

Aber da Sie mit Javascript und Leaflet arbeiten, werde ich einfach zu praktischen Implementierungen springen.

Wenn Sie eine sehr genaue Antwort benötigen, sollten Sie sich the JS implementation of GeographicLib und seine Methoden ansehen, um das direkte geodätische Problem zu lösen.

Wenn Sie nicht wirklich auf Genauigkeit achten (und speziell nicht auf Genauigkeit an den Polen), möchten Sie einen Blick auf cheap-ruler, und speziell seine destination(p, dist, bearing) Methode.

Es gibt mehrere Lösungen, wie die Verwendung einer äquidistanten Kartenprojektion um den Punkt zentriert, oder einige andere Implementierungen der geodätischen Probleme oder einige Tricks oder das Erstellen der Geometrien außerhalb von JS mit ähnlichen Methoden oder was auch immer.

Dieses Problem wurde bereits gelöst, daher rate ich, eine der vorhandenen Lösungen zu verwenden.

+0

Danke für die Antwort, ich bin durch Ihre Links zu lesen. – Aus

+0

Dies funktioniert auch http://jsfiddle.net/czguhjrx/7/ – Aus

+0

Würden Sie meine Lösung unten betrachten und sehen, ob dies für Kreis/Bogenradius unter 100km genau ist? – Aus

1

Dies löste das Problem

\t \t var osmUrl = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png', 
 
\t \t osmAttrib = '&copy; <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors', 
 
\t \t osm = L.tileLayer(osmUrl, { 
 
\t \t  maxZoom: 18, 
 
\t \t  attribution: osmAttrib 
 
\t \t }); 
 

 
\t \t // initialize the map on the "map" div with a given center and zoom 
 
\t \t var map = L.map('map').setView([59.56667, 150.80000], 12).addLayer(osm); 
 

 
\t \t // Script for adding marker on map click 
 
\t \t L.polygon(getPolygon()).addTo(map); 
 

 
\t \t function getPolygon() { 
 
\t \t var fromDeg = 0; 
 
\t \t var toDeg = 120; 
 
\t \t var lat = 59.56667; 
 
\t \t var lon = 150.80000; 
 
\t \t var outR = 200; 
 
\t \t var inR = 180; 
 
\t \t var polygon = []; 
 
\t \t for (var i = fromDeg; i <= toDeg; i++) { 
 
\t \t  polygon.push(getPoint(lat, lon, inR, i)); 
 
\t \t } 
 
\t \t for (var i = toDeg; i >= fromDeg; i--) { 
 
\t \t  polygon.push(getPoint(lat, lon, outR, i)); 
 
\t \t } 
 
\t \t polygon.push(getPoint(lat, lon, inR, fromDeg)); 
 
\t \t return polygon; 
 
\t \t } 
 
     /************************* 
 
     * The solution 
 
     *************************/ 
 
\t \t function getPoint(lat, lon, r, deg) { 
 
\t \t lat2 = (r/111230) * Math.cos(deg2rad(deg)); 
 
\t \t lat2 += lat; 
 
\t \t lon2 = (r/111230) * Math.sin(deg2rad(deg)); 
 
\t \t lon2 = lon2 * (1/Math.cos(deg2rad(lat2))); 
 
\t \t lon2 += lon; 
 
\t \t return [lat2, lon2]; 
 
\t \t } 
 

 
\t \t function deg2rad(deg) { 
 
\t \t return deg * (Math.PI/180); 
 
\t \t }
#map { 
 
    height: 500px; 
 
    width: 80%; 
 
}
<link href="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.css" rel="stylesheet"/> 
 
<script src="http://cdn.leafletjs.com/leaflet-0.7.2/leaflet.js"></script> 
 
<div id="map"></div>

Verwandte Themen