JamesLMilner / terra-draw

A library for drawing on maps that supports Mapbox, MapLibre, Google Maps, OpenLayers and Leaflet out the box
https://terradraw.io
MIT License
448 stars 52 forks source link

Respect user projection in openlayers adapter #319

Open typebrook opened 1 week ago

typebrook commented 1 week ago

Describe the bug Fail to render/add features on different projections

Terra Draw npm version 1.0.0-beta.1

To Reproduce Apply example from doc except setting projection for View:

const map = new Map({

    layers: [
        new TileLayer({
            source: new OSM(),
        }),
    ],
    target: 'map',
    view: new View({
        center: fromLonLat([0, 0]),
        zoom: 2,
        projection: 'EPSG:4326'
    }),
    controls: [],
});

Expected behavior With specific projection, newly added features has coordinate value in lon/lat, and rendered feature could be shown correctly

Screenshots Screenshot_2024-09-01-20-44-04_1920x1080

Related Code

https://github.com/JamesLMilner/terra-draw/blob/1b1e9767fb27f258da700f72d551bc579e5d6b83/src/adapters/openlayers.adapter.ts#L74

In constructor, the following assignment should fix it: this._projection = this._map.getView().getProjection().getCode();

typebrook commented 1 week ago

Sorry, this issue should be related to userProjection in ol/proj, not about ol.View.

My expected behavior should be:

  1. Setting projection with proj.setUserProjection("EPSG:4326") or proj.setGeographic(), than we draw features within coordinates in lon/lat as usual.
  2. Do nothing with user projection, or set projection with proj.setUserProjection("EPSG:3857"), than we draw features within coordinates of EPSG:3857 in meters. For example:
    "geometry": {
    "type": "Point",
    "coordinates": [
        13522713,
        2806345
    ]
    }

Here is a quick workaround

If this kind of behavior is acceptable, than example in guide and validation in geometry/boolean/is-valid-coordinate.ts should be also changed

JamesLMilner commented 1 week ago

Hey @typebrook, that's for your interest in the project and your detailed issue report, super helpful in trying to help you here.

I think the problem is at the moment is that currently Terra Draw only officially supports Web Mercator projections, with some additional support for Globes, so we can't necessarily support user set projections at this point in time. All internal store geometries are stored in WGS84.

This being said I am intrigued what projection: 'EPSG:4326' actually does in OpenLayers, as WGS84 is a geographic coordinate system and not a projection. There might be a way to support both 'EPSG:4326' and 'EPSG: 3857' if I can understand what is going on there exactly. I think this post sort of explains what OpenLayers is doing there, basically naively mapping Latitude and Longitude onto a grid.

Let me experiment with this a little more and get back to you. I don't think we can support arbitrary projections at this point but maybe we can support 'EPSG:4326' for OpenLayers.

typebrook commented 1 week ago

I am intrigued what projection: 'EPSG:4326' actually does in OpenLayers

The trick part is: getCoordinateFromPixel and getPixelFromCoordinate actually returns/use coordinates in user projection, which is defined in ol/proj.

setUserProjection or useGeographic is used to specify user projection.