leaflet.geodesic
Version:
Add-on to draw geodesic lines with leaflet
271 lines (264 loc) • 11.5 kB
TypeScript
/*! leaflet.geodesic 2.7.1 - (c) Henry Thasler - https://github.com/henrythasler/Leaflet.Geodesic#readme */
import * as L from 'leaflet';
interface GeodesicOptions extends L.PolylineOptions {
wrap?: boolean;
steps?: number;
radius?: number;
}
interface WGS84Vector extends L.LatLngLiteral {
bearing: number;
}
interface GeoDistance {
distance: number;
initialBearing: number;
finalBearing: number;
}
declare class GeodesicCore {
readonly options: GeodesicOptions;
readonly ellipsoid: {
a: number;
b: number;
f: number;
};
constructor(options?: GeodesicOptions);
toRadians(degree: number): number;
toDegrees(radians: number): number;
/**
* implements scientific modulus
* source: http://www.codeavenger.com/2017/05/19/JavaScript-Modulo-operation-and-the-Caesar-Cipher.html
* @param n
* @param p
* @return
*/
mod(n: number, p: number): number;
/**
* source: https://github.com/chrisveness/geodesy/blob/master/dms.js
* @param degrees arbitrary value
* @return degrees between 0..360
*/
wrap360(degrees: number): number;
/**
* general wrap function with arbitrary max value
* @param degrees arbitrary value
* @param max
* @return degrees between `-max`..`+max`
*/
wrap(degrees: number, max?: number): number;
/**
* Vincenty direct calculation.
* based on the work of Chris Veness (https://github.com/chrisveness/geodesy)
* source: https://github.com/chrisveness/geodesy/blob/master/latlon-ellipsoidal-vincenty.js
*
* @param start starting point
* @param bearing initial bearing (in degrees)
* @param distance distance from starting point to calculate along given bearing in meters.
* @param maxInterations How many iterations can be made to reach the allowed deviation (`ε`), before an error will be thrown.
* @return Final point (destination point) and bearing (in degrees)
*/
direct(start: L.LatLng, bearing: number, distance: number, maxInterations?: number): WGS84Vector;
/**
* Vincenty inverse calculation.
* based on the work of Chris Veness (https://github.com/chrisveness/geodesy)
* source: https://github.com/chrisveness/geodesy/blob/master/latlon-ellipsoidal-vincenty.js
*
* @param start Latitude/longitude of starting point.
* @param dest Latitude/longitude of destination point.
* @return Object including distance, initialBearing, finalBearing.
*/
inverse(start: L.LatLng, dest: L.LatLng, maxInterations?: number, mitigateConvergenceError?: boolean): GeoDistance;
/**
* Returns the point of intersection of two paths defined by position and bearing.
* This calculation uses a spherical model of the earth. This will lead to small errors compared to an ellipsiod model.
* based on the work of Chris Veness (https://github.com/chrisveness/geodesy)
* source: https://github.com/chrisveness/geodesy/blob/master/latlon-spherical.js
*
* @param firstPos 1st path: position and bearing
* @param firstBearing
* @param secondPos 2nd path: position and bearing
* @param secondBearing
*/
intersection(firstPos: L.LatLng, firstBearing: number, secondPos: L.LatLng, secondBearing: number): L.LatLng | null;
midpoint(start: L.LatLng, dest: L.LatLng): L.LatLng;
}
/** detailled information of the current geometry */
interface Statistics {
/** Stores the distance for each individual geodesic line */
distanceArray: number[];
/** overall distance of all lines */
totalDistance: number;
/** number of positions that the geodesic lines are created from */
points: number;
/** number vertices that were created during geometry calculation */
vertices: number;
}
declare class GeodesicGeometry {
readonly geodesic: GeodesicCore;
steps: number;
constructor(options?: GeodesicOptions);
/**
* A geodesic line between `start` and `dest` is created with this recursive function.
* It calculates the geodesic midpoint between `start` and `dest` and uses this midpoint to call itself again (twice!).
* The results are then merged into one continuous linestring.
*
* The number of resulting vertices (incl. `start` and `dest`) depends on the initial value for `iterations`
* and can be calculated with: vertices == 1 + 2 ** (initialIterations + 1)
*
* As this is an exponential function, be extra careful to limit the initial value for `iterations` (8 results in 513 vertices).
*
* @param start start position
* @param dest destination
* @param iterations
* @return resulting linestring
*/
recursiveMidpoint(start: L.LatLng, dest: L.LatLng, iterations: number): L.LatLng[];
/**
* This is the wrapper-function to generate a geodesic line. It's just for future backwards-compatibility
* if there is another algorithm used to create the actual line.
*
* The `steps`-property is used to define the number of resulting vertices of the linestring: vertices == 1 + 2 ** (steps + 1)
* The value for `steps` is currently limited to 8 (513 vertices) for performance reasons until another algorithm is found.
*
* @param start start position
* @param dest destination
* @return resulting linestring
*/
line(start: L.LatLng, dest: L.LatLng): L.LatLng[];
multiLineString(latlngs: L.LatLng[][]): L.LatLng[][];
lineString(latlngs: L.LatLng[]): L.LatLng[];
/**
*
* Is much (10x) faster than the previous implementation:
*
* ```
* Benchmark (no split): splitLine x 459,044 ops/sec ±0.53% (95 runs sampled)
* Benchmark (split): splitLine x 42,999 ops/sec ±0.51% (97 runs sampled)
* ```
*
* @param startPosition
* @param destPosition
*/
splitLine(startPosition: L.LatLng, destPosition: L.LatLng): L.LatLng[][];
/**
* Linestrings of a given multilinestring that cross the antimeridian will be split in two separate linestrings.
* This function is used to wrap lines around when they cross the antimeridian
* It iterates over all linestrings and reconstructs the step-by-step if no split is needed.
* In case the line was split, the linestring ends at the antimeridian and a new linestring is created for the
* remaining points of the original linestring.
*
* @param multilinestring
* @return another multilinestring where segments crossing the antimeridian are split
*/
splitMultiLineString(multilinestring: L.LatLng[][]): L.LatLng[][];
/**
* Linestrings of a given multilinestring will be wrapped (+- 360°) to show a continuous line w/o any weird discontinuities
* when `wrap` is set to `false` in the geodesic class
* @param multilinestring
* @returns another multilinestring where the points of each linestring are wrapped accordingly
*/
wrapMultiLineString(multilinestring: L.LatLng[][]): L.LatLng[][];
/**
* Creates a circular (constant radius), closed (1st pos == last pos) geodesic linestring.
* The number of vertices is calculated with: `vertices == steps + 1` (where 1st == last)
*
* @param center
* @param radius
* @return resulting linestring
*/
circle(center: L.LatLng, radius: number): L.LatLng[];
/**
* Handles splitting of circles at the antimeridian.
* @param linestring a linestring that resembles the geodesic circle
* @return a multilinestring that consist of one or two linestrings
*/
splitCircle(linestring: L.LatLng[]): L.LatLng[][];
/**
* Calculates the distance between two positions on the earths surface
* @param start 1st position
* @param dest 2nd position
* @return the distance in **meters**
*/
distance(start: L.LatLng, dest: L.LatLng): number;
multilineDistance(multilinestring: L.LatLng[][]): number[];
updateStatistics(points: L.LatLng[][], vertices: L.LatLng[][]): Statistics;
}
/**
* Draw geodesic lines based on L.Polyline
*/
declare class GeodesicLine extends L.Polyline {
/** these should be good for most use-cases */
defaultOptions: GeodesicOptions;
/** does the actual geometry calculations */
readonly geom: GeodesicGeometry;
/** use this if you need some detailled info about the current geometry */
statistics: Statistics;
/** stores all positions that are used to create the geodesic line */
points: L.LatLng[][];
constructor(latlngs?: L.LatLngExpression[] | L.LatLngExpression[][], options?: GeodesicOptions);
/** calculates the geodesics and update the polyline-object accordingly */
private updateGeometry;
/**
* overwrites the original function with additional functionality to create a geodesic line
* @param latlngs an array (or 2d-array) of positions
*/
setLatLngs(latlngs: L.LatLngExpression[] | L.LatLngExpression[][]): this;
/**
* add a given point to the geodesic line object
* @param latlng point to add. The point will always be added to the last linestring of a multiline
* @param latlngs define a linestring to add the new point to. Read from points-property before (e.g. `line.addLatLng(Beijing, line.points[0]);`)
*/
addLatLng(latlng: L.LatLngExpression, latlngs?: L.LatLng[]): this;
/**
* Creates geodesic lines from a given GeoJSON-Object.
* @param input GeoJSON-Object
*/
fromGeoJson(input: GeoJSON.GeoJSON): this;
/**
* Calculates the distance between two geo-positions
* @param start 1st position
* @param dest 2nd position
* @return the distance in meters
*/
distance(start: L.LatLngExpression, dest: L.LatLngExpression): number;
}
/**
* Can be used to create a geodesic circle based on L.Polyline
*/
declare class GeodesicCircleClass extends L.Polyline {
defaultOptions: GeodesicOptions;
readonly geom: GeodesicGeometry;
center: L.LatLng;
radius: number;
statistics: Statistics;
constructor(center?: L.LatLngExpression, options?: GeodesicOptions);
/**
* Updates the geometry and re-calculates some statistics
*/
private update;
/**
* Calculate the distance between the current center and an arbitrary position.
* @param latlng geo-position to calculate distance to
* @return distance in meters
*/
distanceTo(latlng: L.LatLngExpression): number;
/**
* Set a new center for the geodesic circle and update the geometry. Radius may also be set.
* @param center the new center
* @param radius the new radius
*/
setLatLng(center: L.LatLngExpression, radius?: number): void;
/**
* Set a new radius for the geodesic circle and update the geometry. Center may also be set.
* @param radius the new radius
* @param center the new center
*/
setRadius(radius: number, center?: L.LatLngExpression): void;
}
declare module "leaflet" {
type Geodesic = GeodesicLine;
let Geodesic: typeof GeodesicLine;
let geodesic: (...args: ConstructorParameters<typeof GeodesicLine>) => GeodesicLine;
type GeodesicCircle = GeodesicCircleClass;
let GeodesicCircle: typeof GeodesicCircleClass;
let geodesiccircle: (...args: ConstructorParameters<typeof GeodesicCircleClass>) => GeodesicCircleClass;
}
export { GeodesicCircleClass, GeodesicLine };