I serve TMS tile with in two flavours: 256px or 384px through renderd option scale=1.5.
With Openlayers 3, the only way I found to display these 384px tiles their original size is to transform the canvas context like this:
map.getViewport().getElementsByTagName('canvas')[0].getContext("2d").setTransform(1.5, 0, 0, 1.5, -w, -h);
I think it's not the proper way to go, so what would be the right one?
I played a bit with a special ol.tilegrid but with no success, see here:
https://jsfiddle.net/yvecai/owwc5bo8/8/
The output I aim for is on the right map.
There is no need to create a special tile grid or to apply any canvas scaling. All you need to do is set the tilePixelRatio of the source properly, which would be 1.5 in your case:
source: new ol.source.XYZ({
url: "http://www5.opensnowmap.org/base_snow_map_high_dpi/{z}/{x}/{y}.png?debug",
attributions: [/* ... */],
tilePixelRatio: 1.5
})
Also note that your expectation of the result is wrong. I updated your fiddle to compare the standard 256px tiles (on the right) with the hidpi 384px tiles (on the left). If you are viewing the fiddle on a hidpi display, you'll notice the difference. https://jsfiddle.net/owwc5bo8/9/
To summarize:
If you want to display high-dpi tiles on a mobile device with good sharpness, use tilePixelRatio :
https://jsfiddle.net/owwc5bo8/9/
If you want to display tiles with a size differnet than 256x256, create a proper ol.tilegrid, and a proper ol.view:
https://jsfiddle.net/owwc5bo8/12/
var extent = ol.proj.get('EPSG:3857').getExtent();
var tileSizePixels = 384;
var tileSizeMtrs = ol.extent.getWidth(extent) / 384;
var resolutions = [];
for (var i = -1; i <= 20; i++) {
resolutions[i] = tileSizeMtrs / (Math.pow(2, i));
}
var tileGrid = new ol.tilegrid.TileGrid({
extent: extent,
resolutions: resolutions,
tileSize: [384, 384]
});
var center = ol.proj.fromLonLat(
ol.proj.toLonLat([2, 49], 'EPSG:4326'),
'EPSG:3857');
var zoom = 5;
var view1 = new ol.View({
center: center,
zoom: zoom,
maxResolution: 40075016.68557849 / 384
});
I'm drawing a Circle using ol.interaction.Draw.
this.draw = new ol.interaction.Draw({
source: this.vectorSource,
type: 'Circle'
});
this.draw.on('drawend', function( evt ){
// evt.feature have no geometry !!!
}
But How can I get the Circle geometry or anything that tell me how to draw same circle again?
OL3.0 you can create/edit Features, but not Circles... http://openlayers.org/en/v3.0.0/examples/draw-and-modify-features.html
OL3.5 you can create circles, but you can't edit .... http://openlayers.org/en/v3.5.0/examples/draw-features.html
OL_Latest you can't edit circles too: http://openlayers.org/en/latest/examples/draw-and-modify-features.html
I would be happy if I could reproduce the same circle later.
To get the center and radius of the circle feature drawn use the below code
this.draw.on('drawend', function( evt ){
var geometry = evt.feature.getGeometry();
var radius = geometry.getRadius();
var center = geometry.getCenter();
// .... your code
});
Since a circle is drawn the Geometry type would be of type ol.geom.Circle.
Using this Geometry object you can get the radius and center using getRadius() and getCenter() method. For more information about ol.geom.Circle go through this link.
http://openlayers.org/en/latest/apidoc/ol.geom.Circle.html
Almost there!
I'm now able to reproduce the "circle" by adding a geometry function to the draw intaraction.
var geometryFunction = ol.interaction.Draw.createRegularPolygon(90);
this.draw = new ol.interaction.Draw({
source: this.vectorSource,
type: 'Circle',
geometryFunction: geometryFunction,
});
this will generate geometries to the feature so I can store it and load it again later, but it is not a real circle, it is just composed by a 90 points polygon. so I can't edit it as a circle.
Some idea to get the radius of this geometry?
{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-4804935.286197088,-2605909.2147242804],[-4804836.58537814,-2605831.0293000625],[-4804743.578928918,-2605746.149310523],[-4804656.719967494,-2605654.988282439],[-4804576.431661996,-2605557.9903431754],[-4804503.105168979,-2605455.6280569425],[-4804437.097727745,-2605348.4001225093],[-4804378.730919913,-2605236.8289435934],[-4804328.289102704,-2605121.458083764],[-4804286.018023582,-2605002.849618253],[-4804252.123622994,-2604881.581395582],[-4804226.771031053,-2604758.244222341],[-4804210.083763039,-2604633.4389848416],[-4804202.143117644,-2604507.773721655],[-4804202.987780893,-2604381.8606613115],[-4804212.613637674,-2604256.3132395847],[-4804230.973791778,-2604131.7431108924],[-4804257.978794381,-2604008.757168381],[-4804293.497079825,-2603887.954587199],[-4804337.355606593,-2603769.923905379],[-4804389.340700352,-2603655.2401565393],[-4804449.199094949,-2603544.462068375],[-4804516.639166305,-2603438.1293405974],[-4804591.332353169,-2603336.7600155673],[-4804672.914757844,-2603240.8479544464],[-4804760.988919055,-2603150.860431155],[-4804855.125748342,-2603067.2358558625],[-4804954.866620535,-2602990.3816390927],[-4805059.72560813,-2602920.672206864],[-4805169.19184868,-2602858.4471765244],[-4805282.732033666,-2602804.009702166],[-4805399.793006718,-2602757.6249976917],[-4805519.804458544,-2602719.5190447196],[-4805642.1817054115,-2602689.8774916218],[-4805766.328537677,-2602668.8447490656],[-4805891.640124453,-2602656.5232864586],[-4806017.505960285,-2602652.973132728],[-4806143.312839472,-2602658.211583866],[-4806268.447843544,-2602672.213118665],[-4806392.301327342,-2602694.909523055],[-4806514.269889141,-2602726.1902224356],[-4806633.759310369,-2602765.902820383],[-4806750.187450577,-2602813.8538411125],[-4806862.987083566,-2602869.809672071],[-4806971.608660867,-2602933.4977020747],[-4807075.522989073,-2603004.607649443],[-4807174.22380802,-2603082.793073661],[-4807267.230257243,-2603167.6730632004],[-4807354.089218667,-2603258.834091285],[-4807434.3775241645,-2603355.8320305482],[-4807507.704017182,-2603458.194316781],[-4807573.711458416,-2603565.4222512143],[-4807632.078266247,-2603676.99343013],[-4807682.520083456,-2603792.3642899594],[-4807724.791162578,-2603910.972755471],[-4807758.685563167,-2604032.240978142],[-4807784.038155108,-2604155.5781513825],[-4807800.725423122,-2604280.383388882],[-4807808.666068517,-2604406.0486520687],[-4807807.821405267,-2604531.961712412],[-4807798.195548487,-2604657.509134139],[-4807779.8353943825,-2604782.0792628312],[-4807752.83039178,-2604905.0652053426],[-4807717.312106336,-2605025.867786525],[-4807673.453579567,-2605143.8984683445],[-4807621.468485809,-2605258.5822171844],[-4807561.610091211,-2605369.3603053484],[-4807494.170019856,-2605475.693033126],[-4807419.4768329915,-2605577.0623581563],[-4807337.8944283165,-2605672.974419277],[-4807249.8202671055,-2605762.9619425684],[-4807155.683437819,-2605846.586517861],[-4807055.9425656255,-2605923.440734631],[-4806951.083578031,-2605993.1501668594],[-4806841.61733748,-2606055.375197199],[-4806728.077152494,-2606109.8126715575],[-4806611.016179442,-2606156.197376032],[-4806491.004727617,-2606194.303329004],[-4806368.627480749,-2606223.944882102],[-4806244.480648483,-2606244.977624658],[-4806119.169061707,-2606257.299087265],[-4805993.303225876,-2606260.8492409955],[-4805867.496346689,-2606255.610789858],[-4805742.361342616,-2606241.6092550587],[-4805618.507858818,-2606218.9128506687],[-4805496.539297019,-2606187.632151288],[-4805377.049875791,-2606147.9195533404],[-4805260.621735584,-2606099.968532611],[-4805147.822102594,-2606044.0127016525],[-4805039.200525293,-2605980.324671649],[-4804935.286197088,-2605909.2147242804]]]},"properties": null}
The Polygon's centroid can be the circle center I think.... the distance of this centroid to any point in the border can be the radius.... I don't know how to get this using JS.
To take the center:
this.draw.on('drawend', function( evt ){
var aa = evt.feature.getGeometry().getExtent();
var oo = ol.extent.getCenter(aa);
console.log( oo );
});
Now I must find a way to take the radius.
I am new to OpenLayers and would appreciate any help I can get. How do you convert from pixel-based-coordinates to lat/lon? I'm using OL3 to view and draw features on a static image (6494 x 7687 jpg) using projection:
var projection = new ol.proj.Projection({
code: 'xkcd-image',
units: 'pixels',
extent: [0, 0, 6494, 7687]
});
At the end of a polygan draw I have this, which works fine:
draw.on('drawend', function (event) {
var coord = event.feature.getGeometry().getCoordinates();
console.log("YOU DREW A Polygon with coord="+coord);
});
Is there an easy way to convert the above pixel-based coordinates of the polygon to Lat/Lon coordinates? I do have the lat/lons of the four corners of the image.
Instead of specifying a custom pixel projection, configure your static image source with the imageExtent set to your corner coordinates, and set its projection to 'EPSG:4326':
new ol.source.ImageStatic({
// ...
imageExtent: [minLon, minLat, maxLon, maxLat],
projection: 'EPSG:4326'
})
If you want to show your image without being distorted, you have to configure your view with projection: 'EPSG:4326' as well. You'll then be working with geographic coordinates throughout.
Something similar is also shown in one of the official examples: http://openlayers.org/en/latest/examples/reprojection-image.html. The difference is that raster reprojection is used there, because image and view are in different projection.
I recently updated my Cordova mobile mapping app from OL3 V3.1.1 to V3.7.0 to V3.8.2.
Am using PouchDB to store off-line tiles, and with V3.1.1 tiles were visible.
Here is the code snippet:
OSM_bc_offline_pouchdb = new ol.layer.Tile({
//maxResolution: 5000,
//extent: BC,
//projection: spherical_mercator,
//crossOrigin: 'anonymous',
source: new ol.source.XYZ({
//adapted from: http://jsfiddle.net/gussy/LCNWC/
tileLoadFunction: function (imageTile, src) {
pouchTilesDB_osm_bc_baselayer.getAttachment(src, 'tile', function (err, res) {
if (err && err.error == 'not_found')
return;
//if(!res) return; // ?issue -> causes map refresh on movement to stop
imageTile.getImage().src = window.URL.createObjectURL(res);
});
},
tileUrlFunction: function (coordinate, projection) {
if (coordinate == null)
return undefined;
// OSM NW origin style URL
var z = coordinate[0];
var x = coordinate[1];
var y = coordinate[2];
var imgURL = ["tile", z, x, y].join('_');
return imgURL;
}
})
});
trails_mobileMap.addLayer(OSM_bc_offline_pouchdb);
OSM_bc_offline_pouchdb.setVisible(true);
Moving to both V3.7.0 and V3.8.2 causes the tiles to not display. Read the API and I'm missing why this would happen.
What in my code needs updating to work with OL-V3.8.2?
Thanks,
Peter
Your issue might be related to the changes to ol.TileCoord in OpenLayers 3.7.0. From the release notes:
Until now, the API exposed two different types of ol.TileCoord tile coordinates: internal ones that increase left to right and upward, and transformed ones that may increase downward, as defined by a transform function on the tile grid. With this change, the API now only exposes tile coordinates that increase left to right and upward.
Previously, tile grids created by OpenLayers either had their origin at the top-left or at the bottom-left corner of the extent. To make it easier for application developers to transform tile coordinates to the common XYZ tiling scheme, all tile grids that OpenLayers creates internally have their origin now at the top-left corner of the extent.
This change affects applications that configure a custom tileUrlFunction for an ol.source.Tile. Previously, the tileUrlFunction was called with rather unpredictable tile coordinates, depending on whether a tile coordinate transform took place before calling the tileUrlFunction. Now it is always called with OpenLayers tile coordinates. To transform these into the common XYZ tiling scheme, a custom tileUrlFunction has to change the y value (tile row) of the ol.TileCoord:
function tileUrlFunction = function(tileCoord, pixelRatio, projection){
var urlTemplate = '{z}/{x}/{y}';
return urlTemplate
.replace('{z}', tileCoord[0].toString())
.replace('{x}', tileCoord[1].toString())
.replace('{y}', (-tileCoord[2] - 1).toString());
}
If this is your issue, try changing your tileUrlFunction to
function (coordinate, projection) {
if (coordinate == null)
return undefined;
// OSM NW origin style URL
var z = coordinate[0];
var x = coordinate[1];
var y = (-coordinate[2] - 1);
var imgURL = ["tile", z, x, y].join('_');
return imgURL;
}