2

Considering the code below (which uses openlayers and Viglino's ol-ext), how do I get the extent of the geoimg?

var map = new ol.Map({
  target: 'map',
  view: new ol.View({
    zoom: 18,
    center: ol.proj.fromLonLat([4.8728,52.3316])
  }),
  layers: [new ol.layer.Tile({
    source: new ol.source.OSM()
  })]
})

var geoimg = new ol.layer.Image({
  name: "Georef",
  opacity: 0.5,
  source: new ol.source.GeoImage({
    url: 'image.jpg',
    imageCenter: ol.proj.fromLonLat([4.8728,52.3316]),
    projection: 'EPSG:3857',
    imageScale: [1, 1]
  })
})
map.addLayer(geoimg);

Here is a jsfiddle, which shows how a 160x160 pixels geoimage, with an imageScale of [1,1] measures 100 by 100 meters on the map. You can measure it yourself, but I placed the picture on the map between 2 streets that I know are 100 meters apart.

Things that do not work:

geoimg.getExtent()

it correctly says undefined because getExtent only gets the extent that was set for the Image Layer, which is a masking extent according to the OpenLayers documentation.

I also tried to look into geoimg.values_.source.canvas_.extent, which obviously returns the extent of the canvas, i.e. the div with the id="map"

EDIT1: After the discussion I had with @TomazicM in the comments, I noticed that my question might not be clear. The picture I am overlaying is not a map picture as in Vigliano's example, but a regular picture. I don't want to find out the coordinates of where the geoimage should land to be georeferenced. This wouldn't make sense in the context of the image not being an actual map image. I only want to overlay an image somewhere on the map (which works perfectly, with the rotation and everything), and afterwards extract the map coordinates of the corners of the image as it was overlaid on the map.

If imageScale =[1,1] would have meant that 1 pixel = 1 map units, I would have managed to do the math myself. Math is not the problem. The problem is that scale seems to create an image that is about 1 pixel ~ 0.625 meters, for the EPSG:3857 CRS. I don't know whether this 0.625 or a close value is hardcoded somewhere in ol-ext, or in openlayers or maybe is calculated based on something. Either way, what I am missing is a reliable way to calculate the map coordinates of the corners of the image, once the image is overlaid on the map.

Andrei
  • 766
  • 5
  • 16
  • You are the one who will have to tell GeoImage source the extent of image, which in this case means the following parameters: imageCenter, imageScale, imageCrop and imageRotation. (see example http://viglino.github.io/ol-ext/examples/layer/map.geoimage.html) – TomazicM Feb 03 '19 at 11:08
  • I saw the example, but imageCrop just masks part of the image, imageRotation, rotates it, imageCenter gives the center coordinates and imageScale sets an arbitrary scale. What I mean by arbitrary is that for an image 160x160, at a [1,1] scale, the image occupies about 100meters by 100 meters. How can I reliably find out the coordinates of a corner of the image? – Andrei Feb 03 '19 at 11:13
  • Parameters mageCenter, imageRotation and imageScale are not arbitrary, they should reflect actual geo attributes of image. Play with example and you will see how overlayed image changes with them. – TomazicM Feb 03 '19 at 11:41
  • I did, they change the image, but they still don't help me find the coordinates of 2 opposite corners, because imageScale does net set the pixel to mapunits ratio. As I said, for a 160x160 pixels image, with an imageRatio of [1,1] I get a ~ 100m X 100m image overlaid on the map. How am I supposed to find the coordinates? First divide the pixels by the arbitrary number 1.6 and them multiply by scale? – Andrei Feb 03 '19 at 11:51
  • There is no shortcut here. Either you have to know actual paramateters of your image (center, scale) or you have to experimentaly get them by constructing layers like in the exmaple and then play with parameters until you visually get them right. – TomazicM Feb 03 '19 at 12:07
  • There is definitely a misunderstanding, I don't want to georeference the image like in the example (it's not even a map picture, just a regular picture), I just want to overlay it over the map, which I did, and then extract the corner map coordinates of wherever the image was set on the map. I don't care where the image is placed on the map, but after it is placed on the map, I want to extract its corner coordinates. Am I more clear now? – Andrei Feb 03 '19 at 12:18
  • Yes, now it's finally clear! I'll have a look at this after lunch (if nobody gives answer before). – TomazicM Feb 03 '19 at 12:22
  • Yes, scale [1, 1] means that 1 map unit is 1 pixel. Did you try explicitly to set parameter imageScale: [1, 1] ? – TomazicM Feb 03 '19 at 18:19
  • yes, I did try to set it specifically to [1,1] and I measured the distance between the corners approximately on the same osm map in qgis and for an image with a width of 160 pixels, the distance it covers is about 100 meters. I am saying approximately because I couldn't find a way to extract it somehow. I'll try to do a reproduceable example on jsfiddle or something like this and I'll add it to the question. – Andrei Feb 03 '19 at 18:58
  • I did the same with the official example cited above and got the correct results. I measured by latching on singleclick event and the displayed clicked coordinates. What is yout monitor DPI? – TomazicM Feb 03 '19 at 19:17
  • I have 2 screens(92 dpi and 122), but I don't see how this can affect the measurements. Shouldn't the dpi affect both the osm background map and my picture overlay? At this point I feel the need to say that I did NOT literally measured the distance on my screen with a real life ruler, but I used the tool provided in qgis to measure distances. I'm still working on a full reproducible example to post. Thanks a lot for the support – Andrei Feb 03 '19 at 19:30
  • 1
    Should be so. I just asked beacuse you can never know what info might help. I'm really interested to check your jsfiddle. One can always learn something new. – TomazicM Feb 03 '19 at 19:40
  • @TomazicM on https://jsfiddle.net/mirt001/kxuseLgf/5/ I get the same results as on my localhost test. The distance between Wijenburg and Loevestein streets is 100 meters, and the orange image is 160 x 160 pixels. – Andrei Feb 03 '19 at 20:29
  • This is getting interesting. If I click on the left and right border of the overlayed image, I get the following projected x values: 542357 and 542517. Difference is exactly 160, which is 160 projected map units. But when I add ScaleLine control, it shows that distance is actually 100m. This has something to do with the projection, but I'm fairly new to GIS and the moment have no idea why this is so. – TomazicM Feb 03 '19 at 21:35

1 Answers1

1

So here is finally the answer. If GeoImage is declared with imageScale: [1, 1] then each pixel on map measures 1 map unit. These units are usually called meters, but in projected CRS (usually Mercator) do not correspond to actual meters in nature. Further north you go, more distorted they become. Scale factor for short distances is factor = 1 / cos(latitude) (see Calculating distance scale factor by latitude for Mercator). cos(52.3316) is 0.611, almost exactly the value you found out in your calculation.

So, if center of your image in projected coordinates is

var center = ol.proj.fromLonLat([4.8728,52.3316]);

and dimensions of your picture are 160 by 160 pixels, then coordinates of upper left corner of the picture are

var imgUpLeft = ol.proj.toLonLat([center[0] - 80, center[1] - 80]);
TomazicM
  • 25,601
  • 22
  • 29
  • 39