Add a rotated satellite image on the map using OpenLayers 5Displaying georeferenced images using OpenLayers 5How to reproject a vector layer when you switch between base maps of different projectionsBackground Layer in EPSG:900913 causes WMS overlays to failUsing OSM and EPSG:4326 with openlayers increase latitude in near 90 degrees. Why?how to project a flat image to spherical mercator EPGS:900013 to use in a Image Layer in openlayersHere Map Tile API: Retrieve Map tile address from EPSG:3857 coordinateSimple Openlayers + AngularChanging projection in an OpenLayers 2.13 map objectWMS Layer provide by Map Sever rendering incorrectly in ol3Reproject EPSG:28992 to EPSG:3857 (defaults to EPSG:4326)OpenLayers 4 cant´t reproject json file
Function over a list that depends on the index
Found old paper shares of Motorola Inc that has since been broken up
How did Jayne know when to shoot?
What are my hardware upgrade optoins for a late 2009 iMac?
What makes MOVEQ quicker than a normal MOVE in 68000 assembly?
What is the function of "mal" in saying "Das nenn ich mal ein X"?
What's the physical meaning of the statement that "photons don't have positions"?
Are there any satellites in geosynchronous but not geostationary orbits?
Why is this guy handcuffed censored?
Is encryption still applied if you ignore the SSL certificate warning for self-signed certs?
Why teach C using scanf without talking about command line arguments?
Should I have one hand on the throttle during engine ignition?
I want light controlled by one switch, not two
The most secure way to handle someone forgetting to verify their account?
Doesn't the Schrödinger's cat inside the box cause the probability wave function to collapse long before a human opens the box?
Applying for jobs with an obvious scar
What is a Romeo Word™?
Formating slide
How was Luke's prosthetic hand in Episode V filmed?
Does the Bracer of Flying Daggers really let a thief make 4 attacks per round?
What is a Kravchuk transform and how is it related to Fourier transforms?
Do pedestrians imitate automotive traffic?
Last-minute canceled work-trip means I'll lose thousands of dollars on planned vacation
"This used to be my phone number"
Add a rotated satellite image on the map using OpenLayers 5
Displaying georeferenced images using OpenLayers 5How to reproject a vector layer when you switch between base maps of different projectionsBackground Layer in EPSG:900913 causes WMS overlays to failUsing OSM and EPSG:4326 with openlayers increase latitude in near 90 degrees. Why?how to project a flat image to spherical mercator EPGS:900013 to use in a Image Layer in openlayersHere Map Tile API: Retrieve Map tile address from EPSG:3857 coordinateSimple Openlayers + AngularChanging projection in an OpenLayers 2.13 map objectWMS Layer provide by Map Sever rendering incorrectly in ol3Reproject EPSG:28992 to EPSG:3857 (defaults to EPSG:4326)OpenLayers 4 cant´t reproject json file
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
I'm trying to add a satellite image on my map using OpenLayers 5.
The problem is that I'm not able to do this, because I've just found an option to add an image on the map passing the image extent (xmin, ymin, xmax, ymax) and not the bounding box. The image should fit inside the bounding box. For that reason, the image was distorted.
The image is in JPG file (attribute feature.properties.icon). Example: http://exampleserver.com/220/063/353LGN00/353LGN00_thumb_large.jpg
The result that I would like is something like this:
The result that I've got was that:
My code that adds this image on the map is the following:
import ImageLayer from 'ol/layer/Image'
import Static from 'ol/source/ImageStatic'
...
this.olmap = new Map(
target: 'map',
layers: [
baseLayerGroup, rasterLayerGroup, vectorLayer
],
view: new View(
projection: 'EPSG:4326',
center: [ -45.8392, -3.65286 ],
zoom: 8
)
)
...
this.rasterLayerGroup.getLayers().push(
new ImageLayer(
source: new Static(
url: feature.properties.icon,
projection: 'EPSG:4326',
imageExtent: [
feature.properties.bl_longitude, feature.properties.bl_latitude,
feature.properties.tr_longitude, feature.properties.tr_latitude
]
)
)
)
Would someone know how to pass the image bounding box instead of just the image extent?
Thank you in advance.
EDIT 1: Mike's solution
Through Mike's solution I was able to fix a bug that some images have (near to the equator line). For that reason, his answer solved my problem and it inserted the image in a better position that I was expecting in the moment that I created the question.
However, this solution worked to me with images near to the equator line. Images next to the poles stay distorted (Edit 2).
I send below a picture illustrating the final result:
EDIT 2: New problem?
I was testing some images and I have discovered a new bug. Now I have discovered that the image should fit inside the bounding box. If the image does not fit inside the bbox, it stays distorted, such as the print that I send below illustrating.
The image should fit inside the bbox like in the image below [PS 1]:
I believe that it can be a problem of reprojection, but I don't know, because both view projection and image projection is EPSG:4326.
I tried to follow the explanation about Raster Reprojection[1.] on Openlayers site, however I was not able to reproduce it, because, as I said, both projections (view and image) are the same (or they should be).
I send below the GeoJSON that contains the information related to the image above. The image can be found in "properties.icon" (http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.jpg). The bbox coordinates can be found in "geometry.coordinates" or in "properties.bl_latitude", "properties.bl_longitude", "properties.br_latitude" and so on.
"bl" means "bottom left", "br" means "bottom right", "tl" means "top left" and "tr" means "top right". These coordinates inside "properties" are the same inside "geometry.coordinates".
"geometry":
"coordinates": [
[
[
-77.7862,
-50
],
[
-100,
-60
],
[
-80,
-60
],
[
-62.229,
-50
],
[
-77.7862,
-50
]
]
],
"type": "Polygon"
,
"properties":
"alternate": "http://www.dpi.inpe.br/opensearch/v2/granule.json?uid=MOD13Q1.A2018017.h13v14",
"auxpath": null,
"bitslips": null,
"bl_latitude": -60,
"bl_longitude": -100,
"br_latitude": -60,
"br_longitude": -80,
"centerlatitude": -55,
"centerlongitude": -80.0038,
"centertime": null,
"cloud": 0,
"cloudcovermethod": "M",
"dataset": "MOD13Q1",
"date": "2018-01-17T00:00:00",
"enclosure": [
"band": "evi",
"radiometric_processing": "SR",
"type": "MOSAIC",
"url": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.006.2018033223827.hdf"
,
"band": "ndvi",
"radiometric_processing": "SR",
"type": "MOSAIC",
"url": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.006.2018033223827.hdf"
,
...
],
"icon": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.jpg",
"id": "http://www.dpi.inpe.br/opensearch/v2/granule.json?uid=MOD13Q1.A2018017.h13v14",
"orbit": 0,
"path": 14,
"provider": "OP_CBERS1",
"row": 13,
"satellite": "T1",
"sensor": "MODIS",
"title": "MOD13Q1.A2018017.h13v14",
"tl_latitude": -50,
"tl_longitude": -77.7862,
"tr_latitude": -50,
"tr_longitude": -62.229,
"type": "IMAGES",
"updated": "2018-03-01T18:51:56",
"via": "http://www.dpi.inpe.br/opensearch/v2/metadata/MOD13Q1.A2018017.h13v14"
,
"type": "Feature"
Would someone have a new idea?
[PS 1]: The original code that does the image fits inside the bbox is a Leaflet code [2.] and I send it below:
var map = L.map('map').setView([-15.22, -53.23], 5)
...
var anchor = [
[feature.properties.tl_latitude, feature.properties.tl_longitude],
[feature.properties.tr_latitude, feature.properties.tr_longitude],
[feature.properties.br_latitude, feature.properties.br_longitude],
[feature.properties.bl_latitude, feature.properties.bl_longitude]
]
layer._quicklook = L.imageTransform(feature.properties.icon, anchor).addTo(map)
[1.] https://openlayers.org/en/latest/doc/tutorials/raster-reprojection.html
[2.] https://github.com/ScanEx/Leaflet.imageTransform
gis openlayers openlayers-5 satellite-image
add a comment |
I'm trying to add a satellite image on my map using OpenLayers 5.
The problem is that I'm not able to do this, because I've just found an option to add an image on the map passing the image extent (xmin, ymin, xmax, ymax) and not the bounding box. The image should fit inside the bounding box. For that reason, the image was distorted.
The image is in JPG file (attribute feature.properties.icon). Example: http://exampleserver.com/220/063/353LGN00/353LGN00_thumb_large.jpg
The result that I would like is something like this:
The result that I've got was that:
My code that adds this image on the map is the following:
import ImageLayer from 'ol/layer/Image'
import Static from 'ol/source/ImageStatic'
...
this.olmap = new Map(
target: 'map',
layers: [
baseLayerGroup, rasterLayerGroup, vectorLayer
],
view: new View(
projection: 'EPSG:4326',
center: [ -45.8392, -3.65286 ],
zoom: 8
)
)
...
this.rasterLayerGroup.getLayers().push(
new ImageLayer(
source: new Static(
url: feature.properties.icon,
projection: 'EPSG:4326',
imageExtent: [
feature.properties.bl_longitude, feature.properties.bl_latitude,
feature.properties.tr_longitude, feature.properties.tr_latitude
]
)
)
)
Would someone know how to pass the image bounding box instead of just the image extent?
Thank you in advance.
EDIT 1: Mike's solution
Through Mike's solution I was able to fix a bug that some images have (near to the equator line). For that reason, his answer solved my problem and it inserted the image in a better position that I was expecting in the moment that I created the question.
However, this solution worked to me with images near to the equator line. Images next to the poles stay distorted (Edit 2).
I send below a picture illustrating the final result:
EDIT 2: New problem?
I was testing some images and I have discovered a new bug. Now I have discovered that the image should fit inside the bounding box. If the image does not fit inside the bbox, it stays distorted, such as the print that I send below illustrating.
The image should fit inside the bbox like in the image below [PS 1]:
I believe that it can be a problem of reprojection, but I don't know, because both view projection and image projection is EPSG:4326.
I tried to follow the explanation about Raster Reprojection[1.] on Openlayers site, however I was not able to reproduce it, because, as I said, both projections (view and image) are the same (or they should be).
I send below the GeoJSON that contains the information related to the image above. The image can be found in "properties.icon" (http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.jpg). The bbox coordinates can be found in "geometry.coordinates" or in "properties.bl_latitude", "properties.bl_longitude", "properties.br_latitude" and so on.
"bl" means "bottom left", "br" means "bottom right", "tl" means "top left" and "tr" means "top right". These coordinates inside "properties" are the same inside "geometry.coordinates".
"geometry":
"coordinates": [
[
[
-77.7862,
-50
],
[
-100,
-60
],
[
-80,
-60
],
[
-62.229,
-50
],
[
-77.7862,
-50
]
]
],
"type": "Polygon"
,
"properties":
"alternate": "http://www.dpi.inpe.br/opensearch/v2/granule.json?uid=MOD13Q1.A2018017.h13v14",
"auxpath": null,
"bitslips": null,
"bl_latitude": -60,
"bl_longitude": -100,
"br_latitude": -60,
"br_longitude": -80,
"centerlatitude": -55,
"centerlongitude": -80.0038,
"centertime": null,
"cloud": 0,
"cloudcovermethod": "M",
"dataset": "MOD13Q1",
"date": "2018-01-17T00:00:00",
"enclosure": [
"band": "evi",
"radiometric_processing": "SR",
"type": "MOSAIC",
"url": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.006.2018033223827.hdf"
,
"band": "ndvi",
"radiometric_processing": "SR",
"type": "MOSAIC",
"url": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.006.2018033223827.hdf"
,
...
],
"icon": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.jpg",
"id": "http://www.dpi.inpe.br/opensearch/v2/granule.json?uid=MOD13Q1.A2018017.h13v14",
"orbit": 0,
"path": 14,
"provider": "OP_CBERS1",
"row": 13,
"satellite": "T1",
"sensor": "MODIS",
"title": "MOD13Q1.A2018017.h13v14",
"tl_latitude": -50,
"tl_longitude": -77.7862,
"tr_latitude": -50,
"tr_longitude": -62.229,
"type": "IMAGES",
"updated": "2018-03-01T18:51:56",
"via": "http://www.dpi.inpe.br/opensearch/v2/metadata/MOD13Q1.A2018017.h13v14"
,
"type": "Feature"
Would someone have a new idea?
[PS 1]: The original code that does the image fits inside the bbox is a Leaflet code [2.] and I send it below:
var map = L.map('map').setView([-15.22, -53.23], 5)
...
var anchor = [
[feature.properties.tl_latitude, feature.properties.tl_longitude],
[feature.properties.tr_latitude, feature.properties.tr_longitude],
[feature.properties.br_latitude, feature.properties.br_longitude],
[feature.properties.bl_latitude, feature.properties.bl_longitude]
]
layer._quicklook = L.imageTransform(feature.properties.icon, anchor).addTo(map)
[1.] https://openlayers.org/en/latest/doc/tutorials/raster-reprojection.html
[2.] https://github.com/ScanEx/Leaflet.imageTransform
gis openlayers openlayers-5 satellite-image
Do you have lon/lat values for tl and br or a rotation value?
– Mike
Mar 26 at 20:35
Yes, I do lon/lat values for the four points of the image bounding box. They are "bl_latitude, bl_longitude, br_latitude, br_longitude, tl_latitude, tl_longitude, tr_latitude, tr_longitude". A rotation value I do not have. Should I calculate it by the bbox values?
– rmmariano
Mar 27 at 11:38
Does it not belong to GIS SE site?
– Gilles-Antoine Nys
Mar 29 at 16:35
"Ask a question", on OpenLayers site, redirects to StackOverflow instead of GIS SE.
– rmmariano
Mar 29 at 17:25
add a comment |
I'm trying to add a satellite image on my map using OpenLayers 5.
The problem is that I'm not able to do this, because I've just found an option to add an image on the map passing the image extent (xmin, ymin, xmax, ymax) and not the bounding box. The image should fit inside the bounding box. For that reason, the image was distorted.
The image is in JPG file (attribute feature.properties.icon). Example: http://exampleserver.com/220/063/353LGN00/353LGN00_thumb_large.jpg
The result that I would like is something like this:
The result that I've got was that:
My code that adds this image on the map is the following:
import ImageLayer from 'ol/layer/Image'
import Static from 'ol/source/ImageStatic'
...
this.olmap = new Map(
target: 'map',
layers: [
baseLayerGroup, rasterLayerGroup, vectorLayer
],
view: new View(
projection: 'EPSG:4326',
center: [ -45.8392, -3.65286 ],
zoom: 8
)
)
...
this.rasterLayerGroup.getLayers().push(
new ImageLayer(
source: new Static(
url: feature.properties.icon,
projection: 'EPSG:4326',
imageExtent: [
feature.properties.bl_longitude, feature.properties.bl_latitude,
feature.properties.tr_longitude, feature.properties.tr_latitude
]
)
)
)
Would someone know how to pass the image bounding box instead of just the image extent?
Thank you in advance.
EDIT 1: Mike's solution
Through Mike's solution I was able to fix a bug that some images have (near to the equator line). For that reason, his answer solved my problem and it inserted the image in a better position that I was expecting in the moment that I created the question.
However, this solution worked to me with images near to the equator line. Images next to the poles stay distorted (Edit 2).
I send below a picture illustrating the final result:
EDIT 2: New problem?
I was testing some images and I have discovered a new bug. Now I have discovered that the image should fit inside the bounding box. If the image does not fit inside the bbox, it stays distorted, such as the print that I send below illustrating.
The image should fit inside the bbox like in the image below [PS 1]:
I believe that it can be a problem of reprojection, but I don't know, because both view projection and image projection is EPSG:4326.
I tried to follow the explanation about Raster Reprojection[1.] on Openlayers site, however I was not able to reproduce it, because, as I said, both projections (view and image) are the same (or they should be).
I send below the GeoJSON that contains the information related to the image above. The image can be found in "properties.icon" (http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.jpg). The bbox coordinates can be found in "geometry.coordinates" or in "properties.bl_latitude", "properties.bl_longitude", "properties.br_latitude" and so on.
"bl" means "bottom left", "br" means "bottom right", "tl" means "top left" and "tr" means "top right". These coordinates inside "properties" are the same inside "geometry.coordinates".
"geometry":
"coordinates": [
[
[
-77.7862,
-50
],
[
-100,
-60
],
[
-80,
-60
],
[
-62.229,
-50
],
[
-77.7862,
-50
]
]
],
"type": "Polygon"
,
"properties":
"alternate": "http://www.dpi.inpe.br/opensearch/v2/granule.json?uid=MOD13Q1.A2018017.h13v14",
"auxpath": null,
"bitslips": null,
"bl_latitude": -60,
"bl_longitude": -100,
"br_latitude": -60,
"br_longitude": -80,
"centerlatitude": -55,
"centerlongitude": -80.0038,
"centertime": null,
"cloud": 0,
"cloudcovermethod": "M",
"dataset": "MOD13Q1",
"date": "2018-01-17T00:00:00",
"enclosure": [
"band": "evi",
"radiometric_processing": "SR",
"type": "MOSAIC",
"url": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.006.2018033223827.hdf"
,
"band": "ndvi",
"radiometric_processing": "SR",
"type": "MOSAIC",
"url": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.006.2018033223827.hdf"
,
...
],
"icon": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.jpg",
"id": "http://www.dpi.inpe.br/opensearch/v2/granule.json?uid=MOD13Q1.A2018017.h13v14",
"orbit": 0,
"path": 14,
"provider": "OP_CBERS1",
"row": 13,
"satellite": "T1",
"sensor": "MODIS",
"title": "MOD13Q1.A2018017.h13v14",
"tl_latitude": -50,
"tl_longitude": -77.7862,
"tr_latitude": -50,
"tr_longitude": -62.229,
"type": "IMAGES",
"updated": "2018-03-01T18:51:56",
"via": "http://www.dpi.inpe.br/opensearch/v2/metadata/MOD13Q1.A2018017.h13v14"
,
"type": "Feature"
Would someone have a new idea?
[PS 1]: The original code that does the image fits inside the bbox is a Leaflet code [2.] and I send it below:
var map = L.map('map').setView([-15.22, -53.23], 5)
...
var anchor = [
[feature.properties.tl_latitude, feature.properties.tl_longitude],
[feature.properties.tr_latitude, feature.properties.tr_longitude],
[feature.properties.br_latitude, feature.properties.br_longitude],
[feature.properties.bl_latitude, feature.properties.bl_longitude]
]
layer._quicklook = L.imageTransform(feature.properties.icon, anchor).addTo(map)
[1.] https://openlayers.org/en/latest/doc/tutorials/raster-reprojection.html
[2.] https://github.com/ScanEx/Leaflet.imageTransform
gis openlayers openlayers-5 satellite-image
I'm trying to add a satellite image on my map using OpenLayers 5.
The problem is that I'm not able to do this, because I've just found an option to add an image on the map passing the image extent (xmin, ymin, xmax, ymax) and not the bounding box. The image should fit inside the bounding box. For that reason, the image was distorted.
The image is in JPG file (attribute feature.properties.icon). Example: http://exampleserver.com/220/063/353LGN00/353LGN00_thumb_large.jpg
The result that I would like is something like this:
The result that I've got was that:
My code that adds this image on the map is the following:
import ImageLayer from 'ol/layer/Image'
import Static from 'ol/source/ImageStatic'
...
this.olmap = new Map(
target: 'map',
layers: [
baseLayerGroup, rasterLayerGroup, vectorLayer
],
view: new View(
projection: 'EPSG:4326',
center: [ -45.8392, -3.65286 ],
zoom: 8
)
)
...
this.rasterLayerGroup.getLayers().push(
new ImageLayer(
source: new Static(
url: feature.properties.icon,
projection: 'EPSG:4326',
imageExtent: [
feature.properties.bl_longitude, feature.properties.bl_latitude,
feature.properties.tr_longitude, feature.properties.tr_latitude
]
)
)
)
Would someone know how to pass the image bounding box instead of just the image extent?
Thank you in advance.
EDIT 1: Mike's solution
Through Mike's solution I was able to fix a bug that some images have (near to the equator line). For that reason, his answer solved my problem and it inserted the image in a better position that I was expecting in the moment that I created the question.
However, this solution worked to me with images near to the equator line. Images next to the poles stay distorted (Edit 2).
I send below a picture illustrating the final result:
EDIT 2: New problem?
I was testing some images and I have discovered a new bug. Now I have discovered that the image should fit inside the bounding box. If the image does not fit inside the bbox, it stays distorted, such as the print that I send below illustrating.
The image should fit inside the bbox like in the image below [PS 1]:
I believe that it can be a problem of reprojection, but I don't know, because both view projection and image projection is EPSG:4326.
I tried to follow the explanation about Raster Reprojection[1.] on Openlayers site, however I was not able to reproduce it, because, as I said, both projections (view and image) are the same (or they should be).
I send below the GeoJSON that contains the information related to the image above. The image can be found in "properties.icon" (http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.jpg). The bbox coordinates can be found in "geometry.coordinates" or in "properties.bl_latitude", "properties.bl_longitude", "properties.br_latitude" and so on.
"bl" means "bottom left", "br" means "bottom right", "tl" means "top left" and "tr" means "top right". These coordinates inside "properties" are the same inside "geometry.coordinates".
"geometry":
"coordinates": [
[
[
-77.7862,
-50
],
[
-100,
-60
],
[
-80,
-60
],
[
-62.229,
-50
],
[
-77.7862,
-50
]
]
],
"type": "Polygon"
,
"properties":
"alternate": "http://www.dpi.inpe.br/opensearch/v2/granule.json?uid=MOD13Q1.A2018017.h13v14",
"auxpath": null,
"bitslips": null,
"bl_latitude": -60,
"bl_longitude": -100,
"br_latitude": -60,
"br_longitude": -80,
"centerlatitude": -55,
"centerlongitude": -80.0038,
"centertime": null,
"cloud": 0,
"cloudcovermethod": "M",
"dataset": "MOD13Q1",
"date": "2018-01-17T00:00:00",
"enclosure": [
"band": "evi",
"radiometric_processing": "SR",
"type": "MOSAIC",
"url": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.006.2018033223827.hdf"
,
"band": "ndvi",
"radiometric_processing": "SR",
"type": "MOSAIC",
"url": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.006.2018033223827.hdf"
,
...
],
"icon": "http://www.dpi.inpe.br/newcatalog/tmp/MOD13Q1/2018/MOD13Q1.A2018017.h13v14.jpg",
"id": "http://www.dpi.inpe.br/opensearch/v2/granule.json?uid=MOD13Q1.A2018017.h13v14",
"orbit": 0,
"path": 14,
"provider": "OP_CBERS1",
"row": 13,
"satellite": "T1",
"sensor": "MODIS",
"title": "MOD13Q1.A2018017.h13v14",
"tl_latitude": -50,
"tl_longitude": -77.7862,
"tr_latitude": -50,
"tr_longitude": -62.229,
"type": "IMAGES",
"updated": "2018-03-01T18:51:56",
"via": "http://www.dpi.inpe.br/opensearch/v2/metadata/MOD13Q1.A2018017.h13v14"
,
"type": "Feature"
Would someone have a new idea?
[PS 1]: The original code that does the image fits inside the bbox is a Leaflet code [2.] and I send it below:
var map = L.map('map').setView([-15.22, -53.23], 5)
...
var anchor = [
[feature.properties.tl_latitude, feature.properties.tl_longitude],
[feature.properties.tr_latitude, feature.properties.tr_longitude],
[feature.properties.br_latitude, feature.properties.br_longitude],
[feature.properties.bl_latitude, feature.properties.bl_longitude]
]
layer._quicklook = L.imageTransform(feature.properties.icon, anchor).addTo(map)
[1.] https://openlayers.org/en/latest/doc/tutorials/raster-reprojection.html
[2.] https://github.com/ScanEx/Leaflet.imageTransform
gis openlayers openlayers-5 satellite-image
gis openlayers openlayers-5 satellite-image
edited Mar 28 at 12:22
rmmariano
asked Mar 26 at 11:43
rmmarianormmariano
12510 bronze badges
12510 bronze badges
Do you have lon/lat values for tl and br or a rotation value?
– Mike
Mar 26 at 20:35
Yes, I do lon/lat values for the four points of the image bounding box. They are "bl_latitude, bl_longitude, br_latitude, br_longitude, tl_latitude, tl_longitude, tr_latitude, tr_longitude". A rotation value I do not have. Should I calculate it by the bbox values?
– rmmariano
Mar 27 at 11:38
Does it not belong to GIS SE site?
– Gilles-Antoine Nys
Mar 29 at 16:35
"Ask a question", on OpenLayers site, redirects to StackOverflow instead of GIS SE.
– rmmariano
Mar 29 at 17:25
add a comment |
Do you have lon/lat values for tl and br or a rotation value?
– Mike
Mar 26 at 20:35
Yes, I do lon/lat values for the four points of the image bounding box. They are "bl_latitude, bl_longitude, br_latitude, br_longitude, tl_latitude, tl_longitude, tr_latitude, tr_longitude". A rotation value I do not have. Should I calculate it by the bbox values?
– rmmariano
Mar 27 at 11:38
Does it not belong to GIS SE site?
– Gilles-Antoine Nys
Mar 29 at 16:35
"Ask a question", on OpenLayers site, redirects to StackOverflow instead of GIS SE.
– rmmariano
Mar 29 at 17:25
Do you have lon/lat values for tl and br or a rotation value?
– Mike
Mar 26 at 20:35
Do you have lon/lat values for tl and br or a rotation value?
– Mike
Mar 26 at 20:35
Yes, I do lon/lat values for the four points of the image bounding box. They are "bl_latitude, bl_longitude, br_latitude, br_longitude, tl_latitude, tl_longitude, tr_latitude, tr_longitude". A rotation value I do not have. Should I calculate it by the bbox values?
– rmmariano
Mar 27 at 11:38
Yes, I do lon/lat values for the four points of the image bounding box. They are "bl_latitude, bl_longitude, br_latitude, br_longitude, tl_latitude, tl_longitude, tr_latitude, tr_longitude". A rotation value I do not have. Should I calculate it by the bbox values?
– rmmariano
Mar 27 at 11:38
Does it not belong to GIS SE site?
– Gilles-Antoine Nys
Mar 29 at 16:35
Does it not belong to GIS SE site?
– Gilles-Antoine Nys
Mar 29 at 16:35
"Ask a question", on OpenLayers site, redirects to StackOverflow instead of GIS SE.
– rmmariano
Mar 29 at 17:25
"Ask a question", on OpenLayers site, redirects to StackOverflow instead of GIS SE.
– rmmariano
Mar 29 at 17:25
add a comment |
1 Answer
1
active
oldest
votes
If the coordinates are those of the photo and the jpg which contains the rotated photo is in EPSG:4326 (i.e. aligned to meridians and parallels) then you need a bounding box containing all of the corners of the photo
import boundingExtent from 'ol/extent';
....
this.rasterLayerGroup.getLayers().push(
new ImageLayer(
source: new Static(
url: feature.properties.icon,
projection: 'EPSG:4326',
imageExtent: boundingExtent([
[feature.properties.bl_longitude, feature.properties.bl_latitude],
[feature.properties.br_longitude, feature.properties.br_latitude],
[feature.properties.tl_longitude, feature.properties.tl_latitude],
[feature.properties.tr_longitude, feature.properties.tr_latitude]
])
)
)
)
However your top screenshot has the jpg itself rotated. If that is desired the projection isn't EPSG:4326 and you would need to define a custom projection to handle the rotation.
I've managed to get something close, but simply stretching the image to fit the polygon doesn't give the exact alignment at the side that the leaflet method does
var properties =
"bl_latitude": -60,
"bl_longitude": -100,
"br_latitude": -60,
"br_longitude": -80,
"centerlatitude": -55,
"centerlongitude": -80.0038,
"icon": "https://www.mikenunn.net/demo/MOD13Q1.A2018017.h13v14.jpg",
"tl_latitude": -50,
"tl_longitude": -77.7862,
"tr_latitude": -50,
"tr_longitude": -62.229,
;
function overlaySource ( properties )
var projection = ol.proj.get('EPSG:3857'); // leaflet projection
var extentSize = [0, 0, 4096, 4096]; // arbitary extent for the projection transforms
var size0 = extentSize[2];
var size1 = extentSize[3];
var url = properties.icon;
var bl = ol.proj.transform([properties.bl_longitude, properties.bl_latitude], 'EPSG:4326', projection);
var tl = ol.proj.transform([properties.tl_longitude, properties.tl_latitude], 'EPSG:4326', projection);
var br = ol.proj.transform([properties.br_longitude, properties.br_latitude], 'EPSG:4326', projection);
var tr = ol.proj.transform([properties.tr_longitude, properties.tr_latitude], 'EPSG:4326', projection);
function normalTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var left = bl[0] + (tl[0]-bl[0]) * coordinates[i+1]/size1;
var right = br[0] + (tr[0]-br[0]) * coordinates[i+1]/size1;
var top = tl[1] + (tr[1]-tl[1]) * coordinates[i]/size0;
var bottom = bl[1] + (br[1]-bl[1]) * coordinates[i]/size0;
var newCoordinates0 = left + (right-left) * coordinates[i]/size0;
var newCoordinates1 = bottom + (top-bottom) * coordinates[i+1]/size1;
c = ol.proj.transform([newCoordinates0, newCoordinates1], projection, 'EPSG:3857');
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + c[0] + ' ' + c[1]);
coordinates[i] = c[0];
coordinates[i+1] = c[1];
return coordinates;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
c = ol.proj.transform([coordinates[i], coordinates[i+1]], 'EPSG:3857', projection);
var left = bl[0] + (tl[0]-bl[0]) * (c[1]-bl[1]) /(tl[1]-bl[1]);
var right = br[0] + (tr[0]-br[0]) * (c[1]-br[1]) /(tr[1]-br[1]);
var top = tl[1] + (tr[1]-tl[1]) * (c[0]-tl[0])/(tr[0]-tl[0]);
var bottom = bl[1] + (br[1]-bl[1]) * (c[0]-bl[0])/(br[0]-bl[0]);
var newCoordinates0 = (c[0]-left)*size0/(right-left);
var newCoordinates1 = (c[1]-bottom)*size1/(top-bottom);
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + newCoordinates0 + ' ' + newCoordinates1);
coordinates[i] = newCoordinates0;
coordinates[i+1] = newCoordinates1;
return coordinates;
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: extentSize
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(coordinate);
,
function(coordinate)
return normalTransform(coordinate);
);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, "EPSG:4326", "EPSG:3857"));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), "EPSG:3857", "EPSG:4326");
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
imageExtent: extentSize,
url: url
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
var imageLayer = new ol.layer.Image(
source: overlaySource( properties ),
opacity: 0.7
)
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
This is my KML method, but that is a simple rotation of a rectangle by a specified angle, not warping it into a quadrilateral where only two of the sides are parallel.
function kmlOverlaySource ( kmlExtent, // KMLs specify the extent the unrotated image would occupy
url,
rotation,
imageSize,
)
// calculate latitude of true scale of equidistant cylindrical projection based on pixels per degree on each axis
proj4.defs('EPSG:' + url, '+proj=eqc +lat_ts=' +
(Math.acos((ol.extent.getHeight(kmlExtent)/imageSize[1])
/(ol.extent.getWidth(kmlExtent)/imageSize[0]))*180/Math.PI) +
' +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs');
if (ol.proj.proj4 && ol.proj.proj4.register) ol.proj.proj4.register(proj4); // if OL5 register proj4
// convert the extents to source projection coordinates
var projection = ol.proj.get('EPSG:' + url);
var projExtent = ol.proj.transformExtent(kmlExtent, 'EPSG:4326', projection);
var angle = -rotation * Math.PI/180;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var point = new ol.geom.Point([coordinates[i],coordinates[i+1]]);
point.rotate(angle, ol.extent.getCenter(projExtent));
var newCoordinates = point.getCoordinates();
coordinates[i] = newCoordinates[0];
coordinates[i+1] = newCoordinates[1];
return coordinates;
function normalTransform(coordinates, output, dimensions)
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: projExtent
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:4326', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:4326');
);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:3857', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:3857');
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
url: url,
imageExtent: projExtent
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
// these would normally be parsed from a KML file
var kmlExtent = [8.433995415151397, 46.65804355828784, 9.144871415151389, 46.77980155828784];
var url = 'https://raw.githubusercontent.com/ReneNyffenegger/about-GoogleEarth/master/kml/the_png_says.png'
var rotation = 30;
var imageSize = [];
var img = document.createElement('img');
img.onload = imageLoaded;
img.src = url;
function imageLoaded()
imageSize[0] = img.width;
imageSize[1] = img.height;
var imageLayer = new ol.layer.Image(
source: kmlOverlaySource(kmlExtent, url, rotation, imageSize),
);
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
Your solution worked to my images that are next to equator lines, but the ones that are next to the poles stay distorted, unfortunately. Now I have discovered that the images should fit inside the bounding box passed (bl_longitude, bl_latitude, ...). Would you have a new tip that you would like to share? Thank you so much for your reply.
– rmmariano
Mar 27 at 18:30
Can you post the original image for that part of South America and all the coordinates that go with it. Clearly it's going to need a rotated projection of some kind. I've managed those for KML ground overlays designed for Google Earth renenyffenegger.ch/notes/tools/Google-Earth/kml/index to work with OpenLayers i.stack.imgur.com/68bYZ.jpg so something similar may be possible with yours.
– Mike
Mar 27 at 20:45
I updated the question including what you would like. Really, both cases seem similar. How did you do to rotate the PNG image? In the question I included a Leaflet code that plots that South America image on the map. Thank you so much.
– rmmariano
Mar 28 at 12:32
1
I've adding working snippets for an attempt at reproducing the leaflet result and for the KML overlay..
– Mike
Mar 29 at 16:34
Thank you Mike so much for your help.
– rmmariano
Mar 29 at 17:27
|
show 1 more comment
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55356335%2fadd-a-rotated-satellite-image-on-the-map-using-openlayers-5%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
If the coordinates are those of the photo and the jpg which contains the rotated photo is in EPSG:4326 (i.e. aligned to meridians and parallels) then you need a bounding box containing all of the corners of the photo
import boundingExtent from 'ol/extent';
....
this.rasterLayerGroup.getLayers().push(
new ImageLayer(
source: new Static(
url: feature.properties.icon,
projection: 'EPSG:4326',
imageExtent: boundingExtent([
[feature.properties.bl_longitude, feature.properties.bl_latitude],
[feature.properties.br_longitude, feature.properties.br_latitude],
[feature.properties.tl_longitude, feature.properties.tl_latitude],
[feature.properties.tr_longitude, feature.properties.tr_latitude]
])
)
)
)
However your top screenshot has the jpg itself rotated. If that is desired the projection isn't EPSG:4326 and you would need to define a custom projection to handle the rotation.
I've managed to get something close, but simply stretching the image to fit the polygon doesn't give the exact alignment at the side that the leaflet method does
var properties =
"bl_latitude": -60,
"bl_longitude": -100,
"br_latitude": -60,
"br_longitude": -80,
"centerlatitude": -55,
"centerlongitude": -80.0038,
"icon": "https://www.mikenunn.net/demo/MOD13Q1.A2018017.h13v14.jpg",
"tl_latitude": -50,
"tl_longitude": -77.7862,
"tr_latitude": -50,
"tr_longitude": -62.229,
;
function overlaySource ( properties )
var projection = ol.proj.get('EPSG:3857'); // leaflet projection
var extentSize = [0, 0, 4096, 4096]; // arbitary extent for the projection transforms
var size0 = extentSize[2];
var size1 = extentSize[3];
var url = properties.icon;
var bl = ol.proj.transform([properties.bl_longitude, properties.bl_latitude], 'EPSG:4326', projection);
var tl = ol.proj.transform([properties.tl_longitude, properties.tl_latitude], 'EPSG:4326', projection);
var br = ol.proj.transform([properties.br_longitude, properties.br_latitude], 'EPSG:4326', projection);
var tr = ol.proj.transform([properties.tr_longitude, properties.tr_latitude], 'EPSG:4326', projection);
function normalTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var left = bl[0] + (tl[0]-bl[0]) * coordinates[i+1]/size1;
var right = br[0] + (tr[0]-br[0]) * coordinates[i+1]/size1;
var top = tl[1] + (tr[1]-tl[1]) * coordinates[i]/size0;
var bottom = bl[1] + (br[1]-bl[1]) * coordinates[i]/size0;
var newCoordinates0 = left + (right-left) * coordinates[i]/size0;
var newCoordinates1 = bottom + (top-bottom) * coordinates[i+1]/size1;
c = ol.proj.transform([newCoordinates0, newCoordinates1], projection, 'EPSG:3857');
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + c[0] + ' ' + c[1]);
coordinates[i] = c[0];
coordinates[i+1] = c[1];
return coordinates;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
c = ol.proj.transform([coordinates[i], coordinates[i+1]], 'EPSG:3857', projection);
var left = bl[0] + (tl[0]-bl[0]) * (c[1]-bl[1]) /(tl[1]-bl[1]);
var right = br[0] + (tr[0]-br[0]) * (c[1]-br[1]) /(tr[1]-br[1]);
var top = tl[1] + (tr[1]-tl[1]) * (c[0]-tl[0])/(tr[0]-tl[0]);
var bottom = bl[1] + (br[1]-bl[1]) * (c[0]-bl[0])/(br[0]-bl[0]);
var newCoordinates0 = (c[0]-left)*size0/(right-left);
var newCoordinates1 = (c[1]-bottom)*size1/(top-bottom);
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + newCoordinates0 + ' ' + newCoordinates1);
coordinates[i] = newCoordinates0;
coordinates[i+1] = newCoordinates1;
return coordinates;
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: extentSize
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(coordinate);
,
function(coordinate)
return normalTransform(coordinate);
);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, "EPSG:4326", "EPSG:3857"));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), "EPSG:3857", "EPSG:4326");
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
imageExtent: extentSize,
url: url
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
var imageLayer = new ol.layer.Image(
source: overlaySource( properties ),
opacity: 0.7
)
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
This is my KML method, but that is a simple rotation of a rectangle by a specified angle, not warping it into a quadrilateral where only two of the sides are parallel.
function kmlOverlaySource ( kmlExtent, // KMLs specify the extent the unrotated image would occupy
url,
rotation,
imageSize,
)
// calculate latitude of true scale of equidistant cylindrical projection based on pixels per degree on each axis
proj4.defs('EPSG:' + url, '+proj=eqc +lat_ts=' +
(Math.acos((ol.extent.getHeight(kmlExtent)/imageSize[1])
/(ol.extent.getWidth(kmlExtent)/imageSize[0]))*180/Math.PI) +
' +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs');
if (ol.proj.proj4 && ol.proj.proj4.register) ol.proj.proj4.register(proj4); // if OL5 register proj4
// convert the extents to source projection coordinates
var projection = ol.proj.get('EPSG:' + url);
var projExtent = ol.proj.transformExtent(kmlExtent, 'EPSG:4326', projection);
var angle = -rotation * Math.PI/180;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var point = new ol.geom.Point([coordinates[i],coordinates[i+1]]);
point.rotate(angle, ol.extent.getCenter(projExtent));
var newCoordinates = point.getCoordinates();
coordinates[i] = newCoordinates[0];
coordinates[i+1] = newCoordinates[1];
return coordinates;
function normalTransform(coordinates, output, dimensions)
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: projExtent
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:4326', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:4326');
);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:3857', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:3857');
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
url: url,
imageExtent: projExtent
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
// these would normally be parsed from a KML file
var kmlExtent = [8.433995415151397, 46.65804355828784, 9.144871415151389, 46.77980155828784];
var url = 'https://raw.githubusercontent.com/ReneNyffenegger/about-GoogleEarth/master/kml/the_png_says.png'
var rotation = 30;
var imageSize = [];
var img = document.createElement('img');
img.onload = imageLoaded;
img.src = url;
function imageLoaded()
imageSize[0] = img.width;
imageSize[1] = img.height;
var imageLayer = new ol.layer.Image(
source: kmlOverlaySource(kmlExtent, url, rotation, imageSize),
);
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
Your solution worked to my images that are next to equator lines, but the ones that are next to the poles stay distorted, unfortunately. Now I have discovered that the images should fit inside the bounding box passed (bl_longitude, bl_latitude, ...). Would you have a new tip that you would like to share? Thank you so much for your reply.
– rmmariano
Mar 27 at 18:30
Can you post the original image for that part of South America and all the coordinates that go with it. Clearly it's going to need a rotated projection of some kind. I've managed those for KML ground overlays designed for Google Earth renenyffenegger.ch/notes/tools/Google-Earth/kml/index to work with OpenLayers i.stack.imgur.com/68bYZ.jpg so something similar may be possible with yours.
– Mike
Mar 27 at 20:45
I updated the question including what you would like. Really, both cases seem similar. How did you do to rotate the PNG image? In the question I included a Leaflet code that plots that South America image on the map. Thank you so much.
– rmmariano
Mar 28 at 12:32
1
I've adding working snippets for an attempt at reproducing the leaflet result and for the KML overlay..
– Mike
Mar 29 at 16:34
Thank you Mike so much for your help.
– rmmariano
Mar 29 at 17:27
|
show 1 more comment
If the coordinates are those of the photo and the jpg which contains the rotated photo is in EPSG:4326 (i.e. aligned to meridians and parallels) then you need a bounding box containing all of the corners of the photo
import boundingExtent from 'ol/extent';
....
this.rasterLayerGroup.getLayers().push(
new ImageLayer(
source: new Static(
url: feature.properties.icon,
projection: 'EPSG:4326',
imageExtent: boundingExtent([
[feature.properties.bl_longitude, feature.properties.bl_latitude],
[feature.properties.br_longitude, feature.properties.br_latitude],
[feature.properties.tl_longitude, feature.properties.tl_latitude],
[feature.properties.tr_longitude, feature.properties.tr_latitude]
])
)
)
)
However your top screenshot has the jpg itself rotated. If that is desired the projection isn't EPSG:4326 and you would need to define a custom projection to handle the rotation.
I've managed to get something close, but simply stretching the image to fit the polygon doesn't give the exact alignment at the side that the leaflet method does
var properties =
"bl_latitude": -60,
"bl_longitude": -100,
"br_latitude": -60,
"br_longitude": -80,
"centerlatitude": -55,
"centerlongitude": -80.0038,
"icon": "https://www.mikenunn.net/demo/MOD13Q1.A2018017.h13v14.jpg",
"tl_latitude": -50,
"tl_longitude": -77.7862,
"tr_latitude": -50,
"tr_longitude": -62.229,
;
function overlaySource ( properties )
var projection = ol.proj.get('EPSG:3857'); // leaflet projection
var extentSize = [0, 0, 4096, 4096]; // arbitary extent for the projection transforms
var size0 = extentSize[2];
var size1 = extentSize[3];
var url = properties.icon;
var bl = ol.proj.transform([properties.bl_longitude, properties.bl_latitude], 'EPSG:4326', projection);
var tl = ol.proj.transform([properties.tl_longitude, properties.tl_latitude], 'EPSG:4326', projection);
var br = ol.proj.transform([properties.br_longitude, properties.br_latitude], 'EPSG:4326', projection);
var tr = ol.proj.transform([properties.tr_longitude, properties.tr_latitude], 'EPSG:4326', projection);
function normalTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var left = bl[0] + (tl[0]-bl[0]) * coordinates[i+1]/size1;
var right = br[0] + (tr[0]-br[0]) * coordinates[i+1]/size1;
var top = tl[1] + (tr[1]-tl[1]) * coordinates[i]/size0;
var bottom = bl[1] + (br[1]-bl[1]) * coordinates[i]/size0;
var newCoordinates0 = left + (right-left) * coordinates[i]/size0;
var newCoordinates1 = bottom + (top-bottom) * coordinates[i+1]/size1;
c = ol.proj.transform([newCoordinates0, newCoordinates1], projection, 'EPSG:3857');
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + c[0] + ' ' + c[1]);
coordinates[i] = c[0];
coordinates[i+1] = c[1];
return coordinates;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
c = ol.proj.transform([coordinates[i], coordinates[i+1]], 'EPSG:3857', projection);
var left = bl[0] + (tl[0]-bl[0]) * (c[1]-bl[1]) /(tl[1]-bl[1]);
var right = br[0] + (tr[0]-br[0]) * (c[1]-br[1]) /(tr[1]-br[1]);
var top = tl[1] + (tr[1]-tl[1]) * (c[0]-tl[0])/(tr[0]-tl[0]);
var bottom = bl[1] + (br[1]-bl[1]) * (c[0]-bl[0])/(br[0]-bl[0]);
var newCoordinates0 = (c[0]-left)*size0/(right-left);
var newCoordinates1 = (c[1]-bottom)*size1/(top-bottom);
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + newCoordinates0 + ' ' + newCoordinates1);
coordinates[i] = newCoordinates0;
coordinates[i+1] = newCoordinates1;
return coordinates;
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: extentSize
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(coordinate);
,
function(coordinate)
return normalTransform(coordinate);
);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, "EPSG:4326", "EPSG:3857"));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), "EPSG:3857", "EPSG:4326");
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
imageExtent: extentSize,
url: url
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
var imageLayer = new ol.layer.Image(
source: overlaySource( properties ),
opacity: 0.7
)
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
This is my KML method, but that is a simple rotation of a rectangle by a specified angle, not warping it into a quadrilateral where only two of the sides are parallel.
function kmlOverlaySource ( kmlExtent, // KMLs specify the extent the unrotated image would occupy
url,
rotation,
imageSize,
)
// calculate latitude of true scale of equidistant cylindrical projection based on pixels per degree on each axis
proj4.defs('EPSG:' + url, '+proj=eqc +lat_ts=' +
(Math.acos((ol.extent.getHeight(kmlExtent)/imageSize[1])
/(ol.extent.getWidth(kmlExtent)/imageSize[0]))*180/Math.PI) +
' +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs');
if (ol.proj.proj4 && ol.proj.proj4.register) ol.proj.proj4.register(proj4); // if OL5 register proj4
// convert the extents to source projection coordinates
var projection = ol.proj.get('EPSG:' + url);
var projExtent = ol.proj.transformExtent(kmlExtent, 'EPSG:4326', projection);
var angle = -rotation * Math.PI/180;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var point = new ol.geom.Point([coordinates[i],coordinates[i+1]]);
point.rotate(angle, ol.extent.getCenter(projExtent));
var newCoordinates = point.getCoordinates();
coordinates[i] = newCoordinates[0];
coordinates[i+1] = newCoordinates[1];
return coordinates;
function normalTransform(coordinates, output, dimensions)
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: projExtent
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:4326', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:4326');
);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:3857', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:3857');
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
url: url,
imageExtent: projExtent
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
// these would normally be parsed from a KML file
var kmlExtent = [8.433995415151397, 46.65804355828784, 9.144871415151389, 46.77980155828784];
var url = 'https://raw.githubusercontent.com/ReneNyffenegger/about-GoogleEarth/master/kml/the_png_says.png'
var rotation = 30;
var imageSize = [];
var img = document.createElement('img');
img.onload = imageLoaded;
img.src = url;
function imageLoaded()
imageSize[0] = img.width;
imageSize[1] = img.height;
var imageLayer = new ol.layer.Image(
source: kmlOverlaySource(kmlExtent, url, rotation, imageSize),
);
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
Your solution worked to my images that are next to equator lines, but the ones that are next to the poles stay distorted, unfortunately. Now I have discovered that the images should fit inside the bounding box passed (bl_longitude, bl_latitude, ...). Would you have a new tip that you would like to share? Thank you so much for your reply.
– rmmariano
Mar 27 at 18:30
Can you post the original image for that part of South America and all the coordinates that go with it. Clearly it's going to need a rotated projection of some kind. I've managed those for KML ground overlays designed for Google Earth renenyffenegger.ch/notes/tools/Google-Earth/kml/index to work with OpenLayers i.stack.imgur.com/68bYZ.jpg so something similar may be possible with yours.
– Mike
Mar 27 at 20:45
I updated the question including what you would like. Really, both cases seem similar. How did you do to rotate the PNG image? In the question I included a Leaflet code that plots that South America image on the map. Thank you so much.
– rmmariano
Mar 28 at 12:32
1
I've adding working snippets for an attempt at reproducing the leaflet result and for the KML overlay..
– Mike
Mar 29 at 16:34
Thank you Mike so much for your help.
– rmmariano
Mar 29 at 17:27
|
show 1 more comment
If the coordinates are those of the photo and the jpg which contains the rotated photo is in EPSG:4326 (i.e. aligned to meridians and parallels) then you need a bounding box containing all of the corners of the photo
import boundingExtent from 'ol/extent';
....
this.rasterLayerGroup.getLayers().push(
new ImageLayer(
source: new Static(
url: feature.properties.icon,
projection: 'EPSG:4326',
imageExtent: boundingExtent([
[feature.properties.bl_longitude, feature.properties.bl_latitude],
[feature.properties.br_longitude, feature.properties.br_latitude],
[feature.properties.tl_longitude, feature.properties.tl_latitude],
[feature.properties.tr_longitude, feature.properties.tr_latitude]
])
)
)
)
However your top screenshot has the jpg itself rotated. If that is desired the projection isn't EPSG:4326 and you would need to define a custom projection to handle the rotation.
I've managed to get something close, but simply stretching the image to fit the polygon doesn't give the exact alignment at the side that the leaflet method does
var properties =
"bl_latitude": -60,
"bl_longitude": -100,
"br_latitude": -60,
"br_longitude": -80,
"centerlatitude": -55,
"centerlongitude": -80.0038,
"icon": "https://www.mikenunn.net/demo/MOD13Q1.A2018017.h13v14.jpg",
"tl_latitude": -50,
"tl_longitude": -77.7862,
"tr_latitude": -50,
"tr_longitude": -62.229,
;
function overlaySource ( properties )
var projection = ol.proj.get('EPSG:3857'); // leaflet projection
var extentSize = [0, 0, 4096, 4096]; // arbitary extent for the projection transforms
var size0 = extentSize[2];
var size1 = extentSize[3];
var url = properties.icon;
var bl = ol.proj.transform([properties.bl_longitude, properties.bl_latitude], 'EPSG:4326', projection);
var tl = ol.proj.transform([properties.tl_longitude, properties.tl_latitude], 'EPSG:4326', projection);
var br = ol.proj.transform([properties.br_longitude, properties.br_latitude], 'EPSG:4326', projection);
var tr = ol.proj.transform([properties.tr_longitude, properties.tr_latitude], 'EPSG:4326', projection);
function normalTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var left = bl[0] + (tl[0]-bl[0]) * coordinates[i+1]/size1;
var right = br[0] + (tr[0]-br[0]) * coordinates[i+1]/size1;
var top = tl[1] + (tr[1]-tl[1]) * coordinates[i]/size0;
var bottom = bl[1] + (br[1]-bl[1]) * coordinates[i]/size0;
var newCoordinates0 = left + (right-left) * coordinates[i]/size0;
var newCoordinates1 = bottom + (top-bottom) * coordinates[i+1]/size1;
c = ol.proj.transform([newCoordinates0, newCoordinates1], projection, 'EPSG:3857');
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + c[0] + ' ' + c[1]);
coordinates[i] = c[0];
coordinates[i+1] = c[1];
return coordinates;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
c = ol.proj.transform([coordinates[i], coordinates[i+1]], 'EPSG:3857', projection);
var left = bl[0] + (tl[0]-bl[0]) * (c[1]-bl[1]) /(tl[1]-bl[1]);
var right = br[0] + (tr[0]-br[0]) * (c[1]-br[1]) /(tr[1]-br[1]);
var top = tl[1] + (tr[1]-tl[1]) * (c[0]-tl[0])/(tr[0]-tl[0]);
var bottom = bl[1] + (br[1]-bl[1]) * (c[0]-bl[0])/(br[0]-bl[0]);
var newCoordinates0 = (c[0]-left)*size0/(right-left);
var newCoordinates1 = (c[1]-bottom)*size1/(top-bottom);
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + newCoordinates0 + ' ' + newCoordinates1);
coordinates[i] = newCoordinates0;
coordinates[i+1] = newCoordinates1;
return coordinates;
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: extentSize
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(coordinate);
,
function(coordinate)
return normalTransform(coordinate);
);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, "EPSG:4326", "EPSG:3857"));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), "EPSG:3857", "EPSG:4326");
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
imageExtent: extentSize,
url: url
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
var imageLayer = new ol.layer.Image(
source: overlaySource( properties ),
opacity: 0.7
)
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
This is my KML method, but that is a simple rotation of a rectangle by a specified angle, not warping it into a quadrilateral where only two of the sides are parallel.
function kmlOverlaySource ( kmlExtent, // KMLs specify the extent the unrotated image would occupy
url,
rotation,
imageSize,
)
// calculate latitude of true scale of equidistant cylindrical projection based on pixels per degree on each axis
proj4.defs('EPSG:' + url, '+proj=eqc +lat_ts=' +
(Math.acos((ol.extent.getHeight(kmlExtent)/imageSize[1])
/(ol.extent.getWidth(kmlExtent)/imageSize[0]))*180/Math.PI) +
' +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs');
if (ol.proj.proj4 && ol.proj.proj4.register) ol.proj.proj4.register(proj4); // if OL5 register proj4
// convert the extents to source projection coordinates
var projection = ol.proj.get('EPSG:' + url);
var projExtent = ol.proj.transformExtent(kmlExtent, 'EPSG:4326', projection);
var angle = -rotation * Math.PI/180;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var point = new ol.geom.Point([coordinates[i],coordinates[i+1]]);
point.rotate(angle, ol.extent.getCenter(projExtent));
var newCoordinates = point.getCoordinates();
coordinates[i] = newCoordinates[0];
coordinates[i+1] = newCoordinates[1];
return coordinates;
function normalTransform(coordinates, output, dimensions)
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: projExtent
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:4326', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:4326');
);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:3857', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:3857');
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
url: url,
imageExtent: projExtent
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
// these would normally be parsed from a KML file
var kmlExtent = [8.433995415151397, 46.65804355828784, 9.144871415151389, 46.77980155828784];
var url = 'https://raw.githubusercontent.com/ReneNyffenegger/about-GoogleEarth/master/kml/the_png_says.png'
var rotation = 30;
var imageSize = [];
var img = document.createElement('img');
img.onload = imageLoaded;
img.src = url;
function imageLoaded()
imageSize[0] = img.width;
imageSize[1] = img.height;
var imageLayer = new ol.layer.Image(
source: kmlOverlaySource(kmlExtent, url, rotation, imageSize),
);
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
If the coordinates are those of the photo and the jpg which contains the rotated photo is in EPSG:4326 (i.e. aligned to meridians and parallels) then you need a bounding box containing all of the corners of the photo
import boundingExtent from 'ol/extent';
....
this.rasterLayerGroup.getLayers().push(
new ImageLayer(
source: new Static(
url: feature.properties.icon,
projection: 'EPSG:4326',
imageExtent: boundingExtent([
[feature.properties.bl_longitude, feature.properties.bl_latitude],
[feature.properties.br_longitude, feature.properties.br_latitude],
[feature.properties.tl_longitude, feature.properties.tl_latitude],
[feature.properties.tr_longitude, feature.properties.tr_latitude]
])
)
)
)
However your top screenshot has the jpg itself rotated. If that is desired the projection isn't EPSG:4326 and you would need to define a custom projection to handle the rotation.
I've managed to get something close, but simply stretching the image to fit the polygon doesn't give the exact alignment at the side that the leaflet method does
var properties =
"bl_latitude": -60,
"bl_longitude": -100,
"br_latitude": -60,
"br_longitude": -80,
"centerlatitude": -55,
"centerlongitude": -80.0038,
"icon": "https://www.mikenunn.net/demo/MOD13Q1.A2018017.h13v14.jpg",
"tl_latitude": -50,
"tl_longitude": -77.7862,
"tr_latitude": -50,
"tr_longitude": -62.229,
;
function overlaySource ( properties )
var projection = ol.proj.get('EPSG:3857'); // leaflet projection
var extentSize = [0, 0, 4096, 4096]; // arbitary extent for the projection transforms
var size0 = extentSize[2];
var size1 = extentSize[3];
var url = properties.icon;
var bl = ol.proj.transform([properties.bl_longitude, properties.bl_latitude], 'EPSG:4326', projection);
var tl = ol.proj.transform([properties.tl_longitude, properties.tl_latitude], 'EPSG:4326', projection);
var br = ol.proj.transform([properties.br_longitude, properties.br_latitude], 'EPSG:4326', projection);
var tr = ol.proj.transform([properties.tr_longitude, properties.tr_latitude], 'EPSG:4326', projection);
function normalTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var left = bl[0] + (tl[0]-bl[0]) * coordinates[i+1]/size1;
var right = br[0] + (tr[0]-br[0]) * coordinates[i+1]/size1;
var top = tl[1] + (tr[1]-tl[1]) * coordinates[i]/size0;
var bottom = bl[1] + (br[1]-bl[1]) * coordinates[i]/size0;
var newCoordinates0 = left + (right-left) * coordinates[i]/size0;
var newCoordinates1 = bottom + (top-bottom) * coordinates[i+1]/size1;
c = ol.proj.transform([newCoordinates0, newCoordinates1], projection, 'EPSG:3857');
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + c[0] + ' ' + c[1]);
coordinates[i] = c[0];
coordinates[i+1] = c[1];
return coordinates;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
c = ol.proj.transform([coordinates[i], coordinates[i+1]], 'EPSG:3857', projection);
var left = bl[0] + (tl[0]-bl[0]) * (c[1]-bl[1]) /(tl[1]-bl[1]);
var right = br[0] + (tr[0]-br[0]) * (c[1]-br[1]) /(tr[1]-br[1]);
var top = tl[1] + (tr[1]-tl[1]) * (c[0]-tl[0])/(tr[0]-tl[0]);
var bottom = bl[1] + (br[1]-bl[1]) * (c[0]-bl[0])/(br[0]-bl[0]);
var newCoordinates0 = (c[0]-left)*size0/(right-left);
var newCoordinates1 = (c[1]-bottom)*size1/(top-bottom);
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + newCoordinates0 + ' ' + newCoordinates1);
coordinates[i] = newCoordinates0;
coordinates[i+1] = newCoordinates1;
return coordinates;
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: extentSize
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(coordinate);
,
function(coordinate)
return normalTransform(coordinate);
);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, "EPSG:4326", "EPSG:3857"));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), "EPSG:3857", "EPSG:4326");
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
imageExtent: extentSize,
url: url
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
var imageLayer = new ol.layer.Image(
source: overlaySource( properties ),
opacity: 0.7
)
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
This is my KML method, but that is a simple rotation of a rectangle by a specified angle, not warping it into a quadrilateral where only two of the sides are parallel.
function kmlOverlaySource ( kmlExtent, // KMLs specify the extent the unrotated image would occupy
url,
rotation,
imageSize,
)
// calculate latitude of true scale of equidistant cylindrical projection based on pixels per degree on each axis
proj4.defs('EPSG:' + url, '+proj=eqc +lat_ts=' +
(Math.acos((ol.extent.getHeight(kmlExtent)/imageSize[1])
/(ol.extent.getWidth(kmlExtent)/imageSize[0]))*180/Math.PI) +
' +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs');
if (ol.proj.proj4 && ol.proj.proj4.register) ol.proj.proj4.register(proj4); // if OL5 register proj4
// convert the extents to source projection coordinates
var projection = ol.proj.get('EPSG:' + url);
var projExtent = ol.proj.transformExtent(kmlExtent, 'EPSG:4326', projection);
var angle = -rotation * Math.PI/180;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var point = new ol.geom.Point([coordinates[i],coordinates[i+1]]);
point.rotate(angle, ol.extent.getCenter(projExtent));
var newCoordinates = point.getCoordinates();
coordinates[i] = newCoordinates[0];
coordinates[i+1] = newCoordinates[1];
return coordinates;
function normalTransform(coordinates, output, dimensions)
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: projExtent
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:4326', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:4326');
);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:3857', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:3857');
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
url: url,
imageExtent: projExtent
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
// these would normally be parsed from a KML file
var kmlExtent = [8.433995415151397, 46.65804355828784, 9.144871415151389, 46.77980155828784];
var url = 'https://raw.githubusercontent.com/ReneNyffenegger/about-GoogleEarth/master/kml/the_png_says.png'
var rotation = 30;
var imageSize = [];
var img = document.createElement('img');
img.onload = imageLoaded;
img.src = url;
function imageLoaded()
imageSize[0] = img.width;
imageSize[1] = img.height;
var imageLayer = new ol.layer.Image(
source: kmlOverlaySource(kmlExtent, url, rotation, imageSize),
);
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
var properties =
"bl_latitude": -60,
"bl_longitude": -100,
"br_latitude": -60,
"br_longitude": -80,
"centerlatitude": -55,
"centerlongitude": -80.0038,
"icon": "https://www.mikenunn.net/demo/MOD13Q1.A2018017.h13v14.jpg",
"tl_latitude": -50,
"tl_longitude": -77.7862,
"tr_latitude": -50,
"tr_longitude": -62.229,
;
function overlaySource ( properties )
var projection = ol.proj.get('EPSG:3857'); // leaflet projection
var extentSize = [0, 0, 4096, 4096]; // arbitary extent for the projection transforms
var size0 = extentSize[2];
var size1 = extentSize[3];
var url = properties.icon;
var bl = ol.proj.transform([properties.bl_longitude, properties.bl_latitude], 'EPSG:4326', projection);
var tl = ol.proj.transform([properties.tl_longitude, properties.tl_latitude], 'EPSG:4326', projection);
var br = ol.proj.transform([properties.br_longitude, properties.br_latitude], 'EPSG:4326', projection);
var tr = ol.proj.transform([properties.tr_longitude, properties.tr_latitude], 'EPSG:4326', projection);
function normalTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var left = bl[0] + (tl[0]-bl[0]) * coordinates[i+1]/size1;
var right = br[0] + (tr[0]-br[0]) * coordinates[i+1]/size1;
var top = tl[1] + (tr[1]-tl[1]) * coordinates[i]/size0;
var bottom = bl[1] + (br[1]-bl[1]) * coordinates[i]/size0;
var newCoordinates0 = left + (right-left) * coordinates[i]/size0;
var newCoordinates1 = bottom + (top-bottom) * coordinates[i+1]/size1;
c = ol.proj.transform([newCoordinates0, newCoordinates1], projection, 'EPSG:3857');
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + c[0] + ' ' + c[1]);
coordinates[i] = c[0];
coordinates[i+1] = c[1];
return coordinates;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
c = ol.proj.transform([coordinates[i], coordinates[i+1]], 'EPSG:3857', projection);
var left = bl[0] + (tl[0]-bl[0]) * (c[1]-bl[1]) /(tl[1]-bl[1]);
var right = br[0] + (tr[0]-br[0]) * (c[1]-br[1]) /(tr[1]-br[1]);
var top = tl[1] + (tr[1]-tl[1]) * (c[0]-tl[0])/(tr[0]-tl[0]);
var bottom = bl[1] + (br[1]-bl[1]) * (c[0]-bl[0])/(br[0]-bl[0]);
var newCoordinates0 = (c[0]-left)*size0/(right-left);
var newCoordinates1 = (c[1]-bottom)*size1/(top-bottom);
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + newCoordinates0 + ' ' + newCoordinates1);
coordinates[i] = newCoordinates0;
coordinates[i+1] = newCoordinates1;
return coordinates;
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: extentSize
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(coordinate);
,
function(coordinate)
return normalTransform(coordinate);
);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, "EPSG:4326", "EPSG:3857"));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), "EPSG:3857", "EPSG:4326");
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
imageExtent: extentSize,
url: url
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
var imageLayer = new ol.layer.Image(
source: overlaySource( properties ),
opacity: 0.7
)
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
var properties =
"bl_latitude": -60,
"bl_longitude": -100,
"br_latitude": -60,
"br_longitude": -80,
"centerlatitude": -55,
"centerlongitude": -80.0038,
"icon": "https://www.mikenunn.net/demo/MOD13Q1.A2018017.h13v14.jpg",
"tl_latitude": -50,
"tl_longitude": -77.7862,
"tr_latitude": -50,
"tr_longitude": -62.229,
;
function overlaySource ( properties )
var projection = ol.proj.get('EPSG:3857'); // leaflet projection
var extentSize = [0, 0, 4096, 4096]; // arbitary extent for the projection transforms
var size0 = extentSize[2];
var size1 = extentSize[3];
var url = properties.icon;
var bl = ol.proj.transform([properties.bl_longitude, properties.bl_latitude], 'EPSG:4326', projection);
var tl = ol.proj.transform([properties.tl_longitude, properties.tl_latitude], 'EPSG:4326', projection);
var br = ol.proj.transform([properties.br_longitude, properties.br_latitude], 'EPSG:4326', projection);
var tr = ol.proj.transform([properties.tr_longitude, properties.tr_latitude], 'EPSG:4326', projection);
function normalTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var left = bl[0] + (tl[0]-bl[0]) * coordinates[i+1]/size1;
var right = br[0] + (tr[0]-br[0]) * coordinates[i+1]/size1;
var top = tl[1] + (tr[1]-tl[1]) * coordinates[i]/size0;
var bottom = bl[1] + (br[1]-bl[1]) * coordinates[i]/size0;
var newCoordinates0 = left + (right-left) * coordinates[i]/size0;
var newCoordinates1 = bottom + (top-bottom) * coordinates[i+1]/size1;
c = ol.proj.transform([newCoordinates0, newCoordinates1], projection, 'EPSG:3857');
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + c[0] + ' ' + c[1]);
coordinates[i] = c[0];
coordinates[i+1] = c[1];
return coordinates;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
c = ol.proj.transform([coordinates[i], coordinates[i+1]], 'EPSG:3857', projection);
var left = bl[0] + (tl[0]-bl[0]) * (c[1]-bl[1]) /(tl[1]-bl[1]);
var right = br[0] + (tr[0]-br[0]) * (c[1]-br[1]) /(tr[1]-br[1]);
var top = tl[1] + (tr[1]-tl[1]) * (c[0]-tl[0])/(tr[0]-tl[0]);
var bottom = bl[1] + (br[1]-bl[1]) * (c[0]-bl[0])/(br[0]-bl[0]);
var newCoordinates0 = (c[0]-left)*size0/(right-left);
var newCoordinates1 = (c[1]-bottom)*size1/(top-bottom);
//console.log(coordinates[i] + ' ' + coordinates[i+1] + ' ' + newCoordinates0 + ' ' + newCoordinates1);
coordinates[i] = newCoordinates0;
coordinates[i+1] = newCoordinates1;
return coordinates;
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: extentSize
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(coordinate);
,
function(coordinate)
return normalTransform(coordinate);
);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, "EPSG:4326", "EPSG:3857"));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), "EPSG:3857", "EPSG:4326");
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
imageExtent: extentSize,
url: url
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
var imageLayer = new ol.layer.Image(
source: overlaySource( properties ),
opacity: 0.7
)
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
function kmlOverlaySource ( kmlExtent, // KMLs specify the extent the unrotated image would occupy
url,
rotation,
imageSize,
)
// calculate latitude of true scale of equidistant cylindrical projection based on pixels per degree on each axis
proj4.defs('EPSG:' + url, '+proj=eqc +lat_ts=' +
(Math.acos((ol.extent.getHeight(kmlExtent)/imageSize[1])
/(ol.extent.getWidth(kmlExtent)/imageSize[0]))*180/Math.PI) +
' +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs');
if (ol.proj.proj4 && ol.proj.proj4.register) ol.proj.proj4.register(proj4); // if OL5 register proj4
// convert the extents to source projection coordinates
var projection = ol.proj.get('EPSG:' + url);
var projExtent = ol.proj.transformExtent(kmlExtent, 'EPSG:4326', projection);
var angle = -rotation * Math.PI/180;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var point = new ol.geom.Point([coordinates[i],coordinates[i+1]]);
point.rotate(angle, ol.extent.getCenter(projExtent));
var newCoordinates = point.getCoordinates();
coordinates[i] = newCoordinates[0];
coordinates[i+1] = newCoordinates[1];
return coordinates;
function normalTransform(coordinates, output, dimensions)
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: projExtent
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:4326', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:4326');
);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:3857', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:3857');
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
url: url,
imageExtent: projExtent
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
// these would normally be parsed from a KML file
var kmlExtent = [8.433995415151397, 46.65804355828784, 9.144871415151389, 46.77980155828784];
var url = 'https://raw.githubusercontent.com/ReneNyffenegger/about-GoogleEarth/master/kml/the_png_says.png'
var rotation = 30;
var imageSize = [];
var img = document.createElement('img');
img.onload = imageLoaded;
img.src = url;
function imageLoaded()
imageSize[0] = img.width;
imageSize[1] = img.height;
var imageLayer = new ol.layer.Image(
source: kmlOverlaySource(kmlExtent, url, rotation, imageSize),
);
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
function kmlOverlaySource ( kmlExtent, // KMLs specify the extent the unrotated image would occupy
url,
rotation,
imageSize,
)
// calculate latitude of true scale of equidistant cylindrical projection based on pixels per degree on each axis
proj4.defs('EPSG:' + url, '+proj=eqc +lat_ts=' +
(Math.acos((ol.extent.getHeight(kmlExtent)/imageSize[1])
/(ol.extent.getWidth(kmlExtent)/imageSize[0]))*180/Math.PI) +
' +lat_0=0 +lon_0=0 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs');
if (ol.proj.proj4 && ol.proj.proj4.register) ol.proj.proj4.register(proj4); // if OL5 register proj4
// convert the extents to source projection coordinates
var projection = ol.proj.get('EPSG:' + url);
var projExtent = ol.proj.transformExtent(kmlExtent, 'EPSG:4326', projection);
var angle = -rotation * Math.PI/180;
function rotateTransform(coordinates, output, dimensions) 2;
for (var i=0; i<coordinates.length; i+=dims)
var point = new ol.geom.Point([coordinates[i],coordinates[i+1]]);
point.rotate(angle, ol.extent.getCenter(projExtent));
var newCoordinates = point.getCoordinates();
coordinates[i] = newCoordinates[0];
coordinates[i+1] = newCoordinates[1];
return coordinates;
function normalTransform(coordinates, output, dimensions)
var rotatedProjection = new ol.proj.Projection(
code: 'EPSG:' + url + 'rotated',
units: 'm',
extent: projExtent
);
ol.proj.addProjection(rotatedProjection);
ol.proj.addCoordinateTransforms('EPSG:4326', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:4326', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:4326');
);
ol.proj.addCoordinateTransforms('EPSG:3857', rotatedProjection,
function(coordinate)
return rotateTransform(ol.proj.transform(coordinate, 'EPSG:3857', projection));
,
function(coordinate)
return ol.proj.transform(normalTransform(coordinate), projection, 'EPSG:3857');
);
return new ol.source.ImageStatic(
projection: rotatedProjection,
url: url,
imageExtent: projExtent
);
var tileLayer = new ol.layer.Tile(
source: new ol.source.XYZ(
attributions: [
'Powered by Esri',
'Source: Esri, DigitalGlobe, GeoEye, Earthstar Geographics, CNES/Airbus DS, USDA, USGS, AeroGRID, IGN, and the GIS User Community'
],
//attributionsCollapsible: false,
url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/z/y/x',
maxZoom: 23
)
);
// these would normally be parsed from a KML file
var kmlExtent = [8.433995415151397, 46.65804355828784, 9.144871415151389, 46.77980155828784];
var url = 'https://raw.githubusercontent.com/ReneNyffenegger/about-GoogleEarth/master/kml/the_png_says.png'
var rotation = 30;
var imageSize = [];
var img = document.createElement('img');
img.onload = imageLoaded;
img.src = url;
function imageLoaded()
imageSize[0] = img.width;
imageSize[1] = img.height;
var imageLayer = new ol.layer.Image(
source: kmlOverlaySource(kmlExtent, url, rotation, imageSize),
);
var map = new ol.Map(
layers: [tileLayer, imageLayer],
target: 'map',
logo: false,
view: new ol.View()
);
var imageProj = imageLayer.getSource().getProjection();
map.getView().fit(ol.proj.transformExtent(imageProj.getExtent(), imageProj, map.getView().getProjection()), constrainResolution: false);
html, body, .map
margin: 0;
padding: 0;
width: 100%;
height: 100%;
<link href="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/css/ol.css" rel="stylesheet" />
<script src="https://cdn.rawgit.com/openlayers/openlayers.github.io/master/en/v5.3.0/build/ol.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.5.0/proj4.js"></script>
<div id="map" class="map"></div>
edited Mar 29 at 16:31
answered Mar 27 at 12:34
MikeMike
4,4042 gold badges2 silver badges14 bronze badges
4,4042 gold badges2 silver badges14 bronze badges
Your solution worked to my images that are next to equator lines, but the ones that are next to the poles stay distorted, unfortunately. Now I have discovered that the images should fit inside the bounding box passed (bl_longitude, bl_latitude, ...). Would you have a new tip that you would like to share? Thank you so much for your reply.
– rmmariano
Mar 27 at 18:30
Can you post the original image for that part of South America and all the coordinates that go with it. Clearly it's going to need a rotated projection of some kind. I've managed those for KML ground overlays designed for Google Earth renenyffenegger.ch/notes/tools/Google-Earth/kml/index to work with OpenLayers i.stack.imgur.com/68bYZ.jpg so something similar may be possible with yours.
– Mike
Mar 27 at 20:45
I updated the question including what you would like. Really, both cases seem similar. How did you do to rotate the PNG image? In the question I included a Leaflet code that plots that South America image on the map. Thank you so much.
– rmmariano
Mar 28 at 12:32
1
I've adding working snippets for an attempt at reproducing the leaflet result and for the KML overlay..
– Mike
Mar 29 at 16:34
Thank you Mike so much for your help.
– rmmariano
Mar 29 at 17:27
|
show 1 more comment
Your solution worked to my images that are next to equator lines, but the ones that are next to the poles stay distorted, unfortunately. Now I have discovered that the images should fit inside the bounding box passed (bl_longitude, bl_latitude, ...). Would you have a new tip that you would like to share? Thank you so much for your reply.
– rmmariano
Mar 27 at 18:30
Can you post the original image for that part of South America and all the coordinates that go with it. Clearly it's going to need a rotated projection of some kind. I've managed those for KML ground overlays designed for Google Earth renenyffenegger.ch/notes/tools/Google-Earth/kml/index to work with OpenLayers i.stack.imgur.com/68bYZ.jpg so something similar may be possible with yours.
– Mike
Mar 27 at 20:45
I updated the question including what you would like. Really, both cases seem similar. How did you do to rotate the PNG image? In the question I included a Leaflet code that plots that South America image on the map. Thank you so much.
– rmmariano
Mar 28 at 12:32
1
I've adding working snippets for an attempt at reproducing the leaflet result and for the KML overlay..
– Mike
Mar 29 at 16:34
Thank you Mike so much for your help.
– rmmariano
Mar 29 at 17:27
Your solution worked to my images that are next to equator lines, but the ones that are next to the poles stay distorted, unfortunately. Now I have discovered that the images should fit inside the bounding box passed (bl_longitude, bl_latitude, ...). Would you have a new tip that you would like to share? Thank you so much for your reply.
– rmmariano
Mar 27 at 18:30
Your solution worked to my images that are next to equator lines, but the ones that are next to the poles stay distorted, unfortunately. Now I have discovered that the images should fit inside the bounding box passed (bl_longitude, bl_latitude, ...). Would you have a new tip that you would like to share? Thank you so much for your reply.
– rmmariano
Mar 27 at 18:30
Can you post the original image for that part of South America and all the coordinates that go with it. Clearly it's going to need a rotated projection of some kind. I've managed those for KML ground overlays designed for Google Earth renenyffenegger.ch/notes/tools/Google-Earth/kml/index to work with OpenLayers i.stack.imgur.com/68bYZ.jpg so something similar may be possible with yours.
– Mike
Mar 27 at 20:45
Can you post the original image for that part of South America and all the coordinates that go with it. Clearly it's going to need a rotated projection of some kind. I've managed those for KML ground overlays designed for Google Earth renenyffenegger.ch/notes/tools/Google-Earth/kml/index to work with OpenLayers i.stack.imgur.com/68bYZ.jpg so something similar may be possible with yours.
– Mike
Mar 27 at 20:45
I updated the question including what you would like. Really, both cases seem similar. How did you do to rotate the PNG image? In the question I included a Leaflet code that plots that South America image on the map. Thank you so much.
– rmmariano
Mar 28 at 12:32
I updated the question including what you would like. Really, both cases seem similar. How did you do to rotate the PNG image? In the question I included a Leaflet code that plots that South America image on the map. Thank you so much.
– rmmariano
Mar 28 at 12:32
1
1
I've adding working snippets for an attempt at reproducing the leaflet result and for the KML overlay..
– Mike
Mar 29 at 16:34
I've adding working snippets for an attempt at reproducing the leaflet result and for the KML overlay..
– Mike
Mar 29 at 16:34
Thank you Mike so much for your help.
– rmmariano
Mar 29 at 17:27
Thank you Mike so much for your help.
– rmmariano
Mar 29 at 17:27
|
show 1 more comment
Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.
Got a question that you can’t ask on public Stack Overflow? Learn more about sharing private information with Stack Overflow for Teams.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55356335%2fadd-a-rotated-satellite-image-on-the-map-using-openlayers-5%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Do you have lon/lat values for tl and br or a rotation value?
– Mike
Mar 26 at 20:35
Yes, I do lon/lat values for the four points of the image bounding box. They are "bl_latitude, bl_longitude, br_latitude, br_longitude, tl_latitude, tl_longitude, tr_latitude, tr_longitude". A rotation value I do not have. Should I calculate it by the bbox values?
– rmmariano
Mar 27 at 11:38
Does it not belong to GIS SE site?
– Gilles-Antoine Nys
Mar 29 at 16:35
"Ask a question", on OpenLayers site, redirects to StackOverflow instead of GIS SE.
– rmmariano
Mar 29 at 17:25