1

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.

1

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]);
7
  • It is still the same, I think I misunderstand the projection. In Leaflet I can use L.CRS.Simple to set my own coordinate system,and I can use those scale functions to transform my coordinates to pixel,then feed to Leaflet data layers, but I have no idea how to do it in OpenLayers. How do I define the view projection for custom tiles e.g. game or indoor map? I don't know what projection Openlayers uses to transform my coordinates to pixel. Is it the view projection I defined?
    – Chi
    Nov 16 '20 at 2:23
  • and I don't understand how to set the resolution, the scale is 0.05, meaning 1 pixel =0.05 meters
    – Chi
    Nov 16 '20 at 6:38
  • In the view of your comments question is completely different that I thought. Please edit your question with the additional info from your comments.
    – TomazicM
    Nov 16 '20 at 10:29
  • I have updated my question,plz have a look
    – Chi
    Nov 16 '20 at 11:35
  • I think I use the projection in the wrong way, there's no need to reproject the projection, the default one is measured in meters
    – Chi
    Nov 16 '20 at 14:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.