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
Related
Is there any way to keep the map labels with street names and POIs under GMSOverlays like GMSPolygons and GMSPolylines?
I have tried with different Zindex but to no vail.
This is what I get:
But as the polygon is the important thing here, I don't want the map labels on top of it, because they are, in my case, irrelevant. Besides I use a semitransparent fill color and you can still see the street names through it.
Answering my own question:
The only way I found was to add a Tile layer on top of the mapView like this:
mapView.mapType = .none // Set the map type to .none, as it will not be visible
let urls: GMSTileURLConstructor = { (x, y, zoom) in
let url = "https://mt1.google.com/vt/lyrs=r&x=\(x)&y=\(y)&z=\(zoom)&scale=2"
return URL(string: url)
}
let layer = GMSURLTileLayer(urlConstructor: urls)
layer.tileSize = 1024 // To get bigger fonts in mobile device with high resollution
layer.map = mapView
The only drawback is that when the map is rotated the labels are rotated too as you can see in this screenshot:
I have the following code for the laser controls which are perfectly positioned when the camera looks straight ahead after entering VR mode.
<a-entity position="0.25 1.25 -0.2" class="laser-controls">
<a-entity laser-controls="hand: right" line="color: red"></a-entity></a-entity>
The issue is: when I rotate my head (camera), I would like to let the controls follow my head rotation smoothly (I have some code which looks if the rotation is greater than 110 degrees). I don't want the controllers be part of the camera since they should keep their own independent rotation. What I like is the behaviour of the controller model in Oculus Home (Gear VR).
How can I achieve this is my custom component, let's say in my tick function, which is called every two seconds (that code works already).
Thanks!
How about using getAttribute() to check the rotation of the camera component and the laser control's entity? Then you could check if the difference exceeds 110 degrees or not:
let angle = laser.getAttribute('rotation');
if (camera.getAttribute('rotation').y - laser.getAttribute('rotation').y>110){
angle.y++;
laser.setAttribute('rotation',angle);
} else if(camera.getAttribute('rotation').y - laser.getAttribute('rotation').y<-110){
angle.y--;
laser.setAttribute('rotation',angle);
}
UPDATE
If You want to position Your controller near Your head You can:
1.Instead of angle.y++/-- change it to Your camera's rotation. You can also change its x/y position close to the camera ( like camera.position.x + 0.5 )
2.But the above is instant, if You want to make it smooth, You could use the animation component, when the delta degree is >110 deg, set the animation attributes to move to the camera component location/rotation, emit a beginning event, disable the rotation check, listen for the animation end event, and enable the check. a bit like this:
init: function(){
this.check = true;
let check = this.check;
animationel.addEventListener('animationend',function(){
check = true;
});
},tick(){
if(this.check){
if(rotationCheck()){
this.check = false;
}
}
}
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());
});
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.
I've got an issue that I simply can't figure out; probably because I don't have the correct knowledge.
I have a TMX map made in Tiled. The Map is bigger than the screen size (tiles are 32x32pixels and there are 100x100 tiles).
What I want to do is to be able to move the map by swiping the screen.
I've looked at various tutorials online and examined the paddle.m example but still can't get it to work.
All the tutorials I've come across all focus on moving a clamped centered sprite around a map...
Again, what I want to do is to be able to move the map by swiping/sliding the screen; much like when scrolling through your iPod or moving a picture around.
Can anyone help?
Here is my ccTouchMoved code
-(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchPointMap = [touch locationInView: [touch view]];
touchPointMap = [[CCDirector sharedDirector] convertToGL: touchPointMap];
touchPointMap = [self convertToNodeSpace: touchPointMap];
CCLOG(#"Touch Point Map %lf, %lf", touchPointMap.x, touchPointMap.y);
self.position = CGPointMake(touchPointMap.x, touchPointMap.y);
}
To illustrate the problem I'm seeing on screen when I swipe the screen using the code above:
It seems that if I touch the center of the screen, the bottom left corner of the map will jump to that touched coordinate and will move with my touch until my touch is lifted.
The Map's bottom left corner will always move to where I begin my touch.
Also while the map is being moved, it flashes like crazy and if moved excessively, disappears entirely.
Thanks again All, much appreciated.
Best and Kind Regards,
hiro
I found the solution to the problem.
There's a very bright person in the Cocos2D community who has written a controller to not only pan around organically, but zoom in and out.
Link to Controller, example and preview movie
You wont need to write your touchBegan, Moved and End methods; this Controller does it all for you.
My init
self.theMap = [CCTMXTiledMap tiledMapWithTMXFile: #"city_map.tmx"];
self.bgLayer = [theMap layerNamed:#"bg"];
// boundingRect is the area you wish to pan around
CGRect boundingRect = CGRectMake(0, 0, 32*50, 16*50);
theMap.anchorPoint = ccp(0,0);
[self addChild: theMap z: -1];
// _controller is declared in the #interface as an object of CCPanZoomController
_controller = [[CCPanZoomController controllerWithNode:self] retain];
_controller.boundingRect = boundingRect;
_controller.zoomOutLimit = _controller.optimalZoomOutLimit;
_controller.zoomInLimit = 2.0f;
[_controller enableWithTouchPriority:0 swallowsTouches:YES];