Skip to content

Commit

Permalink
Merge pull request Turfjs#1357 from Turfjs/typescript-modules
Browse files Browse the repository at this point in the history
Update nearest-point-to-line & point-to-line-distance TS
  • Loading branch information
DenisCarriere authored Apr 15, 2018
2 parents 1996eed + 385b419 commit a078be7
Show file tree
Hide file tree
Showing 13 changed files with 205 additions and 86 deletions.
32 changes: 32 additions & 0 deletions packages/turf-nearest-point-to-line/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { Feature, FeatureCollection, GeometryCollection, LineString, Point, Properties, Units } from "@turf/helpers";
/**
* Returns the closest {@link Point|point}, of a {@link FeatureCollection|collection} of points,
* to a {@link LineString|line}. The returned point has a `dist` property indicating its distance to the line.
*
* @name nearestPointToLine
* @param {FeatureCollection|GeometryCollection<Point>} points Point Collection
* @param {Feature|Geometry<LineString>} line Line Feature
* @param {Object} [options] Optional parameters
* @param {string} [options.units='kilometers'] unit of the output distance property
* (eg: degrees, radians, miles, or kilometers)
* @param {Object} [options.properties={}] Translate Properties to Point
* @returns {Feature<Point>} the closest point
* @example
* var pt1 = turf.point([0, 0]);
* var pt2 = turf.point([0.5, 0.5]);
* var points = turf.featureCollection([pt1, pt2]);
* var line = turf.lineString([[1,1], [-1,1]]);
*
* var nearest = turf.nearestPointToLine(points, line);
*
* //addToMap
* var addToMap = [nearest, line];
*/
declare function nearestPointToLine<P = {
dist: number;
[key: string]: any;
}>(points: FeatureCollection<Point> | Feature<GeometryCollection> | GeometryCollection, line: Feature<LineString> | LineString, options?: {
units?: Units;
properties?: Properties;
}): Feature<Point, P>;
export default nearestPointToLine;
62 changes: 32 additions & 30 deletions packages/turf-nearest-point-to-line/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
import { Properties, Feature, FeatureCollection, GeometryCollection, Point, LineString, Units } from '@turf/helpers';
import { getType } from '@turf/invariant';
import pointToLineDistance from '@turf/point-to-line-distance';
import { featureEach, geomEach } from '@turf/meta';
import * as objectAssign from 'object-assign';
import { Feature, FeatureCollection, GeometryCollection, LineString, Point, Properties, Units } from "@turf/helpers";
import { getType } from "@turf/invariant";
import { featureEach, geomEach } from "@turf/meta";
import pointToLineDistance from "@turf/point-to-line-distance";
import objectAssign from "object-assign";

/**
* Returns the closest {@link Point|point}, of a {@link FeatureCollection|collection} of points, to a {@link LineString|line}.
* The returned point has a `dist` property indicating its distance to the line.
* Returns the closest {@link Point|point}, of a {@link FeatureCollection|collection} of points,
* to a {@link LineString|line}. The returned point has a `dist` property indicating its distance to the line.
*
* @name nearestPointToLine
* @param {FeatureCollection|GeometryCollection<Point>} points Point Collection
* @param {Feature|Geometry<LineString>} line Line Feature
* @param {Object} [options] Optional parameters
* @param {string} [options.units='kilometers'] unit of the output distance property, can be degrees, radians, miles, or kilometers
* @param {string} [options.units='kilometers'] unit of the output distance property
* (eg: degrees, radians, miles, or kilometers)
* @param {Object} [options.properties={}] Translate Properties to Point
* @returns {Feature<Point>} the closest point
* @example
Expand All @@ -31,24 +32,24 @@ function nearestPointToLine<P = {dist: number, [key: string]: any}>(
line: Feature<LineString> | LineString,
options: {
units?: Units,
properties?: Properties
} = {}
properties?: Properties,
} = {},
): Feature<Point, P> {
var units = options.units;
var properties = options.properties || {};
const units = options.units;
const properties = options.properties || {};

// validation
const pts = normalize(points);
if (!pts.features.length) throw new Error('points must contain features');
if (!pts.features.length) { throw new Error("points must contain features"); }

if (!line) throw new Error('line is required');
if (getType(line) !== 'LineString') throw new Error('line must be a LineString');
if (!line) { throw new Error("line is required"); }
if (getType(line) !== "LineString") { throw new Error("line must be a LineString"); }

var dist = Infinity;
var pt = null;
let dist = Infinity;
let pt: any = null;

featureEach(pts, function (point) {
var d = pointToLineDistance(point, line, { units: units });
featureEach(pts, (point) => {
const d = pointToLineDistance(point, line, { units });
if (d < dist) {
dist = d;
pt = point;
Expand All @@ -60,7 +61,8 @@ function nearestPointToLine<P = {dist: number, [key: string]: any}>(
* 2. inherent Point properties
* 3. dist custom properties created by NearestPointToLine
*/
if (pt) pt.properties = objectAssign({dist: dist}, pt.properties, properties);
if (pt) { pt.properties = objectAssign({dist}, pt.properties, properties); }
// if (pt) { pt.properties = objectAssign({dist}, pt.properties, properties); }
return pt;
}

Expand All @@ -72,21 +74,21 @@ function nearestPointToLine<P = {dist: number, [key: string]: any}>(
* @returns {FeatureCollection<Point>} points
*/
function normalize(points: any): FeatureCollection<Point> {
var features = [];
var type = points.geometry ? points.geometry.type : points.type;
const features: any[] = [];
const type = points.geometry ? points.geometry.type : points.type;
switch (type) {
case 'GeometryCollection':
geomEach(points, function (geom) {
if (geom.type === 'Point') features.push({type: 'Feature', properties: {}, geometry: geom});
case "GeometryCollection":
geomEach(points, (geom) => {
if (geom.type === "Point") { features.push({type: "Feature", properties: {}, geometry: geom}); }
});
return {type: 'FeatureCollection', features: features};
case 'FeatureCollection':
points.features = points.features.filter(function (feature) {
return feature.geometry.type === 'Point';
return {type: "FeatureCollection", features};
case "FeatureCollection":
points.features = points.features.filter((feature: any) => {
return feature.geometry.type === "Point";
});
return points;
default:
throw new Error('points must be a Point Collection');
throw new Error("points must be a Point Collection");
}
}

Expand Down
11 changes: 6 additions & 5 deletions packages/turf-nearest-point-to-line/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@turf/nearest-point-to-line",
"version": "5.1.6",
"version": "6.0.0",
"description": "turf nearest-point-to-line module",
"main": "index",
"types": "index.d.ts",
Expand Down Expand Up @@ -38,19 +38,20 @@
"devDependencies": {
"@turf/circle": "*",
"@turf/truncate": "*",
"@types/object-assign": "*",
"@types/tape": "*",
"benchmark": "*",
"load-json-file": "*",
"typescript": "*",
"tape": "*",
"write-json-file": "*",
"tslint": "*",
"@types/tape": "*"
"typescript": "*",
"write-json-file": "*"
},
"dependencies": {
"@turf/helpers": "6.x",
"@turf/invariant": "6.x",
"@turf/meta": "6.x",
"@turf/point-to-line-distance": "^5.1.5",
"@turf/point-to-line-distance": "6.x",
"object-assign": "*"
}
}
17 changes: 17 additions & 0 deletions packages/turf-nearest-point-to-line/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
/* Basic Options */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"declaration": true, /* Generates corresponding '.d.ts' file. */

/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */

/* Module Resolution Options */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
},
"files": [
"index.ts"
]
}
9 changes: 9 additions & 0 deletions packages/turf-nearest-point-to-line/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {},
"rulesDirectory": []
}
26 changes: 26 additions & 0 deletions packages/turf-point-to-line-distance/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Coord, Feature, LineString, Units } from "@turf/helpers";
/**
* Returns the minimum distance between a {@link Point} and a {@link LineString}, being the distance from a line the
* minimum distance between the point and any segment of the `LineString`.
*
* @name pointToLineDistance
* @param {Feature<Point>|Array<number>} pt Feature or Geometry
* @param {Feature<LineString>} line GeoJSON Feature or Geometry
* @param {Object} [options={}] Optional parameters
* @param {string} [options.units="kilometers"] can be anything supported by turf/convertLength
* (ex: degrees, radians, miles, or kilometers)
* @param {string} [options.method="geodesic"] wether to calculate the distance based on geodesic (spheroid) or
* planar (flat) method. Valid options are 'geodesic' or 'planar'.
* @returns {number} distance between point and line
* @example
* var pt = turf.point([0, 0]);
* var line = turf.lineString([[1, 1],[-1, 1]]);
*
* var distance = turf.pointToLineDistance(pt, line, {units: 'miles'});
* //=69.11854715938406
*/
declare function pointToLineDistance(pt: Coord, line: Feature<LineString> | LineString, options?: {
units?: Units;
method?: "geodesic" | "planar";
}): number;
export default pointToLineDistance;
95 changes: 48 additions & 47 deletions packages/turf-point-to-line-distance/index.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
// Taken from http://geomalgorithms.com/a02-_lines.html
import { featureOf } from '@turf/invariant';
import { segmentEach } from '@turf/meta';
import getDistance from '@turf/distance';
import getPlanarDistance from '@turf/rhumb-distance';
import getDistance from "@turf/distance";
import {
point,
feature,
lineString,
convertLength,
Coord,
feature,
Feature,
Point,
lineString,
LineString,
Coord,
Units
} from '@turf/helpers';
point,
Point,
Units,
} from "@turf/helpers";
import { featureOf } from "@turf/invariant";
import { segmentEach } from "@turf/meta";
import getPlanarDistance from "@turf/rhumb-distance";

/**
* Returns the minimum distance between a {@link Point} and a {@link LineString}, being the distance from a line the
Expand All @@ -23,8 +23,10 @@ import {
* @param {Feature<Point>|Array<number>} pt Feature or Geometry
* @param {Feature<LineString>} line GeoJSON Feature or Geometry
* @param {Object} [options={}] Optional parameters
* @param {string} [options.units='kilometers'] can be anything supported by turf/convertLength, eg degrees, radians, miles, or kilometers
* @param {string} [options.method='geodesic'] wehther to calculate the distance based on geodesic (spheroid) or planar (flat) method. Valid options are 'geodesic' or 'planar'.
* @param {string} [options.units="kilometers"] can be anything supported by turf/convertLength
* (ex: degrees, radians, miles, or kilometers)
* @param {string} [options.method="geodesic"] wether to calculate the distance based on geodesic (spheroid) or
* planar (flat) method. Valid options are 'geodesic' or 'planar'.
* @returns {number} distance between point and line
* @example
* var pt = turf.point([0, 0]);
Expand All @@ -35,64 +37,63 @@ import {
*/
function pointToLineDistance(pt: Coord, line: Feature<LineString> | LineString, options: {
units?: Units,
method?: 'geodesic' | 'planar',
method?: "geodesic" | "planar",
} = {}): number {
// Optional parameters
if (!options.method) options.method = 'geodesic';
if (!options.units) options.units = 'kilometers';
if (!options.method) { options.method = "geodesic"; }
if (!options.units) { options.units = "kilometers"; }

// validation
if (!pt) throw new Error('pt is required');
if (Array.isArray(pt)) pt = point(pt);
else if (pt.type === 'Point') pt = feature(pt);
else featureOf(pt, 'Point', 'point');
if (!pt) { throw new Error("pt is required"); }
if (Array.isArray(pt)) { pt = point(pt);
} else if (pt.type === "Point") { pt = feature(pt);
} else { featureOf(pt, "Point", "point"); }

if (!line) throw new Error('line is required');
if (Array.isArray(line)) line = lineString(line);
else if (line.type === 'LineString') line = feature(line);
else featureOf(line, 'LineString', 'line');
if (!line) { throw new Error("line is required"); }
if (Array.isArray(line)) { line = lineString(line);
} else if (line.type === "LineString") { line = feature(line);
} else { featureOf(line, "LineString", "line"); }

var distance = Infinity;
var p = pt.geometry.coordinates;
segmentEach(line, function (segment) {
var a = segment.geometry.coordinates[0];
var b = segment.geometry.coordinates[1];
var d = distanceToSegment(p, a, b, options);
if (d < distance) distance = d;
let distance = Infinity;
const p = pt.geometry.coordinates;
segmentEach(line, (segment) => {
const a = segment!.geometry.coordinates[0];
const b = segment!.geometry.coordinates[1];
const d = distanceToSegment(p, a, b, options);
if (d < distance) { distance = d; }
});
return convertLength(distance, 'degrees', options.units);
return convertLength(distance, "degrees", options.units);
}


/**
* Returns the distance between a point P on a segment AB.
*
* @private
* @param {Array<number>} p external point
* @param {Array<number>} a first segment point
* @param {Array<number>} b second segment point
* @param {Object} [options={}] Optional parameters
* @param {Object} [options={}] Optional parameters
* @returns {number} distance
*/
function distanceToSegment(p, a, b, options) {
var v = [b[0] - a[0], b[1] - a[1]];
var w = [p[0] - a[0], p[1] - a[1]];
function distanceToSegment(p: number[], a: number[], b: number[], options: any) {
const v = [b[0] - a[0], b[1] - a[1]];
const w = [p[0] - a[0], p[1] - a[1]];

var c1 = dot(w, v);
if (c1 <= 0) return calcDistance(p, a, {method: options.method, units: 'degrees'});
var c2 = dot(v, v);
if (c2 <= c1) return calcDistance(p, b, {method: options.method, units: 'degrees'});
var b2 = c1 / c2;
var Pb = [a[0] + (b2 * v[0]), a[1] + (b2 * v[1])];
return calcDistance(p, Pb, {method: options.method, units: 'degrees'});
const c1 = dot(w, v);
if (c1 <= 0) { return calcDistance(p, a, {method: options.method, units: "degrees"}); }
const c2 = dot(v, v);
if (c2 <= c1) { return calcDistance(p, b, {method: options.method, units: "degrees"}); }
const b2 = c1 / c2;
const Pb = [a[0] + (b2 * v[0]), a[1] + (b2 * v[1])];
return calcDistance(p, Pb, {method: options.method, units: "degrees"});
}

function dot(u, v) {
function dot(u: number[], v: number[]) {
return (u[0] * v[0] + u[1] * v[1]);
}

function calcDistance(a, b, options) {
return options.method === 'planar' ? getPlanarDistance(a, b, options) : getDistance(a, b, options);
function calcDistance(a: number[], b: number[], options: any) {
return options.method === "planar" ? getPlanarDistance(a, b, options) : getDistance(a, b, options);
}

export default pointToLineDistance;
2 changes: 1 addition & 1 deletion packages/turf-point-to-line-distance/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@turf/point-to-line-distance",
"version": "5.1.6",
"version": "6.0.0",
"description": "turf point-to-line-distance module",
"main": "index",
"types": "index.d.ts",
Expand Down
17 changes: 17 additions & 0 deletions packages/turf-point-to-line-distance/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
/* Basic Options */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
"declaration": true, /* Generates corresponding '.d.ts' file. */

/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */

/* Module Resolution Options */
"esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
},
"files": [
"index.ts"
]
}
Loading

0 comments on commit a078be7

Please sign in to comment.