I have some coordinates for example:
A-15.555, 25.6565
B-15.631, 25.9565
C-16.585, 26.2435
...
I want to make a script using my location (by mobile phone).
If my location is in a radius of 500 meters of each position, it will show something as "You're between the position A and B".
So if I'm in the location 15.604, 25.7521, I'm between the A and B positions and the script will tell me that.
I don't know how to do because I'm not expert of the geolocation scripts.
Thanks so much!
--------------------EDIT---------------------
--------------------UPDATE---------------------
Maybe it should be simple in this way:
-I obtain the user's location using the PHP Geolocation.
-I need to make a PHP script to search for the two nearest position based on the user's location
-Display these two position
Is it possible?
One solution (not sure if it's what you're looking for) is to measure the distance between your location and the specified points. So you could say something like this:
if (pointA.distance(MyLocation) < 500 distance_units && pointB.distance(MyLocation) <
500 distance_units) {
notify_user
}
Not sure which programming language you're using, but maybe there are some handy labraries you could use that already have such functions. Otherwise you should make a method to gives you the distance between one geo location and another.
Hope this helps. Have a good night!
I would use a vincenty formula. It will allow you to calculate the distance between two sets of coordinates. Movable Type has JavaScript source code to do so, and it returns the distance in meters. Just remember, that the author extended the JavaScript number object with toRadians() and toDegrees() methods. You will have to do the same. I've used this code previously in a production app and it works well.
Related
I want to rotate GMap by changing the bearing angle value, so the camera rotates around the center point (360-Degree one full round ).
When we change the bearing, there is a easing effect at camera start and end points. How can I control/change that in order to make the rotation smooth when change Bearing values (in order to rotate map in 360 Degree, smooth animation)?
Required this for all languages as it appears the easing effect is different in different language libraries. e.g. Swift, Android, PHP, JS, Node.js, React.
Swift Example (running OK in Linear Animation):
Note that initially the animation did had jerks in iOS as well, but when we make use of CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear along its CATransaction properties then the GMap animation turned into smooth animation. so now if you see the code below, the change in Bearing value does not create jerky effect (due to the easing effect in GMap animation). I am looking for appropriate solution for Android and Web as well.
//Move the map around current location, first loop
let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
CATransaction.begin()
CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
CATransaction.setAnimationTimingFunction(timingFunction)
CATransaction.setCompletionBlock({
//Move the map around current location, second loop
let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
CATransaction.begin()
CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
CATransaction.setAnimationTimingFunction(timingFunction)
CATransaction.setCompletionBlock({
//Move the map around current location, third loop
let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
CATransaction.begin()
CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
CATransaction.setAnimationTimingFunction(timingFunction)
CATransaction.setCompletionBlock({
UIView.animate(withDuration: 0.5, animations: {
self.findingYourLocation.alpha = 0.0
})
//TODO: Set nearest branch
// Zoom in one zoom level
let zoomCamera = GMSCameraUpdate.zoomIn()
self.mapView.animate(with: zoomCamera)
// Center the camera on UBL Branch when animation finished
//let nearestBranch = CLLocationCoordinate2D(latitude: 24.850751, longitude: 67.016589)
let nearestBranch = CLLocationCoordinate2D.init(latitude: 24.806849, longitude: 67.038734)
let nearestBranchCam = GMSCameraUpdate.setTarget(nearestBranch)
CATransaction.begin()
let timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut)
CATransaction.setValue(3.0, forKey: kCATransactionAnimationDuration)
CATransaction.setAnimationTimingFunction(timingFunction)
CATransaction.setCompletionBlock({
self.nextButton.alpha = 1.0
})
self.mapView.animate(with: nearestBranchCam)
self.mapView.animate(toZoom: 15)
self.mapView.animate(toBearing: 0)
self.mapView.animate(toViewingAngle: 0)
CATransaction.commit()
})
self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
CATransaction.commit()
})
self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
CATransaction.commit()
})
self.mapView.animate(toBearing: self.mapView.camera.bearing + 120)
CATransaction.commit()
The Android example code (has problem):
The Android example/sample code can be found here: https://issuetracker.google.com/issues/71738889
Which also includes an .apk file, an .mp4 video of sample app output. Which clearly shows jerky effects when Bearing value changes while rotating the map in 360-Degree.
Giving this as an answer as a comment would be rather hard to read; this is taken from the google documentation.
Consider this code:
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(MOUNTAIN_VIEW) // Sets the center of the map to Mountain View
.zoom(17) // Sets the zoom
.bearing(90) // Sets the orientation of the camera to east
.tilt(30) // Sets the tilt of the camera to 30 degrees
.build(); // Creates a CameraPosition from the builder
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
This code creates a new camera position, and that's exactly what you're trying to mutate: the bearing of the camera. So if you create a new camera position like this:
CameraPosition cameraPosition = new CameraPosition.Builder()
.bearing(50)
.build();
and then animate the camera to that position:
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
That should do the trick. To give some more information on what you will need to use as bearing:
a bearing of 90 degrees results in a map where the upwards direction points due east.
Good luck.
I'm going to write this as another answer as I'd like to take the time to write a wall of text, whereas I'd like to keep the other answer as short as possible since it might still help other people with a similar problem.
The problem
So if I understand correctly, what you're trying to do is build an application with Google maps for different platforms. You're running into an issue with Google maps (the jerky movement) and you're trying to find a fix for all the platforms.
My proposed solutions
I'll divide this into a few sections, because I see different ways to go forward.
Find a solution for all the platforms.
This one seems like the most straightforward, but it could be akin to the XY problem. I've tried to introduce you to some ways of animating views, and you've solved the problem in your iOS app, but at the core what you're dealing with is a flaw in the Google maps animation when changing the bearing. I am not sure if there is a way to tackle this problem on every platform, as I haven't tried.
Use a different map
This sounds like a big step, and depending on your usage something you don't want to do. However, I've successfully used Leaflet (a JS map) with a WKWebView on iOS and Android and that all worked pretty well (this obviously also works fine in the browser). Keep in mind that some other maps might also have the jerky animation.
Wrapping it up
I hope I've given some insight. I'll add to this answer as we find out new things about the problem. Could you try to provide a minimal reproducible example? That way I can give it a better try. Good luck!
After going through all possible cases, I came to know that GMap is not built with required feature of Rotating map in 360-Degree in one go with custom animation. Don't know if this appears in next GMap api version.
For now, the possible solution is to change the animation logic, and instead of rotating 360-Degree we can rotate to e.g. 180-Degree with reduced animation speed (animation duration time).
This allows us to bring required map surrounding search experience to the user.
(For now I am posting this temporary answer, and allow others to update or post latest answer in future).
I have submitted this animation control issue on GMap issue tracker, please START this issue in order to show your interest and feedback, so Google team can take this feature into their final consideration.
https://issuetracker.google.com/u/1/issues/71738889
Here is my approach:
tilt = 45f
zoom = 18
target = currentLocation
bearing = lastKnownLocation.bearingTo(currentLocation)
Use map.animateCamera(); // instead of move camera
CameraPosition cameraPosition;
if (currentLocation.distanceTo(lastKnownLocation) > 50) {
cameraPosition = new CameraPosition.Builder()
.target(currentLatLng).zoom(20).tilt(45f).bearing(bearingValue).build();
} else {
cameraPosition = new CameraPosition.Builder()
.target(currentLatLng).zoom(20).tilt(45f).build();
}
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
What else you have to do?
You must call this method from LocationCallback (where you are getting location updates) and then we can have a smooth experience.
So if the user moved (walked or driving) and the distance between lastKnownLocation and currentLocation is greater than 50 meters then only we will set bearing otherwise we keep changing the targetLocation only.
In this way, we can show heading direction like in google maps.
I am trying to sequence together a series of points for a createjs Tween within Adobe Animate. The idea is for the 'player' object to follow a predetermined set of points, but the player can move backward and forward along the path by clicking on the points, so the array of coordinates that the player needs to travel through can change each time. I have the coordinates just fine, but I am getting errors about the path being invalid, and to check the documentation for valid path details (http://www.createjs.com/docs/tweenjs/classes/MotionGuidePlugin.html) where I see no details about path validity.
Can anyone tell me why this works (player animates fine):
var testArr = [7,278, 240,278, 408,327];
createjs.Tween.get(player).to({guide:{path:testArr}},1000);
but the following does not (player does not animate, throws error: Uncaught invalid 'path' data, please see documentation for valid paths) :
var testArr = [7,278, 240,278, 408,327, 609,327];
createjs.Tween.get(player).to({guide:{path:testArr}},1000);
I have gotten all sorts of animations working just fine, but the MotionGuide plugin seems to have issues with the coordinates I am passing in. I've done a lot of testing and cannot seem to find a pattern to what makes a set of coordinates valid or invalid.
Thanks!
Thought I'd answer in case anyone else had this issue.
It seems as though entering an odd amount of coordinate pairs fixes the issue, instead of an even number of coordinate pairs.
I presume this has to do with n number of curveTo calls happening behind the scenes.
For example I have a simple rout From Warsaw, Poland To Berlin, Germany by car. Now I can calculate distance of all route (572km). How I can calculate distance for each country? Germany ~ 100km and Poland ~ 472km.
I tried to detect country border using start_location for each DirectionsLeg in legs[] and detect country name by start_location. For example:
getCountry(legs[0]) => 'pl'
getCountry(legs[1]) => 'pl'
getCountry(legs[2]) => 'pl'
//border detected
getCountry(legs[3]) => 'de'
getCountry(legs[4]) => 'de'
It's work, but if route is so "big", getCountry() return OVER_QUERY_LIMIT.
UPDATED
Thanks Dr.Molle for help!
Working fiddle.
Warning: Code works fine, but it's not optimized. Be carefully!
P.S. Sorry for my English
You'll need a way which avoids requests for each step to detect the country .
There is a FusionTable which contains the boundaries for countries: https://www.google.com/fusiontables/data?docid=16CTzhDWVwwqa0e5xe4dRxQ9yoyE1hVt_3ekDFQ#map:id=3
Possible workflow:
request the geometries for the countries affected by the route. Using the path directly wouldn't work here, because the URL would be too long, so filter the results based on the bounds of the route(it may return more than the affected countries, but there is no other option)
a sample-query for the route warsaw-berlin would be:
SELECT sovereignt,json_4326
FROM 16CTzhDWVwwqa0e5xe4dRxQ9yoyE1hVt_3ekDFQ
WHERE ST_INTERSECTS(kml_4326,
RECTANGLE(LATLNG(51.88951,13.38593),
LATLNG(52.52003,21.01219)))
The RECTANGLE used in this query will be created based on the bounds-property of the given route. Sample-request: http://jsfiddle.net/doktormolle/vexqe0ps/
based on the returned geometries create an array of polygons(they must not be visible) for each country.
Loop over the steps of the route, and for each step iterate over the polygon-array. Use google.maps.geometry.poly.containsLocation() to check if the start_(or end_)location is placed within the current polygon. When it does, add the distance of the current step to the distance for the current country.
I don't know if my method is faster than your getCountry() but I use the instruction text and search for "Entering" (as in e.g."Entering Germany") - that means you're at the border (but you must use the lat-lng of the next index)
var instr = myroute.legs[0].steps[i].instructions;
isBorder=instr.includes("Entering");
if(isBorder) {
// calculate partial distance with myroute.legs[0].steps[i+1].start_location.lat() etc;
}
EDIT: I just realized there's also an end_location, too, for every step so you don't need the next step as a reference to calculate the subdistance. Or simply use myroute.legs[0].steps[j].distance.value. Also, adding the distances of every step together eliminates the need to call any further functions.
I'm using the ESRI JavaScript API v3.8. (I know 3.11 is out - can't upgrade yet.)
What I'm trying to do is to create a geometric buffer of a size provided by the user from an arbitrary line (or point) selected by the user. Some of the relevant code is shown below:
var params = new esri.tasks.BufferParameters();
params.distances = [values.distance]; //the input distance
params.geometries = [gr.geometry]; //the input geometry
params.unit = esri.tasks.GeometryService.UNIT_FOOT;
params.outSpatialReference = mapView.map.spatialReference; //always 3857
params.bufferSpatialReference = gr.geometry.spatialReference; //always 3857
esri.config.defaults.io.corsEnabledServers.push('mydomain.com');
esri.config.defaults.io.proxyUrl = 'https://serverdomain.com/proxy';
var gsvc = new esri.tasks.GeometryService('https://tasks.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer');
gsvc.simplify(params.geometries, function(geometries){
params.geometries = geometries;
gsvc.buffer(params, function(geometries){
//add output geometry to the map and perform spatial query with it
}, function(err){
//handle error
});
}, function(err){
//handle error
});
The problem is that, if I use an input distance of 500 (feet), then measure the distance from the center line of the input geometry on self._queryGeometry, using ESRI's measurement tool, the actual width of the polygon created is something like 370 feet on either side of the center line.
I've managed to get this to work more accurately using the Illinois State Plane spatial reference, as my test objects are in Illinois, but the logic needs to work everywhere.
When I try various incarnations of doing a geodesic buffer, the input distance unit seems to get ignored and, using an input distance value of 500, I get a buffer that spans the entire world! Either that or the results are exactly the same, depending on how things are set up.
I believe I need to do a geodesic buffer, but I have absolutely no idea how to go about that in such a way that the geometry service will actually pay attention to the units I'm sending in.
Any ideas would be greatly appreciated. Let me know if I've left anything out.
Sounds like there might be a spatial reference issue somewhere. You can try re-projecting geometry into 3857 if that's what the map is and I would inspect the geometry being returned from the buffer and simplify to make sure it looks like what your expecting. I have had issues with the geometry service area's and length's returning slightly incorrect geometries and in my case it ended up being an issue with an incorrect spatial reference. Also, I know you said you can't upgrade, but 3.13 is out and can do geometry options locally without the need for a proxy or any network requests, if possible, it would be worth trying out.
I've got a basic Space Invaders type game going, and I can't get it to recognise when the shot from the player hits the alien. (I'm only checking Alien2 atm, the one second from the left). Since they're both moving, I've decided the only way to check for collisions is with either a range-based if statement (with 2 top coordinates and one left coordinate), or directly comparing the positions along the Y axis with Jquery.
I'm using the range-based solution at the moment, but so far it hasn't worked (not sure why).
My code so far:
if (key == "87"/*&& document.getElementById('BarrelOne').id=='BarrelOne'*/){
var Invader2 = document.getElementById('Alien2');
var Shot1 = document.getElementById('ShortShot');
Shot1.style.webkitAnimationPlayState="running";
setTimeout(function(){
Shot1.style.webkitAnimationPlayState="paused";
}, 1200);
if(document.elementFromPoint(625.5, 265.5) == Shot1){
Invader2.style.visibility="hidden";
}
};
Jsfiddle:
http://jsfiddle.net/ZJxgT/2/
I did something similar, and i found that it was much easier to achieve using gameQuery.
to test for collisions:
var collided = $("#div1").collision("#div2");
you can see full working example here
EDIT
If you're having trouble check out the API. For example, to find out how to use collisions check this part of the API.
the collision works in the following way:
This method returns the list of elements collisioning with the selected one but only those that match with the filter given as parameter. It takes two optional arguments (their order is not important). The filter is a string filtering element used to detect collision, it should contain all the elements the function should search collision into. For example if you look for collision with element of the class ‘foo’ that may be contained in a group you will use the filter ".group,.foo".
So, write something like this:
$("#ShortShot").collision("#Alien2").hide();
// will return the alien if it collides with ShortShot
or, to hide them both:
if (($("#ShortShot").collision("#Alien2")).length) {
$("#ShortShot").remove();
$("#Alien2").remove();
}
Instead of losing hours reinventing the wheel, I would suggest to switch (if still possible, depending on your time deadline) to a real 2D game engine for Javascript, with easy collision detection.
Check as well: 2D Engines for Javascript