UNPKG

plotboilerplate

Version:

A simple javascript plotting boilerplate for 2d stuff.

185 lines (141 loc) 5.39 kB
/** * @modified_by Ikaros Kappler * @date_init 2012-10-17 * @date 2017-07-31 * @modified 2020-08-17 Ported from vanilla JS to TypeScript. * @version 2.0.1 **/ import { Triangle } from "../../Triangle"; import { Vertex } from "../../Vertex"; import { Line as Edge } from "../../Line"; // TODO: cleanup? This seems not to be used. // const EPSILON : number = 1.0e-6; /** * @classdesc A Delaunay pointset triangulation implementation. Inspired by * http://www.travellermap.com/tmp/delaunay.htm * * License: Public Domain * Original C++ code by Joshua Bell * * @requires Triangle * @requires Line * @requires Vertex */ export class Delaunay { private pointList : Array<Vertex>; constructor( pointList:Array<Vertex> ) { this.pointList = pointList; } triangulate(): Array<Triangle> { return this.Triangulate( this.pointList ); } //////////////////////////////////////////////////////////////////////////////// // // Delaunay Triangulation Code, by Joshua Bell // // Inspired by: http://www.codeguru.com/cpp/data/mfc_database/misc/article.php/c8901/ // // This work is hereby released into the Public Domain. To view a copy of the public // domain dedication, visit http://creativecommons.org/licenses/publicdomain/ or send // a letter to Creative Commons, 171 Second Street, Suite 300, San Francisco, // California, 94105, USA. // //////////////////////////////////////////////////////////////////////////////// //------------------------------------------------------------ // Triangulate // // Perform the Delaunay Triangulation of a set of vertices. // // vertices: Array of Vertex objects // // returns: Array of Triangles //------------------------------------------------------------ Triangulate( vertices:Array<Vertex> ) : Array<Triangle> { const triangles : Array<Triangle> = []; // First, create a "supertriangle" that bounds all vertices var st : Triangle = this.createBoundingTriangle( vertices ); triangles.push( st ); // begin the triangulation one vertex at a time for( var i in vertices ) { // NOTE: This is O(n^2) - can be optimized by sorting vertices // along the x-axis and only considering triangles that have // potentially overlapping circumcircles this.AddVertex( vertices[i], triangles ); } // Remove triangles that shared edges with "supertriangle" for( var i in triangles ) { var triangle : Triangle = triangles[i]; if( triangle.a == st.a || triangle.a == st.b || triangle.a == st.c || triangle.b == st.a || triangle.b == st.b || triangle.b == st.c || triangle.c == st.a || triangle.c == st.b || triangle.c == st.c ) { delete triangles[i]; } } return triangles; }; // Triangulate // Internal: create a triangle that bounds the given vertices, with room to spare createBoundingTriangle( vertices:Array<Vertex> ) { // NOTE: There's a bit of a heuristic here. If the bounding triangle // is too large and you see overflow/underflow errors. If it is too small // you end up with a non-convex hull. var minx:number, miny:number, maxx:number, maxy:number; for( var i in vertices ) { var vertex = vertices[i]; if( minx === undefined || vertex.x < minx ) { minx = vertex.x; } if( miny === undefined || vertex.y < miny ) { miny = vertex.y; } if( maxx === undefined || vertex.x > maxx ) { maxx = vertex.x; } if( maxy === undefined || vertex.y > maxy ) { maxy = vertex.y; } } var dx = ( maxx - minx ) * 10; var dy = ( maxy - miny ) * 10; var stv0 : Vertex = new Vertex( minx - dx, miny - dy*3 ); var stv1 : Vertex = new Vertex( minx - dx, maxy + dy ); var stv2 : Vertex = new Vertex( maxx + dx*3, maxy + dy ); return new Triangle( stv0, stv1, stv2 ); }; // END createBoundingTriangle // Internal: update triangulation with a vertex AddVertex( vertex:Vertex, triangles:Array<Triangle> ) : void { var edges : Array<Edge> = []; // Remove triangles with circumcircles containing the vertex for( var i in triangles ) { var triangle : Triangle = triangles[i]; if( triangle.inCircumcircle( vertex ) ) { edges.push( new Edge( triangle.a, triangle.b ) ); edges.push( new Edge( triangle.b, triangle.c ) ); edges.push( new Edge( triangle.c, triangle.a ) ); delete triangles[i]; } } edges = this.mkUniqueEdges( edges ); // Create new triangles from the unique edges and new vertex for( var i in edges ) { // console.log( 'adding triangle' ); var edge = edges[i]; triangles.push( new Triangle( edge.a, edge.b, vertex ) ); } }; // END AddVertex // Internal: remove duplicate edges from an array mkUniqueEdges( edges:Array<Edge> ) : Array<Edge> { // TODO: This is O(n^2), make it O(n) with a hash or some such const uniqueEdges : Array<Edge> = []; for( var i in edges ) { let edge1 : Edge = edges[i]; let unique = true; for( var j in edges ) { if( i != j ) { let edge2 = edges[j]; if( ( edge1.a == edge2.a && edge1.b == edge2.b ) || ( edge1.a == edge2.b && edge1.b == edge2.a ) ) { unique = false; break; } } } if( unique ) { uniqueEdges.push( edge1 ); } } return uniqueEdges; }; // END mkUniqueEdges }; // END class