How to transform MapTile image to to view - openlayers-3

I've created a tile set of an image using MapTiler. MapTiler generates a OL 2 script that centers the tiled image in the viewing window with the following code:
var map, layer;
var mapBounds = new OpenLayers.Bounds(0.000000, -9350.000000, 14450.000000, 0.000000);
var mapMinZoom = 0;
var mapMaxZoom = 6;
var mapMaxResolution = 1.000000;
var gridBounds = new OpenLayers.Bounds(0.000000, -9350.000000, 14450.000000, 0.000000);
function init() {
var options = {
controls: [],
maxExtent : gridBounds,
minResolution: mapMaxResolution,
numZoomLevels: mapMaxZoom+1
};
map = new OpenLayers.Map('map', options);
layer = new OpenLayers.Layer.XYZ( "MapTiler layer", "${z}/${x}/${y}.png", {
transitionEffect: 'resize',
tileSize: new OpenLayers.Size(256, 256),
tileOrigin: new OpenLayers.LonLat(gridBounds.left, gridBounds.top)
});
map.addLayer(layer);
map.zoomToExtent(mapBounds);
I want to use OL3 to display the tiled map but do not know how to implement equivalent OL3 methods to achieve this. Using the following script I can display the tiled image but I cannot figure out how to center the tiles to in the view.
map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM({
url: map_path + '{z}/{x}/{y}.png'
})
})
],
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
I've inspected the map extent which turns out to be:
-20037508.342789244,-20037508.342789244,20037508.342789244,20037508.342789244
My tiled image extent is given in the OL2 code, but I don't known how to use this information in OL3. I think it might have something to do with a transformation or fitExtent but without further direction, it seems I'm just guessing at what to do.

You will have to create a pixel projection for this to work properly. Then you can use fit (replacement for the former fitExtent), as you already suspected, to zoom to the full extent of the image.
The whole OpenLayers 2 code translated to OpenLayers 3 would look like this:
var mapBounds = [0.000000, -9350.000000, 14450.000000, 0.000000];
var mapMaxZoom = 6;
var gridBounds = [0.000000, -9350.000000, 14450.000000, 0.000000];
var projection = new ol.proj.Projection({
code: 'pixels',
units: 'pixels',
extent: gridBounds
});
var map = new ol.Map({
target: 'map',
view: new ol.View({
extent: mapBounds,
projection: projection
})
});
var layer = new ol.layer.Tile({
source: new ol.source.XYZ({
url: '{z}/{x}/{y}.png',
projection: projection,
maxZoom: mapMaxZoom
})
});
map.addLayer(layer);
map.getView().fit(mapBounds, map.getSize());

Related

update position of geolocation marker in Openlayers 3

I wan't to have a marker on the map, which position is dynamically updated.
When I create the layer inside the function of the geolocation.on('change'-event it works, but the layer is added each time the geolocation changes. Therefore I wanted to create the layer outside that function and update only the position of the marker.
With the folowing code I get an 'TypeError: a is null'
var geolocation = new ol.Geolocation({
projection: map.getView().getProjection(),
tracking: true,
trackingOptions: {
enableHighAccuracy: true,
maximumAge: 2000
}
});
var iconStyle = new ol.style.Style({
image: new ol.style.Icon({
anchor: [0.5, 46],
anchorXUnits: 'fraction',
anchorYUnits: 'pixels',
opacity: 0.75,
src: './_img/marker_.png'
})
});
var pos1 = geolocation.getPosition();
var iconFeature = new ol.Feature({
geometry: new ol.geom.Point(pos1)
});
var iconSource = new ol.source.Vector({
features: [iconFeature]
});
var iconLayer = new ol.layer.Vector({
source: iconSource,
style : iconStyle
});
map.addLayer(iconLayer);
geolocation.on('change', function() {
var pos_upd = geolocation.getPosition();
iconFeature.getGeometry().setCoordinates(pos_upd);
view.setCenter(pos_upd);
view.setZoom(18);
});
The browser Geolocation API, which is wrapped by ol.Geolocation, is asynchronous. After initiation, geolocation.getPosition() will always return undefined until the first change event.
The proper thing to do is to add the feature once you get a coordinate, in the change event handler.
You will need to use a conditional to determine if you should add ore update a feature.
I changed the code a bit, so that I created first an iconFeature, that wasn't already bound to a ol.geom.Point()-position. By this way there was no need to use geolocation.getPosition().
Later in the geolocation.on('change')-event I assigned the actual position to the geometry of the iconFeature.
Works like espected
// add an empty iconFeature to the source of the layer
var iconFeature = new ol.Feature();
var iconSource = new ol.source.Vector({
features: [iconFeature]
});
var iconLayer = new ol.layer.Vector({
source: iconSource,
style : iconStyle
});
map.addLayer(iconLayer);
// Update the position of the marker dynamically and zoom to position
geolocation.on('change', function() {
var pos = geolocation.getPosition();
iconFeature.setGeometry(new ol.geom.Point(pos));
view.setCenter(pos);
view.setZoom(18);
});

OL3 offline mapping

I have problem how to coonnect a offline tileLayer in ol3.
This ismy code:
var tileLayer = new ol.source.XYZ("offline",
"Tiles/${x}/${y}/${z}.png", { numZoomLevels: 18, isBaseLayer: true });
It was work fine in ol2 with OpenLayers.Layer.OSM
I spend some time looking for help, but I found a wall.
First you define a tile layer (ol.layer.Tile) and inside this you define the source.
var map = new ol.Map({
target: 'map',
view: new ol.View({
zoom: 1,
center: [0, 0]
}),
layers: [
new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'Tiles/{x}/{y}/{z}.png',
maxZoom: 18
})
})
]
});
Edited the url of the ol.source.XYZ object, moved out the $ chars. Maybe now your tiles will load.

setCenter always ends near southpole

I'm new at OpenLayers3 and trying to build a simple form that centers my map to a given spot. The problem is that i'm always landing somwhere near the south-pole. here is my code:
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM
})
],
view: new ol.View({
center: [0,0],
zoom: 8
})
search.addEventListener("change", searchChanged);
function searchChanged()
{
var searchVal = encodeURIComponent(search.value);
var geocode = 'http://open.mapquestapi.com/nominatim/v1/search.php?key=KEY&format=json&q=' + searchVal;
$.getJSON(geocode, function(data)
{
if(!data)
{
return;
}
map.getView().setCenter(ol.proj.transform([data[0].lon, data[0].lat], 'EPSG:4326', 'EPSG:3857'));
}
);
}
Make sure your coordinate will not be treated as string:
ol.proj.transform([parseFloat(data[0].lon), parseFloat(data[0].lat]), 'EPSG:4326', 'EPSG:3857')
Better, debug it:
var coord = ol.proj.transform([parseFloat(data[0].lon), parseFloat(data[0].lat]), 'EPSG:4326', 'EPSG:3857');
console.info(coord);

How do I dynamically load GeoJSON data, based on the map extent, into my OpenLayers 3.5.0 map layer?

I am migrating from OpenLayers 3.2.0 to 3.5.0 and am having trouble loading my GeoJSON data into my vector layer. I have it working, but I'm transforming the geometry of the features from my GeoJSON data source before I add them to my vector source.
Is there a way to make OpenLayers 3.5.0 apply the transformation automatically?
The data from my GeoJSON data source uses the EPSG:4326, I believe that I need to re-project the geometries to EPSG:3857 in order to display them on my map. The GeoJSON data source has the projection information in it's crs attribute and my vector source also has it's projection set. Still, the feature geometries are not transformed on their own.
I need to pass the bounds of the viewable map area via the URL to my GeoJSON data source, I do not want to load all of the data at once. I have a loader function on my vector source that gets the current map extent and builds the URL for the request.
Sample Data from my GeoJSON source is available, it validates through a linter and I believe it to be reasonable.
Below is the current code that I am using.
var vectorFormat = new ol.format.GeoJSON();
var featureStyle = new ol.style.Style({
image: new ol.style.Circle({
radius: 5,
fill: new ol.style.Fill(
{color: 'rgba(255, 69, 0, 0.75)'}),
stroke: new ol.style.Stroke(
{color: 'rgba(255, 0, 0, 0.95)', width: 1})
})
});
var vectorSource = new ol.source.Vector({
projection: new ol.proj.Projection({'code':'EPSG:3857'}),
strategy: ol.loadingstrategy.bbox,
loader: function(extent, resolution, projection) {
var coordinate1 = ol.proj.transform([extent[0], extent[1]],
'ESPG:3857', 'EPSG:4326')
var coordinate2 = ol.proj.transform([extent[2], extent[3]],
'ESPG:3857', 'EPSG:4326')
var url = 'api/sites/geo/bounds/4326/' + coordinate1[1]
+ ',' + coordinate1[0] + '/' + coordinate2[1] + ','
+ coordinate2[0] + "/";
$.ajax({
url: url,
dataType: 'json'
}).then(function(response) {
var features = vectorFormat.readFeatures(response);
var transformFn = ol.proj.getTransform(
response.crs.properties.name, projection);
for(index in features) {
var feature = features[index];
feature.getGeometry().applyTransform(transformFn);
}
vectorSource.addFeatures(features);
});
}
});
this.state.map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
new ol.layer.Vector({
source: vectorSource,
style: featureStyle
})
],
view: new ol.View({
center: this.transformToOl(this.state.center),
zoom: this.state.zoom
})
});
Any help or pointers in the right direction would be greatly appreciated. :-D
Yes, OpenLayers can do the reprojection for you. You don't even have to set the projection on the source. The geometries will be automatically reprojected to the view projection.
var vectorSource = new ol.source.Vector({
url: 'file.json',
format: new ol.format.GeoJSON()
});
http://jsfiddle.net/h9zwjf88/
Update
In case you want to you use a custom loader, you can specify the target projection when parsing the features (see also ol.format.GeoJSON.html#readFeatures):
var vectorSource = new ol.source.Vector({
strategy: ol.loadingstrategy.bbox,
loader: function(extent, resolution, projection) {
$.ajax(url).then(function(response) {
var features = format.readFeatures(response,
{featureProjection: 'EPSG:3857'});
vectorSource.addFeatures(features);
});
}
});
http://jsfiddle.net/h9zwjf88/1/

Load local zoomify tileset in OL3

I produced a zoomify tileset from some digitized map image and would now like to use OL3 to display that map on a Website. However, my script currently fails loading that map from a local file uri (later, in production, I will upload the tiles on some Web Server and reference the tiles using HTTP). Here is what I have so far:
var url = 'file:///home/user/map_zoomfiy/';
var imgWidth = 17244;
var imgHeight = 9684;
var imgCenter = [imgWidth / 2, - imgHeight / 2];
var proj = new ol.proj.Projection({
code: 'ZOOMIFY',
units: 'pixels',
extend: [0, 0, imgWidth, imgHeight]
});
var source = new ol.source.Zoomify({
url: url,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous'
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: source
})
],
view: new ol.View({
projection: proj,
center: imgCenter,
zoom: 1
})
});
</script>
Any ideas why this fails? Thx.
It's not right way e.g https://developer.mozilla.org/en-US/docs/WebGuide/API/File_System/Introduction#file
I don't see why you do not make a local server instead of fighting to access your file with local url.
Some times ago, I compiled some recipes to do so.
Open your command line, go to your code root dir and follow recipes depending of your favorite programming language.
If the tiles are in a subdirectory (e.g., tiles_zoomify) the following should work
var url = 'tiles_zoomify/';
var imgWidth = 17244;
var imgHeight = 9684;
var imgCenter = [imgWidth / 2, - imgHeight / 2];
var proj = new ol.proj.Projection({
code: 'ZOOMIFY',
units: 'pixels',
extend: [0, 0, imgWidth, imgHeight]
});
var source = new ol.source.Zoomify({
url: url,
size: [imgWidth, imgHeight],
crossOrigin: 'anonymous'
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: source
})
],
view: new ol.View({
projection: proj,
center: imgCenter,
zoom: 1
})
});

Resources