I am trying to use the wikimapia api for finding venues of specific cities or places given their longitude and latidute.
There isn't much of some documentation, but I suppose that it would just be an http request.
Now, the problem I have is about the specific ulr. I tried this one:
http://api.wikimapia.org/?function=search
&key= myKey
&q=lat= theLatidute
&lon= theLongitude
&format=json
but it doesn't seem to work. Any help will be appreciated..
The search API requires that you set a search location (long and lat) as well as the name of something to search for that location.
For example, to find a train station near a particular coordinate:
http://api.wikimapia.org/?function=search&key=[key]&q=Train+Station&lat=[latitude]&lon=[longitude]&format=json
If you're just trying to find a list of objects that are close to a coordinate, without a search term, you need to use the box API with small offsets:
http://api.wikimapia.org/?function=box&key=[key]&lon_min=[lon_min]&lat_min=[lat_min]&lon_max=[lon_max]&lat_max=[lat_max]&format=json
If you only want to input one set of coordinates, you can compute lon_min, lon_max, lat_min and lat_max like this:
// 1 degree latitude is roughly 111km, 0.001 degrees lat is about 100m
var lat_min = latitude - 0.001;
var lat_max = latitude + 0.001;
// 1 degree longitude is not a static value
// it varies in terms of physical distance based on the current latitude
// to compute it in meters, we do cos(latitude) * 111000
var meters_per_longdeg = Math.cos((3.141592 / 180) * latitude) * 111000;
// then we can work out how much longitude constitutes a change of ~100m
var range = 100 / meters_per_longdeg;
var long_min = longitude - range;
var long_max = longitude + range;
Related
I'm hoping to find a way using GEOSwift to take a series of user's LatLngs, construct a linestring and buffer it to always be 30 meters wide regardless of the user's location. I feel like there must be an easier way than the path I'm going down and any help would be appreciated.
Background:
From what I can tell the buffer functions width parameter is currently defined in decimal degrees as my coordinate system is EPSG 4326, which makes calculating the width in meters difficult. I can get a rough estimation of meters per decimal degree for both longitude or latitude with the Haversine formula.
The problem I have is the series of points can move both latitudinally and longitudinally. So the buffer width I need in these cases lies somewhere between ThirtyMetersInLatDegrees and ThirtyMetersInLngDegrees. And in this case the width to supply to the buffer function becomes a weird approximation/ average of the user's overall longitudinal and latitudinal movement throughout the linestring related to ThirtyMetersInLngDegrees and ThirtyMetersInLatDegrees.
i.e. assuming ThirtyMetersInLngDegrees is the max:
ThirtyMetersInLatDegrees <= bufferWidth <= ThirtyMetersInLngDegrees
How can I better accomplish this?
Here's how I'm calculating meters per decimal degree:
//Earth’s radius
let R=6378137.0
let deviceLatitude = 37.535997
let OneMeterInLatDegrees = 1/R * (180/Double.pi)
let OneMeterInLngDegrees = 1/(R*cos(Double.pi*deviceLatitude/180)) * (180/Double.pi)
let ThirtyMetersInLatDegrees = 30 * latDegreesPerMeter
let ThirtyMetersInLngDegrees = 30 * lngDegreesPerMeter
let r: Double = 6371 + (self.locationManager.location?.altitude)!
let xPos = r * cos((self.locationManager.location?.coordinate.longitude)!) * cos((self.locationManager.location?.coordinate.longitude)!)
I'm trying to convert the latitude and longitude to the x,y,z coordinate system in meter. I've searched for many conversion formulas but each one gives a different result. The above code is what i tried. I used this formula: x=(radius+altitude) * cos(altitude) * cos(longitude)
The problem is that i want it in meter, and when i try using this formula in the didUpdateLocations method, the values are not logical. The value of the x is changing with an illogical huge difference.
So i think there's something wrong in the unit of measure. I want it to be in meter. Or maybe the conversion to double is causing troubles?
Any help? Thanks!
I´m developing an iPhone app, and I need some help with this case:
I need to check, if user leave google maps route (GMSPolyline) and if distance from user location to nearest point of route is more than 40 meters -- I need to rebuild route.
I can't find the right algorithm to detect if distance from user to route is more than 40 meters.
I've tried to use this method to find projection of user location (converted to CGPoint by CGPointMake) on route :
+ (CGPoint)projectionOfPoint:(CGPoint)origPoint toSegmentP1:(CGPoint)p1 p2:(CGPoint)p2 {
// for case line is parallel to x axis
if (p2.y == p1.y) {
return CGPointMake(origPoint.x, p1.y);
// for case line is parallel to y axis
} else if (p2.x == p1.x) {
return CGPointMake(p1.x, origPoint.y);
}
// line from segment
CGFloat kKoefLine1 = (p2.x - p1.x)/(p2.y - p1.y);
CGFloat bKoefLine1 = p1.y - kKoefLine1*p1.x;
// perpendicular line
CGFloat kKoefLine2 = -1/kKoefLine1;
CGFloat bKoefLine2 = origPoint.y - kKoefLine2*origPoint.x;
// cross point
CGFloat krossX = (bKoefLine2 - bKoefLine1)/(kKoefLine1 - kKoefLine2);
CGFloat krossY = kKoefLine2*krossX + bKoefLine2;
return CGPointMake(krossX, krossY);}
Then I calculate distance from returned projection (converted to CLLocation) and user location, but it doesn't works.
P.S.: I will be thankful if solution would be written on swift.
There is a GMSGeometryIsLocationOnPath function in the GMSGeometryUtils module in the Google Maps SDK.
You should be able to use that to calculate what you need.
Pseudocode (not tested):
let currentLocation: CLLocationCoordinate2D = ...
let routePath: GMSPath = routePolyline.path
let geodesic = true
let tolerance: CLLocationDistance = 40
let within40Meters = GMSGeometryIsLocationOnPath(currentLocation, routePath, geodesic, tolerance)
for swift 5.0 and based on #Arthur answer I wrote follwoing function
func isInRoute(posLL: CLLocationCoordinate2D, path: GMSPath) -> Bool
{
let geodesic = true
let tolerance: CLLocationDistance = 40
let within40Meters = GMSGeometryIsLocationOnPathTolerance(posLL, path, geodesic, tolerance)
return within40Meters
}
While I don't recall much about the GMS SDK off the top of my head, before I give you an answer, I will say that nobody on here will write your code for you. That's your job and should be done on your time. You haven't given any background as to how far you've gotten in terms of calculating routes, whether or not you've figured out how to calculate distance at all, etc.
With that being said, routes on Google Maps are comprised of "legs", which denote a path to take before a turn is made in efforts to reach the end destination. By querying your "route" dictionary, you can extract an array of dictionaries where each element (which is a dictionary) contains metadata about a "leg". You can then loop through that array, go through each dictionary and extract the "distance" value, and sum them to a single "distance" var.
You can recalculate this as often as needed and use a conditional to check whether or not the leg distance sum is < 40M, else rebuild.
link to an article that should help (I didn't have the time to go through the entire thing for you, so do your due diligence and research) here.
I'm querying my server for a list of locations that are closest to the user based on his observable portion of the mapview.
I'm not entirely sure on how to do this, but should I send the center lat and long of the mapview's visible region and then search for results based on nearest radius?
I know that MKMapView has two properties called region and visibleMapRect. Should I use one of those, and if so, which one is more appropriate based on my question?
EDIT
I'm looking to implement functionality that's identical to the apple maps and Yelp app when you search for nearby locations and it shows you what's relevant based off the visible portion of the map view.
EDIT 2
I have seen a lot of people break up the visible portion of their mapview into quadrants, most commonly NW,NE,SW and SE. However, I'm still not entirely sure why theyr'e doing this. I would like to know the best way to query the back end, which contains a lat and long for each location, to find the locations which exist on the mapview.
I have looked everywhere on stackoverflow and I found a similar question here. However, it doesn't answer my question and there's no mention of visibleMapRect because it's over 5 years old.
Any help is tremendously appreciated.
So you would need to provide your server call with these 2 coord bottomleft and topright 4 points all together.
if lat of location > bottomleft.lat and if lat of location < topright.lat
if long of location > bottomleft.long and if long of location < topright.long
iOS Code would look like this the make server call with these four variables as parameters
fun viewDidLoad() {
super.viewDidLoad()
self.mapView.delegate = self
}
func mapView(mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
// Using region
var span: MKCoordinateSpan = mapView.region.span
var center: CLLocationCoordinate2D = mapView.region.center
// This is the farthest Lat point to the left
var farthestLeft = center.latitude - span.latitudeDelta * 0.5
// This is the farthest Lat point to the Right
var farthestRight = center.latitude + span.latitudeDelta * 0.5
// This is the farthest Long point in the Upward direction
var farthestTop = center.longitude - span.longitudeDelta * 0.5
// This is the farthest Long point in the Downward direction
var farthestBottom = center.longitude + span.longitudeDelta * 0.5
var SWCoord = MKCoordinateForMapPoint(farthestBottom, farthestLeft)
var NECoord = MKCoordinateForMapPoint(farthestTop, farthestRight)
// Using visibleMapRect
var mapRect = mapView.visibleMapRect
// This is the top right Coordinate
var NECoord = getCoordinateFromMapRectanglePoint(MKMapRectGetMaxX(mapRect), y: mapRect.origin.y)
// This is the bottom left Coordinate
var SWCoord = getCoordinateFromMapRectanglePoint(mapRect.origin.x, y: MKMapRectGetMaxY(mapRect))
// Not needed but could be useful
// var NWCoord = getCoordinateFromMapRectanglePoint(MKMapRectGetMinX(mapRect), y: mapRect.origin.y)
// var SECoord = getCoordinateFromMapRectanglePoint(MKMapRectGetMaxX(mapRect), y: MKMapRectGetMaxY(mapRect))
}
func getCoordinateFromMapRectanglePoint(x: Double, y: Double) -> CLLocationCoordinate2D {
var mapPoint = MKMapPointMake(x, y)
return MKCoordinateForMapPoint(mapPoint)
}
If you have anymore questions just comment
EDIT 2 I have seen a lot of people break up the visible portion of their mapview into quadrants, most commonly NW,NE,SW and SE.
However, I'm still not entirely sure why theyr'e doing this. I would
like to know the best way to query the back end, which contains a lat
and long for each location, to find the locations which exist on the
mapview.
I'm not sure if this is what you're referring to but they could be using quadtrees as a way to efficiently search the locations of a huge amount of coordinates.
This post from Thoughtbot demonstrates how to use quadtrees to display thousands of place coordinates as clusters on the map and it includes gifs that very succinctly explain how it works:
A quad tree is a data structure comprising nodes which store a bucket of points and a bounding box. Any point which is contained within the node’s bounding box is added to its bucket. Once the bucket gets filled up, the node splits itself into four nodes, each with a bounding box corresponding to a quadrant of its parents bounding box. All points which would have gone into the parent’s bucket now go into one of its children’s buckets.
Source: How To Efficiently Display Large Amounts of Data on iOS Maps
I am developing a chat app in iOS. In which a user can able to search near by people with a 1 kilo meter radius .
On registration i stored the latitude and longitude of every user .
Now tell me how can i search people near by user within 1 kilo meter radius ??
thanks alot
You can use Haversine formula to calculate the appropriate distance between current latitude, longitude and target latitude, longitude.
define DEG2RAD(degrees) (degrees * 0.01745327)
double currentLatitude = 40.727181; // current latitude of logged in user
double currentLongitude = -73.986786; // current longitude of logged in user
double destinationLatitude = 42.896578; // latitude of target user
double destinationLongitude = -75.784537; // longitude of target user
//convert obtained latitude and longitude to RADS.
double currentLatitudeRad = DEG2RAD(currentLatitude);
double currentLongitudeRad = DEG2RAD(currentLongitude);
double destinationLatitudeRad = DEG2RAD(destinationLatitude);
double destinationLongitudeRad = DEG2RAD(destinationLongitude);
//Haversine Formula.
distance = acos(sin(currentLatitudeRad) * sin(destinationLatitudeRad) + cos(currentLatitudeRad) * cos(destinationLatitudeRad) * cos(currentLongitudeRad - destinationLongitudeRad)) * 6880.1295896;
The distance obtained here is in kilometers.
My solution is directly you can't search users using Radios.Make following steps.
Send Latitude , Longitude and Radios information to Your Backend server using web service.
For your web service developer put query and get nearby users using your information.
Please refer following link:
Geo Distance Search with MySQL
You can compare two locations using this method
CLLocationDistance distanceInMeters = [locationA distanceFromLocation:locationB];
Or calculate from backend(PHP developers) to find the distance, because basically they only store all lat,longs.(i think)