Google Map Bound Calculation without Javascript - google-maps

Do anybody know how the google map bound calculation can be done without using any UI element and Javascript.
I have set of points and different zoom level. I can probably add the screen size and I need to calculate the bounds for provided coordinate and zoom level. I am trying to do this in the plain C# code.
Please help.

as for calculating bounds - you can do it easily by walking array of your coordinates and extend bounds rectangle if point falls out. First coord is a start. I don't familiar with C# but there is the algo using pseudocode:
points = Array of coord(lat, lng)
bounds = object {
top: null
left: null
right: null
bottom: null
function extend(coord: (lat, lng))
{
if (this.top == null) // empty
{
this.top = coord.lat; this.bottom = coord.lat;
this.left = coord.lng; this.right = coord.lng;
}
else
{
if (coord.lng < this.left) this.left = coord.lng;
if (coord.lat < this.bottom) this.bottom = coord.lat;
if (coord.lng > this.right) this.right = coord.lng;
if (coord.lat > this.top) this.top = coord.lat;
}
}
}
But of course much simplier way is to use already written google functionality.
Zoom level can be calculated somehow from the size of bounding box (for example you can find a table with rates in km or miles per pixel, or approximate width or map), but most comfortable way is map.fitBounds(bounds)

Related

function that detects if a ray is intersecting an object

I have a function that detects if a ray is intersecting an object, but it works with a radius around the center of the object, I want it to work with a bounding box, I want to give it 2 Vector3D of the bounding box, and one vector of the origin of the ray and one of the direction of the ray, and it will calculate if there is an intersection, can anyone help me with that? what is the mathematical formula for this?
intersectRay(origin:Vector3D, dir:Vector3D):
Found the solution.
1. I use a bounding box of 8 points, each for each corner.
2. I used this function to give each point a location of x and y on a 2D plain this way I turned the 3D problem into a 2D problem, the x and y are really the horizontal angle of the point relative to the camera position and the vertical angle relative to the camera position point:
public function AngleBetween2vectors(v1:Vector3D,v2:Vector3D):Point
{
var angleX:Number = Math.atan2(v1.x-v2.x,v1.z-v2.z);
angleX = angleX*180/Math.PI;
var angleY:Number = Math.atan2(v1.y-v2.y,v1.z-v2.z);
angleY = angleY*180/Math.PI;
return new Point(angleX,angleY);
}
Then I use a convex hull algorithm to delete the point that are not part of the external outline polygon which marks the place of the object on the screen, can be found on the net, make sure the bounding box doesn't contain duplicate points like if you have a flat plain with no depth, this can cause problem for the algorithm, so when you create the bounding box clean them out.
Then I use this algorithm to determine if the point of the mouse click falls within this polygon or outside of it:
private function pnpoly( A:Array,p:Point ):Boolean
{
var i:int;
var j:int;
var c:Boolean = false;
for( i = 0, j = A.length-1; i < A.length; j = i++ ) {
if( ( ( A[i].y > p.y ) != ( A[j].y > p.y ) ) &&
( p.x < ( A[j].x - A[i].x ) * ( p.y - A[i].y ) / ( A[j].y - A[i].y ) + A[i].x ) )
{
c = !c;
}
}
return c;
}
Then I measure the distance to the object and pick the closest one to the camera position, using this function:
public function DistanceBetween2Vectors(v1:Vector3D,v2:Vector3D):Number
{
var a:Number = Math.sqrt(Math.pow((v1.x-v2.x),2)+Math.pow((v1.y-v2.y),2));
var b:Number = Math.sqrt(Math.pow((v1.z-v2.z),2)+Math.pow((v1.y-v2.y),2));
return Math.sqrt(Math.pow(a,2)+Math.pow(b,2));
}
I'm sure there are more efficient ways, but this way is an interesting one, and it's good enough for me, I like it because it is intuitive, I don't like to work with abstract mathematics, it's very hard for me, and if there is a mistake, it's very hard to find it. If anyone has any suggestions on how I can make it more efficient, I'll be happy to hear them.

turn based movement on a tile grid, isolated tile(s)

This is written in as3 and FlashPunk.
My problem? I have a tank that can move 4 tiles in the 4 directions; north,south,east and west.
Image can be found at http://www.aroderick.com/isolatedTiles.jpg
I've started with a square grid (Lt gray on the image) and used an array to mark out a diamond pattern (in red on the image) from the square grid, which are all the possible movement choices given the tank can only move 4 spaces in the 4 directions.
The tiles with numbers on the image are the actual tiles you see in the game, the numbers are the "col-row" numbers.
Where is gets a little more complex is that I've also removed tiles from the diamond where there are obstacles (water,trees,mountains) which in turn increases the movement cost to get to tiles beyond the obstacle(s).
I should mention at this point this is based on the A* algorithm and uses A* for movement but these are the movement choices that need to be established before a destination tile is chosen.
My problem is isolated tiles that are beyond the move ability of the tank and are isolated on their own from the main movement area where tiles are joined and make a complete path for A* and the tank can be moved from one tile to the next.
Is there a simple, elegant way to deal(get rid of) with these rogue tiles?
I've tried a system of rules i.e.;
//same row going east
if(ob.row == co.row && ob.row == startNode.row && ob.col < co.col && ob.col > startNode.col && ob.c < co.c )
{
extraCost = co.c;
reason = 1;
break;
}
//same row going west
else if(ob.row == co.row && ob.row == startNode.row && ob.col > co.col && ob.col < startNode.col && ob.c < co.c )
{
extraCost = co.c;
reason = 2;
break;
}
Where "c" a a property representing the tile movement "cost" as the crow flies.
But these seem to create as many problems as they solve.
//reusable tile grid
public static function makeTileGrid(entityLoc:Point,moveGrid:Array,travelMax:int,tsize:int = 64):Array
{
//node list
var nodeLst:Array = [];
//counter
var tileCount:int = 0;
//for tile naming
var co_ordX:String = "";
var co_ordY:String = "";
if(moveNode == null) var moveNode:Object;
//subtract the tile range from the current location
//tile range times two because you can go forewards
//or backwards tRange spaces
for (var col:int = travelMax * 2; col >=0;col--)
{
//placeX is an x value so you must multiply both row and tRange by the tile width
var placeX:Number = entityLoc.x - (travelMax*64 - col*64);
//trace(placeX);
for(var row:int = travelMax * 2; row >=0;row--)
{
var placeY:Number = entityLoc.y - (travelMax*64 - row*64);
//trace(moveGrid[col]);
//use tile grid map array
if(moveGrid[tileCount] == 1)
{
//use coordinates for the name value e.g.
co_ordX = col.toString();
co_ordY = row.toString();
moveNode = {col:col,row:row,obst:false,node:co_ordX+"-"+co_ordY,nX:placeX,nY:placeY,ph:0,h:0,g:0,f:0,c:0};
nodeLst.push(moveNode);
}
tileCount ++;
}
}
return nodeLst;
}
My grid code. In case.
Thanks guys,
james-
I think you should use a limited (distance-wise) breadth-first A* search right over that grid, with obstacles playing as walls in the algorithm. This will generate a set of reachable nodes each with distance_left attribute available, in a way that your "isolated tiles" will not get listed. Your code seems to just get the diamond pattern out of starting position and passage matrix, without actual check of the path distance.
public static function getReachableTiles(startTile:Point,distance:int):Array {
var d:Dictionary=new Dictionary(); // will hold visited tiles point by point
var o:Object={d:distance,px:startTile.x,py:startTile.y}; // a simple object info
// add fields as necessary
var a:Array=new Array(); // output array
a.push(o);
d[startTile.y*256+startTile.x]=o; // the simplest hash. You have to ensure
// these never overlap for different pairs of [x,y], and the same hash
// function is used across this method
while (distance>0) {
for each (o in a) {
if (o.d!=distance) continue; // already parsed
var to:Object={d:distance-1,px:o.x-1,py:o.y};
if (Game.isPassable(to.x,to.y)&&!d[to.y*256+to.x]) {
// a new cell, and is valid for the tank to pass
// "isPassable" returns true if (x,y) corresponds to a passable and
// valid position. For example, (-1,2) might return false as it's off borders
d[to.y*256+to.x]=to; // add to dictionary - a parsed cell
a.push(to); // and to output
}
// doing the same for 3 other possible moves
to={d:distance-1,px:o.x,py:o.y-1};
if (Game.isPassable(to.x,to.y)&&!d[to.y*256+to.x]) {
d[to.y*256+to.x]=to;
a.push(to);
}
to={d:distance-1,px:o.x+1,py:o.y};
if (Game.isPassable(to.x,to.y)&&!d[to.y*256+to.x]) {
d[to.y*256+to.x]=to;
a.push(to);
}
to={d:distance-1,px:o.x,py:o.y+1};
if (Game.isPassable(to.x,to.y)&&!d[to.y*256+to.x]) {
d[to.y*256+to.x]=to;
a.push(to);
}
} // okay, entire array was parsed for new cells
distance--; // we've iterated A* once more, lessen the distance
}
// at this point, we've iterated A* "distance" times, return
return a;
}
You need to adjust this snippet for your variable structure, so that Game.isPassable() will be a valid call, and there would be the actual grid under your drawn map. Note, startTile is a grid-based set of coordinates, not pixel-based. Hope this helps.

Distance Between Markers - no result on first click

I have an app that adds a 50mi radius around the current/clicked marker (from mapMarkers[]). I know the selected marker's index number and its LatLng position as "myPosition" and the other markers' LatLng position as mapMarkers[i].point.
After the circle is drawn on the map, I call the following simple function to step thru all the mapMarkers[] to compute the distance from the current marker, and then count how many markers actually fall within the 50mi radius. Simple, right?
Problem: The following routine does not produce any result upon first iteration (i.e., first click) for the current marker. But DOES produce the expected result upon the 2nd and subsequent clicks on the current marker.
function inCircle() {
var j = 0;
var myDistance = 0;
for (var i = 0; i < mapMarkers.length; i++) {
myDistance = google.maps.geometry.spherical.computeDistanceBetween(myPosition, mapMarkers[i].point);
myDistance = parseInt(myDistance/1609.34) //meters to miles
if (myDistance <= 50) {
j = j + 1;
//Do more stuff...
}
}
alert("Markers inside circle: " + j);
}
I call this function just after I BIND the circle to the selected marker. "myPosition" is declared as the map loads. Commenting-out the distance calculations produces results on the first iteration for the current marker.
Any thoughts what might be causing this issue?
WRT my comment above: I think, the geometry library is only loading because you made a request. see here developers.google.com/maps/documentation/javascript/libraries. Include the geometry-spherical library when you call the google maps js(during page load).
Eg:
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false&libraries=drawing,geometry,weather"></script>

Compute the distance between polyline (route) and marker in Google Maps API v3

Is there any convenient way to compute the direct (shortest) distance between Polyline (the route generated by Google Directions) and markers that are NOT situated on that polyline?
The only way I found out is to cycle through Polyline.getPath() vertices manually to calculate the shortest distance but it seems to be a bit harsh:
var path = routes[0].overview_path;
for (var i = 0; i < data.points.length; i++) {
var latLngA = new LatLng(data.points[i].lat, data.points[i].lng);
var shortest_distance = null;
for (var j = 0; j < path.length; j++) {
var distance = google.maps.geometry.spherical.computeDistanceBetween(latLngA, path[i]);
if (shortest_distance == null || distance < shortest_distance) {
shortest_distance = distance;
}
}
console.log(data.points[i].point_title, shortest_distance);
}
Thanks in advance!
As far as I know, the Google Maps API does not give you a way to do this easily. And unfortunately, the algorithm you use will not give an accurate answer, because it gives the distance from the marker to the closest vertex on the path, not the closest point on the polyline itself, which will usually not be one of the points.
If you really need an accurate calculation, the best option I know of is to use the Javascript Topology Suite (JSTS). JSTS has a ton of geographic formulas for calculating this sort of thing. That means converting the polyline returned from the directions API into a JSTS object and calling the right utility function. Not trivial, but not too difficult either.
Use turf - modular geospatial analysis engine.
https://turfjs.org/docs/

google maps : How to find if any markers inside map

I have divided the my google map display in to numbers of parts, Now I want of find it out if any markers are positioned inside a/any particulate cell.
Any Help ?
Farther Explained :
I have got the map bounds by
map.getBounds();
method and then farther divide it into numbers of sub-bounds.
also I have putted markers as
map.addOverlay(markerObject);
Now , I want find if of the cells (which I got by dividing the map by bounds) is containing any markers or not .
I have divide the entire map bounds into numbers of sub bounds
So keep all markers in array. Each marker has a method called get_position( ). After you have finished division of map bound into small sub bounds, you just need to iterate over the sub bounds and check whenever the marker within it.
PS. Also take a look on it, in some cases could be useful.
Suppose you on sub bound cell:
var sub_bounds = new Array();
// here you've pushed into an array the sub bounds
for ( var i = 0; i<sub_bounds.length; ++i)
{
for ( var j = 0; j < markers.length; ++j)
{
var lat = markers[j].get_position( ).lat;
var lng = markers[j].get_position( ).lng;
if ( sub_bounds[i].sw.lat<lat && lat<sub_bounds[i].ne.lat &&
sub_bounds[i].sw.lng<lng && lng<sub_bounds[i].ne.lng)
// marker within cell, do whatever you need to do
}
}
Here is an alternative to the above solution without re-iteration:
First - how big are your sub_bounds? Say 10 latitude and longitude degrees each.
Second - The position of the marker is (floor(marker.lat / 10), floor(marker.lng / 10))
Third - Each marker is added to the map and dropped in a bucket for that subdomain.
so (40, -78) would lie in bucket (4,7) i.e. bucket["4~7"]
Correction: would lie in bucket (4,-7) i.e. bucket["4~-7"]
which would contain all markers between 40 and 50 lat and -70 and -80 lng.
You can use GLatLngBounds as the object that holds all these markers in each bucket, which would give you a good set of methods to use, such as calculating center of the bucket depending on the markers currently in it.
Probably the best solution is given here: how to find out whether a point is inside a polygone:
How to detect that a point is inside a Polygon using Google Maps?