diff --git a/packages/turf-transform-rotate/README.md b/packages/turf-transform-rotate/README.md index 78a223c429..2254c062a2 100644 --- a/packages/turf-transform-rotate/README.md +++ b/packages/turf-transform-rotate/README.md @@ -18,12 +18,12 @@ Rotates any geojson Feature or Geometry of a specified angle, around its `centro ### Examples ```javascript -var poly = turf.polygon([[[0,29],[3.5,29],[2.5,32],[0,29]]]); -var options = {pivot: [0, 25]}; -var rotatedPoly = turf.transformRotate(poly, 10, options); +const poly = turf.polygon([[[0,29],[3.5,29],[2.5,32],[0,29]]]); +const options = {pivot: [0, 25]}; +const rotatedPoly = turf.transformRotate(poly, 10, options); //addToMap -var addToMap = [poly, rotatedPoly]; +const addToMap = [poly, rotatedPoly]; rotatedPoly.properties = {stroke: '#F00', 'stroke-width': 4}; ``` diff --git a/packages/turf-transform-rotate/bench.ts b/packages/turf-transform-rotate/bench.ts index a1aae93a35..ab61c19e0b 100644 --- a/packages/turf-transform-rotate/bench.ts +++ b/packages/turf-transform-rotate/bench.ts @@ -1,8 +1,9 @@ +import { Feature } from "geojson"; import fs from "fs"; import path from "path"; import { fileURLToPath } from "url"; import { loadJsonFileSync } from "load-json-file"; -import Benchmark from "benchmark"; +import Benchmark, { Event } from "benchmark"; import { transformRotate as rotate } from "./index.js"; const __dirname = path.dirname(fileURLToPath(import.meta.url)); @@ -11,7 +12,7 @@ const directory = path.join(__dirname, "test", "in") + path.sep; const fixtures = fs.readdirSync(directory).map((filename) => { return { name: path.parse(filename).name, - geojson: loadJsonFileSync(directory + filename), + geojson: loadJsonFileSync(directory + filename) as Feature, }; }); @@ -54,4 +55,4 @@ for (const { name, geojson } of fixtures) { suite.add(name, () => rotate(geojson, angle, { pivot, mutate: true })); } -suite.on("cycle", (e) => console.log(String(e.target))).run(); +suite.on("cycle", (e: Event) => console.log(String(e.target))).run(); diff --git a/packages/turf-transform-rotate/index.d.ts b/packages/turf-transform-rotate/index.d.ts deleted file mode 100644 index 651024d123..0000000000 --- a/packages/turf-transform-rotate/index.d.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { AllGeoJSON, Coord } from "@turf/helpers"; - -/** - * http://turfjs.org/docs/#transformrotate - */ -declare function transformRotate( - geojson: T, - angle: number, - options?: { - pivot?: Coord; - mutate?: boolean; - } -): T; - -export { transformRotate }; -export default transformRotate; diff --git a/packages/turf-transform-rotate/index.js b/packages/turf-transform-rotate/index.ts similarity index 67% rename from packages/turf-transform-rotate/index.js rename to packages/turf-transform-rotate/index.ts index e0cc28a3b4..4d8216a82a 100644 --- a/packages/turf-transform-rotate/index.js +++ b/packages/turf-transform-rotate/index.ts @@ -1,3 +1,4 @@ +import { GeoJSON, GeometryCollection } from "geojson"; import { centroid } from "@turf/centroid"; import { rhumbBearing } from "@turf/rhumb-bearing"; import { rhumbDistance } from "@turf/rhumb-distance"; @@ -5,7 +6,7 @@ import { rhumbDestination } from "@turf/rhumb-destination"; import { clone } from "@turf/clone"; import { coordEach } from "@turf/meta"; import { getCoords } from "@turf/invariant"; -import { isObject } from "@turf/helpers"; +import { isObject, Coord } from "@turf/helpers"; /** * Rotates any geojson Feature or Geometry of a specified angle, around its `centroid` or a given `pivot` point. @@ -18,20 +19,27 @@ import { isObject } from "@turf/helpers"; * @param {boolean} [options.mutate=false] allows GeoJSON input to be mutated (significant performance increase if true) * @returns {GeoJSON} the rotated GeoJSON feature * @example - * var poly = turf.polygon([[[0,29],[3.5,29],[2.5,32],[0,29]]]); - * var options = {pivot: [0, 25]}; - * var rotatedPoly = turf.transformRotate(poly, 10, options); + * const poly = turf.polygon([[[0,29],[3.5,29],[2.5,32],[0,29]]]); + * const options = {pivot: [0, 25]}; + * const rotatedPoly = turf.transformRotate(poly, 10, options); * * //addToMap - * var addToMap = [poly, rotatedPoly]; + * const addToMap = [poly, rotatedPoly]; * rotatedPoly.properties = {stroke: '#F00', 'stroke-width': 4}; */ -function transformRotate(geojson, angle, options) { +function transformRotate( + geojson: T, + angle: number, + options?: { + pivot?: Coord; + mutate?: boolean; + } +): T { // Optional parameters options = options || {}; if (!isObject(options)) throw new Error("options is invalid"); - var pivot = options.pivot; - var mutate = options.mutate; + const pivot = options.pivot; + const mutate = options.mutate; // Input validation if (!geojson) throw new Error("geojson is required"); @@ -42,17 +50,19 @@ function transformRotate(geojson, angle, options) { if (angle === 0) return geojson; // Use centroid of GeoJSON if pivot is not provided - if (!pivot) pivot = centroid(geojson); + const pivotCoord = pivot ?? centroid(geojson); // Clone geojson to avoid side effects if (mutate === false || mutate === undefined) geojson = clone(geojson); // Rotate each coordinate coordEach(geojson, function (pointCoords) { - var initialAngle = rhumbBearing(pivot, pointCoords); - var finalAngle = initialAngle + angle; - var distance = rhumbDistance(pivot, pointCoords); - var newCoords = getCoords(rhumbDestination(pivot, distance, finalAngle)); + const initialAngle = rhumbBearing(pivotCoord, pointCoords); + const finalAngle = initialAngle + angle; + const distance = rhumbDistance(pivotCoord, pointCoords); + const newCoords = getCoords( + rhumbDestination(pivotCoord, distance, finalAngle) + ); pointCoords[0] = newCoords[0]; pointCoords[1] = newCoords[1]; }); diff --git a/packages/turf-transform-rotate/package.json b/packages/turf-transform-rotate/package.json index d28ac59441..e917fb179b 100644 --- a/packages/turf-transform-rotate/package.json +++ b/packages/turf-transform-rotate/package.json @@ -65,6 +65,7 @@ "tape": "^5.7.2", "tsup": "^8.0.1", "tsx": "^4.6.2", + "typescript": "^5.2.2", "write-json-file": "^5.0.0" }, "dependencies": { @@ -75,6 +76,8 @@ "@turf/meta": "workspace:^", "@turf/rhumb-bearing": "workspace:^", "@turf/rhumb-destination": "workspace:^", - "@turf/rhumb-distance": "workspace:^" + "@turf/rhumb-distance": "workspace:^", + "@types/geojson": "7946.0.8", + "tslib": "^2.6.2" } } diff --git a/packages/turf-transform-rotate/test.ts b/packages/turf-transform-rotate/test.ts index d74246ae0c..f60a98187e 100644 --- a/packages/turf-transform-rotate/test.ts +++ b/packages/turf-transform-rotate/test.ts @@ -1,3 +1,4 @@ +import { Feature, GeoJSON, GeometryCollection } from "geojson"; import fs from "fs"; import test from "tape"; import path from "path"; @@ -12,6 +13,7 @@ import { lineString, featureCollection, geometryCollection, + Coord, } from "@turf/helpers"; import { transformRotate as rotate } from "./index.js"; @@ -26,7 +28,7 @@ const fixtures = fs.readdirSync(directories.in).map((filename) => { return { filename, name: path.parse(filename).name, - geojson: loadJsonFileSync(directories.in + filename), + geojson: loadJsonFileSync(directories.in + filename) as Feature, }; }); @@ -55,9 +57,12 @@ test("rotate -- throws", (t) => { [12, 15], ]); + // @ts-expect-error testing JS runtime for mis-typed option t.throws(() => rotate(null, 100), /geojson is required/, "missing geojson"); + // @ts-expect-error testing JS runtime for mis-typed option t.throws(() => rotate(line, null), /angle is required/, "missing angle"); t.throws( + // @ts-expect-error testing JS runtime for mis-typed option () => rotate(line, 56, { pivot: "notApoint" }), /coord must be GeoJSON Point or an Array of numbers/, "coord must be GeoJSON Point or an Array of numbers" @@ -116,7 +121,10 @@ test("rotate -- geometry support", (t) => { }); // style result -function colorize(geojson) { +function colorize(geojson: Feature) { + // We are going to add some properties, so make sure properties attribute is + // present. + geojson.properties = geojson.properties ?? {}; if ( geojson.geometry.type === "Point" || geojson.geometry.type === "MultiPoint" @@ -130,9 +138,10 @@ function colorize(geojson) { return geojson; } -function makePivot(pivot, geojson) { +function makePivot(pivot: Coord, geojson: GeoJSON | GeometryCollection) { if (!pivot) { const pt = centroid(geojson); + pt.properties = pt.properties ?? {}; pt.properties["marker-symbol"] = "circle"; return pt; } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 09a7502ec6..6c3bd610b3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5784,6 +5784,12 @@ importers: '@turf/rhumb-distance': specifier: workspace:^ version: link:../turf-rhumb-distance + '@types/geojson': + specifier: 7946.0.8 + version: 7946.0.8 + tslib: + specifier: ^2.6.2 + version: 2.6.2 devDependencies: '@turf/truncate': specifier: workspace:^ @@ -5812,6 +5818,9 @@ importers: tsx: specifier: ^4.6.2 version: 4.6.2 + typescript: + specifier: ^5.2.2 + version: 5.3.3 write-json-file: specifier: ^5.0.0 version: 5.0.0