For quite some time now I've been trying to get a "game map" into Google Maps. My goal is to have the map being able to zoom etc. (default Google Maps features & done already) and to place markers on it, showing objects from the game. This is where my problem's at.
The game (ArmA) has a variable coordinate system which totally depends on the "world" you're playing in. Let's just say my world has 10200 by 10200 units which can be float, so 5212.123 would be possible.
I have all objects that I want to display on my map stored in a JS array which looks like the following:
["class_name",5200,4800]
The first one describes the class name or let's just pretend the name of the object, the other two describe the X and the Y value. I banged my head against the wall trying to find some way which enables me to define pixel coordinates on the base zoom level which then change on zooming in / out... but that didn't work out / or rather I didn't find anything on it.
Now I tried converting the coordinates to Lat / Long but I guess Lat / Long aren't constant because it still is not very accurate: I tried dividing the 170 lat units by my 10200 game units and it brought some nice results... but as said: Not very accurate ones.
Is there any way which is some kind of "intelligent, clever or smooth" to do this? Or is Google Maps not the tool for this?
Edit:
Here's how I currently do it...
// The game caculates the Y axis from the bottom up, so I turn it around by
// subtracting the coord of the object from the highest possible value
$worldspaceCoords[0] = $worldspaceCoords[0];
$worldspaceCoords[1] = 10200 - $worldspaceCoords[1];
// My lat ranges from -85 to +85 = 170 in total, same goes for the long
// I use 9100 and 9700 because I have calculated offsets in my map
$latCoF = 170 / 9100;
$lonCoF = 360 / 9700;
// Now I calculate lat and long by starting at the min value and going to the max
$worldspaceLatLon['lat'] = 85 - $worldspaceCoords[1] * $latCoF;
$worldspaceLatLon['lon'] = -180 + $worldspaceCoords[0] * $lonCoF;
I get the objects via PHP and output them to a section where they are stored in the array later parsed by the marker creator loop.
This is how they SHOULD look (old map version, not Google Maps)
(http://i.imgur.com/8clKv4B.jpg)
This is how my results look so far with the code i posted earlier (Google Maps)
(http://i.imgur.com/ozNw54K.jpg)
Related
I have a scenario in my JavaScript application where I have the coordinates of a starting point which consist of Latitude and Longitude, similarly an ending point with it's respective coordinates.
Now I need to search for a location which basically provides with a set of coordinates and find if the recently entered location lies in between the previously mentioned starting point or ending point. However, the location does not need to match exactly within the points of the path of the start and end point. That is even if the location lies around the distance of say 2-3 km from the derived path, it should give a match.
I believe that we can create a triangle by providing three coordinates i.e start-point, end-point and a third point. So once the triangle is formed we can use google.maps.geometry.poly.containsLocation method to find if our searched location is present inside this triangle.
So my question is how can we get a third point to create a triangle which will provide locations that are nearby within 2-3 km from start to end point.
Else is there any alternate approach to deal with my use case?
Use googlemap's geometry library
This function specifically
isLocationOnEdge
Here's an example
0.001 tolerance value would be 100m
var isLocationNear = google.maps.geometry.poly.isLocationOnEdge(
yourLatLng,
new google.maps.Polyline({
path: [
new google.maps.LatLng(point1Lat, point1Long),
new google.maps.LatLng(point2Lat, point2Long),
]
}),
.00001);
Please note that the following answer assumes Plane Geometry where you should be using Spherical Geometry instead. Although this will be fine for less accurate purposes (like approximate distance, etc..)
It seems more of a geometry question than a programming question. A triangle like you mentioned won't be able to cover a straight line path in a uniform way. The situation can be thought of more like a distance between point and a line problem (Refer the given diagram
Here you can just find the distance between point C and line AB which you can check whether it's below 2.5 KMs (I've omitted all the units and conversions for simplicity)
Please note that you will also need to convert the distances from radian to appropriate units that you require using haversine formula, etc. which is not a trivial task (https://www.movable-type.co.uk/scripts/latlong.html).
Is there a library (JS or .NET) or a set of formulas that would help me calculate set of gps coordinates based on starting location, direction and distance.
For example.
I have an exact lon/lat of a certain location. I'd like to calculate an exact lon/lot 5 miles NE from that location.
With Javascript you can use the geodesy library (under the MIT license), which is the code behind the Movable-Type.co.uk website.
For example:
const LatLon = require('geodesy').LatLonSpherical;
const p1 = new LatLon(59.912140, 10.743796);
const distance = 42*10**3;
const bearing = 240.0
const p2 = p1.rhumbDestinationPoint(distance, bearing);
console.log(p2); // LatLon { lat: 59.72328246275707, lon: 10.093154371545552 }
This finds a second point given initial position, distance and bearing. This particular code is for Node, but it can also be used in the browser.
It should be noted that there are often several different ways to do the various calculations. Some are complex and accurate, while some are simple and less accurate. Using a spherical earth model, as I did in my example, is less accurate, but good enough for ordinary use.
Another library you could check out is geolib.
Perhaps this might or might not fit your needs but have you tried Entity Framework Spatial?
My goal is to calculate the distance between two Cesium entities in kilometers. As a bonus, I eventually want to be able to measure their distance in pixels.
I have a bunch of placemarks in KML format like this:
<Placemark>
<name>Place</name>
<Point><coordinates>48.655,-31.175</coordinates></Point>
<styleUrl>#style</styleUrl>
<ExtendedData>
...
</ExtendedData>
</Placemark>
I am importing them into Cesium like so:
viewer.dataSources.add(Cesium.KmlDataSource.load('./data.kml', options)).then(function(dataSource) {
var entities = dataSource.entities._entities._array;
I have attempted to create new Cartesian3 objects of entities I care about, but the x, y, and z values I get from the entity object are in the hundreds of thousands. The latitude and longitude from my KML are nowhere to be found in the entity objects.
If I do create Cartesian3 objects and compute the distance like so:
var distance = Cesium.Cartesian3.distance(firstPoint, secondPoint);
it returns numbers in the millions. I have evaluated the distance between multiple points this way and when I compare those values returned to the result of an online calculator which returns the actual value in kilometers, the differences in the distances are not linear (some of the distances returned by Cesium are 900 times the actual distance and some are 700 times the actual distance).
I hope that is enough to receive help. I am not sure where to start fixing this. Any help would be appreciated. Thank you.
A couple of things are going on here. The Cesium.Cartesian3 class holds meters, so it is correct to divide by 1000 to get km, but that's not the full story. Cartesian3s are positions on a 3D globe, and if you compute a simple Cartesian.distance between two of them on opposite sides of that globe, you'll get the Cartesian linear distance, as in the length of a line that cuts through the middle of the globe to get from one to the other, rather than traveling around the surface of the globe to get to the far side.
To get the distance you actually want -- the distance of a line that follows the curvature of the surface of the Earth -- check out the answer to Cesium JS Line Length on GIS SE.
I've implemented some code to create some code to treat an image of a relatively small location like plane for converting between locations on the image I have stored and incoming Lat/Long information.
Using the formulas provided at https://msdn.microsoft.com/en-us/library/jj635757(v=vs.85).aspx I wrote these lines of code among others
var vector = math.matrix(
[[x1],
[y1],
[x2],
[y2]]);
var matrix = math.matrix(
[[lat1,long1,1,0]
,[-long1,lat1,0,1]
,[lat2,long2,1,0]
,[-long2,lat2,0,1]]);
var solution = math.multiply(math.inv(matrix),vector);
There is an implicit conversion from the vector returned to solution into conversiondata as I put it into and take it back out of my database.
a = parseFloat(conversiondata['A']);
b = parseFloat(conversiondata['B']);
c = parseFloat(conversiondata['C']);
d = parseFloat(conversiondata['D']);
var long = position.coords.longitude;
var lat = position.coords.latitude;
var x = a * lat + b * long + c;
var y = b * lat - a * long + d;
The values x1, x2, y1, y2 are supplied by getting user click data.
The values lat1, lat2, long1, long2 are supplied by the user in response to two clicks on the map image.
When putting x,y back onto the map its not quite in the right position, the position on the map seems to almost be on the opposite side of the line defined by (x1,y1) and (x2,y2). I'm trying to tell what the reason for the inaccuracy is. (I am however assuming for the time being that the apparent reflection is a coincidence)
If someone could help me narrow down what could be going wrong here are things I've considered (the map doesn't reach even a mile in any direction for reference).
The affine transformation simply doesn't work - But acccording to the link provided it includes scaling so that shouldn't be the cause of the problem
There is a problem with my setting of variables - I've been looking at my code too long to see it if it is.
I am losing too much accuracy moving the var data to MySQL as a float or to PHP as a string
I am not giving accurate enough information from click data / lat/long input. - I zoomed i significantly when clicking on the map and getting the lat/long from google maps though
SVG isn't accuracte enough - Though looking at the xml data it keeps the decimals.
The area that I'm working with is too big to simplify by assuming that the local map is a flat plane
Any help is appreciated, thanks for reading this far.
For further reference I put the lat/long data that JavaScript gave me into google maps and i'm comparing accuracy to that rather than my actual location.
Additional reference: I found "landmarks" on the east and west edges of my image and have calculated the longitude difference to be 0.02695 with the length of the image being at least twice the height.
Sample values of a full run-through of values.
Reference Points
Point 1 (x,y) = (619,564)
Point 1 (lat,long) = (X.099546,-Y.465179)
Point 2 (x,y) = (1181,190)
Point 2 (lat,long) = (X.10365341,-Y.457014)
Geolocation
Predicted coordinate (x,y) = (975,262)
Given coordinate(lat,long) = (X.102851,-Y.459996)
Real Blip (x,y) = (1022.7498707999475,351.02335709985346)
Real blip (approximate lat,long) = (X.101964, -Y.459340)
(Real blip lat long is approximate as it is in a body of water with no good landmarks)
For safety's sake I've taken the digits before the decimal out of the lat/long coordinates but I can confirm that all the X's are equal and all the Y's are equal
Additionally I played with the lat long values in Chrome's developer tools, it seems like the axes are a bit rotated approximately 30 degrees from what it should be
After sufficient poking around I figured out that I had ordered lat and long incorrectly. On my map that has not been rotated from N at the top the following code brings me within just a few feet, more than explainable than the lack of precision resulting from relying on user input and the pixel grid.
var matrix = math.matrix(
[[long1,lat1,1,0]
,[-lat1,long1,0,1]
,[long2,lat2,1,0]
,[-lat2,long2,0,1]]);
And
var x = a * long + b * lat + c;
var y = b * long - a * lat + d;
For anyone else that is interested in pursuing this as a potential solution to simplify the math of their app
The drift that occurred was less than 40 feet over a map with a diagonal of 8000 feet and a difference in reference points of around 3000 feet. This means the drift is little over 1% of the distance of the reference points, this includes the effect of human error.
This error should decrease as you work on smaller maps and increase as you work on bigger maps.
I tested it again on a map with a ~90 degree rotation and the code held up
I'm going to create 3D Earth with search input. Could someone guide how to write code that finds point (exact place point) by input search, using WebGL?
I think your question is really vague but I can imagine that what you want to do is to rotate your 3D Earth so the point you queried for appears in the center of the view (or what it is the same, on the view axis of the camera).
To do it you need to:
assign every landmark a set of
spherical coordinates
given that you are locating
points on the surface of the sphere
you can forget about the radius and
only assign elevation and
azimuth to each point.
then you write the code for the
user to input the point of interest.
Say "Rome".
you look for this point in a
javascript array and recover the
elevation and the azimuth values
you apply the correspondent
rotations to your Model-View Matrix. Assuming you are using glMatrix you
should have something like this:
var M = mat4.create();
var Y_axis = [0,1,0];
var X_axis = [1,0,0];
mat4.rotate(M,azimuth,Y_axis);
mat4.rotate(M,elevation,X_axis);
the point of interest should be
displayed now