Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

transformTranslate distorts the polygon shape #2419

Open
just-ajs opened this issue Mar 27, 2023 · 14 comments
Open

transformTranslate distorts the polygon shape #2419

just-ajs opened this issue Mar 27, 2023 · 14 comments

Comments

@just-ajs
Copy link

Turf 6.5.0

TransformTranslate distorts the shape when translated across bigger distances, this is visible in this example, when used transformTransalte with parameters 2000, 66.

const leningrTranslated = transformTranslate(leningr.data, 2000, 66);

The original shape:
image

And transformed shape:
image

@stebogit
Copy link
Collaborator

stebogit commented Apr 2, 2023

@just-ajs though without seeing much details, from your little code I believe the issue could be due to mercator projection when you translate your polygon way up north.
That is a known problem on web - i.e. flat - maps.

@smallsaucepan
Copy link
Member

Hi @just-ajs. Do you still have the geojson used to generate the screenshots above? Would you mind attaching them to this issue so we can reproduce it?

@jtheisen
Copy link

The implementation seems to translate each vertex of the shape individually instead of really moving the shape.

I had the exact same issue in my naive implementation and was therefore looking for an existing library doing this job for me. Alas, turfjs does the same thing.

You see what's going on in this notebook.

@smallsaucepan
Copy link
Member

Hi @jtheisen. Would you mind making your notebook public? Can't access it currently.

@jtheisen
Copy link

@smallsaucepan Sorry, it's public now.

@smallsaucepan
Copy link
Member

Thanks @jtheisen. Can access it now.

From what I can see this is the expected behaviour. transformTranslate currently only works on a 2d projection. What looks distorted on a globe:

Image

Looks as expected when projected in 2D:

Image

The problem reported by OP is definitely an issue, though that distortion only occurs when the geometry is also moved laterally. We see that with the green square:

Image

Hope that helps to explain what you're seeing. Any remaining questions though, please drop us a node.

@jtheisen
Copy link

@smallsaucepan thanks for the response.

I still believe this is ultimately the same issue for both me and @just-ajs, it's just that translating a rectangle straight north happens to not distort it when projected equirectangularly. I believe what the function is doing internally is simple moving all points of the shape along the Rhumb lines, which will never really preserve shapes under any projection, even Mercator itself (where the Rhumb lines are straight) - I may be mistaken though, I'm not very familiar with this.

I would recommend two things.

At the very least, update the documentation for this function. Currently, the page doesn't mention any projection at all, so I think it's reasonable to assume that it would translate the shape on the sphere, and we agree that's not what it's doing.

As a second much more distant suggestion I wonder why the semantics I was expecting aren't offered as well. I've searched around a bit and I can't find a library implementation of this anywhere (in js). This is needed for example in those "see how big this country is when placed here next to this other on the globe" type of renderings (You could also draw two things on top of each other and use two different projections, one rotated. That works, but I use observable.Plot, and that doesn't let me use two projections in one chart).

Implementation-wise, it would probably have to transform the coords into 3-vectors, then rotate them together, and then convert each of them back. (That would move them along great circles, not Rhumb lines though.) Maybe there's also some tricky stuff with meridian cutting again.

@jtheisen
Copy link

To those souls who find this issue and need a solution, here's a way to do this using threejs:

function makeRotateSphere(x, y, z, a) {
  const f = (2 * Math.PI) / 360;
  const quaternion = new THREE.Quaternion();
  quaternion.setFromAxisAngle(new THREE.Vector3(x, y, z), a * f);
  const v = new THREE.Vector3();
  const s = new THREE.Spherical(1, 0, 0);
  return function rotate([longitude, latitude]) {
    const polar0 = 90 - latitude;
    const azimu0 = longitude;
    s.radius = 1;
    s.phi = polar0 * f;
    s.theta = azimu0 * f;
    v.setFromSpherical(s);
    v.applyQuaternion(quaternion);
    s.setFromVector3(v);
    return [s.theta / f, 90 - s.phi / f];
  };
}

makeRotateSphere(x, y, z, a) creates a function that rotates a pair of coordinates around the sphere's center (and thereby "translates" the point along great circles) along the axis given by x, y and z by a degrees. Applying this to every coordinate in the shape does this for the shape. There seems to be no further difficulty.

@smallsaucepan
Copy link
Member

Hi @jtheisen.

I believe what the function is doing internally is simple moving all points of the shape along the Rhumb lines

Agree that does seem to be the root of the problem with the skewing shown in the original post. What I was getting at though was fixing the skewing won't necessarily fix your issue as well. Even when operating correctly the kind of translation offered (planar) would still give you coords that render as a narrowing polygon if laid out on a sphere.

Understand that isn't what you want. Unfortunately though Turf doesn't currently offer both planar and spherical implementations for many functions.

I wonder why the semantics I was expecting aren't offered as well

It's just resourcing. Over time Turf has become a mix of planar and spherical implementations, and making that cohesive takes time, especially with it being a volunteer run project.

At the very least, update the documentation for this function

For sure. Would you like to contribute by submitting a PR to add some clarifying notes?

@jtheisen
Copy link

@smallsaucepan Sure, I made a pull request in the doc repo:

Turfjs/turf-www#217

@jtheisen
Copy link

It's just resourcing. Over time Turf has become a mix of planar and spherical implementations, and making that cohesive takes time, especially with it being a volunteer run project.

Btw, I was more puzzled about this kind of thing not being anywhere to be found in the js world, not specifically in turfjs. I kind of expected it to be in d3.

@smallsaucepan
Copy link
Member

Oh, got you. Not sure why it isn't elsewhere. Might be more people in that space turn to python or a similar science-y language first.

Thanks for submitting that PR. Would you mind though adding those lines in the Turfjs/turf repo instead? The docs in turf-www are generated automatically from the comments in the code.

https://github.com/Turfjs/turf/blob/master/packages/turf-transform-translate/index.ts

Then we can do a doc generation run and that will go out to the website.

@jtheisen
Copy link

There's a new pull request, #2831, and I've removed the old one.

@smallsaucepan
Copy link
Member

Awesome. Thank you!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants