3

I apologize for the vague title, I really can't figure out a batter way to sum it up. Suggestions are more than welcome.

I'm working on a project that really doesn't NEED a google map, it'd just create extra overhead for this project. But, I can't figure out how to do this WITHOUT google maps... so far.

If I were to place a graphical overlay of a floor plan into google maps, I could use a browser location to approximate a users position. For this, it's a VERY large place, so there's room for some poor accuracy.

Now what I'm trying to do is knowing the bounding of that overlay, place the image into a div, then calculate the users position in the div based on their browser lat/lng.

I'm able to get close using an image that is square in that the top of the sides are horizontal and vertical, because that crates my area. But since none of the world works like that, I need an area that isn't square to appear squared. I'm really struggling on the math.

Here's what I'm trying to do!

And here's a link that tests my concept, but doesn't account for an image that needs to be rotated on a map: http://www.freeptools.com/mapster/singlerun/maptest.php

Like I said, I'm sure that this can be done, but I haven't been able to figure out the math for it just yet. It's driving me crazy.

Here's my code that's doing the magic. A function gets the browser coordinates and sends them to the initialize function. Then based on mapping it myself earlier, I have the bounds of the image I'm trying to map. I'm using the haversine formuls to try to get the height and width at the points of the user (since the map curves, it'll be inaccurate anywhere else) position, then the distance from the top and left most points, then taking the distance from the left/top and dividing it by the width/height to get a percentage of how far they are from the left/top to position the dot. This idea, while I can't get it to be super accurate, works in this example, because the image lines up horizontally on a map. My problem is how do I calculate those distances when the image is rotated on a map? I can't figure out that math.

function initialize(y3, x3) { //lat, lon

//var overlayBounds = new google.maps.LatLngBounds(new google.maps.LatLng(41.11246878918085, -90.5712890625), new google.maps.LatLng(47.68652571374621, -82.001953125));
var box = $("#map_canvas");

//image bounds
var x1 = -82.001953125;
var x2 = -90.5712890625;
var y1 = 41.11246878918085;
var y2 = 47.68652571374621;

var boxWidth = x2 - x1;
var boxHeight = y2 - y1;

//now we need to figure out where this rests, first we get the percentage
//var posLeft = haversine(y3, x1, y3, x3); //(x3 - x1);
var posLeft = (x3 - x1);
var posLeftPct = (posLeft/boxWidth)*100;

//var posTop = haversine(y2, x3, y3, x3); //(y2 - y3);
var posTop = (y2 - y3);
var posTopPct = (posTop/boxHeight)*100;

box.append('<img src="http://www.freeptools.com/mapster/icons/icon23.png" style="position:absolute; z-index:200; right:'+posLeftPct+'%; top:'+posTopPct+'%">');

}

John Sly
  • 763
  • 1
  • 10
  • 31
  • What does your code look like? (please post a [Minimal, Complete, Tested and Readable example](http://stackoverflow.com/help/mcve) in the question itself, not just external links) – geocodezip Dec 09 '14 at 20:01
  • I just added the code. The problem I have right now isn't as much witht he code itself, but the concept behind it. I noted above in the edit, the code I have currently only works as a concept because the image's orientation is up and down. if an image is rotated, it completely throws this concept out the window, and that's where I'm really struggling. – John Sly Dec 09 '14 at 20:48
  • where do you get the data for the image(bounds & rotation) from? – Dr.Molle Dec 09 '14 at 21:09
  • In this case, I started in google maps, and positioned it myself, then took that bounding data to use in this example. As for the next example I'd like to attempt, I haven't figured that bounding data, but I have looked on the map enough to know the building I'd like to handle isn't vertical, it's rotated, so the bounding box wouldn't line up with the image I'd like to display in a standalone div. – John Sly Dec 09 '14 at 21:12
  • I don't know if [this SO Post](http://stackoverflow.com/questions/14329691/covert-latitude-longitude-point-to-a-pixels-x-y-on-mercator-projection) will help, but the math behind the Spherical Mercator projection (which the assumption of a spherical geoid), as used on Google Maps, is actually quite straight forward. Over large areas, things that have straight edges on maps, are curved in the real world, but for small areas this shouldn't be a problem. You can use basic trig to actually rotate objects, if you know what your axis of orientation is, naturally. – John Powell Dec 10 '14 at 07:01

1 Answers1

5

Assuming the area is a parallelogram, you'll need to know 3 of the vertices of the area and the width/height of the area where you want to draw the pin(e.g. the floorplan-image).

The following will use the Geo-and LatLon-libraries from http://www.movable-type.co.uk/scripts/latlong.html

An image for better understanding:enter image description here

initially calculate some values:

  • bearings(nw to sw and nw to ne) via LatLon.bearingTo
  • distances(sw to nw and ne to nw) via LatLon.distanceTo

now calculate the intersections(marked as intersection-x and intersection-y in the image) via LatLon.intersection

The calculation would be:

  • intersection-x:
    LatLon.intersection(ne, bearingNWtoSW, target, bearingNWtoNE)
  • intersection-y:
    LatLon.intersection(sw, bearingNWtoNE, target,bearingNWtoSW)

now calculate percentual values for the distance of border-north to target and border-west to target:

  • border-north to target:
    ((distanceNWtoNE-(target.distanceTo(intersection-x)))*100)/distanceNWtoNE
  • border-west to target:
    ((distanceNWtoSW-(target.distanceTo(intersection-y)))*100)/distanceNWtoSW

Finally calculate the coordinates based on the width/height of the given floorplan and the results of the previous calculation

x=((width*distanceBorderNorthToTargetInPercent)/100);
y=((height*distanceBorderWestToTargetInPercent)/100);

A method(extension of the mentioned LatLon-library) that performs all these calculations:

/**
  *@param w int width of the drawing
  *@param h int height of the drawing
  *@param sw object LatLon of southwest of the drawing     
  *@param nw object LatLon of northwest of the drawing     
  *@param ne object LatLon of northeast of the drawing
  *@return mixed object with x/y-coordinates or null when LatLon is outside of the area        
  **/  
LatLon.prototype.translate = function(w,h,sw,nw,ne) {
    var x = {distance:nw.distanceTo(ne),bearing:nw.bearingTo(ne)},
        y = {distance:nw.distanceTo(sw),bearing:nw.bearingTo(sw)},
        intersectionY = LatLon.intersection(sw, x.bearing, this, y.bearing),
        intersectionX = LatLon.intersection(ne, y.bearing, this, x.bearing),
        distanceX,distanceY; 

    if(intersectionX && intersectionY){
       distanceX=((x.distance-(this.distanceTo(intersectionX)))*100)/x.distance,
       distanceY=((y.distance-(this.distanceTo(intersectionY)))*100)/y.distance;
       return {x:((w*distanceX)/100),y:((h*distanceY)/100)};
    }
    return null;
};

Demo:http://jsfiddle.net/doktormolle/nsbqpcvg/embedded/result/
Hover the highlighted floorplan on the google-map to see the result of the calculation(the google-Maps-API is only used for the demonstration, the calculation will be done without using the Maps-API)

Dr.Molle
  • 116,463
  • 16
  • 195
  • 201
  • That looks like it's working in my test area. haha now to see if I can get a GPS signal that's accurate enough to be useful! Thanks! – John Sly Dec 15 '14 at 18:20