icons must be visible at different view level - icons

I use openlayers3 to build an application
I would like to change the zoomlevel icons are visible at
https://bestofosm.org/?lon=4.0798&lat=50.9136&zoom=15#interesting-het-loo-garden
for example
if you go to London you see airports are visible at zoomlevel 10
lets say I want all touristic icons visible at zoomlevel 10
and airport icons at zoomlevel 15
is this possible?

The most simple solution is to put your markers in different layers and give each layer a minResolution and maxResolution. When the map zooms outside these resolutions the layers will automatically become hidden. Something like:
var touristicIcons = new ol.layer.Vector({
source: touristicIconsSource,
minResolution: xx
maxResolution: xx
});
// Repeat for airports layer, with different resolutions
Writing down a zoom level as a resolution will not work. You will need to find out what resolution belongs to your desired zoom level. The easiest way to do this is with this little hack, that logs the zoom level and resolution every time you scroll through the map:
map.getView().on('change:resolution', function (event) {
var view = event.currentTarget;
console.log('Zoom: ' + view.getZoom() +
', resolution: ' + view.getResolution());
});

Related

How can I learn pixels band values from image in screen of Earth Engine?

I want to learn pixels band values, for example when I clik on mNDWI image in screen of Earth Engine, I need learning values of red, green and blue
var geometry=ee.Geometry.Polygon([[38.877002459052335,40.75574968156597],
[41.206104021552335,41.17882292442983],
[40.645801287177335,41.59918091806734],
[40.052539568427335,41.84517989453356],
[39.569141130927335,41.886088143011904],
[38.800098162177335,41.48405920501165],
[38.877002459052335,40.75574968156597],
]);
var s2SR = ee.ImageCollection('COPERNICUS/S2_SR')
//filter start and end date
.filter(ee.Filter.calendarRange(2020,2020,'year'))
.filter(ee.Filter.calendarRange(8,8,'month'))
//filter according to drawn boundary
.filterBounds(geometry)
.filterMetadata('CLOUD_COVERAGE_ASSESSMENT', 'less_than',10);
//Map.addLayer(s2SR, {bands:['B4', 'B3', 'B2'], min:0, max:8000}, 's2SR');
// adding mNDWI function
var addMNDWI = function(image) {
var mndwi = ee.Image(image).normalizedDifference(['B3', 'B11']).rename('MNDWI');
return ee.Image(image).addBands(mndwi);
};
var mndwı=s2SR
.map(addMNDWI);
Map.addLayer(mndwı.first(), { min:245, max:5000}, 'mndwı');
It is simple to view the values for any displayed image. First, click on the “Inspector” tab in the top right pane of the Earth Engine Code Editor.
Then, click wherever you want on the map. The Inspector tab will display:
The coordinates of the location you clicked.
The values of every band of every image under that point. (When there are many, as a chart.)
The details of the image (or feature), including properties.

Google Earth Plugin - Restricted Extent or Box

In OpenLayers 2D maps there's a property called restricted extent that doesn't allow to pan or zoom outside a defined bounding box.
Can I make something similar with Google Earth Plugin in 3D?
Obviously the problem is that one can bend (incline) the view, something that cant be achieved in 2D.
I have already restricted the view if thers no bend or incline in the map but that's far from being what I want..
Thanks!!
Update 1:
By now I have restricted the bbox with a handler on viewchangeend event, if the actual viewport (north, south, east, west) is outside some predefined initial values I move the view to the initial position again.
var viewchangeend = function viewchangeendhandler(){
var actualViewport = {
north: ge.getView().getViewportGlobeBounds().getNorth(),
south: ge.getView().getViewportGlobeBounds().getSouth(),
east: ge.getView().getViewportGlobeBounds().getEast(),
west: ge.getView().getViewportGlobeBounds().getWest()
};
if (actualViewport.north > initialViewport.north || actualViewport.south < initialViewport.south ||
actualViewport.east > initialViewport.east || actualViewport.west < initialViewport.west){
var la = ge.createLookAt('');
la.set(initialX, initialY, 0, ge.ALTITUDE_RELATIVE_TO_GROUND, 0 , 0, 50000);
ge.getView().setAbstractView(la);
}
}
For example in the initial case where I dont incline the view the relation north-south (north minus south) is static, but when I incline the view the relation grows and the initial viewport cannot be used to know if the actual viewport is ok.
Thanks again!
Perhaps you should consider using hitTest() instead of getViewportGlobeBounds()
See this SO Question which links to this Google Example
Have a play with the Google Example by tilting the view and see the resulting difference between the two

Removing X-axis tiling of google maps

In a given instance of google maps...
Is there a way to turn off the other instances of the maps which tile to the right and left of the initial central map?
I've seen ways to restrict the pan ability of the map ... but it uses lat + lng to determine when to re-center the map ... and thus the usage falls apart at different zoom levels.
For example: https://google-developers.appspot.com/maps/documentation/javascript/examples/map-simple
If on zooms all the way out, you can see how the map of the globe is tiled along the x-axis.
I would like a single instance of the map.
You could add an observer to the zoom_changed event, and set the minZoom if more than 90 degrees of map is shown. The second statement recursively reduces the zoom to an acceptable limit before the limit is known.
var zoomObserver = function () {
width = Math.abs(map.getBounds().getNorthEast().lat() -
map.getBounds().getSouthWest().lat());
if (width > 90){
var opt = { minZoom: map.getZoom()};
map.setOptions(opt);
}
if (width > 179){
map.setZoom(map.getZoom() + 1);
}
};
google.maps.event.addListener(map,'zoom_changed', zoomObserver );
This simple solution works for most use cases, doesn't take into account doubling the width of the map through resizing the browser window, so you may need to add the observer to another event in that case.

Flex scrolling more than 10.000 pixels

The Flex Canvas container is limited to 10,000x10,000 pixels. Yet, I've seen Flex apps that are scrolling way more than 10,000 pixels. Any idea how this can be done?
The content I want to scroll is in pieces already, but I need to add those pieces to something that can scroll vertically more than 10,000 pixels.
Depending on what you actually want to display you may be able to split your content into tiles. This is how Google Maps works, every time the map is moved the program determines which tiles are visible on the screen and loads them in. Any markers or overlays that are on the map are notified that the map has moved and determine where their new location is. If their location is off the screen they can be removed from the canvas. For example, the width of all the tiles at zoom level 20 on Google Maps is (256 pixels * 2^20) which equals 268,435,456 total pixels.
Essentially you just need to create a special Sprite that keeps track of the actual x,y location it is supposed to be positioned at. Any time the container moves you simply iterate through all of the child objects and determine where to put them.
function onCanvasScroll() {
//determine the top left coordinates of the canvas
//you will figure out how to do this depending on how the scrolling window
//is implemented
var canvas_scroll_x;
var canvas_scroll_y;
//create a bounding box for the canvas
var view_bounds = new Rectangle(canvas_scroll_x, canvas_scroll_y, canvas.width, canvas.height);
for (child in canvas) {
var x = child.actual_x - view_bounds.x;
var y = child.actual_y - view_bounds.y;
var childBounds = new Rectangle(x, y, child.width, child.height);
//determine if the component is visible on screen
if (view_bounds.intersects(child_bounds)) {
child.visible = true;
child.x = x;
child.y = y;
}
else {
child.visible = false;
}
}
}
So if you have a canvas that is positioned at (100, 20000), a sprite that is positioned at (300, 20100), and a window that is (640,408), you would place it at (200, 100) and it would be visible on the screen.
Instead of just setting visible to true or false a better approach would be to remove the items from the canvas entirely when they are not within the bounds of the view.

Resize markers depending on zoom Google maps v3

I have a Google map running on the v3 API, I added some custom markers, is it possible to make them scale depending on the zoom level of the map?
I tried searching the reference but can't seem to find any methods to resize a MarkerImage.
Maybe I have to remove markers everything the map changes zoom and create new markers in a different size?
This code will resize every time the map is zoomed so it always covers the same geographic area.
//create a marker image with the path to your graphic and the size of your graphic
var markerImage = new google.maps.MarkerImage(
'myIcon.png',
new google.maps.Size(8,8), //size
null, //origin
null, //anchor
new google.maps.Size(8,8) //scale
);
var marker = new google.maps.Marker({
position: new google.maps.LatLng(38, -98),
map: map,
icon: markerImage //set the markers icon to the MarkerImage
});
//when the map zoom changes, resize the icon based on the zoom level so the marker covers the same geographic area
google.maps.event.addListener(map, 'zoom_changed', function() {
var pixelSizeAtZoom0 = 8; //the size of the icon at zoom level 0
var maxPixelSize = 350; //restricts the maximum size of the icon, otherwise the browser will choke at higher zoom levels trying to scale an image to millions of pixels
var zoom = map.getZoom();
var relativePixelSize = Math.round(pixelSizeAtZoom0*Math.pow(2,zoom)); // use 2 to the power of current zoom to calculate relative pixel size. Base of exponent is 2 because relative size should double every time you zoom in
if(relativePixelSize > maxPixelSize) //restrict the maximum size of the icon
relativePixelSize = maxPixelSize;
//change the size of the icon
marker.setIcon(
new google.maps.MarkerImage(
marker.getIcon().url, //marker's same icon graphic
null,//size
null,//origin
null, //anchor
new google.maps.Size(relativePixelSize, relativePixelSize) //changes the scale
)
);
});
Unfortunately, you would have to setIcon every single time. However, you can pre-define them, and then just apply them to the marker.
zoomIcons = [null, icon1, icon2]; // No such thing as zoom level 0. A global variable or define within object.
marker.setIcon(zoomIcons[map.getZoom()]);
To add to the map an image that follows the zoom level, use a GroundOverlay.
https://developers.google.com/maps/documentation/javascript/groundoverlays

Resources