I am using meshm to plot densities.
How do I calculate the center point for each of the bins? I want to associate the data in m with the centerpoints I have looked at the source code of meshm and believe the solution will be a modified version of meshm that returns the latitude and longitudes of each bin's center point.
meshm calls the function meshgrat which returns the latitude and longitude points of the mesh that will be plotted by surfacem. The problem is that the lat and lon matrices are not the same size as m. I need to match the latitude and longitude points with the density data in m I believe I need to scale the data based on GRATSIZE a variable in meshgrat.
NOTE: meshm is part of the Matlab Mapping Toolbox
NOTE NOTE: This is a follow-up question to Determine distance from coastline in Matlab
You can get the edges of the mesh using MESHGRAT, which is the function called by meshm when it makes the grid for binning.
%# create the mesh that is used by meshm
[latgrat,longrat] = meshgrat(m,termaplegend);
%# find the latitudes of the center points
latPts = (latgrat(1:end-1,1:end-1) + latgrat(2:end,1:end-1))/2;
%# find the longitudes of the center points
lonPts = (longrat(1:end-1,1:end-1) + longrat(1:end-1,2:end))/2;
The center of the bin in 2nd row, 5th col is [latPts(2,5),lonPts(2,5)].
Within meshm just modify the inputs to meshgrat:
[lat,lon] = meshgrat(Z, R, gratsize); % original
[lat, lon] = meshgrat(Z,R); % modification
By default, gratsize = [] which in meshgrat will return the default graticule size of 50 X 100. By not passing in gratsize, the graticule is set to the same size as Z.
Related
I am developing a GIS based iOS application using Swift 3.0. I want to draw tiles on Map and tiles images are stored in SQLite Database.
My question is how can I retrieve tile image from database and draw thoses image on Map, as database contains columns zoom (values will be 12, 13, etc.), tile_row (values will be 4122, 3413, etc.), tile_column (values will be 4122, 3413, etc.) and data but I get zoom level value in thousands and I get latitude and longitude values in iOS app, so I need to convert these values to match values in database. I found a way to convert zoom level to 1 to 18 scale but I don't know can I match the tile_row and tile_column value using latitude and longitude.
Also please verify that my code which convert zoom level to 1 to 18 (similar to google map zoom level) is correct:
let zoomLevel = Int(log2(360 / MKCoordinateRegionForMapRect(mapRect).span.longitudeDelta))
Thanks.
In IOS (and most mapping systems) the tile images are stored in a directory structure where each zoom level is a parent directory named with the zoom-level number. Under that directory, there are one or more directories named with the longitudinal tile numbers of the tiles below - e.g., at zoom level 10 there are 1024 tiles across and your directories could be 750, 751, 752, and 753 if that's where their images fell relatively. Under each longitude (x-coordinate) directory are the images (256 X 256 pixels) for that y-coordinate, each named for the x tile coordinate, again out of 1024 at zoom level 10.
To find where you are in those ranges, use MKMapPointForCoordinate(CLLocationCoordinate2D), which will give you the lat (y) and lon (x) map points of a location when fully zoomed out. To get the longitude (y) tile number use:
Int((pow(2.0, Double(z)) as Double) * point.y / 268435456.0)
...where the big number is the total number of points on the x-axis at zoom level 0 (2^20 tiles * 256 pixels / tile). That way if point.x is 1/3 of the big number, the image is the tile 1/3 of the way through 1024, and the integer representing the 256-pixel interval (i.e., tile) that number falls into is the name of the directory.
The latitude (y) map point and tile number are calculated similarly, and that number is the name of the image file. So, at zoom level 10 the image for the tile 752 out of 1024 along the x-axis and 486 out of 1024 along the y-axis would be in the file:
...Documents/Maps/yourDirectory/10/752/486.png
...provided you name your overall map directory Maps and the specific directory for this set of tiles yourDirectory. When you use the overlay, you'd use this directory information along with the rest of the setup to instantiate an MKTileOverlay object. Note that the offsets are from the bottom left corner unless you specify that they're reversed since they're thinking x and y axes (remind you of using CoreGraphics for a UIImage?).
Finally, here's how I calculate the zoom level given two corner points of a region that I want to capture a snapshot for:
let position1 = MKMapPointForCoordinate(bottomRight)
let position2 = MKMapPointForCoordinate(topLeft)
let xPosition1 = position1.x / Setting.shared.mapScale
let xPosition2 = position2.x / Setting.shared.mapScale
let yPosition1 = position1.y / Setting.shared.mapScale
let yPosition2 = position2.y / Setting.shared.mapScale
let relativeSpanX = xPosition1 - xPosition2 // X distance between points relative to size of full map
let relativeSpanY = yPosition1 - yPosition2 // Y distance between points relative to size of full map
let spanForZoom = max(relativeSpanX, relativeSpanY)
startingZoom = max(10, Int(log2(1.0 / spanForZoom)) - 1)
That gets you the zoom level for a tile that fits the size of the area that includes both points, but note that no one standard tile of that size (or any size less than the full map) may include those two points depending on where they lie relative to the grid. For example if they span the prime meridian the first step to 4 tiles at zoom level 1 will separate them, so you may need 2 - 4 tiles of the starting zoom size to get both. Ideally, write a function that tells you the tile number (x and y) that includes a CLLocationCoordinate2D since that gets very handy as you pick, download, and collect your tiles.
While you can get away with a geometrical approach like you're showing to calculate longitudinal / y-axis values, MKMapPointForCoordinate() is indispensable for latitude / y-axis calculations since the mercator map is non-linear as you move north or south, and the function takes care of that for you.
That should get you started, but it's a picky process - one thing to focus on is the fact that the layout is always from the lower left; it's easy to get confused as you gather and label the tiles.
I use the following function to calculate the x and y coordinates for the tile that a point is in for a given zoom level:
func getTileCoordinates(location: CLLocationCoordinate2D, z: Int) -> (x: Int, y: Int)
{
let point = MKMapPointForCoordinate(location)
let locationX = Int((pow(2.0, Double(z)) as Double) * point.x / 268435456.0)
let locationY = Int((pow(2.0, Double(z)) as Double) * point.y / 268435456.0)
return (locationX, locationY)
}
...again, where 268435456.0 is the total number of pixels in the zoom level 20 map along the x or y axis. Note, all of this is for Apples MapKit maps and the functions to display them.
I have calculated field of view
float FOV = camera.activeFormat.videoFieldOfView;
But its the iPhone field of view.
I need to calculate width of object using field of view. How can i calculate either
1) Field of view for particular object
or
2)Width of object using Camera
i have below mark in the pic :
Angle AOB =FOV i have
A'O and B'O i have calculated already.
Need to calculate
angle A'OB' and using which finally my aim to calculate A'B' (width of object)
You need 3 independent informations about a triangle to characterize it, otherwise you are just describing a class of triangles. Informations can be angles or lengths.
In your case you have two information about triangle OA'B' and one about OAB, so you can't do anything.
If you had more information, as the horizontal % of the screen taken by your object, you could find a relation between FOV and the angle A'OB' you need by multiplication. (X% * FOV= A'OB')
Now if you have A'OB', OA' and OB' you can compute A'B' with trigonometry.
If I'm understanding you correctly, you still need the distance to the object. Once you have that, you have two sides of a triangle, and can now calculate A'OB', as follows:
Let's call A'B'/2 (i.e. the midpoint of A'B'), C'. (OC' is then the distance to the object.)
A'C'O (or B'OC') form a right triangle.
OC'/OA' is equal to the cosine of A'OC'.
If we multiply the arccosine of OC'/OA' by 2, we will end up with the angle A'OB'.
If you just want the length of A'B', things become even simpler. Multiply the square root of (OA' squared minus OC' squared)' by 2, and you'll have the length of A'B'
Does that make sense?
The HERE Maps (the old Nokia Maps) has a variety of APIs, the most useful of which for non-web desktop applications looks like the Map Image API. This API allows you to specify a center location and a zoom level to get an image, along with an image size.
How do you georeference the returned image? The image is specified by center and zoom level, not by a bounding box or corner coordinates. If you need to display the map image as the background to other, geolocated data, how do find the coordinates of the image corners in order to render the map correctly?
My guess is that you can do so by using the zoom level, so, for example, a square image of any pixel size at a specific zoom level would have specific real-world dimensions. However, this is only a guess. The API documentation doesn't seem to have any content addressing georeferencing the map results at all.
The easiest way to do this would be to use the nomrk parameter and add two hidden poi markers for the top-left and bottom-right corners - as in this example of the Strait of Dover across the English Channel. [50N,2E - 51N,3E]
Ideally since the maps use the normalized Mercator projection, you should specify h and w to be the same value and keep the number of degrees latitude requested = number of degrees longitude requested. This will ensure that the POIs are in the corners of the map.
As an alternative, there is also the Map Tile API (log-in required), which uses standard Tile Map Service (TMS) addressing techniques. You can calculate the required tile using the following (sample code is in Java)
public void calculatePosition(int latitude, int longitude, int zoom) {
int p= Math.pow(2, zoom); double x= longitude /Math.PI; x=(x+1)/2;
double y= latitude/Math.PI; y = (log(tan(pi/4.0+latitude/2.0))+1)/2; y = 1 - y;
int column=(int) x*p; int row=(int)y*p;
System.out.println("[zoom,col,row] = " + zoom + "," + col+ "," + row);
}
I would like to get the formula on how to calculate the Euclidian distance between two geographical co-ordinates on earth and heading angle relative to True North. Say from New York to New Dehli , I draw a straight line THROUGH THE EARTH - as they were two points in space. How can I calculate that angle from say New York to New Dehli if I was to draw a straight line through the surface of the earth . What kind of mathematical calculation/formula would be involved in order to do that ?
Rhumb Line Navigation
Rhumb lines or loxodromes are tracks of constant true course. With the exception of meridians and the equator, they are not the same as great circles. They are not very useful approaching either pole, where they become tightly wound spirals. The formulae below fail if any point actually is a pole.
East-West rhumb lines are special. They follow the latitude parallels and form a closed curve. Other rhumb lines extend from pole-to-pole, encircling each pole an infinite number of times. Despite this, they have a finite length given by pi/abs(cos(tc)) (in our angular units, multiply by the radius of the earth to get it in distance units).
When two points (lat1,lon1), (lat2,lon2) are connected by a rhumb line with true course tc :
lon2-lon1=-tan(tc)*(log((1+sin(lat2))/cos(lat2))-
log((1+sin(lat1))/cos(lat1)))
=-tan(tc)*(log((1+tan(lat2/2))/(1-tan(lat2/2)))-
log((1+tan(lat1/2))/(1-tan(lat1/2))))
=-tan(tc)*(log(tan(lat2/2+pi/4)/tan(lat1/2+pi/4)))
(logs are "natural" logarithms to the base e.)
The true course between the points is given by:
tc= mod(atan2(lon1-lon2,log(tan(lat2/2+pi/4)/tan(lat1/2+pi/4))),2*pi)
The dist, d between the points is given by:
if (abs(lat2-lat1) < sqrt(TOL)){
q=cos(lat1)
} else {
q= (lat2-lat1)/log(tan(lat2/2+pi/4)/tan(lat1/2+pi/4))
}
d=sqrt((lat2-lat1)^2+ q^2*(lon2-lon1)^2)
This formula fails if the rhumb line in question crosses the 180 E/W meridian. Allowing this as a possibility, the true course tc, and distance d, for the shortest rhumb line connecting two points is given by:
dlon_W=mod(lon2-lon1,2*pi)
dlon_E=mod(lon1-lon2,2*pi)
dphi=log(tan(lat2/2+pi/4)/tan(lat1/2+pi/4))
if (abs(lat2-lat1) < sqrt(TOL)){
q=cos(lat1)
} else {
q= (lat2-lat1)/dphi
}
if (dlon_W < dlon_E){// Westerly rhumb line is the shortest
tc=mod(atan2(-dlon_W,dphi),2*pi)
d= sqrt(q^2*dlon_W^2 + (lat2-lat1)^2)
} else{
tc=mod(atan2(dlon_E,dphi),2*pi)
d= sqrt(q^2*dlon_E^2 + (lat2-lat1)^2)
}
See http://williams.best.vwh.net/avform.htm#Rhumb
How to get Random Geo-points[ lat/long in decimal], placed anywhere inside a 100 meter radius circle? The center of the circle is another reference GeoPoint.
Is there any Function/Formulae that implements this?
Basically I am reading the GPS input of my android device and need to generate random Geo-Points around the device [In a circle of radius 100 meters centered at my device].
Please note : There are no Geo-Points pre-stored in Database. I need to create all the Geo-points on the fly as mentioned above.
I just wrote a a Ruby method which extends Random to provide this.
Caveat: The points all lay within a box, not a circle.
class Random
def location(lat, lng, max_dist_meters)
This is called with Random.new.location(mid_lat, mid_lng, dist). It will return a point which is probably within max_dist_meters of a the mid point.
max_radius = Math.sqrt((max_dist_meters ** 2) / 2.0)
Without adjusting to max_radius we'd get points inside a square outside the circle (i.e. in the corners), where the distance would be greater than max_dist_meters. This constrains us to a square inside the circle which is probably more what you want.
lat_offset = rand(10 ** (Math.log10(max_radius / 1.11)-5))
lng_offset = rand(10 ** (Math.log10(max_radius / 1.11)-5))
The 1.11 and 5 come from here.
lat += [1,-1].sample * lat_offset
lng += [1,-1].sample * lng_offset
lat = [[-90, lat].max, 90].min
lng = [[-180, lng].max, 180].min
We should probably wrap around here instead of just clamping the value, fixes welcome.
[lat, lng]
end
end
Comments / clean up welcome!
Sample output here which you can see nicely if you paste the lat/lngs here.
Pick random points on a square (i.e. pairs of uniform random numbers), then discard any that don't lie within a circle inscribed in that square. Given (x,y) pairs, a point is within your circle if:
(x - c_x)^2 + (y - c_y)^2 < r,
where (c_x, c_y) is the centre of your circle and r is its radius.
Start here: Generate a random point within a circle (uniformly). Then figure out how to center that circle at the reference lat/long. Then figure out how to map the randomly generated points to lat/long values. Hint: you want to add the individual components (say, x and y on your circle) to the circle's center.