Google Maps API: Bézier curve polyline wrap - javascript

By using the Bezier curve polyline draw function provided by nicoabie I was able to draw a curved line from one point on the map to another. The problem is that this function does not take in to account the fact that when a point is past the maximum coordinate mark it is not necessarily on the other side of the map, since it wraps around.
For example, drawing a curved line from Seattle to Tokyo. A regular polyline would go across the Pacific ocean, but the the curved line draws east across the whole globe.
geodesic: true does not work in this case since the line must have a consistent curvature.
My question is: can a consistently curved line be drawn that takes in to account map wrapping?

Use the option third "nowrap" argument of the google.maps.LatLng class to force all the relevant points to have the same sign (set it to true, it defaults to false).
gmarkers[10].setPosition(new google.maps.LatLng(35.689488,139.69170)); // Tokyo
gmarkers[0].setPosition(new google.maps.LatLng(47.60621,(360-122.332071),true)); // Seattle
boundsCenter.setPosition(new google.maps.LatLng(36.096756,(360-178.986565),true)); // control point 1
gmarkers[6].setPosition(new google.maps.LatLng(48.511996,180)); // control point 2
var curvedLine = new GmapsCubicBezier(gmarkers[0].getPosition().lat(), gmarkers[0].getPosition().lng(), boundsCenter.getPosition().lat(), boundsCenter.getPosition().lng(), gmarkers[6].getPosition().lat(), gmarkers[6].getPosition().lng(), gmarkers[10].getPosition().lat(), gmarkers[10].getPosition().lng(), 0.01, map);
working fiddle

Related

How to specify altitude for a circle or symbol layer in Mapbox?

I have two layers built on FeatureCollection GeoJSON data. One of them is of type circle and the other is symbol. Here they are:
Thing is, as you can see in our project we use 3D buildings on the map, and we need our objects to be at a certain altitude above the ground. The question is, how to do this in Mapbox?
Here's what I've tried:
GeoJSON feature coordinates
An OPTIONAL third-position element SHALL be the height in meters
above or below the WGS 84 reference ellipsoid. In the absence of
elevation values, applications sensitive to height or depth SHOULD
interpret positions as being at local ground or sea level.
— GeoJSON spec.
I've tried setting the third argument for a feature's geometry, which is a point, but it didn't help. Looks like the third value is just being ignored.
return {
type: 'Feature',
id: l.id,
geometry: {
type: 'Point',
coordinates: [l.coordinates.lng, l.coordinates.lat, 50]
}
}
circle-translate
The geometry's offset. Values are [x, y] where negatives indicate left and up, respectively.
I've tried setting this but the result looked super weird, it didn't look like a normal elevation.
Example
I've modified an example from Mapbox so you can play around with this — here.
There is no support for setting elevation on symbol layers. See https://github.com/mapbox/mapbox-gl-js/issues/3993 and https://github.com/mapbox/mapbox-gl-js/issues/10483

Mapbox adding a long object that lines up with the road

Is it possible to draw a line that curves around the road when only given Geo point and a length?
Using Mapbox GL.
example will be I have a train I want to draw on the rail.
train object will be
{ gps: {lat:xxxxx, long:xxxx }, length: 5}
I would like it to draw on the map so that it curves around the rail as a map layer

What is the Ideal way to create a Triangle-Coordinates in Google Map API with two location points consisting of latitude & longitude

I have a scenario in my JavaScript application where I have the coordinates of a starting point which consist of Latitude and Longitude, similarly an ending point with it's respective coordinates.
Now I need to search for a location which basically provides with a set of coordinates and find if the recently entered location lies in between the previously mentioned starting point or ending point. However, the location does not need to match exactly within the points of the path of the start and end point. That is even if the location lies around the distance of say 2-3 km from the derived path, it should give a match.
I believe that we can create a triangle by providing three coordinates i.e start-point, end-point and a third point. So once the triangle is formed we can use google.maps.geometry.poly.containsLocation method to find if our searched location is present inside this triangle.
So my question is how can we get a third point to create a triangle which will provide locations that are nearby within 2-3 km from start to end point.
Else is there any alternate approach to deal with my use case?
Use googlemap's geometry library
This function specifically
isLocationOnEdge
Here's an example
0.001 tolerance value would be 100m
var isLocationNear = google.maps.geometry.poly.isLocationOnEdge(
yourLatLng,
new google.maps.Polyline({
path: [
new google.maps.LatLng(point1Lat, point1Long),
new google.maps.LatLng(point2Lat, point2Long),
]
}),
.00001);
Please note that the following answer assumes Plane Geometry where you should be using Spherical Geometry instead. Although this will be fine for less accurate purposes (like approximate distance, etc..)
It seems more of a geometry question than a programming question. A triangle like you mentioned won't be able to cover a straight line path in a uniform way. The situation can be thought of more like a distance between point and a line problem (Refer the given diagram
Here you can just find the distance between point C and line AB which you can check whether it's below 2.5 KMs (I've omitted all the units and conversions for simplicity)
Please note that you will also need to convert the distances from radian to appropriate units that you require using haversine formula, etc. which is not a trivial task (https://www.movable-type.co.uk/scripts/latlong.html).

Google map polygon with outside map tinted [duplicate]

This question already has an answer here:
Google Maps API Polygon with "Hole" In Center
(1 answer)
Closed 7 years ago.
First of all, for the issue you're going to read, I used this snippet of code to highlight my polygon :
Highlight polygon and tint rest of map using Google Maps
Here is my code (it's Angular) :
var boundaries = [];
// big area
var overlay = [
new $rootScope.googleApi.LatLng(80.0, -90.0),
new $rootScope.googleApi.LatLng(-60.0, -90.0),
new $rootScope.googleApi.LatLng(-60.0, 90.0),
new $rootScope.googleApi.LatLng(80.0, 90.0)
];
// my polygon
angular.forEach(settings_boundaries, function(val, key) {
boundaries.push(new $rootScope.googleApi.LatLng(val[1], val[0]));
});
// create a polygon with overlay first
var poly = new $rootScope.googleApi.Polygon({
paths: [overlay, boundaries],
strokeColor: "blue",
strokeWeight: "1",
fillColor: "black",
fillOpacity: 0.4,
clickable: false
});
poly.setMap(interactiveMap);
Now, the real problem is,
If I use these coordinates (which I don't remember how I got them in the first place) :
[[1.6101837158203125,49.00274483644452],
[1.6294097900390625,49.01175312475694],
[1.5947341918945312,48.98787759766659],
[1.6101837158203125,49.00274483644452]]
Everything works fine (as you can see here).
But if I use these ones :
[[1.6809940338134766,48.98337149775796],
[1.6791915893554688,48.96849847697763],
[1.7185020446777344,48.995199140974066],
[1.6809940338134766,48.98337149775796]]
This is not working anymore.
As you can see here.
I used this website to generate the coordinates :
http://www.the-di-lab.com/polygon/ (view screenshot)
I searched for a long time what the issue could be, but I have really no idea. It's approximately the same coordinates. The first lat,lon values are the same than the last ones, for both of them.
If you have any idea (I guess there's something special in the coordinates), I would like to know !
Thanks !
Structurally, the coordinates of the triangle are correct. Only a geometrical difference the first triangle (the one functioning) is drawn in a clockwise direction while the latter is drawn counterclockwise. I have already met a situation like this but I do not remember which site. Then try to reverse the direction of drawing of the triangle in this way:
[[1.6809940338134766,48.98337149775796],
[1.7185020446777344,48.995199140974066]
[1.6791915893554688,48.96849847697763]
[1.6809940338134766,48.98337149775796]]

Exclude overlaid element from Google Maps viewport bounds

I am using Google Maps API v3 to create an inline map on a website. In its container element, I also have an absolute positioned overlay which shows some detail information, visually hovering over the map. Determining on context this element may grow up to the size of the entire map element.
All this is working fine, however the Maps instance of course still considers the overlaid part of the map a valid usable part of the map. This means that, especially if the overlay is at maximum height, setCenter doesn't focus on the visible center, and routes drawn with DirectionsRenderer are partially underneath the overlay.
See this image:
Is there a way to limit the actual viewport to the blueish area, so that setCenter centers on the arrow tip and setBounds fits to the blue part?
I have managed to implement an acceptably functional workaround for the time being.
Some general notes which are good to know:
Every Map object has a Projection, which can convert between LatLng points to map points.
The map points a Projection uses for calculation are in 'world' coordinates, meaning they are pixels on the world map at zoom level 0.
Every zoom level exactly doubles the number of pixels shown. This means that the number of pixels in a given map point equals 2 ^ zoom.
The samples below assume a 300px wide sidebar on the right - adapting to other borders should be easy.
Centering
Using this knowledge, it becomes trivial to write a custom function for off-center centering:
function setCenter(latlng)
{
var z = Math.pow(2, map.getZoom());
var pnt = map.getProjection().fromLatLngToPoint(latlng);
map.setCenter(map.getProjection().fromPointToLatLng(
new google.maps.Point(pnt.x + 150/z, pnt.y)));
}
The crucial bits here are the z variable, and the pnt.x + 150/z calculation in the final line. Because of the above assumptions, this moves the point to center on 150 pixels to the left for the current zoom level, and as such compensates for the missing 300 pixels on the right sidebar.
Bounding
The bounds issue is far less trivial. The reason for this is that to offset the points correctly, you need to know the zoom level. For recentering this doesn't change, but for fitting to previously unknown bounds it nearly always will. Since Google Maps uses unknown margins itself internally when fitting to bounds, there is no reliable way to predict the required zoom level.
Thus a possible solution is to invoke a two-step rocket. First off, call fitBounds with the entire map. This should make the bounds and zoom level at least nearly correct. Then right after that, do a second call to fitBounds corrected for the sidebar.
The following sample implementation should be called with a LatLngBounds object as parameter, or no parameters to default to the current bounds.
function setBounds(bnd, cb)
{
var prj = map.getProjection();
if(!bnd) bnd = map.getBounds();
var ne = prj.fromLatLngToPoint(bnd.getNorthEast()),
sw = prj.fromLatLngToPoint(bnd.getSouthWest());
if(cb) ne.x += (300 / Math.pow(2, map.getZoom()));
else google.maps.event.addListenerOnce(map,'bounds_changed',
function(){setBounds(bnd,1)});
map.fitBounds(new google.maps.LatLngBounds(
prj.fromPointToLatLng(sw), prj.fromPointToLatLng(ne)));
}
What we do here at first is get the actual points of the bounds, and since cb isn't set we install a once-only event on bounds_changed, which is then fired after the fitBounds is completed. This means that the function is automatically called a second time, after the zoom has been corrected. The second invocation, with cb=1, then offsets the box to correct for the 300 pixel wide sidebar.
In certain cases, this can lead to a slight off-animation, but in practice I've only seen this occur when really spamclicking on buttons causing a fit operation. It's running perfectly well otherwise.
Hope this helps someone :)
You can use the map panBy() method which allows you to change the center of the map by a given distance in pixels.
Hope this helps!
I had a similar need and ended up just forcing some "padding" to the east of a LatLngBounds object.
On the upside, it's simple and it works. On the downside it's not really versatile. Just a quick little hack.
// start with a standard LatLngBounds object, extending as you usually would...
bounds = new google.maps.LatLngBounds();
// ...
ne = bounds.getNorthEast();
sw = bounds.getSouthWest();
// the multiplier used to add space; positive for east, negative for west
lngPadding = 1.5
extendedLng = ne.lng() + (ne.lng() - sw.lng()) * lngPadding;
// copy original and extend with the new Lng
extendedBounds = bounds;
extendedBounds.extend(new google.maps.LatLng(ne.lat(), extendedLng));
map.fitBounds(extendedBounds);

Categories

Resources