Socket
Socket
Sign inDemoInstall

turf-tin

Package Overview
Dependencies
Maintainers
8
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

turf-tin - npm Package Compare versions

Comparing version 1.0.2 to 1.0.3

9

bench.js

@@ -1,6 +0,6 @@

var tin = require('./');
global.tin = require('./');
var Benchmark = require('benchmark');
var fs = require('fs');
var points = JSON.parse(fs.readFileSync(__dirname+'/geojson/Points.geojson'));
global.points = JSON.parse(fs.readFileSync(__dirname+'/geojson/Points.geojson'));

@@ -10,3 +10,3 @@ var suite = new Benchmark.Suite('turf-tin');

.add('turf-tin',function () {
tin(points, 'elevation');
global.tin(global.points, 'elevation');
})

@@ -17,4 +17,3 @@ .on('cycle', function (event) {

.on('complete', function () {
})
.run();
.run();
//http://en.wikipedia.org/wiki/Delaunay_triangulation
//https://github.com/ironwallaby/delaunay
var polygon = require('turf-polygon');
var nearest = require('turf-nearest');
var point = require('turf-point');
var featurecollection = require('turf-featurecollection');

@@ -10,121 +9,95 @@ /**

* creates a [Triangulated Irregular Network](http://en.wikipedia.org/wiki/Triangulated_irregular_network),
* or a TIN for short. These are often used
* or a TIN for short, returned as a collection of Polygons. These are often used
* for developing elevation contour maps or stepped heat visualizations.
*
* This triangulates the points, as well as adds properties called `a`, `b`,
* and `c` representing the value of the given `propertyName` at each of
* the points that represent the corners of the triangle.
*
* @module turf/tin
* @param {GeoJSONFeatureCollection} points - a GeoJSON FeatureCollection containing
* Features with Point geometries
* @param {string} propertyName - name of the property from which to pull z values
* @return {GeoJSONFeatureCollection} output
* @param {FeatureCollection} points - a GeoJSON FeatureCollection containing
* Features with {@link Point} geometries
* @param {string=} propertyName - name of the property from which to pull z values.
* This is optional: if not given, then there will be no extra data added to the derived triangles.
* @return {FeatureCollection} TIN output
* @example
* var fs = require('fs')
* var z = 'elevation'
* var pts = JSON.parse(fs.readFileSync('/path/to/pts.geojson'))
* var tinPolys = turf.tin(pts, z)
* console.log(tinPolys)
* // generate some random point data
* var points = turf.random('points', 30, {
* bbox: [50, 30, 70, 50]
* });
* //=points
* // add a random property to each point between 0 and 9
* for (var i = 0; i < points.features.length; i++) {
* points.features[i].properties.z = ~~(Math.random() * 9);
* }
* var tin = turf.tin(points, 'z')
* for (var i = 0; i < tin.features.length; i++) {
* var properties = tin.features[i].properties;
* // roughly turn the properties of each
* // triangle into a fill color
* // so we can visualize the result
* properties.fill = '#' + properties.a +
* properties.b + properties.c;
* }
* //=tin
*/
module.exports = function(points, z){
module.exports = function(points, z) {
//break down points
var vertices = [];
points.features.forEach(function(p){
vertices.push({x:p.geometry.coordinates[0], y:p.geometry.coordinates[1]});
})
var triangulated = triangulate(vertices);
var triangles = {
type: 'FeatureCollection',
features: []
};
triangulated.forEach(function(triangle){
var coords = [[[triangle.a.x, triangle.a.y], [triangle.b.x, triangle.b.y], [triangle.c.x, triangle.c.y]]];
var poly = polygon(coords, {a: null, b: null, c: null});
triangles.features.push(poly);
});
if(z){
// add values from vertices
triangles.features.forEach(function(tri){
var coordinateNumber = 1;
tri.geometry.coordinates[0].forEach(function(c){
var closest = nearest(point(c[0], c[1]), points);
if(coordinateNumber === 1){
tri.properties.a = closest.properties[z];
}
else if(coordinateNumber === 2){
tri.properties.b = closest.properties[z];
}
else if(coordinateNumber === 3){
tri.properties.c = closest.properties[z];
}
coordinateNumber++;
return featurecollection(triangulate(points.features.map(function(p) {
var point = {
x: p.geometry.coordinates[0],
y: p.geometry.coordinates[1]
};
if (z) point.z = p.properties[z];
return point;
})).map(function(triangle) {
return polygon([[
[triangle.a.x, triangle.a.y],
[triangle.b.x, triangle.b.y],
[triangle.c.x, triangle.c.y],
[triangle.a.x, triangle.a.y]
]], {
a: triangle.a.z,
b: triangle.b.z,
c: triangle.c.z
});
});
}
}));
};
triangles.features.forEach(function(tri){
tri = correctRings(tri);
});
return triangles;
}
function correctRings(poly){
poly.geometry.coordinates.forEach(function(ring){
var isWrapped = ring[0] === ring.slice(-1)[0];
if(!isWrapped){
ring.push(ring[0]);
}
})
return poly;
}
function Triangle(a, b, c) {
this.a = a
this.b = b
this.c = c
this.a = a;
this.b = b;
this.c = c;
var A = b.x - a.x,
B = b.y - a.y,
C = c.x - a.x,
D = c.y - a.y,
E = A * (a.x + b.x) + B * (a.y + b.y),
F = C * (a.x + c.x) + D * (a.y + c.y),
G = 2 * (A * (c.y - b.y) - B * (c.x - b.x)),
minx, miny, dx, dy
B = b.y - a.y,
C = c.x - a.x,
D = c.y - a.y,
E = A * (a.x + b.x) + B * (a.y + b.y),
F = C * (a.x + c.x) + D * (a.y + c.y),
G = 2 * (A * (c.y - b.y) - B * (c.x - b.x)),
minx, miny, dx, dy;
/* If the points of the triangle are collinear, then just find the
* extremes and use the midpoint as the center of the circumcircle. */
if(Math.abs(G) < 0.000001) {
minx = Math.min(a.x, b.x, c.x)
miny = Math.min(a.y, b.y, c.y)
dx = (Math.max(a.x, b.x, c.x) - minx) * 0.5
dy = (Math.max(a.y, b.y, c.y) - miny) * 0.5
if (Math.abs(G) < 0.000001) {
minx = Math.min(a.x, b.x, c.x);
miny = Math.min(a.y, b.y, c.y);
dx = (Math.max(a.x, b.x, c.x) - minx) * 0.5;
dy = (Math.max(a.y, b.y, c.y) - miny) * 0.5;
this.x = minx + dx
this.y = miny + dy
this.r = dx * dx + dy * dy
this.x = minx + dx;
this.y = miny + dy;
this.r = dx * dx + dy * dy;
} else {
this.x = (D * E - B * F) / G;
this.y = (A * F - C * E) / G;
dx = this.x - a.x;
dy = this.y - a.y;
this.r = dx * dx + dy * dy;
}
else {
this.x = (D*E - B*F) / G
this.y = (A*F - C*E) / G
dx = this.x - a.x
dy = this.y - a.y
this.r = dx * dx + dy * dy
}
}
Triangle.prototype.draw = function(ctx) {
ctx.beginPath()
ctx.moveTo(this.a.x, this.a.y)
ctx.lineTo(this.b.x, this.b.y)
ctx.lineTo(this.c.x, this.c.y)
ctx.closePath()
ctx.stroke()
}
function byX(a, b) {
return b.x - a.x
return b.x - a.x;
}

@@ -134,16 +107,17 @@

var j = edges.length,
a, b, i, m, n
a, b, i, m, n;
outer: while(j) {
b = edges[--j]
a = edges[--j]
i = j
while(i) {
n = edges[--i]
m = edges[--i]
if((a === m && b === n) || (a === n && b === m)) {
edges.splice(j, 2)
edges.splice(i, 2)
j -= 2
continue outer
outer:
while (j) {
b = edges[--j];
a = edges[--j];
i = j;
while (i) {
n = edges[--i];
m = edges[--i];
if ((a === m && b === n) || (a === n && b === m)) {
edges.splice(j, 2);
edges.splice(i, 2);
j -= 2;
continue outer;
}

@@ -156,19 +130,21 @@ }

/* Bail if there aren't enough vertices to form any triangles. */
if(vertices.length < 3)
return []
if (vertices.length < 3)
return [];
/* Ensure the vertex array is in order of descending X coordinate
* (which is needed to ensure a subquadratic runtime), and then find
* the bounding box around the points. */
vertices.sort(byX)
/* Ensure the vertex array is in order of descending X coordinate
* (which is needed to ensure a subquadratic runtime), and then find
* the bounding box around the points. */
vertices.sort(byX);
var i = vertices.length - 1,
xmin = vertices[i].x,
xmax = vertices[0].x,
ymin = vertices[i].y,
ymax = ymin
var i = vertices.length - 1,
xmin = vertices[i].x,
xmax = vertices[0].x,
ymin = vertices[i].y,
ymax = ymin;
while(i--) {
if(vertices[i].y < ymin) ymin = vertices[i].y
if(vertices[i].y > ymax) ymax = vertices[i].y
while (i--) {
if (vertices[i].y < ymin)
ymin = vertices[i].y;
if (vertices[i].y > ymax)
ymax = vertices[i].y;
}

@@ -184,41 +160,51 @@

* for triangles which do not.) */
var dx = xmax - xmin,
dy = ymax - ymin,
dmax = (dx > dy) ? dx : dy,
xmid = (xmax + xmin) * 0.5,
ymid = (ymax + ymin) * 0.5,
open = [
new Triangle(
{x: xmid - 20 * dmax, y: ymid - dmax, __sentinel: true},
{x: xmid , y: ymid + 20 * dmax, __sentinel: true},
{x: xmid + 20 * dmax, y: ymid - dmax, __sentinel: true}
)
],
closed = [],
edges = [],
j, a, b
var dx = xmax - xmin,
dy = ymax - ymin,
dmax = (dx > dy) ? dx : dy,
xmid = (xmax + xmin) * 0.5,
ymid = (ymax + ymin) * 0.5,
open = [
new Triangle({
x: xmid - 20 * dmax,
y: ymid - dmax,
__sentinel: true
},
{
x: xmid,
y: ymid + 20 * dmax,
__sentinel: true
},
{
x: xmid + 20 * dmax,
y: ymid - dmax,
__sentinel: true
}
)],
closed = [],
edges = [],
j, a, b;
/* Incrementally add each vertex to the mesh. */
i = vertices.length
while(i--) {
/* Incrementally add each vertex to the mesh. */
i = vertices.length;
while (i--) {
/* For each open triangle, check to see if the current point is
* inside it's circumcircle. If it is, remove the triangle and add
* it's edges to an edge list. */
edges.length = 0
j = open.length
while(j--) {
edges.length = 0;
j = open.length;
while (j--) {
/* If this point is to the right of this triangle's circumcircle,
* then this triangle should never get checked again. Remove it
* from the open list, add it to the closed list, and skip. */
dx = vertices[i].x - open[j].x
if(dx > 0 && dx * dx > open[j].r) {
closed.push(open[j])
open.splice(j, 1)
continue
dx = vertices[i].x - open[j].x;
if (dx > 0 && dx * dx > open[j].r) {
closed.push(open[j]);
open.splice(j, 1);
continue;
}
/* If not, skip this triangle. */
dy = vertices[i].y - open[j].y
if(dx * dx + dy * dy > open[j].r)
continue
dy = vertices[i].y - open[j].y;
if (dx * dx + dy * dy > open[j].r)
continue;

@@ -230,15 +216,15 @@ /* Remove the triangle and add it's edges to the edge list. */

open[j].c, open[j].a
)
open.splice(j, 1)
);
open.splice(j, 1);
}
/* Remove any doubled edges. */
dedup(edges)
dedup(edges);
/* Add a new triangle for each edge. */
j = edges.length
while(j) {
b = edges[--j]
a = edges[--j]
open.push(new Triangle(a, b, vertices[i]))
j = edges.length;
while (j) {
b = edges[--j];
a = edges[--j];
open.push(new Triangle(a, b, vertices[i]));
}

@@ -249,20 +235,13 @@ }

* remove any triangles that share a vertex with the supertriangle. */
Array.prototype.push.apply(closed, open)
Array.prototype.push.apply(closed, open);
i = closed.length
while(i--)
if(closed[i].a.__sentinel ||
closed[i].b.__sentinel ||
closed[i].c.__sentinel)
closed.splice(i, 1)
i = closed.length;
while (i--)
if (closed[i].a.__sentinel ||
closed[i].b.__sentinel ||
closed[i].c.__sentinel)
closed.splice(i, 1);
/* Yay, we're done! */
return closed
/* Yay, we're done! */
return closed;
}
/*if (typeof module !== 'undefined') {
module.exports = {
Triangle: Triangle,
triangulate: triangulate
}
}*/
{
"name": "turf-tin",
"version": "1.0.2",
"version": "1.0.3",
"description": "turf tin module",
"main": "index.js",
"scripts": {
"test": "tape test.js"
"test": "tape test.js",
"doc": "dox -r < index.js | doxme --readme > README.md"
},
"repository": {
"type": "git",
"url": "https://github.com/morganherlocker/turf-tin.git"
"url": "https://github.com/Turfjs/turf-tin.git"
},

@@ -21,14 +22,15 @@ "keywords": [

"bugs": {
"url": "https://github.com/morganherlocker/turf-tin/issues"
"url": "https://github.com/Turfjs/turf-tin/issues"
},
"homepage": "https://github.com/morganherlocker/turf-tin",
"homepage": "https://github.com/Turfjs/turf-tin",
"devDependencies": {
"benchmark": "^1.0.0",
"tape": "^3.0.3"
"tape": "^3.0.3",
"dox": "^0.6.1",
"doxme": "^1.4.2"
},
"dependencies": {
"turf-nearest": "^1.0.1",
"turf-point": "^1.2.0",
"turf-polygon": "^1.0.0"
"turf-featurecollection": "^1.0.0",
"turf-polygon": "^1.0.1"
}
}

@@ -1,38 +0,145 @@

turf-tin
========
# turf-tin
[![build status](https://secure.travis-ci.org/Turfjs/turf-tin.png)](http://travis-ci.org/Turfjs/turf-tin)
Takes a set of points and the name of a z-value property and creates a tin (Triangulated Irregular Network). These are often used for developing elevation contour maps or stepped heat visualizations.
turf tin module
###Install
```sh
npm install turf-tin
```
### `turf.tin(points, propertyName)`
###Parameters
Takes a set of points and the name of a z-value property and
creates a [Triangulated Irregular Network](http://en.wikipedia.org/wiki/Triangulated_irregular_network),
or a TIN for short, returned as a collection of Polygons. These are often used
for developing elevation contour maps or stepped heat visualizations.
|name|description|
|---|---|
|pts|a point featurecollection|
|z|a z value to encode|
This triangulates the points, as well as adds properties called `a`, `b`,
and `c` representing the value of the given `propertyName` at each of
the points that represent the corners of the triangle.
###Usage
### Parameters
| parameter | type | description |
| -------------- | ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `points` | FeatureCollection | - a GeoJSON FeatureCollection containing Features with Point geometries |
| `propertyName` | string | _optional:_ - name of the property from which to pull z values. This is optional: if not given, then there will be no extra data added to the derived triangles. |
### Example
```js
tin(pts, z)
// generate some random point data
var points = turf.random('points', 30, {
bbox: [50, 30, 70, 50]
});
//=points
// add a random property to each point between 0 and 9
for (var i = 0; i < points.features.length; i++) {
points.features[i].properties.z = ~~(Math.random() * 9);
}
var tin = turf.tin(points, 'z')
for (var i = 0; i < tin.features.length; i++) {
var properties = tin.features[i].properties;
// roughly turn the properties of each
// triangle into a fill color
// so we can visualize the result
properties.fill = '#' + properties.a +
properties.b + properties.c;
}
//=tin
```
###Example
```javascript
var tin = require('turf-tin')
var fs = require('fs')
### `undefined`
var z = 'elevation'
var pts = JSON.parse(fs.readFileSync('/path/to/pts.geojson'))
If the points of the triangle are collinear, then just find the
extremes and use the midpoint as the center of the circumcircle.
var tinPolys = tin(pts, z)
console.log(tinPolys)
```
### `undefined`
Bail if there aren't enough vertices to form any triangles.
### `undefined`
Ensure the vertex array is in order of descending X coordinate
(which is needed to ensure a subquadratic runtime), and then find
the bounding box around the points.
### `dx`
Find a supertriangle, which is a triangle that surrounds all the
vertices. This is used like something of a sentinel value to remove
cases in the main algorithm, and is removed before we return any
results.
Once found, put it in the "open" list. (The "open" list is for
triangles who may still need to be considered; the "closed" list is
for triangles which do not.)
### `undefined`
Incrementally add each vertex to the mesh.
### `length`
For each open triangle, check to see if the current point is
inside it's circumcircle. If it is, remove the triangle and add
it's edges to an edge list.
### `undefined`
If this point is to the right of this triangle's circumcircle,
then this triangle should never get checked again. Remove it
from the open list, add it to the closed list, and skip.
### `undefined`
If not, skip this triangle.
### `undefined`
Remove the triangle and add it's edges to the edge list.
### `undefined`
Remove any doubled edges.
### `undefined`
Add a new triangle for each edge.
### `undefined`
Copy any remaining open triangles to the closed list, and then
remove any triangles that share a vertex with the supertriangle.
### `undefined`
Yay, we're done!
## Installation
Requires [nodejs](http://nodejs.org/).
```sh
$ npm install turf-tin
```
## Tests
```sh
$ npm test
```
var test = require('tape');
var fs = require('fs');
var tin = require('./');
var tin = require('./index.js');
test('tin', function(t){
var points = JSON.parse(fs.readFileSync(__dirname+'/geojson/Points.geojson'));
var tinned = tin(points, 'elevation');

@@ -9,0 +8,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc