├── .gitignore ├── LICENSE ├── README.md ├── ch.js ├── lib ├── ch1d.js ├── ch2d.js └── chnd.js ├── package.json └── test └── test.js /.gitignore: -------------------------------------------------------------------------------- 1 | lib-cov 2 | *.seed 3 | *.log 4 | *.csv 5 | *.dat 6 | *.out 7 | *.pid 8 | *.gz 9 | 10 | pids 11 | logs 12 | results 13 | 14 | npm-debug.log 15 | node_modules/* 16 | *.DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2014 Mikola Lysenko 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in 14 | all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | convex-hull 2 | =========== 3 | This module is a wrapper over various convex hull modules which exposes a simple interface for computing convex hulls of point sets in any dimension. 4 | 5 | # Example 6 | 7 | ```javascript 8 | var ch = require('convex-hull') 9 | 10 | var points = [ 11 | [0,0], 12 | [1,0], 13 | [0,1], 14 | [0.15,0.15], 15 | [0.5, 0.5] 16 | ] 17 | 18 | 19 | //Picture: 20 | // 21 | // [0,1] * 22 | // |\ 23 | // | \ 24 | // | \ 25 | // | \ 26 | // | \ 27 | // | \ 28 | // | \ 29 | // | * [0.5,0.5] 30 | // | \ 31 | // | \ 32 | // | \ 33 | // | \ 34 | // | \ 35 | // | * \ 36 | // | [0.15,0.15] \ 37 | // [0,0] *---------------* [1,0] 38 | // 39 | 40 | console.log(ch(points)) 41 | ``` 42 | 43 | Output: 44 | 45 | ```javascript 46 | [[0, 1], [1, 2], [2, 0]] 47 | ``` 48 | 49 | # Install 50 | 51 | ``` 52 | npm install convex-hull 53 | ``` 54 | 55 | If you want to use it in a webpage, use [browserify](http://browserify.org). 56 | 57 | # API 58 | 59 | #### `require('convex-hull')(points)` 60 | Computes the convex hull of `points` 61 | 62 | * `points` is an array of points encoded as `d` length arrays 63 | 64 | **Returns** A polytope encoding the convex hull of the point set. 65 | 66 | **Time complexity** The procedure takes O(n^floor(d/2) + n log(n)) time. 67 | 68 | **Note** This module is a wrapper over incremental-convex-hull and monotone-convex-hull for convenience. It will select an optimal algorithm for whichever dimension is appropriate. 69 | 70 | 71 | # Credits 72 | (c) 2014 Mikola Lysenko. MIT License -------------------------------------------------------------------------------- /ch.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | var convexHull1d = require('./lib/ch1d') 4 | var convexHull2d = require('./lib/ch2d') 5 | var convexHullnd = require('./lib/chnd') 6 | 7 | module.exports = convexHull 8 | 9 | function convexHull(points) { 10 | var n = points.length 11 | if(n === 0) { 12 | return [] 13 | } else if(n === 1) { 14 | return [[0]] 15 | } 16 | var d = points[0].length 17 | if(d === 0) { 18 | return [] 19 | } else if(d === 1) { 20 | return convexHull1d(points) 21 | } else if(d === 2) { 22 | return convexHull2d(points) 23 | } 24 | return convexHullnd(points, d) 25 | } -------------------------------------------------------------------------------- /lib/ch1d.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | 3 | module.exports = convexHull1d 4 | 5 | function convexHull1d(points) { 6 | var lo = 0 7 | var hi = 0 8 | for(var i=1; i points[hi][0]) { 13 | hi = i 14 | } 15 | } 16 | if(lo < hi) { 17 | return [[lo], [hi]] 18 | } else if(lo > hi) { 19 | return [[hi], [lo]] 20 | } else { 21 | return [[lo]] 22 | } 23 | } -------------------------------------------------------------------------------- /lib/ch2d.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | module.exports = convexHull2D 4 | 5 | var monotoneHull = require('monotone-convex-hull-2d') 6 | 7 | function convexHull2D(points) { 8 | var hull = monotoneHull(points) 9 | var h = hull.length 10 | if(h <= 2) { 11 | return [] 12 | } 13 | var edges = new Array(h) 14 | var a = hull[h-1] 15 | for(var i=0; i= front[k]) { 36 | x += 1 37 | } 38 | } 39 | c[j] = x 40 | } 41 | } 42 | } 43 | return cells 44 | } 45 | 46 | function convexHullnD(points, d) { 47 | try { 48 | return ich(points, true) 49 | } catch(e) { 50 | //If point set is degenerate, try to find a basis and rerun it 51 | var ah = aff(points) 52 | if(ah.length <= d) { 53 | //No basis, no try 54 | return [] 55 | } 56 | var npoints = permute(points, ah) 57 | var nhull = ich(npoints, true) 58 | return invPermute(nhull, ah) 59 | } 60 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "convex-hull", 3 | "version": "1.0.3", 4 | "description": "Any dimensional convex hull", 5 | "main": "ch.js", 6 | "dependencies": { 7 | "affine-hull": "^1.0.0", 8 | "incremental-convex-hull": "^1.0.1", 9 | "monotone-convex-hull-2d": "^1.0.1" 10 | }, 11 | "devDependencies": { 12 | "tape": "^3.0.3" 13 | }, 14 | "scripts": { 15 | "test": "tape test/*.js" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/mikolalysenko/convex-hull.git" 20 | }, 21 | "keywords": [ 22 | "convex", 23 | "hull", 24 | "any", 25 | "dimension" 26 | ], 27 | "author": "Mikola Lysenko", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/mikolalysenko/convex-hull/issues" 31 | }, 32 | "homepage": "https://github.com/mikolalysenko/convex-hull" 33 | } 34 | -------------------------------------------------------------------------------- /test/test.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | var tape = require('tape') 4 | var hull = require('../ch') 5 | 6 | tape('convex-hull', function(t) { 7 | 8 | //Check 2D hull ok 9 | t.same(hull([[0,0], [1,0], [2,0]]), []) 10 | 11 | //Check 3d degenerate hull 12 | t.same(hull([ 13 | [0,0,0], 14 | [0,1,0], 15 | [1,0,0], 16 | [1,1,0], 17 | [2,3,0] 18 | ]), []) 19 | 20 | 21 | console.log(hull([ 22 | [0,0,0], 23 | [0,1,0], 24 | [1,0,0], 25 | [0.5,0.5,0], 26 | [1,1,0], 27 | [0.5,0.5,1] 28 | ])) 29 | 30 | t.end() 31 | }) 32 | --------------------------------------------------------------------------------