Converting Longitude & Latitude to X Y on a map with Calibration points - gps

If i have a jpeg map with size sizeX, sizeY
and some calibration points on the map (X, Y, Lon, Lat)
What would be the algorithm for calculating the corresponding XY point in the map with a given Longitude / Latitude pair?

Here's what worked for me, without so much bs.
int x = (int) ((MAP_WIDTH/360.0) * (180 + lon));
int y = (int) ((MAP_HEIGHT/180.0) * (90 - lat));
The lat,lon coordinates were given to me by Android devices. So they should be in the same standard used by all Google Earth/Map products.

If using the Equidistant Cylindrical Projection type map, here is what you need to do:
Find the Latitude and longitude of your location tutorial here: http://lifehacker.com/267361/how-to-find-latitude-and-longitude
Input that information into the following formulas:
x = (total width of image in px) * (180 + latitude) / 360
y = (total height of image in px) * (90 - longitude) / 180note: when using negative longitude of latitude make sure to add or subtract the negative number i.e. +(-92) or -(-35) which would actually be -92 and +35
You now have your X and Y to plot on your imageMore information can be found about this formula and the map type here: http://www.progonos.com/furuti/MapProj/Dither/CartHow/HowER_W12/howER_W12.html#DeductionEquirectangular

There is plenty of information on the Internet about calculating the distance between two pairings of latitude and longitude. We're using those calculations on our public website and they are not trivial to understand/discuss (so I won't try to cover them here). That said, they are easy to implement.
Once you have a function that returns distance, you should be able to caculate the width and height of the map in terms of distance between the corners.
Then you can calculate the horizontal and vertical distance of your point from the top-left corner.
Now you find out what ratio of the map's width is represented by the distance between the left side and your point, apply that ratio to the pixel width and you have the number of pixels between the left side and your point. Repeat for the y-axis.
(Pixels from left side) = (total width in pixels) * ((geocode distance between left and your point) / (geocode distance between left side and right side))
(Pixels from top) = (total height in pixels) * ((geocode distance between top and your point) / (geocode distance between top and bottom))
EDIT: As you research this further you will note that some solutions will present more accurate results than others due to the fact that you are approximating distance between two points on a spherical surface and mapping that on a flat surface. The accuracy decreases as the distance increases. Best advice to you is to try it out first and see if it meets your needs.

This is fairly straight forward and simple.. let me explain how its possible.
Latitude and Longitude are imaginary lines drawn on earth so that you can accurately pinpoint any location on the world . simply put they are the X and Y coords of a plane.
Latitude is a vertical line running from north to south with its 90 deg at the north pole and -90deg at the south pole.
Longitude on the other hand is a horizontal line running east to south with -180deg in the west and 180deg in the east.
you can convert the latLng into pixel coords as by assuming that the width of the html container is the width of the world and the same applies to the the height.
Formula - Longitude - pixel
(givenLng*widthOfContainerElement)/360
where 360 is the total longitude in degrees
Formula -Latitude - pixel
(givenLat*heightOfContainerElement)/180
where 180 is the total latitude in degree
//Height is calculated from the bottom
you can find a working implementation of this formula here, on my website (it uses JavaScript only)
http://www.learntby.me/javascript/latLngconversion.php
let me know if you still need any clarifications.

There are many different map projection schemes. You would have to know which one(s) are used by your maps.
For more information about map projection algorithms and forward/reverse mapping check out this link. It provides the formulas for a number of common projections.

Just make this(for Mercator projection map):
extension UIView
{
func addLocation(coordinate: CLLocationCoordinate2D)
{
// max MKMapPoint values
let maxY = Double(267995781)
let maxX = Double(268435456)
let mapPoint = MKMapPointForCoordinate(coordinate)
let normalizatePointX = CGFloat(mapPoint.x / maxX)
let normalizatePointY = CGFloat(mapPoint.y / maxY)
let pointView = UIView(frame: CGRectMake(0, 0, 5, 5))
pointView.center = CGPointMake(normalizatePointX * frame.width, normalizatePointY * frame.height)
pointView.backgroundColor = UIColor.blueColor()
addSubview(pointView)
}
}
My simple project for adding coordinate on UIView: https://github.com/Glechik/MapCoordinateDrawer

<!DOCTYPE html>
<html>
<head>
<style>
#point{font-face:Arial; font-size:18px; color:#FFFF00; width:12px; height:12px;text-shadow: 2px 2px #000000}
#canvas {position: absolute; top: 0px; left: 0px; z-index: -2}
html,
body,
#canvas {
width: 100%;
height: 100%;
overflow: hidden;
margin: 0
}
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.2/jquery.min.js"></script>
<script>
$(window).on("load resize",function(e){
var w = $("#canvas").width();
var h = $("#canvas").height();
// New York, NY (https://maps.googleapis.com/maps/api/geocode/json?address=New%20York,%20NY)
var lat = 40.91525559999999;
var long = -73.70027209999999;
var x = ((w/360) * (180 + long)) - 9;
var y = ((h/180) * (90 - lat)) - 18;
$("#text").text('X:'+x+', Y:'+y);
$("#point").offset({ top: y, left: x });
});
</script>
</head>
<body>
<div id="text"></div>
<div id="point">▼</div>
<img id="canvas" border="0" src="http://friday.westnet.com/~crywalt/dymaxion_2003/earthmap10k.reduced.jpg">
</body>
</html>

I have tried this approach:
int x = (int) ((MAP_WIDTH/360.0) * (180 + lon));
int y = (int) ((MAP_HEIGHT/180.0) * (90 - lat));
but this one works better for me : https://medium.com/#suverov.dmitriy/how-to-convert-latitude-and-longitude-coordinates-into-pixel-offsets-8461093cb9f5
here is a shortcut to code part of the article above :
https://gist.github.com/blaurt/b0ca054a7384ebfbea2d5fce69ae9bf4#file-latlontooffsets-js

Related

How to teleport a player two block on his left?

I tried several things, like using vectors, but It didn't work for me. Than I tried searching on the internet and it didn't work as well.
Vector direc = l.getDirection().normalize();
direc.setY(l.getY());
direc.normalize();
direc.multiply(-1);
l.add(direc);
Player#teleport(l.getBlock().getLocation());
// or
Player#teleport(l);
Use Vector#rotateAroundY​ to rotate the player's direction vector 90 degrees to the left.
Vector dir = player.getLocation().getDirection(); // get player's direction vector
dir.setY(0).normalize(); // get rid of the y component
dir.rotateAroundY(Math.PI / 2); // rotate it 90 degrees to the left
dir.multiply(2); // make the vector's length 2
Location newLocation = player.getLocation().add(dir); // add the vector to the player's location to get the new location
Location location = player.getLocation();
Vector direction = location.getDirection();
direction.normalize();
float newZ = (float)(location.getZ() + (2 * Math.sin(Math.toRadians(location.getYaw() + 90 * direction)))); //2 is your block amount in Z direction
float newX = (float)(location.getX() + (Math.cos(Math.toRadians(location.getYaw() + 90 * direction))));
You have to know in which direction you want to teleport the player

Cytoscape zoom alignment

I'm having an issue with my background image maintaining proper alignment with the network image, when using mouse to zoom in or out. Without zoom, the network matches the background. With zoom in however, the background shifts right (out of alignment). The background image stays same width as network, only shifted. Same with zoom out, but to the left.
In order to get zoom to work to this degree, I needed to adjust zoom factor:
cy.on('zoom', function(evt){
var newpct = 135.0 * cy.zoom();
document.getElementById('cy').style.backgroundSize = newpct + '%';
});
The header CSS for image, etc:
#cy {
background-image: url("background6.png");
background-repeat: no-repeat;
background-size: 100%;
width: 100%;
height: 100%;
position: absolute;
top: 0px;
left: 0px;
}
The image is from an 11" x 8.5" MS Publisher file, saved as a PNG
Pan is working well, but an adjustment was needed:
cy.on('pan', function(evt){
var pan = cy.pan();
var x = pan.x - 92;
var y = pan.y - 48;
document.getElementById('cy').style.backgroundPosition = x +'px ' + y + 'px ';
});
Any help is much appreciated
You have to keep your co-ordinates synched, and this has to be done exactly. If you adjust some scale values and translation offsets experimentally or with relative values, you'll probably be off.
For scale, s, and translation, t, applied to your image in CSS, find the constants s0 and t0 such that
s = zoom * s0 and t = { x: pan.x + t0.x, y: pan.y + t0.y }
You can find s0 and t0 by aligning the image at zoom 1 and pan (0, 0).
You can't use percents for anything; you ought to use pixels (or ems if you measure everything in ems).
Thank you so much for your answer. After some more work I learned that the zoom event was afterwards triggering the pan event. So I put the translation (covering both pan and zoom shifts) only in pan event function, like this:
var ax = -120 * cy.zoom();
var ay = -60 * cy.zoom();
var x = pan.x + ax;
var y = pan.y + ay;
document.getElementById('cy').style.backgroundPosition = x +'px ' + y + 'px ';
It is working perfectly now. Thanks again for your support!

Google Maps - Deriving Lat/Lon points

I would like to derive the lat/lon which stands x inches east and y inches south from a given lat/lon point.
For this purpose I used information and formulas from the following link: http://www.appelsiini.net/2008/11/introduction-to-marker-clustering-with-google-maps
Basically my methods do the following:
public static double adjustLongitudeByPixels(double longitude, long pixelsY) {
int zoom = 21; // use zoom level 21
double scaledPixels = (pixelsY << (21 - zoom)) / GOOGLE_SCALING_AT_ZOOM_21;
return xToLongitude(longitudeToX(longitude) + scaledPixels);
}
public static double adjustLatitudeByPixels(int overviewScale, double latitude, long pixelsX) {
int zoom = 21; // use zoom level 21
double scaledPixels = (pixelsX << (21 - zoom)) / GOOGLE_SCALING_AT_ZOOM_21;
return yToLatitude(latitudeToY(latitude) + scaledPixels);
}
...where longitude/latitude are the ones from the starting point and the pixels are the number of pixels east or south from the starting point.
I obtain the pixelsX and pixelsY by multiplying my real x/y inch distances by 96 (number of pixels per inch). So I basically obtain the pixels at scaling 1:1.
Since the latitudeToY and longitudeToX use units pixels at zoom level 21, I divide by the scaling at zoom level 21.
If I am not wrong this scaling is 1:282.124305.
This method does not yield the expected results, though. The resulting lat/lon are slightly different than what I expect.
Please let me know if I have flaws in my logic...
Thanks in advance!

How do I display a full 360 degrees using Actionscript 2 and Trigonometry?

I'm creating a game that uses trigonometry to calculate and display distance and degrees in dynamic text boxes. I'm calculating the distance of my cursor from center of a movie clip. And using that center of the movie clip, I'm trying to calculate and display a full 360º as my cursor moves around the swf. I have the distance part of the game working but the part that displays degrees is not working properly. The dynamic text box only display from 90º thru 270º. Instead of going past 270º to 360º/0º to 90º, it just counts back down from 270º to 90º. Below is my actionscript. I'd greatly appreciate any help or suggestions. Thanks!
//Mouse and Dynamic Text Boxes-------------------------
Mouse.hide();
onMouseMove = function () {
feedback.text = "You are moving your mouse";
cursor._x = _xmouse;
cursor._y = _ymouse;
updateAfterEvent();
xmouse_value.text = Math.atan2((a), (b));
ymouse_value.text = Math.round(radians*180/Math.PI)
updateAfterEvent();
};
Mouse.addListener(myListener);
//distance (RANGE)
_root.onEnterFrame = function () {
xmid = Stage.width/2;
ymid = Stage.height/2;
a = _root._ymouse-ymid;
b = _root._xmouse-xmid;
c = Math.sqrt(Math.pow(a, 2)+Math.pow(b, 2));
feedbacka.text = Math.round(a);
feedbackb.text = Math.round(b);
feedbackc.text = Math.round(c/30.4);
updateAfterEvent();
var radians:Number;
var degrees:Number;
//Calculcate Radians
//Radians specify an angle by measuring the length around the path of the circle.
radians = Math.atan2((c), (b))
//calculate degrees
//the angle the circle is in relation to the center point
//update text box inside circle
radians_txt = Math.round(radians*360/Math.PI);
degrees_txt = Math.round(radians*180/Math.PI);
updateAfterEvent();
//getting past 270 degrees
radians2_txt = Math.round(radians/Math.PI);
radians2_txt = Math.floor(radians + -270);
}
The parameters to atan2 should be the delta-y and delta-x between the two points, but you are passing the distance between the two points and the delta-x. Try this instead:
radians = Math.atan2(a, b);
The next problem is to convert the radians into degrees. To convert radians to degrees, you can do this:
degrees_txt = radians * 180 / Math.PI;
Note that atan2 returns from between -Math.PI / 2 to Math.PI / 2. When converted to degrees, this range becomes -180 to 180. To convert to 0 to 360, you can add 360 to the result if it is negative:
if(degrees_txt < 0) degrees_txt += 360;

calculate latitude and longitude along a circumference of a known circle with known distance

I dont need help with a programming language, I need help from someone to calculate the gps coordinates of points of a specific distance, namely 22 feet apart, on the circumference of a circle. I know the beginning gps coordinates and the radius. I am pretty sure the haversine, or the speherical law of cosines has the answer, but its been a long time since I have used any trig formulas and I cant figure it out. I am using decimal degrees and am programing in this vb.net. If someone could dumb this down for me it would be a great help.
As I understand you have:
Coordinate of the center of
circumference.
Distance between
two point on the circumference of a
circle.
Radius of circumference.
In my opinion this is not enough for calculating other point's coordinates. You should have as minimum yet one point coordinate, because we only can guess where points are placed on the circumference.
Here's the basic algorithm:
Calculate the angular measure whose arc length is 22 feet, with the given radius
numPoints = Math.PI * 2 / angularMeasure
for i in range(numPoints):
calculate proportion around the circle we are, in terms of degrees or radians
calculate the location of the endpoint of a great circle or rhumb arc from the center point moving in the specific azimuth direction (from the proportion around the circle) the given radius
This last point is the hardest part. Here's code from the WorldWind SDK (available: http://worldwind.arc.nasa.gov/java/) (Note- you'll have to calculate the radius in terms of angles, which you can do pretty easily given the radius / circumference of the earth)
/*
Copyright (C) 2001, 2006 United States Government
as represented by the Administrator of the
National Aeronautics and Space Administration.
All Rights Reserved.
*/
/**
* Computes the location on a rhumb line with the given starting location, rhumb azimuth, and arc distance along the
* line.
*
* #param p LatLon of the starting location
* #param rhumbAzimuth rhumb azimuth angle (clockwise from North)
* #param pathLength arc distance to travel
*
* #return LatLon location on the rhumb line.
*/
public static LatLon rhumbEndPosition(LatLon p, Angle rhumbAzimuth, Angle pathLength)
{
if (p == null)
{
String message = Logging.getMessage("nullValue.LatLonIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
if (rhumbAzimuth == null || pathLength == null)
{
String message = Logging.getMessage("nullValue.AngleIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
double lat1 = p.getLatitude().radians;
double lon1 = p.getLongitude().radians;
double azimuth = rhumbAzimuth.radians;
double distance = pathLength.radians;
if (distance == 0)
return p;
// Taken from http://www.movable-type.co.uk/scripts/latlong.html
double lat2 = lat1 + distance * Math.cos(azimuth);
double dPhi = Math.log(Math.tan(lat2 / 2.0 + Math.PI / 4.0) / Math.tan(lat1 / 2.0 + Math.PI / 4.0));
double q = (lat2 - lat1) / dPhi;
if (Double.isNaN(dPhi) || Double.isNaN(q) || Double.isInfinite(q))
{
q = Math.cos(lat1);
}
double dLon = distance * Math.sin(azimuth) / q;
// Handle latitude passing over either pole.
if (Math.abs(lat2) > Math.PI / 2.0)
{
lat2 = lat2 > 0 ? Math.PI - lat2 : -Math.PI - lat2;
}
double lon2 = (lon1 + dLon + Math.PI) % (2 * Math.PI) - Math.PI;
if (Double.isNaN(lat2) || Double.isNaN(lon2))
return p;
return new LatLon(
Angle.fromRadians(lat2).normalizedLatitude(),
Angle.fromRadians(lon2).normalizedLongitude());
}
You are looking for the equation of what is called a "small circle". Look at this book for the equation of the small circle and the arc length equation for that small circle. However, because your distances are so small, you could consider your area flat and use simpler geometry. Using UTM coordinates would make the calculations much simpler than using lat/long.
The Haversine formula relates to great circles, not small circles...