Question

J'ai cette image: http://imgur.com/99tSz.png . Une carte du Royaume-Uni (hors Irlande du Sud).

J'ai réussi à obtenir une latitude et la longitude et la sur cette parcelle carte en prenant la longitude et la longitude extrême gauche extrême droite du Royaume-Uni et les utiliser pour déterminer où mettre le point sur la carte.

Voici le code (pour une utilisation dans Processing.js mais pourrait être utilisé comme js ou quoi que ce soit):

// Size of the map
int width = 538;
int height = 811;
// X and Y boundaries
float westLong = -8.166667;
float eastLong = 1.762833;
float northLat = 58.666667;
float southLat = 49.95;

void drawPoint(float latitude, float longitude){

 fill(#000000);

 x = width * ((westLong-longitude)/(westLong-eastLong));
 y = (height * ((northLat-latitude)/(northLat-southLat)));

 console.log(x + ", " + y);
 ellipseMode(RADIUS);
 ellipse(x, y, 2, 2);    

}

Cependant, je ne l'ai pas été en mesure de mettre en œuvre une projection de Mercator sur ces valeurs. Les parcelles sont assez précises, mais ils ne sont pas assez bonne et cette projection permettrait de le régler.

Je ne peux pas comprendre comment le faire. Tous les exemples que je trouve expliquent comment le faire pour le monde entier. Cette est une bonne ressource d'exemples expliquant comment mettre en œuvre la projection, mais je n'ai pas été capable de le faire fonctionner.

Une autre ressource est le où je suis les valeurs de latitude et de longitude de la zone de délimitation autour du Royaume-Uni. Ils sont également ici:

northLat = 58.666667; 
northLong = -3.366667; 
eastLat = 52.481167; 
eastLong = 1.762833; 
southLat = 49.95;
southLong = -5.2; 
westLat = 54.45;
westLong = -8.166667;

Si quelqu'un pouvait me aider, je serais très heureux!

Merci

Était-ce utile?

La solution

Je pense qu'il vaut la peine de garder à l'esprit que toutes les cartes plates sont des projections Mercator. Sans en savoir plus sur cette carte en particulier, il est difficile d'en être sûr. Vous pouvez constater que la plupart des cartes d'une petite région du monde sont plus susceptibles d'être conique projection du type, où la zone d'intérêt sur la carte est « plus plat » que serait sur une projection globale Mercator . Ceci est particulièrement le plus important plus on se éloigne de l'équateur (et le Royaume-Uni est assez loin pour qu'il importe).

Vous pouvez être en mesure d'obtenir « assez près » en utilisant les calculs que vous essayez, mais pour une meilleure précision que vous pouvez soit utiliser une carte avec une projection bien définie, ou créer votre propre carte.

Autres conseils

J'ai écrit une fonction qui fait exactement ce que vous recherchez. Je sais qu'il est un peu tard, mais peut-être il y a d'autres personnes intéressées par.

Vous avez besoin d'une carte qui est une projection de mercator et vous avez besoin de connaître les positions lat / long de votre carte. Vous obtenez de grandes cartes personnalisées avec mercator parfaite adéquation lat / positions de LON TileMill qui est un logiciel libre MapBox

J'utilise ce script et testé avec des positions de Google Earth. Il a fonctionné parfaitement au niveau des pixels. En fait, je ne ai pas tester cela sur des cartes différentes ou plus. J'espère que cela vous aide!

Raphael;)

<?php

$mapWidth = 1500;
$mapHeight = 1577;

$mapLonLeft = 9.8;
$mapLonRight = 10.2;
$mapLonDelta = $mapLonRight - $mapLonLeft;

$mapLatBottom = 53.45;
$mapLatBottomDegree = $mapLatBottom * M_PI / 180;

function convertGeoToPixel($lat, $lon)
{
    global $mapWidth, $mapHeight, $mapLonLeft, $mapLonDelta, $mapLatBottom, $mapLatBottomDegree;

    $x = ($lon - $mapLonLeft) * ($mapWidth / $mapLonDelta);

    $lat = $lat * M_PI / 180;
    $worldMapWidth = (($mapWidth / $mapLonDelta) * 360) / (2 * M_PI);
    $mapOffsetY = ($worldMapWidth / 2 * log((1 + sin($mapLatBottomDegree)) / (1 - sin($mapLatBottomDegree))));
    $y = $mapHeight - (($worldMapWidth / 2 * log((1 + sin($lat)) / (1 - sin($lat)))) - $mapOffsetY);

    return array($x, $y);
}

$position = convertGeoToPixel(53.7, 9.95);
echo "x: ".$position[0]." / ".$position[1];

?>

Voici l'image que je crée avec TileMill et que j'utilisé dans cet exemple: image de la carte

En plus de ce que Raphaël a posté Wichmann (Merci d'ailleurs!), ici est la fonction inverse, en actionscript:

function convertPixelToGeo(tx:Number, ty:Number):Point
{   
    /* called worldMapWidth in Raphael's Code, but I think that's the radius since it's the map width or circumference divided by 2*PI  */   
    var worldMapRadius:Number = mapWidth / mapLonDelta * 360/(2 * Math.PI);     
    var mapOffsetY:Number = ( worldMapRadius / 2 * Math.log( (1 + Math.sin(mapLatBottomRadian) ) / (1 - Math.sin(mapLatBottomRadian))  ));
    var equatorY:Number = mapHeight + mapOffsetY;   
    var a:Number = (equatorY-ty)/worldMapRadius;

    var lat:Number = 180/Math.PI * (2 * Math.atan(Math.exp(a)) - Math.PI/2);
    var long:Number = mapLonLeft+tx/mapWidth*mapLonDelta;
    return new Point(lat,long);
}

Je l'ai converti le code PHP fourni par Raphael à JavaScript et peut le confirmer a fonctionné et ce code fonctionne moi-même. Tout le crédit à Raphael.

/*
var mapWidth = 1500;
var mapHeight = 1577;

var mapLonLeft = 9.8;
var mapLonRight = 10.2;
var mapLonDelta = mapLonRight - mapLonLeft;

var mapLatBottom = 53.45;
var mapLatBottomDegree = mapLatBottom * Math.PI / 180;
*/

function convertGeoToPixel(latitude, longitude ,
                           mapWidth , // in pixels
                           mapHeight , // in pixels
                           mapLonLeft , // in degrees
                           mapLonDelta , // in degrees (mapLonRight - mapLonLeft);
                           mapLatBottom , // in degrees
                           mapLatBottomDegree) // in Radians
{
    var x = (longitude - mapLonLeft) * (mapWidth / mapLonDelta);

    latitude = latitude * Math.PI / 180;
    var worldMapWidth = ((mapWidth / mapLonDelta) * 360) / (2 * Math.PI);
    var mapOffsetY = (worldMapWidth / 2 * Math.log((1 + Math.sin(mapLatBottomDegree)) / (1 - Math.sin(mapLatBottomDegree))));
    var y = mapHeight - ((worldMapWidth / 2 * Math.log((1 + Math.sin(latitude)) / (1 - Math.sin(latitude)))) - mapOffsetY);

    return { "x": x , "y": y};
}

Voici une autre implémentation Javascript. Ceci est une simplification de la solution de @Rob Willet ci-dessus. Au lieu d'exiger des valeurs calculées en tant que paramètres à la fonction, il faut que les valeurs essentielles et calcule tout d'eux:

function convertGeoToPixel(latitude, longitude,
                  mapWidth, // in pixels
                  mapHeight, // in pixels
                  mapLngLeft, // in degrees. the longitude of the left side of the map (i.e. the longitude of whatever is depicted on the left-most part of the map image)
                  mapLngRight, // in degrees. the longitude of the right side of the map
                  mapLatBottom) // in degrees.  the latitude of the bottom of the map
{
    const mapLatBottomRad = mapLatBottom * Math.PI / 180
    const latitudeRad = latitude * Math.PI / 180
    const mapLngDelta = (mapLngRight - mapLngLeft)

    const worldMapWidth = ((mapWidth / mapLngDelta) * 360) / (2 * Math.PI)
    const mapOffsetY = (worldMapWidth / 2 * Math.log((1 + Math.sin(mapLatBottomRad)) / (1 - Math.sin(mapLatBottomRad))))

    const x = (longitude - mapLngLeft) * (mapWidth / mapLngDelta)
    const y = mapHeight - ((worldMapWidth / 2 * Math.log((1 + Math.sin(latitudeRad)) / (1 - Math.sin(latitudeRad)))) - mapOffsetY)

    return {x, y} // the pixel x,y value of this point on the map image
}

Je sais que la question a été posée il y a un certain temps, mais la bibliothèque proj4js est idéal pour transformer entre les différentes projections de carte en JavaScript.

cartes du Royaume-Uni ont tendance à utiliser National Grid du OSGB qui est basé sur une projection Mercator Transverse. C'est à dire. comme un Mercator classique, mais tourné de 90 degrés, de sorte que le « équateur » devient un méridien.

extrait @Xarinko Actionscript en Javascript (avec certaines valeurs de test)

var mapWidth = 1500;
var mapHeight = 1577;

var mapLonLeft = 9.8;
var mapLonRight = 10.2;
var mapLonDelta = mapLonRight - mapLonLeft;

var mapLatBottom = 53.45;
var mapLatBottomRadian = mapLatBottom * Math.PI / 180;



function convertPixelToGeo(tx, ty)
{   
    /* called worldMapWidth in Raphael's Code, but I think that's the radius since it's the map width or circumference divided by 2*PI  */   
    var worldMapRadius = mapWidth / mapLonDelta * 360/(2 * Math.PI);     
    var mapOffsetY = ( worldMapRadius / 2 * Math.log( (1 + Math.sin(mapLatBottomRadian) ) / (1 - Math.sin(mapLatBottomRadian))  ));
    var equatorY = mapHeight + mapOffsetY;   
    var a = (equatorY-ty)/worldMapRadius;

    var lat = 180/Math.PI * (2 * Math.atan(Math.exp(a)) - Math.PI/2);
    var long = mapLonLeft+tx/mapWidth*mapLonDelta;
    return [lat,long];
}

convertPixelToGeo(241,444)

Si vous voulez éviter certains des aspects de messier des projections lat / lng intrinsèques à proj4js, vous pouvez utiliser D3, qui offre de nombreuses projections cuit au four et rend magnifiquement. Voici un exemple interactif de plusieurs saveurs de projection azimutale. Je préfère Albers pour les cartes USA.

Si D3 est pas une option utilisateur final - dire, vous devez soutenir IE 7/8 - vous pouvez rendre dans D3 puis accrocher les coordonnées xy du fichier SVG résultant qui D3 génère. Vous pouvez ensuite rendre ces coordonnées xy Raphaël.

Cette fonction fonctionne très bien pour moi parce que je veux définir le mapHeight basé sur la carte Je veux tracer. Je générer des cartes PDF. Tout ce que je dois faire est de passer en max Lat, Lon min de la carte et il retourne la taille des pixels pour la carte comme [hauteur, largeur].

convertGeoToPixel (maxlatitude, maxlongitude)

Une note à l'étape finale où $ y est fixé, ne pas soustraire le calcul de la mapHeight si votre système de coordonnées « xy » commence au bas / gauche, comme avec les fichiers PDF, ce inversera la carte.

$y =  (($worldMapWidth / 2 * log((1 + sin($lat)) / (1 - sin($lat)))) - $mapOffsetY);

implémentation C #:

private Point ConvertGeoToPixel(
    double latitude, double longitude, // The coordinate to translate
    int imageWidth, int imageHeight, // The dimensions of the target space (in pixels)
    double mapLonLeft, double mapLonRight, double mapLatBottom // The bounds of the target space (in geo coordinates)
) {
    double mapLatBottomRad = mapLatBottom * Math.PI / 180;
    double latitudeRad = latitude * Math.PI / 180;

    double mapLonDelta = mapLonRight - mapLonLeft;
    double worldMapWidth = (imageWidth / mapLonDelta * 360) / (2 * Math.PI);
    double mapOffsetY = worldMapWidth / 2 * Math.Log((1 + Math.Sin(mapLatBottomRad)) / (1 - Math.Sin(mapLatBottomRad)));

    double x = (longitude - mapLonLeft) * (imageWidth / mapLonDelta);
    double y = imageHeight - ((worldMapWidth / 2 * Math.Log((1 + Math.Sin(latitudeRad)) / (1 - Math.Sin(latitudeRad)))) - mapOffsetY);

    return new Point()
    {
        X = Convert.ToInt32(x),
        Y = Convert.ToInt32(y)
    };
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top