TransWikia.com

How do I transform custom coordinates to pixel in vector layer in OpenLayers 6

Geographic Information Systems Asked on June 7, 2021

I have a XYZ layer for tiles(generated from an 1065 * 950 Image using gdal2tiles), and a vector layer for features, I want to use my own pixel transformation to set the coordinates of the features.

 this.extent = [0, 0, this.imgWidth, this.imgHeight];

 this.projection = new Projection({
  code: "warehouse-tile-image",
  units: "pixel",
  extent: this.extent,
});

this.view = new View({
  projection: this.projection,
  center: getCenter(
   this.extent
  ),
  zoom: 2,
  maxZoom: 3,
});
this.tileSource = new XYZ({
  url: "assets/map/{z}/{x}/{y}.png",
  minZoom: 0,
  projection: this.projection,
  maxZoom: 3,
  tileSize: 256,
});
 this.layer = new VectorLayer({
  source: new VectorSource(),
});

I want to use this d3 scale function to set the pixel coordinates:

//The coordinate of data is in meter
const scale= 0.05
const max_x = scale* this.imgWidth + this.origin.x; 
const max_y = scale* this.imgHeight + this.origin.y;
this.xScale = scaleLinear()
  .domain([this.origin.x, max_x])
  .range([0, this.imgWidth]);
this.yScale = scaleLinear()
  .domain([this.origin.y, max_y])
  .range([this.imgHeight, 0]);

So I can transform the custom coordinates to pixel by using

this.xScale(x) = pixel x

and

this.yScale(y) = pixel y

This is how I do in Leaflet in order to re-projection:

    const denominator = Math.pow(2, this.maxZoom);
    L.CRS.MySimple = L.Util.extend({}, L.CRS.Simple, {
        /**
         * max zoom level >= log2(max(width,height)/tilesize)
         * a,c = 1 / 2^max zoom level
         **/
        transformation: new L.Transformation(
            1 / denominator, //a
            0, //b
            1 / denominator, //c
            0 //d
        ),
    });
 this.mapOptions = {
        layers: [
            L.tileLayer(this.tileUrl, {
                maxZoom: this.maxZoom,
                tileSize: 256,
                noWrap: true,
                bounds: bounds,
            }),
        ],
        zoom: this.maxZoom,
        crs: L.CRS.MySimple,
        maxZoom: this.maxZoom,
        minZoom: 0,
        maxBounds: bounds,
        zoomControl: false,
        center: L.latLng([this.imgWidth, this.imgHeight]),
    };
 private transformCoord(coordinate: { x: number; y: number }): number[] {
    //This function will transform custom coordinates to pixel coordinate using d3 scale
    return [this.xScale(coordinate.x), this.yScale(coordinate.y)];
}
//Feature geometry 
geometry: {
                type: "Point",
                coordinates: this.transformCoord(data.pose.position),
            },

And then I just use those scale function to transform the coordinates to pixel coordinates and feed to the data layer(Leaflet-realtime which use a Geojson layer).

However, it is different in OpenLayers which seems to do the pixel transformation automatically for me.
My problem is I don’t understand how the projections work in OpenLayers, I have no idea how to do the same as in Leaflet.

One Answer

You can define reverse scale functions, where all you have to do is to exchange .domain and .range values:

this.xScaleReverse = scaleLinear()
  .domain([0, this.imgWidth])
  .range([this.origin.x, max_x]);
this.yScaleReverse = scaleLinear()
  .domain([this.imgHeight, 0])
  .range([this.origin.y, max_y]);

Answered by TomazicM on June 7, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP