I need to add markers on the map for the data that I have.
Out of the thought process, I went through map.data.loadGeoJson('google.json'); with which I will be able to have custom data attached to the map. Now, there is a requirement that I need to show properties of the features present in the map viewport. I cannot loop through all the items and check for .contains(), I have a huge data. Is there default google way to get the properties of the features present in the map viewport?
I like using TurfJS for tasks like these. I've tested it w/ 1M points and it works more quickly than one'd expect.
Pseudocode
load your GeoJSON once and initialize it as a turf feature collection
transform your map viewport's bounds into a GeoJSON polygon
run the pointsWithinPolygon function
pass the resulting feature collection onto the map data layer using addGeoJson
rinse & repeat within a throttled bounds_changed event
Actual Code
/*
You'd load your own geojson like so:
const points = turf.featureCollection(geojsonObject.features)
*/
// random 1M points as a demo
const points = turf.randomPoint(1e6, {
bbox: [-180, -90, 180, 90]
});
const {
west,
south,
east,
north
} = map.getBounds().toJSON();
// extent in minX, minY, maxX, maxY order
const viewport_as_polygon = turf.bboxPolygon([west, south, east, north])
const points_within = turf.pointsWithinPolygon(points, viewport_as_polygon)
Note: Since none of this interacts with the DOM until you call addGeoJSON, it's gonna be faster than for instance generating markers for each feature and then hiding/modifying the transparency of those that are outside of the viewport.
Related
Autodesk.AEC.Minimap3DExtension provides a 3d and 2d sync forge viewer where a user can use 2d viewer and move the avatar to navigate. In order to navigate user has to move the avatar or a dot icon in 2d viewer to navigate in 3d model.
My question is where is there any possibility where I can send the set of coordinates which are with me and can I move the avatar programmatically so that user don't have to do so.
here is any example why I am asking so,
I have a geometry on my forge viewer which is on 2D and I am looking to make a first person view over that geometry.
So If I have all the points of geometry I want to make it use with Autodesk.AEC.Minimap3DExtension so that I can move first person to different views
here is the sample I am rereferring to link
I had been following this wonderful blog link
with the help of this I am aware little bit aware how to work with 2dto3d
here in above link
const worldPos = sheetToWorld(intersection.intersectPoint, viewer2D.model,
viewer3D.model);
the above line of code gives me worldPos with which a geometric point is
created in the 3d viewer in spite of creating a geometry how can I use to
show view of that particular place
basically in this below line of code which transits camera from one position to another
viewer.navigation.setRequestTransition(true, newPos, newTarget,
viewer.navigation.getHorizontalFov());
I'm glad you like the blog post :)
After reading the question I have the impression that you have already answered it yourself. If you have some kind of a geometry, let's say a polyline, overlaid on top of the 2D drawing, you can use the same logic explained in the blog post, but when calling viewer.hitTest, instead of passing in some mouse coordinates, you would just supply one of the points of your polyline.
Instead of:
viewer2D.container.addEventListener('click', function (ev) {
const intersection = viewer2D.hitTest(ev.clientX, ev.clientY);
viewer3D.isolate([]);
if (intersection) {
viewer3D.isolate(intersection.dbId);
const worldPos = sheetToWorld(intersection.intersectPoint, viewer2D.model, viewer3D.model);
if (worldPos) {
let mesh = new THREE.Mesh(geometry, material);
mesh.position.set(worldPos.x, worldPos.y, worldPos.z);
viewer3D.overlays.addMesh(mesh, 'indicator-scene');
}
}
});
It could look something like this:
function moveCameraToPointOnSheet(x, y) {
const intersection = viewer2D.hitTest(x, y);
if (intersection) {
const worldPos = sheetToWorld(intersection.intersectPoint, viewer2D.model, viewer3D.model);
if (worldPos) {
const eyeVec = viewer3D.navigation.getEyeVector();
const newPos = worldPos;
const newTarget = newPos.clone().add(eyeVec);
const fov = viewer3D.navigation.getHorizontalFov();
viewer3D.navigation.setRequestTransition(true, newPos, newTarget, fov);
}
}
});
just looking for a way to control geojson layers by zoomlevel like minZoom , maxZoom for tileLayers, any ideas?
Descrition: geojson points layer, different classes of points, say Nation capitol, Province Capitol, Department, capitol, rest of simple towns.
Goal: at zoom level 4 display only Nation capitol (one only piont)
at zoom level 6 diplay all of 24 province capitols (you will only see a part of them)
at zoom level 8 display 524 departments capitols (you will only see a part of them)
at zoom level 10 display rest of towns, same idea.
thanks in advance.
JC
Check out Map events in the Leaflet Docs.
You can subscribe to the 'zoomend' event as well as 'zoomstart' and a few others
map.on('zoomend', function (e) {
myZoomHandler();
});
In your zoom handler function, loop over your layers and add or remove layers as needed.
function myZoomHandler() {
var currentZoom = map.getZoom();
switch (currentZoom) {
case 4:
//show Capitols
break;
case 6:
//show Provinces
break;
default:
// etc
break;
}
}
Leaflet has a viewereset event that is triggered when the map updates (on load, on zoom).
You can do something like:
map.on('viewreset', function() {
var zoom = this.getZoom();
// show/hide layers based on zoom level
}, map);
One way to show/hide layers is through L.GeoJSON's setStyle() method (use display or visibility properties).
I need to highlight a section of a street between two intersections. I have found a similar question which was asked more than a year ago (see here) which says that Google, Bing, etc. do not provide street data through their APIs. Does anyone know if anything has changed in the APIs, and whether I can get street location latitude/longitude data from somewhere now?
I have done this in API V2, but it should not be to difficult to rewrite it for V3.
Have a look at this website http://www.fvs.de/anfahrt.php (in German) and click the "Weg in Karte zeigen" buttons ("show way in map") in the sections below the map. Each button highlights another street line in the map.
It is basically done by using directions object of Google Maps to plot a route between two arbitrary street points in the map (e.g. your two intersections). The points must be encoded with their LatLng coordinates. Here is a code example (as said this is API V2):
function initMap() { // called by page onload event
if (GBrowserIsCompatible()) {
// Display the map, with some controls and set the initial location
gMap = new GMap2(document.getElementById("map_canvas"));
gMap.addControl(new GLargeMapControl());
// ...
gMap.setCenter(GLatLng(49.238326, 6.977761), 15);
// init directions object and attach listener to handle route loads from function highliteRoute()
gDir = new GDirections();
gPoly = null;
GEvent.addListener(gDir, 'load', function(){
gPoly = gDir.getPolyline();
gMap.addOverlay(gPoly);
// zoom & pan to poly
var polyBds = gPoly.getBounds();
var polyZoom = gMap.getBoundsZoomLevel(polyBds);
gMap.setZoom(polyZoom);
gMap.panTo(polyBds.getCenter());
});
}
}
function highliteRoute(){
if(gPoly!=null) gPoly.hide();
gDir.load('from: 49.313530,6.969109 to: 49.238326,6.977761', {getPolyline:true});
}
Dear all. I'm pretty new in coding with location, so be nice.
I have a list of location (lat & lng), that could be really anywhere (ie : all in the same city ; one in bangladesh and one in paris...).
When initializing google map, I would like to center on the barycentre on these location.
So this is my first question : How to calculate a barycentre with location object
Then, I would also like the initial map do display all the location (markers). So this is a problem of zoom, and is my second question : How to calculate the zoom in a google map so that all the markers on the map are displayed
I hope I've been clear. Also, take note that I was meaning barycentre with all points coefed to 1.
Best regards.
To zoom to include a set of results:
var locations = new google.maps.LatLngBounds();
...
function zoomToViewports(locations) {
var bounds = new google.maps.LatLngBounds();
for (var i in locations) {
bounds.union(locations[i].geometry.viewport);
}
map.fitBounds(bounds);
}
Having done that, the barycentre is in the middle of the screen, so if you actually need it's value it's easily calculated [(max(lat)-min(lat)/2,(max(lng)-min(lng)/2]
HTH?
You are welcome to lift the JS from this page on my website, which does what you describe
I've just begun using the Google Maps API (v3.0) and have had a good deal of success so far. I am loading a set of objects with Latitude & Longitude values from a database, passing them into my script, and looping over them in the script in order to add them to the map.
I am using the "bounds.extend() / map.fitBounds()" method of setting the map's zoom & bounds (see code below), which works as expected the first time around; however, if I clear out the existing markers, fetch another set of objects, and do the same thing on the same map instance, it sets the bounds incorrectly, usually resulting in a minimum zoom (an astronaut's view).
My suspicion is that my map object has some memory of the previous set of bounds that I've given it and that I need to find a way to clear these bounds before assigning my new ones, but I really can't be too sure.
Any help is greatly appreciated!
var locationList = [];
for (var i = 0; i < mapPoints.length; i++) { // mapPoints is a collection of DTOs
var mapPoint = mapPoints[i];
var location = new google.maps.LatLng(mapPoint.Latitude, mapPoint.Longitude);
locationList.push(location);
var marker = new google.maps.Marker({
map: map,
icon: '/Content/images/map/' + mapPoint.Status.Icon,
shadow: '/Content/images/map/shadow.png',
position: location
});
markers.push(marker); // markers is an Array that is managed outside this loop
}
var bounds = new google.maps.LatLngBounds();
for (var j = 0; j < locationList.length; j++)
bounds.extend(locationList[j]);
map.fitBounds(bounds);
This isn't the answer, so to speak, but a (slightly hacky) workaround that I discovered on a thread in the Google Maps Javascript API v3 group:
//map.fitBounds(bounds);
setTimeout( function() { map.fitBounds( bounds ); }, 1 );
if the above answer doesn't work for you (it didn't for me), the problem might lie in bootstrap (assuming you're using it). bootstrap modals specifically generate all sorts of wonky behaviour when i embed a map object in it.. curiously correcting itself if/when i drop an 'alert' in there.. in any case, i solved all my problems by just building my own modal (ie, not using bootstraps modals).