High-resolution maps using the HERE Maps API - here-api

How would I display a high-resolution map similar to the one at https://beta.here.com using the HERE Maps API for JavaScript?
From the API reference there is an option to change the pixelRatio when creating a map.
var map = new H.Map(
document.getElementById('map'),
defaultLayers.normal.map,
{ pixelRatio: 2 }
);
This works great and produces a high-resolution map on high-DPI screens, however, this changes the scale of the map and all map objects become small and text becomes difficult to read.

The PPI settings aren't documented very well in the JavaScript API reference, but is documented in the Map Tile API.
Pixels per inch. Resolution that can be requested, valid values are:
72 – normal, used by default if no value provided
250 – mobile
320 – hi-res
You can specify the PPI when creating a default layer (second option).
var defaultLayers = platform.createDefaultLayers(512, 320);
var map = new H.Map(
document.getElementById('map'),
defaultLayers.normal.map,
{ pixelRatio: 2 }
);

You can also ask the window:
var hidpi = ('devicePixelRatio' in window && devicePixelRatio > 1);
and create the default Layers like this:
var defaultLayers = platform.createDefaultLayers(hidpi ? 512 : 256, hidpi ? 320 : null);

For the benefit of anyone using the HereMap tiles without the Javascript API (such as through Leaflet), the crucial parameters are &ppi=250 (&ppi=72 for low-dpi) and /512/ instead of /256/ after the {z}/{x}/{y}.

Related

Geometry has too many edges (Google Earth Engine). Help me

I have problem during working in Google Earth Engine. I was processing some vector files. And i am getting below code:
The geometry has too many vertices. You can try to simplify it using:
// Get a feature collection and subset the first feature.
var feature = ee.FeatureCollection("TIGER/2018/States").first();
// Simplify the feature - think of max error as resolution.
// Setting to 100 means that the geometry is accurate to
// within 100 meters, for example.
var featureSimple = ee.Feature(feature).simplify({maxError: 100});
or for a ee.FeatureCollection:
// Get a feature collection.
var featureCol = ee.FeatureCollection("TIGER/2018/States");
// Simplify each feature in the collection, by mapping the
// .simplify() function over it.
var simplifiedCol = featureCol.map(function(feature) {
return feature.simplify({maxError: 100});
});

'item.geometry.location.kb' and 'item.geometry.location.jb' returning undefined

I'm using Google Maps to get an autocomplete list of cities.
I used to use item.geometry.location.kb as the longitude and item.geometry.location.jb as the latitude, but they are not defined since today/yesterday.
Apparently, one has to use item.geometry.location.lng() and .lat() instead.
I didn't know that and I have an app using item.geometry.location.kb and jb in Google Play and the App Store.
So my apps are not working any more.
Why has a change has been made and how can I revert to kb and jb?
autocomplete = new google.maps.places.Autocomplete(input, options);
google.maps.event.addListener(autocomplete, 'place_changed', function(event) {
var item = autocomplete.getPlace();
curLon = item.geometry.location.kb;
curLat = item.geometry.location.jb;
// ...
Don't use undocumented properties of the Google APIs. They can and do change with every release.
geometry.location is a google.maps.LatLng object, and the documented methods to get latitude and longitude are .lat() and .lng().

openlayers show half wms layer with googlemap v3 api

Hi I need to show some shapefiles over a map, for that I use geoserver, openlayers and google maps V3, it works as far I do not use OpenLayers.Layer.Google, I can see my shapefile.
This is my working code:
var map = new OpenLayers.Map('map');
var ghyb = new OpenLayers.Layer.Google(
"Google Hybrid",
{type: google.maps.MapTypeId.HYBRID, numZoomLevels: 30,srs:'EPSG:2077'}
// used to be {type: G_HYBRID_MAP, numZoomLevels: 20}
);
var wms = new OpenLayers.Layer.WMS( "Italy WMS",
"http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
var regioni_wms = new OpenLayers.Layer.WMS(
"comuni",
"http://localhost:8080/geoserver/wms",
{
layers: "prov2011_g" ,
transparent: "true",
format: "image/png",
srs:'EPSG:2077',
},
{isBaseLayer: false}
);
map.addLayer(regioni_wms);
//map.addLayer(ghyb);
map.addLayer(wms)
map.zoomToMaxExtent();
if I add the layer ghyb to the map, only half of my polygon is rendered and if zoom in it disappears.I do not know if is a problem of mercator nor how to fix it.
Google layers are only projected in EPSG 900913. If you try to use anything else it is doubtful it will work. The good news is that Geoserver will reproject your wms service on the fly to EPSG 9000913. I would suggest chaniging to this projection in both your layers and seeing if that makes a difference.
One thing to note about this is if you are trying to print your layers they will not be to scale along the x axis. Also if you are using a measuring tool on your website you will need to ensure it can operate in a geodesic fassion.

Render conditional templates with Twig

I've a layout template with a left sidebar where I show information of Location passed entities as an array.
Also in this template, I show a object Map with all of this locations.
I want to do click on a Location of my sidebar and then on the same template show another object Map replacing the previous with information of this Location. Keeping the sidebar with the information and not doing new queries on the database.
How to achieve this?
Ajax? Conditional layout?
I read this article but I don't understand how to solved my problem: http://twig.sensiolabs.org/doc/recipes.html#overriding-a-template-that-also-extends-itself
PD: I'm using Twig template and Symfony2
You could have a separate template for printing object map and, as you guessed, this would have to be done using AJAX. You would pass the data you want to show on map (not id as you don't want to query database again) and the controller would return formatted HTML.
However, this seems to me a bit overkill. I would always consider doing JS (with optional framework) in order to swap the content of sidebar with Map object.
It really depends on which map API do you use. If it could be controlled via JS I would look no further. It it could not, well then, AJAX is your natural choice....
UPDATE:
OK, what you should do is create initial Map object that will be modified later on:
var theMap = null;
function initializeMap(){
var mapOptions = {
center: new google.maps.LatLng(some_latitude, some_longitude),
zoom: 8, // goes from 0 to 18
mapTypeId: google.maps.MapTypeId.ROADMAP
};
theMap = new google.maps.Map(document.getElementById("map_canvas"),mapOptions);
// you must have some element with ID = 'map_canvas'
}
some_latitude and some_longitude are fairly unimportant as you will most likely set new coordinates in a few moments.
Now assuming (but not crucial at all) that you use some of the JS frameworks (I prefer jQuery) you could bind click event to those location links:
var onlyMarker = null;
$('.location').click(function(){
var $t = $(this);
var newLatLang = new google.maps.LatLng($t.attr('data-lat') ,$t.attr('data-lng'));
if ( onlyMarker == null ) {
onlyMarker = new google.maps.Marker({
position: newLatLang
map: theMap,
title: $t.attr('title')
});
}else{
onlyMarker.setPosition(newLatLang);
}
});
Now, relying on HTML5's 'data-*' attibutes is not good idea in particular as if you use any other version lower you will most likely end-up with invalid markup. The workaround is to for link (<a>) to carry id/key to LatLng object, for example:
// initially generated from `AJAX` or in `Twig` loop
var allLatlangs = [
new google.maps.LatLngf(some_latitude, some_longitude),
new google.maps.LatLngf(some_latitude, some_longitude),
new google.maps.LatLngf(some_latitude, some_longitude),
];
$('.location').click(function(){
var id = $(this).attr('id');
var newLatLang = allLatLang(id);
//....
// everything else is the same
// ....
});
Don't forget to include Maps API with proper API key:
https://maps.googleapis.com/maps/api/js?key=API_KEY_HERE&sensor=true
In order to obtain valid API key follow this link: API KEY HOW-TO
This link basically covers key steps that I have described here so study it and it should all come together nicely.
Also, if you're unsure how to retrieve some things from Maps you should consult reference:
REFERENCE which has every method call described pretty good
Remember not to execute any of this code until everything is being loaded.
Hope this helped a bit :)

Automatically Finding Appropriate Zoom for Geocoding Result

I'm using Google Maps and Google Geocoding service for my location service application. I use Google Geocoding service for translating address to lat/lng position. My problem is how to automatically find an appropriate zoom for a certain address like the maps.google.com does.
For example, when I search a street in maps.google.com (e.g. Cisitu Baru, Bandung), it will show the street in smaller zoom. When I search a region (e.g. Bandung), it will show larger zoom. And a larger zoom for province (e.g. Jawa Barat / West Java), and so on.
I have tried both
var geocoder = new google.maps.Geocoder();
geocoder.geocode( {
'address': someAddress
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
console.dir(results);
//cut
map.panToBounds(results[0].geometry.bounds); //setting bound
//cut
}
});
and
//cut
map.panToBounds(results[0].geometry.viewports); //setting bound
//cut
(Honestly, I still don't know what's the difference between bounds and viewport and what are their uses from code.google.com/apis/maps/documentation/javascript/geocoding.html)
but both still don't display the map in appropriate zoom.
Right now, I use a small hack like this
var tabZoom = {
street_address: 15,
route: 15,
sublocality: 14,
locality: 13,
country: 10
};
//cut
map.setCenter(results[0].geometry.location);
if (tabZoom[results[0].types[0]] != undefined){
map.setZoom(tabZoom[results[0].types[0]]);
} else {
map.zetZoom(10);
}
//cut
Is there other solution? (Or anything from Google Map API that I don't know yet?)
Thanks!
use GLatLngBounds class
an example:
// map: an instance of GMap2
// latlng: an array of instances of GLatLng
var latlngbounds = new GLatLngBounds( );
for ( var i = 0; i < latlng.length; i++ )
{
latlngbounds.extend( latlng[ i ] );
}
map.setCenter( latlngbounds.getCenter( ), map.getBoundsZoomLevel( latlngbounds ) );
^
The trick is to add the list of all points that need to be visible on the map simultaneously into a GLatLngBounds object. The Google Maps API can do the rest of the maths.
or in v3 you can use LatLngBounds class (similar to GLatLngBounds in v2), link: http://code.google.com/apis/maps/documentation/javascript/reference.html#LatLngBounds
for an example
better check this out: http://unicornless.com/code/google-maps-v3-auto-zoom-and-auto-center
use viewport of the result geometry. if your search result does not have specific bounds, you will get an error with geometry.bounds
viewport gives you best view for the result.
map.fitBounds(results[0].geometry.viewport);

Resources