I'm trying to make a request to my Geoserver to retrieve the features near the tap of a user on the map.
The map takes all the space. Therefore I computed the BBOX in this way:
region = mMap.getProjection().getVisibleRegion().latLngBounds;
double left = region.southwest.longitude;
double top = region.northeast.latitude;
double right = region.northeast.longitude;
double bottom = region.southwest.latitude;
and the width and height are taken as belows:
mMapFragment.getView().getWidth();
mMapFragment.getView().getHeight();
while the X and Y parameter are calculated in the following way:
Point click = mMap.getProjection().toScreenLocation(latLng);
where latLng is the point that came from the event onMapClick(LatLng) (reference here: https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap.OnMapClickListener).
The resulting URL that I obtain is:
http://localhost/geoserver/sindot/wms?service=WMS&request=GetFeatureInfo&info_format=application%2Fjson&version=1.1.1&srs=EPSG%3A3857&bbox=1222173.74033,5056403.44084,1222174.11356,5056403.7028&query_layers=sindot:verticale&layers=sindot:verticale&feature_count=3&styles=tabletb3lab&width=2048&height=1262&x=1441&y=503
The problem is that the server returns always an empty response even if I know that there are features there because I can see the spots on the map. What could it be?
Thanks in advance.
It onlytook to add &buffer=10 (or another number according to your needs) to the request.
Related
I have implemented WorldWind in my application. I need to get the visible portion of the globe so that I can find the Northeast and Southwest latitude and longitude coordinates of this visible part.
How do I get the boundaries of the visible part of the globe?
The question can be complicated. For example, if the horizon is visible, then your view is not bounded by four geodetic positions.
If you are in a method that provides a DrawContext, there is a convenience method for returning the visible sector:
Sector visibleSector = dc.getVisibleSector();
LatLon[] corners = visibleSector.getCorners();
If you don't have access to the DrawContext, but you can guarantee that all four corners of your view will intersect the globe, then you can use the following snippet from the worldwind forums:
View view = WorldwindCore.getInstance().getWw().getView();
Rectangle viewport = view.getViewPort();
LatLon corners[] = new LatLon[4];
corners[0] = view.computePositionFromScreenPoint(viewport.getMinX(), viewport.getMinY());
corners[1] = view.computePositionFromScreenPoint(viewport.getMinX(), viewport.getMaxY());
corners[2] = view.computePositionFromScreenPoint(viewport.getMaxX(), viewport.getMaxY());
corners[3] = view.computePositionFromScreenPoint(viewport.getMaxX(), viewport.getMinY());
Suppose if a marker's longitude is 124.4567. How can I calculate the longitude which is 1 centimetre away to the left side of the screen? It will vary depending on the screen density and zoom level. Is there any inbuilt method to calculate that longitude?
PS: I am sorry, it was "longitude". I always am confused by the two. I have edited the question.
I am not trying to calculate geological distances between two markers. Basically, I want to know how much longitude is 1 centimetre on the screen (not 1 centimetre of actual land) of the device. I mean, 1cm on the screen could be 30 degree longitude difference if I have zoom it out on my phone, but 1cm on the screen could be 1 degree longitude on your phone if you have zoomed it in.
You got distance calculation between 2 coordinator from here:
Distance betwee
n coordinator
And you have destination long, source long, source lat, and distance just find out destination lat.
And about zoom level, you have scale ratio of google map here:
Google map scale ratio
"To the left side" means western direction. Actually, latitude varies from -90 to 90 degrees, so there is no latitude 124.
If you have any point LatLng, you can find point 1 meter to the left via simple math.
Radius of a parallel ring is r = R * cos(latitude_in_radians), so 1 meter takes 360 / r of longitude.
Therefore you can calculate your point as follows without any library.
var EarthR = 6378137;
var point = {lat: 45, lng: 124};
var point2 = {lat: point.lat, lng: point.lng - 360 / ( EarthR * Math.cos(point.lat * Math.PI / 180))};
console.log(point2);
After a lot of Google search, I have found this How to access Google Maps API v3 marker's DIV and its pixel position?. The answer showed how to convert screen locations to lat/lng coordinates. So I modified it a little to get the position 1 centimetre on the left, no matter what the zoom level is.
I put a marker on the left for visual debugging, when a marker is clicked. Here is the code. I am hoping it could be helpful to future people.
var dpi = resources.displayMetrics.densityDpi;
var pixelsInCm = (dpi/2.54).toInt();
var existingPoint = mMap!!.projection.toScreenLocation(marker.position);
var leftPoint = Point(existingPoint.x - pixelsInCm, existingPoint.y);
var leftLatLng = mMap!!.projection.fromScreenLocation(leftPoint);
//The code below is only for visual test. Not necessary.
var leftMarker = MarkerOptions()
leftMarker.position(leftLatLng);
leftMarker.title("1cm to the left");
mMap!!.addMarker(leftMarker);
I need find angle of vehicle turn measured in degrees.
Location points update with equal intervals (1 sec). Therefore device makes like 4-5 points during turn. I schematically displayed that on picture.
Is it possible to calculate the angle of turn using Location? If it is possible, how?
What I tried:
Create two geometric vectors from points 3, 4 and 1, 2 respectively and find angle between those vectors. Coordinates of vectors I calculated like Vector1 (lat2 - lat1; lon2 - lon2). Not sure this approach could be applied to Location coordinates.
Use location1.bearingTo(location2). But this doesn't give expected results. Seems like it gives "compass" results. Perhabs I could use it somehow but not sure.
Also tried few trigonometric formulas like here or here or here. They didn't give expected angle.
EDIT: Solution
The accepted answer works great. But to complete the answer I have to show that method of angleDifference. This one works for me:
public int getAngleDifference(int currentAngle){
int r = 0;
angleList.add(currentAngle);
if (angleList.size() == 4) {
int d = Math.abs(angleList.get(0) - angleList.get(3)) % 360;
r = d > 180 ? 360 - d : d;
angleList.clear();
}
return r;
}
I add points to list untill there're 4 of them and then calculate angle difference between 1st and 4th points for better results.
Hope it will help for someone!
vect1 = LatLon2 - LatLon1; // vector subtraction
vect2 = LatLon4 - LatLon3;
By definition of the dot product has the property:
vect1.vect2 = ||vect1||*||vect2||*Cos(theta)
Here's a breakdown of the notation
The term vect1.vect2 is the dot product of vect1 and vect2.
The general form of a dot product can be broken down component wise let v1 = <x1,y1> and v2=<x2,y2> for two arbitrary vectors v1 and v2 the dot product would be:
v1.v2 = x1*x2 + y1*y2
and the magnitude of some arbitrary vector v is:
||v|| = sqrt(v.v); which is a scalar.
The above is equivalent to the Euclidean distance formula with components x and y:
||v|| = sqrt(x^2 + y^2)
Getting the angle
Find a value for theta given the two vectors vect1 and vect2:
theta = Math.ArcCos(vect1.vect2/(||vect1||*||vect2||))
Approach 1 does not work as you described: Lat, Lon are not cartesian coordinates (One degree of longitude expressed in meters is not one degree of latitide, this is only valid at the equator). You would have first to transform to a (local) cartesian system.
An error is in the drawing: The angle marked with "?" is placed at the wrong side. You most probably want angle: 180 - ?
In your example the car ist turning less than 90°, altough your angle shows more than 90°.
To understand better make another drawing where the car turns left for only 10 degrees. In your drawing this would be 170°, which is wrong.
Approach 2) works better, but you need to sum up the angle differences.
You have to write yourself a method
double angleDifference(double angle1, double angle2);
This look easier than it is, although the code is only a few lines long.
Make sure that you have some test cases that tests the behaviour when crossing the 360° limit.
Example
(turn from bearing 10 to bearing 350), should either give 20 or -20, depending if you want that the method give sthe absolut evalue or the relative angle
In my game, a body is randomly relocated on the screen after the user does something. However, if the object is relocated on top of another body, then both are pushed slightly (to make room!). I would like to check the location of the randomly generated coordinates first, so that the relocation only takes place if the position is free (within a certain diameter anyway).
Something like.. location.hasBody(). There surely must be a function for this that I haven't found. Thanks!
There is no way to query a world with a point and get the body, but what you can do is query the world with a small box:
// Make a small box.
b2AABB aabb;
b2Vec2 d;
d.Set(0.001f, 0.001f);
aabb.lowerBound = p - d;
aabb.upperBound = p + d;
// Query the world for overlapping shapes.
QueryCallback callback(p);
m_world->QueryAABB(&callback, aabb);
if (callback.m_fixture)
{
//it had found a fixture at that position
}
Solution originally posted here: Cocos2d-iphone forum
Not sure if box2d includes a 'clean' way to do it. I'd just manually iterate over all bodies in the world just before adding a new one, and manually check if their positions + radio/size overlap with the new body shape.
try
b2Vec2 vec = body->GetPosition(); // in meters
or
CGPoint pos = ccp(body->GetPosition().x * PTM_RATIO, body->GetPosition().y * PTM_RATIO); // in pixels
I'm working on a mapping app that plots pins on a MapView based on a user's query. I'm trying to scale the map to fit all the results pins, but I've run into a seemingly strange situation.
I have two variables set up:
latSpan is the difference between the maximum latitude and minimum latitude of any of the results points
lonSpan is the difference between the maximum longitude and minimum longitude of any of the results points
This method
while ((mapView.getLatitudeSpan()) < latSpan) || (mapView.getLongitudeSpan() < lonSpan)){
mapController.zoomOut();
}//end of while loop
is supposed to zoom out to make sure all the pins fit on the viewable map screen.
But I'm experiencing something rather strange. The results of mapView.getLatitudeSpan() and mapView.getLongitudeSpan() are routinely greater than my latSpan and lonSpan values, so the MapController doesn't zoom out enough.
My map is zoomed in pretty far--level 15 or higher.
As an example, one set of search results gave the following values:
latSpan = 17928
lonSpan = 11636
mapView.getLatitudeSpan() = 21933
mapView.getLongitudeSpan() = 20598
Based on these numbers, you wouldn't think that the MapController would need to zoom out. Yet there are pins plotted both above the top and below the bottom of the screen. I changed my WHILE loop to read
while ((mapView.getLatitudeSpan() - 6000) < latSpan...
and that helps, but the right query will still cause issues.
But the real question is, why is this happening?
I'm not sure why you're code isn't working from the snippet provided. Its possible that you are not converting your latSpan and lonSpan to microDegrees (as shown below) and this would cause some issues.
Also if you're trying to make sure your mapView is showing all of the results, there's not much point trying to determine if it needs to zoom before zooming, just zoom it every time. If it turns out that it doesn't need to zoom then nothing will appear to happen and if it does then it does.
You can set a map up to encompass all of your points and move to the centroid of the points as follows:
GeoPoint max = new GeoPoint(maxLatitude, maxLongitude);
GeoPoint min = new GeoPoint(minLatitude, minLongitude);
int maxLatMicro = max.getLatitudeE6();
int maxLonMicro = max.getLongitudeE6();
int minLatMicro = min.getLatitudeE6();
int minLonMicro = min.getLongitudeE6();
GeoPoint center = new GeoPoint((maxLatMicro+minLatMicro)/2,(maxLonMicro + minLonMicro)/2);
controller.zoomToSpan(maxLatMicro - minLatMicro, maxLonMicro - minLonMicro);
controller.animateTo(center);