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
Turf Transform #752
Turf Transform #752
Conversation
👍 awesome stuff @stebogit I'm going to find the time this week to have a look at this in more details. Keep it up! |
@dpmcmlxxvi @morganherlocker @DenisCarriere I implemented the first module Thoughts? Suggestions? |
Also, I worked based on the assumption that the transformations were meant to be on the plain, forgetting about, or better ignoring on purpose, the earth's curvature. This would make the transformations valid only in relatively "small" (compared to earth radius) areas. |
Using the |
I agree that the FWIW, there's nothing wrong with having a more efficient implementation that makes certain assumptions (e.g., local plane approximation) but you may want to implement that as an option if users complain about performance issues and not preemptively optimize. |
👍 I'll rewrite it then |
I implemented |
/** | ||
* http://turfjs.org/docs/#transform-rotate | ||
*/ | ||
declare function rotate(geojson: Feature<any> | GeometryObject, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🥇 These Typescript definitions are not obvious, the goal with this would be to have the Input be equal to the Ouptut.
Which would equal to:
Geometry<Point>
=>Feature<Point>
Feature<Polygon>
=>Feature<Polygon>
Right now the current state mutates the geometry type to any
:
Geometry<Point>
=>Feature<any>
Feature<Polygon>
=>Feature<any>
rotate
type GeometryObject = GeoJSON.GeometryObject;
type Feature<Geom extends GeometryObject> = GeoJSON.Feature<Geom>;
type Point = Feature<GeoJSON.Point> | GeoJSON.Point | number[];
/**
* http://turfjs.org/docs/#transform-rotate
*/
declare function rotate<Geom extends GeometryObject>(
geojson: Feature<Geom> | Geom,
angle: number,
pivot?: Point): Feature<Geom>;
Example from translate
type GeometryObject = GeoJSON.GeometryObject;
type Feature<Geom extends GeometryObject> = GeoJSON.Feature<Geom>;
/**
* http://turfjs.org/docs/#transform-translate
*/
declare function translate<Geom extends GeometryObject>(
geojson: Feature<Geom> | Geom,
distance: number,
direction: number,
units?: string): Feature<Geom>;
Note: I'll push a commit to update those definitions.
*/ | ||
const suite = new Benchmark.Suite('turf-transform-rotate'); | ||
for (const {name, geojson} of fixtures) { | ||
let {angle, pivot} = geojson.properties || {}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let
is used if the variable will be reassigned, in this scenario const
should be used since it doesn't change after it's been declared.
This code will still work, but some aggressive linters have started to catch this as an linting error.
* @param {number} distance length of the motion; negative values determine motion in opposite direction | ||
* @param {number} direction of the motion; angle from North between -180 and 180 decimal degrees, positive clockwise | ||
* @param {string} [units=kilometers] in which `distance` will be express; miles, kilometers, degrees, or radians | ||
* (optional, default `kilometers`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(optional, default "kilometers")
is not required since it's already defined as optional using the square brackets.
/**
* @param {string} [units=kilometers]
"dependencies": { | ||
"@turf/helpers": "^4.3.0", | ||
"@turf/invariant": "^4.3.0", | ||
"@turf/meta": "^4.3.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since @turf/meta
does not exist in the index.js
there's a new test in package/turf/test.js
that will catch this as an error.
const fs = require('fs'); | ||
const load = require('load-json-file'); | ||
const write = require('write-json-file'); | ||
const helpers = require('@turf/helpers'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the tests are now written in ES6 (NodeJS 6+) you can use the following when importing multiple methods from a module:
const {point, featureCollection} = require('@turf/helpers');
|
||
const translated = translate(geojson, distance, direction, units, zTranslation); | ||
|
||
// style result |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap these styled results as their own dedicated functions (ex: colorize(geojson)
).
That way the tests can be more readable and the colorize
method can be reused if need be.
function colorize(geojson) {
// style result
if (geojson.geometry.type === 'Point' || geojson.geometry.type === 'MultiPoint') {
geojson.properties['marker-color'] = '#F00';
geojson.properties['marker-symbol'] = 'star';
} else {
geojson.properties['stroke'] = '#F00';
geojson.properties['stroke-width'] = 4;
}
return geojson;
}
var rotatedPoly = turf.rotate(poly, 85); | ||
|
||
//addToMap | ||
var addToMap = [rotatedPoly]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might want to include "before" & "after", simply seeing 1 polygon won't show you much (might want to change the colour of the fill).
import {Point} from '@turf/helpers' | ||
|
||
export type GeometryObject = GeoJSON.GeometryObject; | ||
export type Feature<Geom extends GeometryObject> = GeoJSON.Feature<Geom>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this modules are single export methods, you can only have 1 dedicated export, can't have multiple exports.
index.d.ts(15,1): error TS2309: An export assignment cannot be used in a module with
other exported elements.
* @param {number} [yRotation=0] angle of rotation, respect to the horizontal (x,y) plain, about the y axis; | ||
* @returns {Feature<any>} the rotated GeoJSON feature | ||
* @example | ||
* var poly = turf.polygon([[0,29],[3.5,29],[2.5,32],[0,29]]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
invalid polygon 🤦♂️ , needs an extra []
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add these tests directly in the main Turf tests package/turf/test.js
.
A test that actually tests if all the JSDocs are being tested, it's currently doing this in turf-www
.
- Typescript definition - Drop extra dependencies - Update readme - Minor refactoring to tests - Added typescript tests
rotated.properties["stroke"] = "#F00"; | ||
rotated.properties["stroke-width"] = 4; | ||
} | ||
if (pivot) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This type of logic makes the tests confusing.
Simplified this as a single function.
function makePivot(pivot, geojson) {
if (!pivot) return centroid(geojson, {'marker-symbol': 'circle'});
return point(getCoord(pivot), {'marker-symbol': 'circle'});
}
"type": "Feature", | ||
"properties": { | ||
"angle": 200, | ||
"pivot": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not too sure if pivot
should be nested as a GeoJSON point, could simply be an Array [2.48291015625, 27.819644755099446]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noticed you applied this change to other fixtures (looks like this was the only one) 👍
@@ -45,8 +45,6 @@ test('rotate -- throws', t => { | |||
t.throws(() => rotate(featureCollection([line]), 100), /FeatureCollection is not supported/, 'featureCollection'); | |||
t.throws(() => rotate(geometryCollection([line.geometry]), 100), /GeometryCollection is not supported/, 'geometryCollection'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DenisCarriere this currently fails because geojson.type == 'Feature'
so it won't trigger the Error
; was it working before?
Man now the code looks so nice! Love it! 😃 @DenisCarriere in regard to this your comment I'm not sure I got what you mean. |
Added a test case for the z coord. Is that an expected result of |
@stebogit Turf truncate removes the |
@stebogit Are you planning on refactoring I can help refactor it after you've done your first pass at it. |
Changes Unknown when pulling 68553b2 on turf-transform into ** on master**. |
@@ -11,7 +11,8 @@ declare function rotate<Geom extends Geoms>( | |||
angle: number, | |||
pivot?: Point, | |||
xRotation?: number, | |||
yRotation?: number): Geom; | |||
yRotation?: number, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we keeping xRotation
and yRotation
or this is just a leftover?
@DenisCarriere yes I am 😃 , but I won't be able to do it until tonight (PST). |
👍 I'll let you tackle that one, lots of stuff is going on in that repo and it's going to go a lot faster if you do it since you built it, i'd get stomped if I get an error at the end. However |
Changes Unknown when pulling 6d98ed9 on turf-transform into ** on master**. |
These coveralls notifications are cool, but also a bit annoying. Going to remove this for now, but I'm looking forward to have coverage feedback in the PRs. |
// Clone geojson to avoid side effects | ||
if (mutate === false || mutate === undefined) geojson = JSON.parse(JSON.stringify(geojson)); | ||
|
||
var motionVector = getCoords(rhumbDestination([0, 0], distance, direction, units)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@stebogit Not sure if this has been discussed but this motionVector
based translation approach is not doing what you may be expecting it to do. The rhumb line should be calculated from the given point not from the origin and then translated. Won't give the same answer. You should be able to apply the same logic from the scale approach and just apply the rhumb transformation in the coordEach
loop.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK, just saw the comment where you were planning on doing this.
updated bench; updated README; restored geometry support tests; removed unused dependencies;
t.assert(translate(geometryCollection([line.geometry]).geometry, 100, 50), 'geometryCollection support'); | ||
t.assert(translate(featureCollection([line]), 100, 50), 'featureCollection support'); | ||
t.assert(translate(line.geometry, 100, 50), 'geometry line support'); | ||
t.assert(translate(line.geometry, 100, 50), 'geometry pt support'); | ||
// t.assert(translate(line.geometry.coordinates, 100, 50), 'pt coordinate support'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@DenisCarriere I believe this test, which fails, is actually wrong; we are passing here an array of coordinates, which is not a GeoJSON object
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true, this should throw an error 👍
Changes Unknown when pulling 23d18a1 on turf-transform into ** on master**. |
1 similar comment
Changes Unknown when pulling 23d18a1 on turf-transform into ** on master**. |
var translatedCoords = [].concat.apply([], resultVector); // flatten translated vector | ||
return translatedCoords; | ||
// Translate each coordinate | ||
coordEach(geojson, function (pointCoords) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, what a big change! 👍 Looks too good to be true!
Changes Unknown when pulling 3e64de8 on turf-transform into ** on master**. |
Changes Unknown when pulling 0cd7b6b on turf-transform into ** on master**. |
Changes Unknown when pulling 0cd7b6b on turf-transform into ** on master**. |
@DenisCarriere how come that the branch has been merged but it is shown as still separate in the graph? Can I still work on the |
@stebogit We've noticed that in the past, I believe the reason is because when I merged I chose "Squash and merge". I don't know if that's an intended feature/bug in GitHub. It's best to start a new branch (like you've done). |
Implemented first module
@turf/transform-translate
Note: I used
@turf/rhumb-destination
to create the translation vector, which defines the motion; needs to be checked if the length of the resulting translation matches the provideddistance
.Please feel free to comment, suggest, correct, add tests.
(Ref: #747)