Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 0 additions & 16 deletions packages/turf-line-offset/index.d.ts

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,10 @@ import {
lineString,
multiLineString,
lengthToDegrees,
Units,
} from "@turf/helpers";
import { intersection } from "./lib/intersection.js";
import { Feature, LineString, MultiLineString, Position } from "geojson";

/**
* Takes a {@link LineString|line} and returns a {@link LineString|line} at offset by the specified distance.
Expand All @@ -26,25 +28,29 @@ import { intersection } from "./lib/intersection.js";
* var addToMap = [offsetLine, line]
* offsetLine.properties.stroke = "#00F"
*/
function lineOffset(geojson, distance, options) {
function lineOffset<T extends LineString | MultiLineString>(
geojson: Feature<T> | T,
distance: number,
options: { units?: Units } = {}
) {
// Optional parameters
options = options || {};
if (!isObject(options)) throw new Error("options is invalid");
var units = options.units;
const { units = "kilometers" } = options;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was the units default value not being set? 😬

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's eventually set in @turf/helpers' lengthToRadians


// Valdiation
if (!geojson) throw new Error("geojson is required");
if (distance === undefined || distance === null || isNaN(distance))
throw new Error("distance is required");

var type = getType(geojson);
var properties = geojson.properties;
var properties = geojson.type === "Feature" ? geojson.properties : {};

switch (type) {
case "LineString":
return lineOffsetFeature(geojson, distance, units);
case "MultiLineString":
var coords = [];
var coords: Position[][] = [];
flattenEach(geojson, function (feature) {
coords.push(
lineOffsetFeature(feature, distance, units).geometry.coordinates
Expand All @@ -65,11 +71,15 @@ function lineOffset(geojson, distance, options) {
* @param {string} [units=kilometers] units
* @returns {Feature<LineString>} Line offset from the input line
*/
function lineOffsetFeature(line, distance, units) {
var segments = [];
function lineOffsetFeature(
line: Feature<LineString | MultiLineString> | LineString | MultiLineString,
distance: number,
units: Units
) {
var segments: [[number, number], [number, number]][] = [];
var offsetDegrees = lengthToDegrees(distance, units);
var coords = getCoords(line);
var finalCoords = [];
var finalCoords: [number, number][] = [];
coords.forEach(function (currentCoords, index) {
if (index !== coords.length - 1) {
var segment = processSegment(
Expand Down Expand Up @@ -101,7 +111,10 @@ function lineOffsetFeature(line, distance, units) {
}
}
});
return lineString(finalCoords, line.properties);
return lineString(
finalCoords,
line.type === "Feature" ? line.properties : {}
);
}

/**
Expand All @@ -114,7 +127,11 @@ function lineOffsetFeature(line, distance, units) {
* @param {number} offset Offset
* @returns {Array<Array<number>>} offset points
*/
function processSegment(point1, point2, offset) {
function processSegment(
point1: [number, number],
point2: [number, number],
offset: number
): [[number, number], [number, number]] {
var L = Math.sqrt(
(point1[0] - point2[0]) * (point1[0] - point2[0]) +
(point1[1] - point2[1]) * (point1[1] - point2[1])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
* @param {Array<Array<number>>} segment - 2 vertex line segment
* @returns {Array<number>} coordinates [x, y]
*/
function ab(segment) {
function ab(segment: [number, number][]): [number, number] {
var start = segment[0];
var end = segment[1];
return [end[0] - start[0], end[1] - start[1]];
Expand All @@ -25,7 +25,7 @@ function ab(segment) {
* @param {Array<number>} v2 coordinates [x, y]
* @returns {Array<number>} Cross Product
*/
function crossProduct(v1, v2) {
function crossProduct(v1: [number, number], v2: [number, number]) {
return v1[0] * v2[1] - v2[0] * v1[1];
}

Expand All @@ -37,7 +37,7 @@ function crossProduct(v1, v2) {
* @param {Array<number>} v2 coordinates [x, y]
* @returns {Array<number>} Add
*/
function add(v1, v2) {
function add(v1: [number, number], v2: [number, number]): [number, number] {
return [v1[0] + v2[0], v1[1] + v2[1]];
}

Expand All @@ -49,7 +49,7 @@ function add(v1, v2) {
* @param {Array<number>} v2 coordinates [x, y]
* @returns {Array<number>} Sub
*/
function sub(v1, v2) {
function sub(v1: [number, number], v2: [number, number]): [number, number] {
return [v1[0] - v2[0], v1[1] - v2[1]];
}

Expand All @@ -61,7 +61,7 @@ function sub(v1, v2) {
* @param {Array<number>} v coordinates [x, y]
* @returns {Array<number>} scalarMult
*/
function scalarMult(s, v) {
function scalarMult(s: number, v: [number, number]): [number, number] {
return [s * v[0], s * v[1]];
}

Expand All @@ -73,7 +73,10 @@ function scalarMult(s, v) {
* @param {Array<number>} b coordinates [x, y]
* @returns {Array<number>} intersection
*/
function intersectSegments(a, b) {
function intersectSegments(
a: [number, number][],
b: [number, number][]
): [number, number] {
var p = a[0];
var r = ab(a);
var q = b[0];
Expand All @@ -95,7 +98,7 @@ function intersectSegments(a, b) {
* @param {Array<number>} b coordinates [x, y]
* @returns {boolean} true if a and b are parallel (or co-linear)
*/
function isParallel(a, b) {
function isParallel(a: [number, number][], b: [number, number][]): boolean {
var r = ab(a);
var s = ab(b);
return crossProduct(r, s) === 0;
Expand All @@ -109,10 +112,10 @@ function isParallel(a, b) {
* @param {Array<number>} b coordinates [x, y]
* @returns {Array<number>|boolean} true if a and b are parallel (or co-linear)
*/
function intersection(a, b) {
export function intersection(
a: [number, number][],
b: [number, number][]
): [number, number] | false {
if (isParallel(a, b)) return false;
return intersectSegments(a, b);
}

export { intersection };
export default intersection;
4 changes: 3 additions & 1 deletion packages/turf-line-offset/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,14 @@
"tape": "^5.9.0",
"tsup": "^8.4.0",
"tsx": "^4.19.4",
"typescript": "^5.8.3",
"write-json-file": "^6.0.0"
},
"dependencies": {
"@turf/helpers": "workspace:*",
"@turf/invariant": "workspace:*",
"@turf/meta": "workspace:*",
"@types/geojson": "^7946.0.10"
"@types/geojson": "^7946.0.10",
"tslib": "^2.8.1"
}
}
8 changes: 4 additions & 4 deletions packages/turf-line-offset/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ let fixtures = fs.readdirSync(directories.in).map((filename) => {
test("turf-line-offset", (t) => {
fixtures.forEach((fixture) => {
const name = fixture.name;
const geojson = fixture.geojson;
const geojson = fixture.geojson as any;
const properties = geojson.properties || {};
const distance = properties.distance || 50;
const units = properties.units;

const output = truncate(lineOffset(geojson, distance, { units: units }), {
precision: 4,
});
output.properties.stroke = "#00F";
output.properties!.stroke = "#00F";
const results = featureCollection([output, geojson]);

if (process.env.REGEN)
Expand All @@ -54,8 +54,8 @@ test("turf-line-offset - Throws Errors", (t) => {
[10, 10],
[0, 0],
]);
t.throws(() => lineOffset(), /geojson is required/);
t.throws(() => lineOffset(line), /distance is required/);
t.throws(() => (lineOffset as any)(), /geojson is required/);
t.throws(() => (lineOffset as any)(line), /distance is required/);
t.end();
});

Expand Down
6 changes: 6 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.