From a51609a3eb7d50af3e6bf9c296085bb411a6f2b4 Mon Sep 17 00:00:00 2001 From: Bradley Odell Date: Mon, 10 Sep 2018 14:43:30 -0700 Subject: [PATCH] Updated "delaunator" typings to version 2.0+ (#28665) * Updated "delaunator" typings to version 2.0+ * Added "d3-delaunay" types for version 4.1. --- types/d3-delaunay/d3-delaunay-tests.ts | 118 ++++++++ types/d3-delaunay/index.d.ts | 359 +++++++++++++++++++++++++ types/d3-delaunay/tsconfig.json | 24 ++ types/d3-delaunay/tslint.json | 3 + types/delaunator/delaunator-tests.ts | 20 +- types/delaunator/index.d.ts | 44 ++- types/delaunator/tslint.json | 5 +- 7 files changed, 549 insertions(+), 24 deletions(-) create mode 100644 types/d3-delaunay/d3-delaunay-tests.ts create mode 100644 types/d3-delaunay/index.d.ts create mode 100644 types/d3-delaunay/tsconfig.json create mode 100644 types/d3-delaunay/tslint.json diff --git a/types/d3-delaunay/d3-delaunay-tests.ts b/types/d3-delaunay/d3-delaunay-tests.ts new file mode 100644 index 0000000000..7f3103f60e --- /dev/null +++ b/types/d3-delaunay/d3-delaunay-tests.ts @@ -0,0 +1,118 @@ +/** + * TypeScript definition tests for d3-delaunay module + * + * Note: These tests are intended to test the definitions only + * in the sense of typing and call signature consistency. They + * are not intended as functional tests. + */ + +import * as d3 from 'd3-delaunay'; + +// Test Delaunay class + +const constructedDelaunay = new d3.Delaunay([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]); +const defaultDelaunayFromArray: d3.Delaunay<[number, number]> = d3.Delaunay.from([[0, 0], [1, 0], [0, 1], [1, 1]]); +const defaultDelaunayFromIterator = d3.Delaunay.from((function*() { + yield [0, 0]; + yield [1, 0]; + yield [0, 1]; + yield [1, 1]; +})()); +const customDelaunayFromArray = d3.Delaunay.from({length: 4}, (d, i) => i & 1, (d, i) => (i >> 1) & 1); +const customDelaunayFromIterator = d3.Delaunay.from((function*() { + yield {x: 0, y: 0}; + yield {x: 1, y: 0}; + yield {x: 0, y: 1}; + yield {x: 1, y: 1}; +})(), p => p.x, p => p.y); + +const {points, halfedges, hull, triangles} = defaultDelaunayFromArray; +for (let i = 0, l = points.length; i < l; i++) { + typeof(points[i]); +} +for (let i = 0, l = halfedges.length; i < l; i++) { + const j = halfedges[i]; + const ti = triangles[i]; + const tj = triangles[j]; + const pix = points[ti * 2]; + const piy = points[ti * 2 + 1]; + const pjx = points[tj * 2]; + const pjy = points[tj * 2 + 1]; +} +for (let n = hull.next; n !== hull; n = n.next) { + const i: number = n.i; + const x: number = n.x; + const y: number = n.y; + const t: number = n.t; + const next: d3.Delaunay.Node = n.next; + const prev: d3.Delaunay.Node = n.prev; + const removed: boolean = n.removed; +} +for (let i = 0, l = triangles.length; i < l; i++) { + const t0 = triangles[i * 3 + 0]; + const t1 = triangles[i * 3 + 1]; + const t2 = triangles[i * 3 + 2]; + const p0x = points[t0 * 2]; + const p0y = points[t0 * 2 + 1]; + const p1x = points[t1 * 2]; + const p1y = points[t1 * 2 + 1]; + const p2x = points[t2 * 2]; + const p2y = points[t2 * 2 + 1]; +} +const findClosest = defaultDelaunayFromArray.find(0.5, 0.5); +for (const neighbor of defaultDelaunayFromArray.neighbors(0)) { + typeof(neighbor); +} +const render: string = defaultDelaunayFromArray.render(); +const renderHull: string = defaultDelaunayFromArray.renderHull(); +const renderTriangle: string = defaultDelaunayFromArray.renderTriangle(0); +const renderPoints: string = defaultDelaunayFromArray.renderPoints(); +const renderPointsRadius: string = defaultDelaunayFromArray.renderPoints(void 0, 3); +for (const p of defaultDelaunayFromArray.hullPolygon()) { + const x = p[0]; + const y = p[1]; +} +for (const poly of defaultDelaunayFromArray.trianglePolygons()) { + for (const p of poly) { + const x = p[0]; + const y = p[1]; + } +} +for (const p of defaultDelaunayFromArray.trianglePolygon(0)) { + const x = p[0]; + const y = p[1]; +} + +// Test Voronoi class + +const v = defaultDelaunayFromArray.voronoi(); +const {circumcenters, vectors} = v; +const d: d3.Delaunay<[number, number]> = v.delaunay; +for (let i = 0, l = circumcenters.length; i < l; i++) { + const x: number = circumcenters[i * 2]; + const y: number = circumcenters[i * 2 + 1]; +} +for (let i = 0, l = vectors.length; i < l; i++) { + const vx: number = vectors[i * 4]; + const vy: number = vectors[i * 4 + 1]; + const wx: number = vectors[i * 4 + 2]; + const wy: number = vectors[i * 4 + 3]; +} +const xmin: number = v.xmin; +const ymin: number = v.ymin; +const xmax: number = v.xmax; +const ymax: number = v.ymax; +const contains: boolean = v.contains(0, 0.5, 0.5); +const vrender: string = v.render(); +const vrenderBounds: string = v.renderBounds(); +const renderCell: string = v.renderCell(0); +for (const poly of v.cellPolygons()) { + for (const p of poly) { + const x = p[0]; + const y = p[1]; + } +} +for (const p of v.cellPolygon(0)) { + const x = p[0]; + const y = p[1]; +} diff --git a/types/d3-delaunay/index.d.ts b/types/d3-delaunay/index.d.ts new file mode 100644 index 0000000000..c5d10e8aa3 --- /dev/null +++ b/types/d3-delaunay/index.d.ts @@ -0,0 +1,359 @@ +// Type definitions for d3-delaunay 4.1 +// Project: https://github.com/d3/d3-delaunay +// Definitions by: Bradley Odell +// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped + +/** + * Delaunay triangulation + */ +export class Delaunay

{ + /** + * The coordinates of the points as an array [x0, y0, x1, y1, ...]. + * Typically, this is a Float64Array, however you can use any array-like type in the constructor. + */ + points: ArrayLike; + + /** + * The halfedge indices as an Int32Array [j0, j1, ...]. + * For each index 0 <= i < halfedges.length, there is a halfedge from triangle vertex j = halfedges[i] to triangle vertex i. + */ + halfedges: Int32Array; + + /** + * An arbitrary node on the convex hull. + * The convex hull is represented as a circular doubly-linked list of nodes. + */ + hull: Delaunay.Node; + + /** + * The triangle vertex indices as an Uint32Array [i0, j0, k0, i1, j1, k1, ...]. + * Each contiguous triplet of indices i, j, k forms a counterclockwise triangle. + * The coordinates of the triangle's points can be found by going through 'points'. + */ + triangles: Uint32Array; + + /** + * The incoming halfedge indexes as a Int32Array [e0, e1, e2, ...]. + * For each point i, inedges[i] is the halfedge index e of an incoming halfedge. + * For coincident points, the halfedge index is -1; for points on the convex hull, the incoming halfedge is on the convex hull; for other points, the choice of incoming halfedge is arbitrary. + */ + inedges: Int32Array; + + /** + * The outgoing halfedge indexes as a Int32Array [e0, e1, e2, ...]. + * For each point i on the convex hull, outedges[i] is the halfedge index e of the corresponding outgoing halfedge; for other points, the halfedge index is -1. + */ + outedges: Int32Array; + + /** + * Returns the Delaunay triangulation for the given flat array [x0, y0, x1, y1, …] of points. + */ + constructor(points: ArrayLike); + + /** + * Returns the Delaunay triangulation for the given array or iterable of points where each point is an array in the form: [x, y]. + */ + static from(points: ArrayLike|Iterable): Delaunay; + + /** + * Returns the Delaunay triangulation for the given array or iterable of points. + * Otherwise, the getX and getY functions are invoked for each point in order, and must return the respective x- and y-coordinate for each point. + * If that is specified, the functions getX and getY are invoked with that as this. + * (See Array.from for reference.) + */ + static from

(points: ArrayLike

|Iterable

, + getX: Delaunay.GetCoordinate|Iterable

>, + getY: Delaunay.GetCoordinate|Iterable

>, + that?: any): Delaunay

; + + /** + * Returns the index of the input point that is closest to the specified point ⟨x, y⟩. + * The search is started at the specified point i. If i is not specified, it defaults to zero. + */ + find(x: number, y: number, i?: number): number; + + /** + * Returns an iterable over the indexes of the neighboring points to the specified point i. + * The iterable is empty if i is a coincident point. + */ + neighbors(i: number): IterableIterator; + + /** + * Returns the closed polygon [[x0, y0], [x1, y1], ..., [x0, y0]] representing the convex hull. + */ + hullPolygon(): Delaunay.Polygon; + + /** + * Returns the closed polygon [[x0, y0], [x1, y1], [x2, y2], [x0, y0]] representing the triangle i. + */ + trianglePolygon(i: number): Delaunay.Triangle; + + /** + * Returns an iterable over the polygons for each triangle, in order. + */ + trianglePolygons(): IterableIterator; + + /** + * Renders the edges of the Delaunay triangulation to an SVG path string. + */ + render(): string; + + /** + * Renders the edges of the Delaunay triangulation to the specified context. + * The specified context must implement the context.moveTo and context.lineTo methods from the CanvasPathMethods API. + */ + render(context: Delaunay.MoveContext & Delaunay.LineContext): void; + + /** + * Renders the convex hull of the Delaunay triangulation to an SVG path string. + */ + renderHull(): string; + + /** + * Renders the convex hull of the Delaunay triangulation to the specified context. + * The specified context must implement the context.moveTo and context.lineTo methods from the CanvasPathMethods API. + */ + renderHull(context: Delaunay.MoveContext & Delaunay.LineContext): void; + + /** + * Renders triangle i of the Delaunay triangulation to an SVG path string. + */ + renderTriangle(i: number): string; + + /** + * Renders triangle i of the Delaunay triangulation to the specified context. + * The specified context must implement the context.moveTo, context.lineTo and context.closePath methods from the CanvasPathMethods API. + */ + renderTriangle(i: number, context: Delaunay.MoveContext & Delaunay.LineContext & Delaunay.ClosableContext): void; + + /** + * Renders the input points of the Delaunay triangulation to an SVG path string as circles with radius 2. + */ + renderPoints(): string; + + /** + * Renders the input points of the Delaunay triangulation to an SVG path string as circles with the specified radius. + */ + renderPoints(context: undefined, radius: number): string; + + /** + * Renders the input points of the Delaunay triangulation to the specified context as circles with the specified radius. + * If radius is not specified, it defaults to 2. + * The specified context must implement the context.moveTo and context.arc methods from the CanvasPathMethods API. + */ + renderPoints(context: Delaunay.MoveContext & Delaunay.ArcContext, radius?: number): void; + + /** + * Returns the Voronoi diagram for the associated points. + * When rendering, the diagram will be clipped to the specified bounds = [xmin, ymin, xmax, ymax]. + * If bounds is not specified, it defaults to [0, 0, 960, 500]. + * See To Infinity and Back Again for an interactive explanation of Voronoi cell clipping. + */ + voronoi(bounds?: Delaunay.Bounds): Voronoi

; +} + +export namespace Delaunay { + /** + * A point represented as an array tuple [x, y]. + */ + type Point = number[]; + + /** + * A closed polygon [[x0, y0], [x1, y1], [x2, y2], [x0, y0]] representing a triangle. + */ + type Triangle = Point[]; + + /** + * A closed polygon [[x0, y0], [x1, y1], ..., [x0, y0]]. + */ + type Polygon = Point[]; + + /** + * A rectangular area [x, y, width, height]. + */ + type Bounds = number[]; + + /** + * A function to extract a x- or y-coordinate from the specified point. + */ + type GetCoordinate = (point: P, i: number, points: PS) => number; + + /** + * A point node on a convex hull (represented as a circular linked list). + */ + interface Node { + /** + * The index of the associated point. + */ + i: number; + + /** + * The x-coordinate of the associated point. + */ + x: number; + + /** + * The y-coordinate of the associated point. + */ + y: number; + + /** + * The index of the (incoming or outgoing?) associated halfedge. + */ + t: number; + + /** + * The previous node on the hull. + */ + prev: Node; + + /** + * The next node on the hull. + */ + next: Node; + + /** + * Whether the node has been removed from the linked list. + */ + removed: boolean; + } + + /** + * An interface for the rect() method of the CanvasPathMethods API. + */ + interface RectContext { + /** + * rect() method of the CanvasPathMethods API. + */ + rect(x: number, y: number, width: number, height: number): void; + } + + /** + * An interface for the moveTo() method of the CanvasPathMethods API. + */ + interface MoveContext { + /** + * moveTo() method of the CanvasPathMethods API. + */ + moveTo(x: number, y: number): void; + } + + /** + * An interface for the lineTo() method of the CanvasPathMethods API. + */ + interface LineContext { + /** + * lineTo() method of the CanvasPathMethods API. + */ + lineTo(x: number, y: number): void; + } + + /** + * An interface for the arc() method of the CanvasPathMethods API. + */ + interface ArcContext { + /** + * arc() method of the CanvasPathMethods API. + */ + arc(x: number, y: number, radius: number, + startAngle: number, endAngle: number, + counterclockwise?: boolean): void; + } + + /** + * An interface for the closePath() method of the CanvasPathMethods API. + */ + interface ClosableContext { + /** + * closePath() method of the CanvasPathMethods API. + */ + closePath(): void; + } +} + +/** + * Voronoi regions + */ +export class Voronoi

{ + /** + * The Voronoi diagram’s associated Delaunay triangulation. + */ + delaunay: Delaunay

; + + /** + * The circumcenters of the Delaunay triangles [cx0, cy0, cx1, cy1, ...]. + * Each contiguous pair of coordinates cx, cy is the circumcenter for the corresponding triangle. + * These circumcenters form the coordinates of the Voronoi cell polygons. + */ + circumcenters: Float64Array; + + /** + * An array [vx0, vy0, wx0, wy0, ...] where each non-zero quadruple describes an open (infinite) cell + * on the outer hull, giving the directions of two open half-lines. + */ + vectors: Float64Array; + + /** + * The bounds of the viewport [xmin, ymin, xmax, ymax] for rendering the Voronoi diagram. + * These values only affect the rendering methods (voronoi.render, voronoi.renderBounds, cell.render). + */ + xmin: number; + ymin: number; + xmax: number; + ymax: number; + + /** + * Internally used to implement Delaunay#voronoi. + */ + constructor(delaunay: Delaunay

, bounds: Delaunay.Bounds); + + /** + * Returns true if the cell with the specified index i contains the specified point ⟨x, y⟩. + * (This method is not affected by the associated Voronoi diagram’s viewport bounds.) + */ + contains(i: number, x: number, y: number): boolean; + + /** + * Returns the convex, closed polygon [[x0, y0], [x1, y1], ..., [x0, y0]] representing the cell for the specified point i. + */ + cellPolygon(i: number): Delaunay.Polygon; + + /** + * Returns an iterable over the polygons for each cell, in order. + */ + cellPolygons(): IterableIterator; + + /** + * Renders the mesh of Voronoi cells to an SVG path string. + */ + render(): string; + + /** + * Renders the mesh of Voronoi cells to the specified context. + * The specified context must implement the context.moveTo and context.lineTo methods from the CanvasPathMethods API. + */ + render(context: Delaunay.MoveContext & Delaunay.LineContext): void; + + /** + * Renders the viewport extent to an SVG path string. + */ + renderBounds(): string; + + /** + * Renders the viewport extent to the specified context. + * The specified context must implement the context.rect method from the CanvasPathMethods API. + * Equivalent to context.rect(voronoi.xmin, voronoi.ymin, voronoi.xmax - voronoi.xmin, voronoi.ymax - voronoi.ymin). + */ + renderBounds(context: Delaunay.RectContext): void; + + /** + * Renders the cell with the specified index i to an SVG path string. + */ + renderCell(i: number): string; + + /** + * Renders the cell with the specified index i to the specified context. + * The specified context must implement the context.moveTo, context.lineTo, and context.closePath methods from the CanvasPathMethods API. + */ + renderCell(i: number, context: Delaunay.MoveContext & Delaunay.LineContext & Delaunay.ClosableContext): void; +} diff --git a/types/d3-delaunay/tsconfig.json b/types/d3-delaunay/tsconfig.json new file mode 100644 index 0000000000..ab2a753d44 --- /dev/null +++ b/types/d3-delaunay/tsconfig.json @@ -0,0 +1,24 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "lib": [ + "es6" + ], + "noImplicitAny": true, + "noImplicitThis": true, + "strictNullChecks": true, + "strictFunctionTypes": true, + "baseUrl": "../", + "typeRoots": [ + "../" + ], + "types": [], + "noEmit": true, + "forceConsistentCasingInFileNames": true + }, + "files": [ + "index.d.ts", + "d3-delaunay-tests.ts" + ] +} \ No newline at end of file diff --git a/types/d3-delaunay/tslint.json b/types/d3-delaunay/tslint.json new file mode 100644 index 0000000000..f93cf8562a --- /dev/null +++ b/types/d3-delaunay/tslint.json @@ -0,0 +1,3 @@ +{ + "extends": "dtslint/dt.json" +} diff --git a/types/delaunator/delaunator-tests.ts b/types/delaunator/delaunator-tests.ts index 1d50e0273a..6310448c83 100644 --- a/types/delaunator/delaunator-tests.ts +++ b/types/delaunator/delaunator-tests.ts @@ -1,9 +1,12 @@ import * as Delaunator from 'delaunator'; -import { Points, GetPoint } from 'delaunator'; + +// Zipped points [x0, y0, x1, y1, ...] +const zippedPoints = [168, 180, 168, 178, 168, 179, 168, 181, 168, 183, 167, 183, 167, 184]; +const zipped = new Delaunator(zippedPoints); // Default [x, y] -const points: Points = [[168, 180], [168, 178], [168, 179], [168, 181], [168, 183], [167, 183], [167, 184]]; -const d = new Delaunator(points); +const defaultPoints = [[168, 180], [168, 178], [168, 179], [168, 181], [168, 183], [167, 183], [167, 184]]; +const d = Delaunator.from(defaultPoints); // Custom getX & getY interface CustomPoint { @@ -15,17 +18,18 @@ const customPoints = [{x: 168, y: 180}, {x: 168, y: 178}, {x: 168, y: 179}, {x: const getX = (point: CustomPoint) => point.x; const getY = (point: CustomPoint) => point.y; -new Delaunator(customPoints, point => point.x, point => point.y); -new Delaunator(customPoints, getX, getY); +Delaunator.from(customPoints, point => point.x, point => point.y); +Delaunator.from(customPoints, getX, getY); // To get the coordinates of all triangles, use: const triangles = d.triangles; const halfedges = d.halfedges; +const hull = d.hull; const coordinates: number[][][] = []; for (let i = 0; i < triangles.length; i += 3) { coordinates.push([ - points[triangles[i]], - points[triangles[i + 1]], - points[triangles[i + 2]] + defaultPoints[triangles[i]], + defaultPoints[triangles[i + 1]], + defaultPoints[triangles[i + 2]] ]); } diff --git a/types/delaunator/index.d.ts b/types/delaunator/index.d.ts index 5761fec4a8..c717feec95 100644 --- a/types/delaunator/index.d.ts +++ b/types/delaunator/index.d.ts @@ -1,13 +1,14 @@ -// Type definitions for delaunator 1.0 +// Type definitions for delaunator 2.0 // Project: https://github.com/mapbox/delaunator#readme // Definitions by: Denis Carriere +// Bradley Odell // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped -declare class Delaunator { +declare class Delaunator

{ /** - * A flat Int32Array array of triangle vertex indices (each group of three numbers forms a triangle). All triangles are directed counterclockwise. + * A flat Uint32Array array of triangle vertex indices (each group of three numbers forms a triangle). All triangles are directed counterclockwise. */ - triangles: Int32Array; + triangles: Uint32Array; /** * A flat Int32Array array of triangle half-edge indices that allows you to traverse the triangulation. @@ -19,17 +20,36 @@ declare class Delaunator { halfedges: Int32Array; /** - * Constructs a delaunay triangulation object given an array of points ([x, y] by default). Duplicate points are skipped. + * A circular doubly-linked list that holds a convex hull of the delaunay triangulation. */ - constructor(points: Delaunator.Points); - constructor(points: T[], getX: Delaunator.GetPoint, getY: Delaunator.GetPoint); + hull: Delaunator.Node; + + /** + * Constructs a delaunay triangulation object given a typed array of point coordinates of the form: [x0, y0, x1, y1, ...]. + */ + constructor(points: ArrayLike); + + /** + * Constructs a delaunay triangulation object given an array of points (e.g. [x, y]). Duplicate points are skipped. + */ + static from(points: ArrayLike>): Delaunator>; + + /** + * Constructs a delaunay triangulation object given an array of custom points. Duplicate points are skipped. + */ + static from

(points: ArrayLike

, getX: (point: P) => number, getY: (point: P) => number): Delaunator

; } declare namespace Delaunator { - type Point = number[]; - type Points = Point[]; - type Triangles = Int32Array; - type HalfEdges = Int32Array; - type GetPoint = (point: T) => number; + interface Node { + i: number; + x: number; + y: number; + t: number; + prev: Node|null; + next: Node|null; + removed: boolean; + } } + export = Delaunator; diff --git a/types/delaunator/tslint.json b/types/delaunator/tslint.json index f2ffe2445b..b4b47a0378 100644 --- a/types/delaunator/tslint.json +++ b/types/delaunator/tslint.json @@ -1,6 +1,3 @@ { - "extends": "dtslint/dt.json", - "rules": { - "no-duplicate-imports": false - } + "extends": "dtslint/dt.json" }