B
B
busidoway2020-02-03 16:19:32
JavaScript
busidoway, 2020-02-03 16:19:32

How to position the image on the map by points?

Good afternoon. Depend on one task.

Let's say we're loading an image on a page. Specify two points A and B on the image. The coordinates of the points are specified in pixels: the left input field - top indent (y coordinate), the right input field - left indent (x coordinate).

5e37e611a05f0682355980.png

Next, on the map, we indicate two points where you want to place the image. The maps used by OpenStreetMap are rendered via the LeafLet library .

5e37f20d98ccc099624639.png

Here the coordinates are in degrees.

Next, the image is loaded on top of the map. The points on the image must match the points on the map. The dots match, but the image is stretched.

5e38123486a87805440733.png

So far, I've got this option.

To place the image, I used a self-written formula:

Ax - x point A on the image; Ay - y point A on the image
Bx - x point B on the image; By - y point A on the image
Agx - x point A on the map (longitude); Agy - y point A on the map (latitude)
Bgx - x point B on the map (longitude); Bgy - y point B on the map (latitude)
W - image width; H - image height

Find the delta of points A and B by x (on the image):
ABX = Ax - Bx
Find the delta of points A and B by y (on the image):
ABY = Ay - By

Find the delta of points A and B by x ( on the image): map):
ABGX = Agx - Bgx
Find the delta of points A and B by y (on the map):
ABGY = Agy - Bgy

Find the coordinates of points:
GX1 = (0 - Ax) * ABGX / ABX + Agx
GX2 = GX3 = (W - Ax) * ABGX / ABX + Agx
GY1 = GY2 = (0 - Ay) * ABGY / ABY + Agy
GY3 = (H - Ay) * ABGY / ABY + Agy

GX3 and GY3 are additional coordinates. In principle, they can be ignored. Needed to expand the image on the map.

Here is an example code:

//отображение изображения по координатам из файла data_file_map.json (в файле содержатся данные координат)
$.ajax({
    url: '/uploads/data_file_map.json',
    dataType: 'json',
    success: function (data) {

        //координаты, по которым выстраивается изображение
        var bounds = ;
        //создание слоя для изображения
        var image_layer = L.imageOverlay('/uploads/'+data.fileName, bounds, {opacity:0.4});
        //добавление слоя на карте
        image_layer.addTo(map);

    }
});

//получение данных изображения из data_image_param.json
$.ajax({
    url: '/uploads/data_image_param.json',
    dataType: 'json',
    success: function (data) {

        //координаты точек на карте
        var lat1 = $('#lat1').val(),
            lat2 = $('#lat2').val(),
            lat3 = $('#lat3').val(),
            lng1 = $('#lng1').val(),
            lng2 = $('#lng2').val(),
            lng3 = $('#lng3').val();
        
        //данные изображения
        var x1 = 0,
            y1 = 0,
            px1 = data.lng1, //x точки A
            py1 = data.lat1, //y точки A
            px2 = data.lng2, //x точки B
            py2 = data.lat2, //y точки B
            img_width = data.imgWidth, //ширина изображения
            img_height = data.imgHeight; //высота изображения
            
        var dpx = parseInt(px1) - parseInt(px2); //x точки А минус x точки B (на изображении)
        var dpy = parseInt(py1) - parseInt(py2); //y точки А минус y точки B (на изображении)
        var dpgx = lng1 - lng2; //долгота точки A минус долгота точки B (на карте)
        var dpgy = lat1 - lat2; //широта точки A минус широта точки B (на карте)
        
        //находим координаты для точек
        var gx1 = (0          - px1) * dpgx / dpx + parseFloat(lng1);
        var gx3 = (img_width  - px1) * dpgx / dpx + parseFloat(lng1);
        var gy1 = (0          - py1) * dpgy / dpy + parseFloat(lat1);
        var gy3 = (img_height - py1) * dpgy / dpy + parseFloat(lat1);
        var gx2 = gx3;
        var gy2 = gy1;

        //gx3 и gy3 нужны для корректного отображения изображения на карте (так требует leaflet, иначе изображение отобржается не так как надо)

        //полученные данные (gx1, gx2, gx3, gy1, gy2, gy3) сохраняются, допустим, в файл data_file_map.json, который используется для отображения изображения на карте

        /*

        .....
        
        */
                
    }
});


As a result, the image should be placed exactly on the points while maintaining its proportions and, if necessary, with the angle of inclination. Like here:

5e38149a10b59655425068.png

Actually, the question arises: how to set the exact dimensions and determine the angle of inclination in order to achieve a match in points without violating the proportions of the image?

PS

To find the angle, I tried the following option.

Uploaded an image. The image is stretched by dots. I found the length of the segments between points A and B both on the image and on the map. Determined the percentage of the difference between the segments. With the help of this percentage, I set the width for the image. The result is an image with preserved proportions.
Next, to calculate the rotation angle, I defined an "imaginary" triangle between points A, B (image) and B (map).

5e3819374f867219140256.png

Wrote a function to calculate the arc cosine like this one:

//арккосинус A
function getAcosA(a, b, c) {
          
  var arccos, angle;
  arccos = (a*a + c*c - b*b)/(2*a*c);
  angle = Math.acos(arccos);
  return (angle*180)/Math.PI;
          
}


The angle counts, but is rather inaccurate.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
H
hint000, 2020-02-03
@busidoway

Without stretching, calculate the angle alpha of vector AB relative to OY (or OX) in the picture.
Then calculate the beta angle on the map in the same way. Subtract one angle from the other - get the desired angle of rotation.
And the compression / stretching coefficient is just the ratio of the lengths of the segments AB in the picture and on the map (oh, why did you designate them with the same letters? at least in one place small letters, in another large ones, otherwise it’s inconvenient ...)
PS In general case, you need to take into account the cartographic projection , but this will complicate the task by an order of magnitude.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question