I need to access a Esri REST service, which has a weird XYZ-Format. For example:
On a normal XYZ-Service, z is 14 where on this specific service, on the same height, z is 8.
Does anyone know how to convert them and use the "weird" one on OpenLayers?
This is the "normal" service:
...../15/17122/11081.png
And this the "weird" one:
...../8/458/170
They both are roughly for the same location, on equal height.
It is a custom tile grid for an EPSG:25832 projection.
The settings needed to set up the grid in OpenLayers can be found in https://karte.breitbandmessung.de/servertmp/rest/services/Mobilfunkversorgung/MonitoringPortal_DT_4G/Mapserver?f=pjson Only origin and resolutions are needed, but including extent will prevent out of range tiles being requested - the xmax of the fullExtent seems slightly too small and cuts off the eastern most edge of the country, so I made up an extent based on level 0 being 3 tiles wide
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<link rel="stylesheet" href="https://openlayers.org/en/v6.4.3/css/ol.css" type="text/css">
<script src="https://openlayers.org/en/v6.4.3/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.6.1/proj4.js"></script>
<style>
html, body, .map {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<script>
proj4.defs("EPSG:25832", "+proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");
ol.proj.proj4.register(proj4);
var origin = [233184, 6120719];
var resolutions = [
1222.9948985513972,
611.4974492756991,
305.7487246378482,
152.87436231920458,
76.43718115960229,
38.21859057966118,
19.109295289886575,
9.5546476449433,
4.7773238224716374
];
//var extent = [280300, 5235800, 912300, 6106300];
var extent = [origin[0], origin[1] - 3 * 256 * resolutions[0], origin[0] + 3 * 256 * resolutions[0], origin[1]];
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM(),
}),
new ol.layer.Tile({
source: new ol.source.XYZ({
url: "https://karte.breitbandmessung.de/servertmp/rest/services/Mobilfunkversorgung/MonitoringPortal_DT_4G/Mapserver/tile/{z}/{y}/{x}",
projection: "EPSG:25832",
tileGrid: new ol.tilegrid.TileGrid({
origin: origin,
extent: extent,
resolutions: resolutions,
tileSize: [256, 256],
}),
}),
opacity: 0.5,
}),
],
view: new ol.View({
projection: "EPSG:25832",
})
});
map.getView().fit(extent);
</script>
</body>
</html>
Related
I'm trying to plot about 300 points on an openlayers map from a table of about 300 latitude and longitude cordinates. All I found on how to do it is the draw features from their website, but it can plot a point from a mouse click by the user, not automatically. Is there a way to plot a point on the map from the code?
Thank you.
To draw points (or any other geometry) on the map, you just need to,
Create a source, in this case a vector source, with the features you want to draw.
Create a layer, in this case a vector layer, with the source from step 1, and the style you prefer.
Add the layer to the map.
That is all you need to do. Take a look at the example I made for you, it generate 300 random points features and then follow the steps I describe before.
<!doctype html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.2.1/css/ol.css" type="text/css">
<style>
.map {
height: 400px;
width: 100%;
}
</style>
<script src="https://cdn.jsdelivr.net/gh/openlayers/openlayers.github.io#master/en/v6.2.1/build/ol.js"></script>
<title>Random Points From Code</title>
</head>
<body>
<h2>300 Random Points From Code</h2>
<div id="map" class="map"></div>
<script type="text/javascript">
// generate 300 random points features
const getRandomNumber = function (min, ref) {
return Math.random() * ref + min;
}
const features = [];
for (i = 0; i < 300; i++) {
features.push(new ol.Feature({
geometry: new ol.geom.Point(ol.proj.fromLonLat([
-getRandomNumber(50, 50), getRandomNumber(10, 50)
]))
}));
}
// create the source and layer for random features
const vectorSource = new ol.source.Vector({
features
});
const vectorLayer = new ol.layer.Vector({
source: vectorSource,
style: new ol.style.Style({
image: new ol.style.Circle({
radius: 2,
fill: new ol.style.Fill({color: 'red'})
})
})
});
// create map and add layers
const map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vectorLayer
],
view: new ol.View({
center: ol.proj.fromLonLat([-75, 35]),
zoom: 2
})
});
</script>
</body>
</html>
In my web page, users can draw a polygon and then modify it. However, I would like to only allow users to drag and drop the drawn corners, not add new points into polygon when a polygon is modified.
In the example below, I created a polygon with four corners and would like to keep four corners during modifying (only drag the corners).
I think we should use condition in the modify function, but not sure how to find out the difference between clicking the corner or edge of a polygon.
<!DOCTYPE html>
<html>
<head>
<title>Draw Features</title>
<link rel="stylesheet" href="https://openlayers.org/en/v5.3.0/css/ol.css" type="text/css">
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
</head>
<body>
<div id="map" class="map"></div>
<script>
var raster = new ol.layer.Tile({
source: new ol.source.OSM()
});
var source = new ol.source.Vector({wrapX: false});
var offset = 1000000;
var ply = new ol.geom.Polygon([[
[-11000000 - offset, 4600000 - offset],
[-11000000 + offset, 4600000 - offset],
[-11000000 + offset, 4600000 + offset],
[-11000000 - offset, 4600000 + offset]]]);
var feature = new ol.Feature(ply);
source.addFeatures([feature]);
var vector = new ol.layer.Vector({
source: source
});
var map = new ol.Map({
layers: [raster, vector],
target: 'map',
view: new ol.View({
center: [-11000000, 4600000],
zoom: 4
})
});
var modify = new ol.interaction.Modify({source: source})
map.addInteraction(modify);
</script>
</body>
</html>
var modify = new ol.interaction.Modify({
source: source,
insertVertexCondition: ol.events.condition.never
});
I am quite new into the we map topic and quite frustrated. After reading lots of examples with different libraries etc I managed to get even more confused. So I will start with a trivial example. I provide here the trivial code to plot a web map using openlayers. My aim is to have a polar projection of the map.
html file:
<html>
<head>
<title>Accessible Map</title>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<link rel="stylesheet" href="https://openlayers.org/en/v4.2.0/css/ol.css" type="text/css">
<link rel="stylesheet" href="style.css">
<script src="https://openlayers.org/en/v4.2.0/build/ol.js"></script>
<script src="map.js"></script>
</head>
<body>
<div id="map" class="map" ></div>
<script>init();</script>
</body>
</html>
javascript:
function init(){
var map = new ol.Map({
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
})
],
target: 'map',
controls: ol.control.defaults({
attributionOptions: /** #type {olx.control.AttributionOptions} */ ({
collapsible: false
})
}),
view: new ol.View({
center: [0, 0],
zoom: 2
})
});
}
This code while produce a map with a default Web Mercator projection (EPSG:3857)
According to https://openlayers.org/en/latest/doc/faq.html
in order to change the projection we need to register our desired one. So in my function I added:
var epsg3413 = new ol.proj.Projection({ //NSIDC Sea Ice Polar Stereographic North
code: "EPSG:3413",
extent: [-4194304, 4194304, 4194304, -4194304],
units: "m"
});
var epsg4326 = ol.proj.get("EPSG:4326");
Then with the view method we can change the map projection so i added:
center: ol.proj.transform([85, 85], epsg4326, epsg3413),
projection: epsg3413
With the additions regarding the projection change the map is not working at all. Even a
console.log(ol.proj.transform([85, 85], epsg4326, epsg3413))
is returning the same point (85,85) which means the projection transformation is not even working. Is there an obvious mistake I am doing here? Please correct me also to this basic question: the ol.source.OSM() gets data from a tiled WMS server. By default the tiles are in web mercator projection. Can I plot them at all in polar stereographic or I should find a WMS server which be default provides tiles in polar projections?
Your projection definition is not correct. I can recommend to use proj4j:
// projection definition (http://www.spatialreference.org/ref/epsg/wgs-84-nsidc-sea-ice-polar-stereographic-north/proj4js/)
proj4.defs('EPSG:3413', "+proj=stere +lat_0=90 +lat_ts=70 +lon_0=-45 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs");
var transformedCoordinate = ol.proj.transform([85,85], 'EPSG:4326', 'EPSG:3413');
// results in [415170.5793604837, 348369.4800170395]
I'm trying to center a tile layer in OpenLayers 3 but it seems to ignore the center attribute of the map. I know the height and width of the original big image if it helps.
here is my code (also available in jsbin):
<!DOCTYPE html>
<html>
<head>
<title>XYZ</title>
<link rel="stylesheet" href="http://openlayers.org/en/v3.13.0/css/ol.css" type="text/css">
<script src="http://openlayers.org/en/v3.13.0/build/ol.js"></script>
</head>
<body>
<div id="map" class="map" style="width: 100%; height: 500px; border: 1px solid #000;"></div>
<script>
var layer = new ol.layer.Tile({
source: new ol.source.XYZ({
url: 'http://thinker.cloudapp.net/test/{z}-{x}-{y}.png',
wrapX: false
})
});
var map = new ol.Map({
target: 'map',
layers: [layer],
view: new ol.View({
center: [0,0],
zoom: 2
})
});
</script>
</body>
</html>
How can I center the map, and if possible zoom to fit screen width or height?
Update:
I've updated the code and added a jsbin link too.
The original image size is 4864x3328 if it helps.
I think this has to do with projection and setting the grid size in pixels, but i couldn't find anything helpful.
My first answer isn't a good one. Go this way:
var pixelProj = new ol.proj.Projection({
code: 'pixel',
units: 'pixels',
extent: [0, 0, 4864, 3328]
});
var layer = new ol.layer.Tile({
source: new ol.source.XYZ({
projection: pixelProj,
wrapX: false,
url: 'http://thinker.cloudapp.net/test/{z}-{x}-{y}.png'
})
});
var map = new ol.Map({
target: 'map',
layers: [layer],
view: new ol.View({
zoom: 2,
center: [1364, 2400],
projection: pixelProj
})
});
http://jsfiddle.net/jonataswalker/6f233kLy/
To achieve this you'll need to wait until all tiles are loaded, then get the layer extent, finally fit the view to this extent.
var tile_loading = 0, tile_loaded = 0;
yourTileLayer.getSource().on('tileloadstart', function(evt){
++tile_loading;
});
yourTileLayer.getSource().on('tileloadend', function(evt){
++tile_loaded;
if(tile_loaded === tile_loading){
tile_loading = 0;
tile_loaded = 0;
// put some logic here to do just once
// all tiles are loaded - get the layer extent
var extent = yourTileLayer.getExtent();
map.getView().fit(extent, map.getSize());
}
});
Like the title said I have a vector of points on a OpenLayers map that I need to turn into a heatmap. I already have this code below (which works just fine for me) but I need to add thousands of more points(in a different data file) and be able to visualize it with a density/heatmap. Its current state is a simple open street map with one layer of locations plotted on a world map! I would post an image but reputation rules...
<!DOCTYPE HTML>
<html>
<head>
<title>AIS Map Template</title>
<script src="http://www.openlayers.org/api/OpenLayers.js"></script>
<script>
function init() {
map = new OpenLayers.Map("mapdiv");
var mapnik = new OpenLayers.Layer.OSM();
map.addLayer(mapnik);
// ADD POINTS TO A LAYER
var pois = new OpenLayers.Layer.Vector("Ships",
{
projection: new OpenLayers.Projection("EPSG:4326"),
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP(
{
url: "./AISdecoded.txt",
format: new OpenLayers.Format.Text(
{
extractStyles: true,
extractAttributes: true
})
})
});
// ADD POINTS LAYER TO MAP
map.addLayer(pois);
var layer_switcher= new OpenLayers.Control.LayerSwitcher({});
map.addControl(layer_switcher);
var lonlat = new OpenLayers.LonLat(0,0).transform(
new OpenLayers.Projection("EPSG:4326"), // transform from WGS 1984
new OpenLayers.Projection("EPSG:900913") // to Spherical Mercator
);
var zoom = 1;
map.setCenter(lonlat, zoom);
}
</script>
<style>
#mapdiv { width:900px; height:600px; }
div.olControlAttribution { bottom:3px; }
</style>
</head>
<body onload="init();">
<p>AIS Map Data</p>
<div id="mapdiv"></div>
</body>
</html>
The testing data looks like this:
lat lon title description icon iconSize iconOffset
49.4756 0.13138 227006760 Navigation Status: 0 ship_sea_ocean.png 16,16 -8,-8
51.2377 4.41944 205448890 Navigation Status: 0 ship_sea_ocean.png 16,16 -8,-8
I have tried various methods to try and get a heatmap produced but unfortunaetly I'm a little lacking on the Javascript/HTML side of things. I have looked at the examples online including the earthquake example provided by OpenLayers but 99% of them deal with KML files and since I need this application to run offline on a localhost server I cannot do it that way.
I have attempted this without success, among other flailing:
var heatmapLayer = new ol.layer.Heatmap({
source: new OpenLayers.Layer.Vector("Ships",
{
projection: new OpenLayers.Projection("EPSG:4326"),
strategies: [new OpenLayers.Strategy.Fixed()],
protocol: new OpenLayers.Protocol.HTTP(
{
url: "./AISdecoded.txt",
format: new OpenLayers.Format.Text(
{
extractStyles: true,
extractAttributes: true
})
})
}),
opacity: 0.9
});
// Create a tile layer from OSM
var osmLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
// Create the map with the previous layers
var map = new ol.Map({
target: 'map', // The DOM element that will contains the map
renderer: 'canvas', // Force the renderer to be used
layers: [osmLayer, heatmapLayer],
// Create a view centered on the specified location and zoom level
view: new ol.View({
center: ol.proj.transform([2.1833, 41.3833], 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
});
I have a feeling this is much easier than I think it is but I have been trying to do this for about a week now and my patience is nearing its end. If you know how to do this specifically that's awesome! But if you don't, can you push me in the right direction? Any help is much appreciated, thanks!
EDIT
OK so I edited the code a bit to be fully OL3 and use a geoJSON approach. It now looks like this:
<!DOCTYPE HTML>
<html>
<head>
<title>AIS Map Template</title>
<script src="http://openlayers.org/en/v3.5.0/build/ol.js" type="text/javascript"></script>
<link rel='stylesheet' href='http://ol3js.org/en/master/css/ol.css'>
<script>
function init() {
var vector = new ol.layer.Heatmap({
source: new ol.source.GeoJSON({
url: './AISdecoded.geojson',
projection: 'EPSG:3857'
}),
opacity: .9
});
var osmLayer = new ol.layer.Tile({
source: new ol.source.OSM()
});
// Create the map with the previous layers
var map = new ol.Map({
target: 'map', // The DOM element that will contain the map
renderer: 'canvas', // Force the renderer to be used
layers: [osmLayer,vector],
// Create a view centered on the specified location and zoom level
view: new ol.View({
center: ol.proj.transform([2.1833, 41.3833], 'EPSG:4326', 'EPSG:3857'),
zoom: 4
})
});
}
</script>
<style>
#map { width:900px; height:600px; }
div.olControlAttribution { bottom:3px; }
</style>
</head>
<body onload="init();">
<p>AIS Map Data</p>
<div id="map"></div>
</body>
</html>
But it's still not working, only a map, no layer. This is the way I found how to do via examples like this one. Firebug is saying "TypeError: ol.source.GeoJSON is not a constructor" but I don't know how to do this any other way. pls halp, thanks!
Change this:
var vector = new ol.layer.Heatmap({
source: new ol.source.GeoJSON({
url: './AISdecoded.geojson',
projection: 'EPSG:3857'
}),
to:
var vector = new ol.layer.Heatmap({
source: new ol.source.Vector({
url: './AISdecoded.geojson',
projection: 'EPSG:3857',
format: new ol.format.GeoJSON()
}),