Parcourir la Source

Initial release

Yonaba il y a 12 ans
commit
f91c716890
11 fichiers modifiés avec 2497 ajouts et 0 suppressions
  1. 6 0
      .gitignore
  2. 106 0
      README.md
  3. 448 0
      delaunay.lua
  4. 801 0
      docs/index.html
  5. 801 0
      docs/scripts/delaunay.html
  6. 38 0
      performance/bench.lua
  7. 82 0
      specs/delaunay.lua
  8. 53 0
      specs/edge.lua
  9. 49 0
      specs/point.lua
  10. 109 0
      specs/triangle.lua
  11. 4 0
      version_history.md

+ 6 - 0
.gitignore

@@ -0,0 +1,6 @@
+*.bat
+ldoc*
+telescope*
+tsc
+config*
+test*

+ 106 - 0
README.md

@@ -0,0 +1,106 @@
+Delaunay
+=====
+
+*delaunay* is a Lua module for [delaunay triangulation](http://en.wikipedia.org/wiki/Delaunay_triangulation) of a convex polygon.
+
+##Download
+
+###Git
+
+````
+git clone http://github.com/Yonaba/delaunay.git
+````
+
+###Archive
+
+* [zip](http://github.com/Yonaba/delaunay/archive/3delaunay-0.6.0.zip) | [tar.gz](http://github.com/Yonaba/30log/archive/30log-0.6.0.tar.gz) | [all](http://github.com/Yonaba/30log/tags)
+
+###LuaRocks
+
+````
+luarocks install delaunay
+````
+
+###MoonRocks
+
+````
+luarocks install --server=http://rocks.moonscript.org/manifests/Yonaba delaunay
+````
+
+##Installation
+Copy the file [delaunay.lua](https://github.com/Yonaba/delaunay/blob/master/delaunay.lua) inside your project folder,
+call it with [require](http://pgl.yoyo.org/luai/i/require) function. It will return the `Delaunay` module, keeping safe the global environment.<br/>
+
+##Usage
+
+The module provides 3 classes: <br/> 
+* `Point`
+* `Edge`
+* `Triangle`
+
+It also provides a single function named `triangulate`. This function accepts
+a variable list (*vararg* `...`) of instances of class `Point`. Assuming those 
+points are the vertices of a convex polygon, it returns a table of instances of the class `Triangle` forming a *Delaunay triangulation* of the given polygon.
+
+A basic code example:
+```lua
+local Delaunay = require 'Delaunay'
+local Point    = Delaunay.Point
+
+-- Creating 10 random points
+local points = {}
+for i = 1, 10 do
+  points[i] = Point(math.random() * 100, math.random() * 100)
+end
+
+-- Triangulating de convex polygon made by those points
+local triangles = Delaunay.triangulate(unpack(points))
+
+-- Printing the results
+for i, triangle in ipairs(triangles) do
+  print(triangle)
+end
+````
+
+See the documentation for more details.
+```
+
+##Testing
+###Specification
+
+This repository include unit tests. You can run them using [Telescope](https://github.com/norman/telescope) with the following command from the root foolder:
+
+```
+lua tsc -f specs/*
+```
+
+###Performance
+
+You can run the random performance tests included with the following command from the root folder:
+
+```lua
+lua performance/bench.lua
+````
+
+##License
+This work is under [MIT-LICENSE](http://www.opensource.org/licenses/mit-license.php).<br/>
+Copyright (c) 2013 Roland Yonaba
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be included
+    in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

+ 448 - 0
delaunay.lua

@@ -0,0 +1,448 @@
+#!/usr/bin/env lua
+---------------
+-- ## Delaunay, Lua module for convex polygon triangulation
+-- @author Roland Yonaba
+-- @copyright 2013
+-- @license MIT
+-- @script delaunay
+
+-- ================
+-- Private helpers
+-- ================
+
+local setmetatable = setmetatable
+local tostring     = tostring
+local assert       = assert
+local unpack       = unpack
+local remove       = table.remove
+local sqrt         = math.sqrt
+local max          = math.max
+
+-- Internal class constructor
+local class = function(...)
+  local klass = {}
+  klass.__index = klass
+  klass.__call = function(_,...) return klass:new(...) end
+  function klass:new(...)
+    local instance = setmetatable({}, klass)
+    klass.__init(instance, ...)
+    return instance
+  end
+  return setmetatable(klass,{__call = klass.__call})
+end
+
+-- Triangle semi-perimeter by Heron's formula
+local function quatCross(a, b, c)
+  local p = (a + b + c) * (a + b - c) * (a - b + c) * (-a + b + c)
+  return sqrt(p)
+end
+
+
+-- Cross product (p1-p2, p2-p3)
+local function crossProduct(p1, p2, p3)
+  local x1, x2 = p2.x - p1.x, p3.x - p2.x
+  local y1, y2 = p2.y - p1.y, p3.y - p2.y
+  return x1 * y2 - y1 * x2
+end
+
+-- Checks if angle (p1-p2-p3) is flat
+local function isFlatAngle(p1, p2, p3)
+  return (crossProduct(p1, p2, p3) == 0)
+end
+
+-- ================
+-- Module classes
+-- ================
+
+--- `Edge` class
+-- @type Edge
+local Edge = class()
+Edge.__eq = function(a, b) return (a.p1 == b.p1 and a.p2 == b.p2) end
+Edge.__tostring = function(e)
+  return (('Edge :\n  %s\n  %s'):format(tostring(e.p1), tostring(e.p2)))
+end
+
+--- Creates a new `Edge`
+-- @name Edge:new
+-- @param p1 a `Point`
+-- @param p2 a `Point`
+-- @return a new `Edge`
+-- @usage
+-- local Delaunay = require 'Delaunay'
+-- local Edge     = Delaunay.Edge
+-- local Point    = Delaunay.Point
+-- local e = Edge:new(Point(1,1), Point(2,5))
+-- local e = Edge(Point(1,1), Point(2,5)) -- Alias to Edge.new
+-- print(e) -- print the edge members p1 and p2
+--
+function Edge:__init(p1, p2)
+  self.p1, self.p2 = p1, p2
+end
+
+--- Test if `otherEdge` is similar to self. It does not take into account the direction.
+-- @param otherEdge an `Edge`
+-- @return `true` or `false`
+-- @usage
+-- local e1 = Edge(Point(1,1), Point(2,5))
+-- local e2 = Edge(Point(2,5), Point(1,1))
+-- print(e1:same(e2)) --> true
+-- print(e1 == e2)) --> false, == operator considers the direction
+--
+function Edge:same(otherEdge)
+  return ((self.p1 == otherEdge.p1) and (self.p2 == otherEdge.p2))
+      or ((self.p1 == otherEdge.p2) and (self.p2 == otherEdge.p1))
+end
+
+--- Returns the length.
+-- @return the length of self
+-- @usage
+-- local e = Edge(Point(), Point(10,0))
+-- print(e:length()) --> 10
+--
+function Edge:length()
+  return self.p1:dist(self.p2)
+end
+
+--- Returns the midpoint coordinates.
+-- @return the x-coordinate of self midpoint
+-- @return the y-coordinate of self midpoint
+-- @usage
+-- local e = Edge(Point(), Point(10,0))
+-- print(e:getMidPoint()) --> 5, 0
+--
+function Edge:getMidPoint()
+  local x = self.p1.x + (self.p2.x - self.p1.x) / 2
+  local y = self.p1.x + (self.p2.y - self.p1.y) / 2
+  return x, y
+end
+
+--- Point class
+-- @type Point
+local Point = class()
+Point.__eq = function(a,b)  return (a.x == b.x and a.y == b.y) end
+Point.__tostring = function(p)
+  return ('Point (%s) x: %.2f y: %.2f'):format(p.id, p.x, p.y)
+end
+
+--- Creates a new `Point`
+-- @name Point:new
+-- @param x the x-coordinate
+-- @param y the y-coordinate
+-- @return a new `Point`
+-- @usage
+-- local Delaunay = require 'Delaunay'
+-- local Point    = Delaunay.Point
+-- local p = Point:new(1,1)
+-- local p = Point(1,1) -- Alias to Point.new
+-- print(p) -- print the point members x and y
+--
+function Point:__init(x, y)
+  self.x, self.y, self.id = x or 0, y or 0, '?'
+end
+
+--- Returns the square distance to another `Point`.
+-- @param p a `Point`
+-- @return the square distance from self to `p`.
+-- @usage
+-- local p1, p2 = Point(), Point(1,1)
+-- print(p1:dist2(p2)) --> 2
+--
+function Point:dist2(p)
+  local dx, dy = (self.x - p.x), (self.y - p.y)
+  return dx * dx + dy * dy
+end
+
+--- Returns the distance to another `Point`.
+-- @param p a `Point`
+-- @return the distance from self to `p`.
+-- @usage
+-- local p1, p2 = Point(), Point(1,1)
+-- print(p1:dist2(p2)) --> 1.4142135623731
+--
+function Point:dist(p)
+  return sqrt(self:dist2(p))
+end
+
+--- Checks if self lies into the bounds of a circle
+-- @param cx the x-coordinate of the circle center
+-- @param cy the y-coordinate of the circle center
+-- @param r the radius of the circle
+-- @return `true` or `false`
+-- @usage
+-- local p = Point()
+-- print(p:isInCircle(0,0,1)) --> true
+--
+function Point:isInCircle(cx, cy, r)
+  local dx = (cx - self.x)
+  local dy = (cy - self.y)
+  return ((dx * dx + dy * dy) <= (r * r))
+end
+
+--- `Triangle` class
+-- @type Triangle
+
+local Triangle = class()
+Triangle.__tostring = function(t)
+  return (('Triangle: \n  %s\n  %s\n  %s')
+    :format(tostring(t.p1), tostring(t.p2), tostring(t.p3)))
+end
+
+--- Creates a new `Triangle`
+-- @name Triangle:new
+-- @param p1 a `Point`
+-- @param p2 a `Point`
+-- @param p3 a `Point`
+-- @return a new `Triangle`
+-- @usage
+-- local Delaunay = require 'Delaunay'
+-- local Triangle = Delaunay.Triangle
+-- local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+-- local t = Triangle:new(p1, p2, p3)
+-- local t = Triangle(p1, p2, p3) -- Alias to Triangle.new
+-- print(t) -- print the triangle members p1, p2 and p3
+--
+function Triangle:__init(p1, p2, p3)
+  assert(not isFlatAngle(p1, p2, p3), ("angle (p1, p2, p3) is flat:\n  %s\n  %s\n  %s")
+    :format(tostring(p1), tostring(p2), tostring(p3)))
+  self.p1, self.p2, self.p3 = p1, p2, p3
+  self.e1, self.e2, self.e3 = Edge(p1, p2), Edge(p2, p3), Edge(p3, p1)
+end
+
+--- Checks if the triangle is defined clockwise (sequence p1-p2-p3)
+-- @return `true` or `false`
+-- @usage
+-- local p1, p2, p3 = Point(), Point(1,1), Point(2,0)
+-- local t = Triangle(p1, p2, p3)
+-- print(t:isCW()) --> true
+--
+function Triangle:isCW()
+  return (crossProduct(self.p1, self.p2, self.p3) < 0)
+end
+
+--- Checks if the triangle is defined counter-clockwise (sequence p1-p2-p3)
+-- @return `true` or `false`
+-- @usage
+-- local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+-- local t = Triangle(p1, p2, p3)
+-- print(t:isCCW()) --> true
+--
+function Triangle:isCCW()
+  return (crossProduct(self.p1, self.p2, self.p3) > 0)
+end
+
+--- Returns the length of the edges
+-- @return the length of the edge p1-p2
+-- @return the length of the edge p2-p3
+-- @return the length of the edge p3-p1
+-- @usage
+-- local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+-- local t = Triangle(p1, p2, p3)
+-- print(t:getSidesLength()) --> 2  1.4142135623731  1.4142135623731
+--
+function Triangle:getSidesLength()
+  return self.e1:length(), self.e2:length(), self.e3:length()
+end
+
+--- Returns the coordinates of the center
+-- @return the x-coordinate of the center
+-- @return the y-coordinate of the center
+-- @usage
+-- local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+-- local t = Triangle(p1, p2, p3)
+-- print(t:getCenter()) --> 1 0.33333333333333
+--
+function Triangle:getCenter()
+  local x = (self.p1.x + self.p2.x + self.p3.x) / 3
+  local y = (self.p1.y + self.p2.y + self.p3.y) / 3
+  return x, y
+end
+
+--- Returns the coordinates of the circumcircle center and its radius
+-- @return the x-coordinate of the circumcircle center
+-- @return the y-coordinate of the circumcircle center
+-- @return the radius of the circumcircle
+-- @usage
+-- local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+-- local t = Triangle(p1, p2, p3)
+-- print(t:getCircumCircle()) --> 1	0	1
+--
+function Triangle:getCircumCircle()
+  local x, y = self:getCircumCenter()
+  local r = self:getCircumRadius()
+  return x, y, r
+end
+
+--- Returns the coordinates of the circumcircle center
+-- @return the x-coordinate of the circumcircle center
+-- @return the y-coordinate of the circumcircle center
+-- @usage
+-- local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+-- local t = Triangle(p1, p2, p3)
+-- print(t:getCircumCenter()) --> 1	0
+--
+function Triangle:getCircumCenter()
+  local p1, p2, p3 = self.p1, self.p2, self.p3
+  local D =  ( p1.x * (p2.y - p3.y) +
+               p2.x * (p3.y - p1.y) +
+               p3.x * (p1.y - p2.y)) * 2
+  local x = (( p1.x * p1.x + p1.y * p1.y) * (p2.y - p3.y) +
+             ( p2.x * p2.x + p2.y * p2.y) * (p3.y - p1.y) +
+             ( p3.x * p3.x + p3.y * p3.y) * (p1.y - p2.y))
+  local y = (( p1.x * p1.x + p1.y * p1.y) * (p3.x - p2.x) +
+             ( p2.x * p2.x + p2.y * p2.y) * (p1.x - p3.x) +
+             ( p3.x * p3.x + p3.y * p3.y) * (p2.x - p1.x))
+  return (x / D), (y / D)
+end
+
+--- Returns the radius of the circumcircle
+-- @return the radius of the circumcircle
+-- @usage
+-- local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+-- local t = Triangle(p1, p2, p3)
+-- print(t:getCircumRadius()) --> 1
+--
+function Triangle:getCircumRadius()
+  local a, b, c = self:getSidesLength()
+  return ((a * b * c) / quatCross(a, b, c))
+end
+
+--- Returns the area
+-- @return the area
+-- @usage
+-- local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+-- local t = Triangle(p1, p2, p3)
+-- print(t:getArea()) --> 1
+--
+function Triangle:getArea()
+  local a, b, c = self:getSidesLength()
+  return (quatCross(a, b, c) / 4)
+end
+
+--- Checks if a given point lies into the triangle circumcircle
+-- @param p a `Point`
+-- @return `true` or `false`
+-- @usage
+-- local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+-- local t = Triangle(p1, p2, p3)
+-- print(t:inCircumCircle(Point(1,-1))) --> true
+--
+function Triangle:inCircumCircle(p)
+  return p:isInCircle(self:getCircumCircle())
+end
+
+--- Delaunay module
+-- @section public
+
+--- Delaunay module
+-- @table Delaunay
+-- @field Point reference to the `Point` class
+-- @field Edge reference to the `Edge` class
+-- @field Triangle reference to the `Triangle` class
+-- @field _VERSION the version of the current module
+local Delaunay = {
+  Point    = Point,
+  Edge     = Edge,
+  Triangle = Triangle,
+  _VERSION = "0.1"
+}
+
+--- Triangulates a set of given vertices
+-- @param ... a `vargarg` list of objects of type `Point`
+-- @return a set of objects of type `Triangle`
+-- @usage
+-- local Delaunay = require 'Delaunay'
+-- local Point    = Delaunay.Point 
+-- local p1, p2, p3, p4 = Point(), Point(2,0), Point(1,1), Point(1,-1)
+-- local triangles = Delaunay.triangulate(p1, p2, p3, p4)
+-- for i = 1, #triangles do
+--   print(triangles[i])
+-- end
+--
+function Delaunay.triangulate(...)
+  local vertices = {...}
+  local nvertices = #vertices
+  assert(nvertices > 2, "Cannot triangulate, needs more than 3 vertices")
+  if nvertices == 3 then
+    return {Triangle(unpack(vertices))}
+  end
+
+  local trmax = nvertices * 4
+
+  local minX, minY = vertices[1].x, vertices[1].y
+  local maxX, maxY = minX, minY
+
+  for i = 1, #vertices do
+    local vertex = vertices[i]
+    vertex.id = i
+    if vertex.x < minX then minX = vertex.x end
+    if vertex.y < minY then minY = vertex.y end
+    if vertex.x > maxX then maxX = vertex.x end
+    if vertex.y > maxY then maxY = vertex.y end
+  end
+
+  local dx, dy = maxX - minX, maxY - minY
+  local deltaMax = max(dx, dy)
+  local midx, midy = (minX + maxX) * 0.5, (minY + maxY) * 0.5
+
+  local p1 = Point(midx - 2 * deltaMax, midy - deltaMax)
+  local p2 = Point(midx, midy + 2 * deltaMax)
+  local p3 = Point(midx + 2 * deltaMax, midy - deltaMax)
+  p1.id, p2.id, p3.id = nvertices + 1, nvertices + 2, nvertices + 3
+  vertices[p1.id] = p1
+  vertices[p2.id] = p2
+  vertices[p3.id] = p3
+
+  local triangles = {}
+  triangles[#triangles + 1] = Triangle(vertices[nvertices + 1],
+                                       vertices[nvertices + 2],
+                                       vertices[nvertices + 3]
+                              )
+
+  for i = 1, nvertices do
+  
+    local edges = {}
+    local ntriangles = #triangles
+
+    for j = #triangles, 1, -1 do
+      local curTriangle = triangles[j]
+      if curTriangle:inCircumCircle(vertices[i]) then
+        edges[#edges + 1] = curTriangle.e1
+        edges[#edges + 1] = curTriangle.e2
+        edges[#edges + 1] = curTriangle.e3
+        remove(triangles, j)
+      end
+    end
+
+    for j = #edges - 1, 1, -1 do
+      for k = #edges, j + 1, -1 do
+        if edges[j] and edges[k] and edges[j]:same(edges[k]) then
+          remove(edges, j)
+          remove(edges, k-1)
+        end
+      end
+    end
+
+    for j = 1, #edges do
+      local n = #triangles
+      assert(n <= trmax, "Generated more than needed triangles")
+      triangles[n + 1] = Triangle(edges[j].p1, edges[j].p2, vertices[i])
+    end
+   
+  end
+
+  for i = #triangles, 1, -1 do
+    local triangle = triangles[i]
+    if (triangle.p1.id > nvertices or 
+        triangle.p2.id > nvertices or 
+        triangle.p3.id > nvertices) then
+      remove(triangles, i)
+    end
+  end
+
+  for _ = 1,3 do remove(vertices) end
+
+  return triangles
+
+end
+
+return Delaunay

+ 801 - 0
docs/index.html

@@ -0,0 +1,801 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+    <title>Delaunay module documentation</title>
+    <link rel="stylesheet" href="ldoc.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+	<div id="product_logo"></div>
+	<div id="product_name"><big><b></b></big></div>
+	<div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Delaunay (v0.1)</h1>
+
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Class_Edge">Class Edge </a></li>
+<li><a href="#Class_Point">Class Point </a></li>
+<li><a href="#Class_Triangle">Class Triangle </a></li>
+<li><a href="#Delaunay_module">Delaunay module </a></li>
+</ul>
+
+
+<h2>Scripts</h2>
+<ul class="nowrap">
+  <li><strong>delaunay</strong></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Script <code>delaunay</code></h1>
+
+<p>
+<h2>Delaunay, Lua module for convex polygon triangulation</h2>
+</p>
+<p>
+
+</p>
+    <h3>Info:</h3>
+    <ul>
+        <li><strong>Copyright</strong>: 2013</li>
+        <li><strong>License</strong>: MIT</li>
+        <li><strong>Author</strong>: Roland Yonaba</li>
+    </ul>
+
+
+<h2><a href="#Class_Edge">Class Edge </a></h2>
+<table class="function_list">
+	<tr>
+	<td class="name" nowrap><a href="#Edge:new">Edge:new (p1, p2)</a></td>
+	<td class="summary">Creates a new <a href="index.html#Class_Edge">Edge</a> </td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Edge:same">Edge:same (otherEdge)</a></td>
+	<td class="summary">Test if <code>otherEdge</code> is similar to self.</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Edge:length">Edge:length ()</a></td>
+	<td class="summary">Returns the length.</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Edge:getMidPoint">Edge:getMidPoint ()</a></td>
+	<td class="summary">Returns the midpoint coordinates.</td>
+	</tr>
+</table>
+<h2><a href="#Class_Point">Class Point </a></h2>
+<table class="function_list">
+	<tr>
+	<td class="name" nowrap><a href="#Point:new">Point:new (x, y)</a></td>
+	<td class="summary">Creates a new <a href="index.html#Class_Point">Point</a> </td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Point:dist2">Point:dist2 (p)</a></td>
+	<td class="summary">Returns the square distance to another <a href="index.html#Class_Point">Point</a> .</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Point:dist">Point:dist (p)</a></td>
+	<td class="summary">Returns the distance to another <a href="index.html#Class_Point">Point</a> .</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Point:isInCircle">Point:isInCircle (cx, cy, r)</a></td>
+	<td class="summary">Checks if self lies into the bounds of a circle</td>
+	</tr>
+</table>
+<h2><a href="#Class_Triangle">Class Triangle </a></h2>
+<table class="function_list">
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:new">Triangle:new (p1, p2, p3)</a></td>
+	<td class="summary">Creates a new <a href="index.html#Class_Triangle">Triangle</a> </td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:isCW">Triangle:isCW ()</a></td>
+	<td class="summary">Checks if the triangle is defined clockwise (sequence p1-p2-p3)</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:isCCW">Triangle:isCCW ()</a></td>
+	<td class="summary">Checks if the triangle is defined counter-clockwise (sequence p1-p2-p3)</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getSidesLength">Triangle:getSidesLength ()</a></td>
+	<td class="summary">Returns the length of the edges</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getCenter">Triangle:getCenter ()</a></td>
+	<td class="summary">Returns the coordinates of the center</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getCircumCircle">Triangle:getCircumCircle ()</a></td>
+	<td class="summary">Returns the coordinates of the circumcircle center and its radius</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getCircumCenter">Triangle:getCircumCenter ()</a></td>
+	<td class="summary">Returns the coordinates of the circumcircle center</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getCircumRadius">Triangle:getCircumRadius ()</a></td>
+	<td class="summary">Returns the radius of the circumcircle</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getArea">Triangle:getArea ()</a></td>
+	<td class="summary">Returns the area</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:inCircumCircle">Triangle:inCircumCircle (p)</a></td>
+	<td class="summary">Checks if a given point lies into the triangle circumcircle</td>
+	</tr>
+</table>
+<h2><a href="#Delaunay_module">Delaunay module </a></h2>
+<table class="function_list">
+	<tr>
+	<td class="name" nowrap><a href="#Delaunay">Delaunay</a></td>
+	<td class="summary">Delaunay module</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Delaunay.triangulate">Delaunay.triangulate (...)</a></td>
+	<td class="summary">Triangulates a set of given vertices</td>
+	</tr>
+</table>
+
+<br/>
+<br/>
+
+
+    <h2><a name="Class_Edge"></a>Class Edge </h2>
+
+    <dl class="function">
+    <dt>
+    <a name = "Edge:new"></a>
+    <strong>Edge:new (p1, p2)</strong>
+    </dt>
+    <dd>
+    Creates a new <a href="index.html#Class_Edge">Edge</a>
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">p1</span>
+         a <a href="index.html#Class_Point">Point</a>
+        </li>
+        <li><span class="parameter">p2</span>
+         a <a href="index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        a new <a href="index.html#Class_Edge">Edge</a>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> Delaunay = <span class="global">require</span> <span class="string">'Delaunay'</span>
+ <span class="keyword">local</span> Edge     = Delaunay.Edge
+ <span class="keyword">local</span> Point    = Delaunay.Point
+ <span class="keyword">local</span> e = Edge:new(Point(<span class="number">1</span>,<span class="number">1</span>), Point(<span class="number">2</span>,<span class="number">5</span>))
+ <span class="keyword">local</span> e = Edge(Point(<span class="number">1</span>,<span class="number">1</span>), Point(<span class="number">2</span>,<span class="number">5</span>)) <span class="comment">-- Alias to Edge.new
+</span> <span class="global">print</span>(e) <span class="comment">-- print the edge members p1 and p2
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Edge:same"></a>
+    <strong>Edge:same (otherEdge)</strong>
+    </dt>
+    <dd>
+    Test if <code>otherEdge</code> is similar to self.  It does not take into account the direction.
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">otherEdge</span>
+         an <a href="index.html#Class_Edge">Edge</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        <code>true</code> or <code>false</code>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> e1 = Edge(Point(<span class="number">1</span>,<span class="number">1</span>), Point(<span class="number">2</span>,<span class="number">5</span>))
+ <span class="keyword">local</span> e2 = Edge(Point(<span class="number">2</span>,<span class="number">5</span>), Point(<span class="number">1</span>,<span class="number">1</span>))
+ <span class="global">print</span>(e1:same(e2)) <span class="comment">--&gt; true
+</span> <span class="global">print</span>(e1 == e2)) <span class="comment">--&gt; false, == operator considers the direction
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Edge:length"></a>
+    <strong>Edge:length ()</strong>
+    </dt>
+    <dd>
+    Returns the length.
+
+
+    <h3>Returns:</h3>
+    <ol>
+
+        the length of self
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> e = Edge(Point(), Point(<span class="number">10</span>,<span class="number">0</span>))
+ <span class="global">print</span>(e:length()) <span class="comment">--&gt; 10
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Edge:getMidPoint"></a>
+    <strong>Edge:getMidPoint ()</strong>
+    </dt>
+    <dd>
+    Returns the midpoint coordinates.
+
+
+    <h3>Returns:</h3>
+    <ol>
+        <li>
+        the x-coordinate of self midpoint</li>
+        <li>
+        the y-coordinate of self midpoint</li>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> e = Edge(Point(), Point(<span class="number">10</span>,<span class="number">0</span>))
+ <span class="global">print</span>(e:getMidPoint()) <span class="comment">--&gt; 5, 0
+</span></pre>
+    </ul>
+
+</dd>
+</dl>
+    <h2><a name="Class_Point"></a>Class Point </h2>
+
+    <dl class="function">
+    <dt>
+    <a name = "Point:new"></a>
+    <strong>Point:new (x, y)</strong>
+    </dt>
+    <dd>
+    Creates a new <a href="index.html#Class_Point">Point</a>
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">x</span>
+         the x-coordinate
+        </li>
+        <li><span class="parameter">y</span>
+         the y-coordinate
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        a new <a href="index.html#Class_Point">Point</a>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> Delaunay = <span class="global">require</span> <span class="string">'Delaunay'</span>
+ <span class="keyword">local</span> Point    = Delaunay.Point
+ <span class="keyword">local</span> p = Point:new(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> p = Point(<span class="number">1</span>,<span class="number">1</span>) <span class="comment">-- Alias to Point.new
+</span> <span class="global">print</span>(p) <span class="comment">-- print the point members x and y
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Point:dist2"></a>
+    <strong>Point:dist2 (p)</strong>
+    </dt>
+    <dd>
+    Returns the square distance to another <a href="index.html#Class_Point">Point</a> .
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">p</span>
+         a <a href="index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        the square distance from self to <code>p</code>.
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2 = Point(), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="global">print</span>(p1:dist2(p2)) <span class="comment">--&gt; 2
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Point:dist"></a>
+    <strong>Point:dist (p)</strong>
+    </dt>
+    <dd>
+    Returns the distance to another <a href="index.html#Class_Point">Point</a> .
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">p</span>
+         a <a href="index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        the distance from self to <code>p</code>.
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2 = Point(), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="global">print</span>(p1:dist2(p2)) <span class="comment">--&gt; 1.4142135623731
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Point:isInCircle"></a>
+    <strong>Point:isInCircle (cx, cy, r)</strong>
+    </dt>
+    <dd>
+    Checks if self lies into the bounds of a circle
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">cx</span>
+         the x-coordinate of the circle center
+        </li>
+        <li><span class="parameter">cy</span>
+         the y-coordinate of the circle center
+        </li>
+        <li><span class="parameter">r</span>
+         the radius of the circle
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        <code>true</code> or <code>false</code>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p = Point()
+ <span class="global">print</span>(p:isInCircle(<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>)) <span class="comment">--&gt; true
+</span></pre>
+    </ul>
+
+</dd>
+</dl>
+    <h2><a name="Class_Triangle"></a>Class Triangle </h2>
+
+    <dl class="function">
+    <dt>
+    <a name = "Triangle:new"></a>
+    <strong>Triangle:new (p1, p2, p3)</strong>
+    </dt>
+    <dd>
+    Creates a new <a href="index.html#Class_Triangle">Triangle</a>
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">p1</span>
+         a <a href="index.html#Class_Point">Point</a>
+        </li>
+        <li><span class="parameter">p2</span>
+         a <a href="index.html#Class_Point">Point</a>
+        </li>
+        <li><span class="parameter">p3</span>
+         a <a href="index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        a new <a href="index.html#Class_Triangle">Triangle</a>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> Delaunay = <span class="global">require</span> <span class="string">'Delaunay'</span>
+ <span class="keyword">local</span> Triangle = Delaunay.Triangle
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle:new(p1, p2, p3)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3) <span class="comment">-- Alias to Triangle.new
+</span> <span class="global">print</span>(t) <span class="comment">-- print the triangle members p1, p2 and p3
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:isCW"></a>
+    <strong>Triangle:isCW ()</strong>
+    </dt>
+    <dd>
+    Checks if the triangle is defined clockwise (sequence p1-p2-p3)
+
+
+    <h3>Returns:</h3>
+    <ol>
+
+        <code>true</code> or <code>false</code>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">1</span>,<span class="number">1</span>), Point(<span class="number">2</span>,<span class="number">0</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:isCW()) <span class="comment">--&gt; true
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:isCCW"></a>
+    <strong>Triangle:isCCW ()</strong>
+    </dt>
+    <dd>
+    Checks if the triangle is defined counter-clockwise (sequence p1-p2-p3)
+
+
+    <h3>Returns:</h3>
+    <ol>
+
+        <code>true</code> or <code>false</code>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:isCCW()) <span class="comment">--&gt; true
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getSidesLength"></a>
+    <strong>Triangle:getSidesLength ()</strong>
+    </dt>
+    <dd>
+    Returns the length of the edges
+
+
+    <h3>Returns:</h3>
+    <ol>
+        <li>
+        the length of the edge p1-p2</li>
+        <li>
+        the length of the edge p2-p3</li>
+        <li>
+        the length of the edge p3-p1</li>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getSidesLength()) <span class="comment">--&gt; 2  1.4142135623731  1.4142135623731
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getCenter"></a>
+    <strong>Triangle:getCenter ()</strong>
+    </dt>
+    <dd>
+    Returns the coordinates of the center
+
+
+    <h3>Returns:</h3>
+    <ol>
+        <li>
+        the x-coordinate of the center</li>
+        <li>
+        the y-coordinate of the center</li>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getCenter()) <span class="comment">--&gt; 1 0.33333333333333
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getCircumCircle"></a>
+    <strong>Triangle:getCircumCircle ()</strong>
+    </dt>
+    <dd>
+    Returns the coordinates of the circumcircle center and its radius
+
+
+    <h3>Returns:</h3>
+    <ol>
+        <li>
+        the x-coordinate of the circumcircle center</li>
+        <li>
+        the y-coordinate of the circumcircle center</li>
+        <li>
+        the radius of the circumcircle</li>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getCircumCircle()) <span class="comment">--&gt; 1	0	1
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getCircumCenter"></a>
+    <strong>Triangle:getCircumCenter ()</strong>
+    </dt>
+    <dd>
+    Returns the coordinates of the circumcircle center
+
+
+    <h3>Returns:</h3>
+    <ol>
+        <li>
+        the x-coordinate of the circumcircle center</li>
+        <li>
+        the y-coordinate of the circumcircle center</li>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getCircumCenter()) <span class="comment">--&gt; 1	0
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getCircumRadius"></a>
+    <strong>Triangle:getCircumRadius ()</strong>
+    </dt>
+    <dd>
+    Returns the radius of the circumcircle
+
+
+    <h3>Returns:</h3>
+    <ol>
+
+        the radius of the circumcircle
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getCircumRadius()) <span class="comment">--&gt; 1
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getArea"></a>
+    <strong>Triangle:getArea ()</strong>
+    </dt>
+    <dd>
+    Returns the area
+
+
+    <h3>Returns:</h3>
+    <ol>
+
+        the area
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getArea()) <span class="comment">--&gt; 1
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:inCircumCircle"></a>
+    <strong>Triangle:inCircumCircle (p)</strong>
+    </dt>
+    <dd>
+    Checks if a given point lies into the triangle circumcircle
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">p</span>
+         a <a href="index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        <code>true</code> or <code>false</code>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:inCircumCircle(Point(<span class="number">1</span>,-<span class="number">1</span>))) <span class="comment">--&gt; true
+</span></pre>
+    </ul>
+
+</dd>
+</dl>
+    <h2><a name="Delaunay_module"></a>Delaunay module </h2>
+
+    <dl class="function">
+    <dt>
+    <a name = "Delaunay"></a>
+    <strong>Delaunay</strong>
+    </dt>
+    <dd>
+    Delaunay module
+
+    <h3>Fields:</h3>
+    <ul>
+        <li><span class="parameter">Point</span>
+         reference to the <a href="index.html#Class_Point">Point</a>  class
+        </li>
+        <li><span class="parameter">Edge</span>
+         reference to the <a href="index.html#Class_Edge">Edge</a>  class
+        </li>
+        <li><span class="parameter">Triangle</span>
+         reference to the <a href="index.html#Class_Triangle">Triangle</a>  class
+        </li>
+        <li><span class="parameter">_VERSION</span>
+         the version of the current module
+        </li>
+    </ul>
+
+
+
+
+
+</dd>
+    <dt>
+    <a name = "Delaunay.triangulate"></a>
+    <strong>Delaunay.triangulate (...)</strong>
+    </dt>
+    <dd>
+    Triangulates a set of given vertices
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">...</span>
+         a <code>vargarg</code> list of objects of type <a href="index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        a set of objects of type <a href="index.html#Class_Triangle">Triangle</a>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> Delaunay = <span class="global">require</span> <span class="string">'Delaunay'</span>
+ <span class="keyword">local</span> Point    = Delaunay.Point
+ <span class="keyword">local</span> p1, p2, p3, p4 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>), Point(<span class="number">1</span>,-<span class="number">1</span>)
+ <span class="keyword">local</span> triangles = Delaunay.triangulate(p1, p2, p3, p4)
+ <span class="keyword">for</span> i = <span class="number">1</span>, #triangles <span class="keyword">do</span>
+   <span class="global">print</span>(triangles[i])
+ <span class="keyword">end</span></pre>
+    </ul>
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.0</a></i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>

+ 801 - 0
docs/scripts/delaunay.html

@@ -0,0 +1,801 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
+<head>
+    <title>Delaunay module documentation</title>
+    <link rel="stylesheet" href="../ldoc.css" type="text/css" />
+</head>
+<body>
+
+<div id="container">
+
+<div id="product">
+	<div id="product_logo"></div>
+	<div id="product_name"><big><b></b></big></div>
+	<div id="product_description"></div>
+</div> <!-- id="product" -->
+
+
+<div id="main">
+
+
+<!-- Menu -->
+
+<div id="navigation">
+<br/>
+<h1>Delaunay (v0.1)</h1>
+
+
+<h2>Contents</h2>
+<ul>
+<li><a href="#Class_Edge">Class Edge </a></li>
+<li><a href="#Class_Point">Class Point </a></li>
+<li><a href="#Class_Triangle">Class Triangle </a></li>
+<li><a href="#Delaunay_module">Delaunay module </a></li>
+</ul>
+
+
+<h2>Scripts</h2>
+<ul class="nowrap">
+  <li><strong>delaunay</strong></li>
+</ul>
+
+</div>
+
+<div id="content">
+
+<h1>Script <code>delaunay</code></h1>
+
+<p>
+<h2>Delaunay, Lua module for convex polygon triangulation</h2>
+</p>
+<p>
+
+</p>
+    <h3>Info:</h3>
+    <ul>
+        <li><strong>Copyright</strong>: 2013</li>
+        <li><strong>License</strong>: MIT</li>
+        <li><strong>Author</strong>: Roland Yonaba</li>
+    </ul>
+
+
+<h2><a href="#Class_Edge">Class Edge </a></h2>
+<table class="function_list">
+	<tr>
+	<td class="name" nowrap><a href="#Edge:new">Edge:new (p1, p2)</a></td>
+	<td class="summary">Creates a new <a href="../index.html#Class_Edge">Edge</a> </td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Edge:same">Edge:same (otherEdge)</a></td>
+	<td class="summary">Test if <code>otherEdge</code> is similar to self.</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Edge:length">Edge:length ()</a></td>
+	<td class="summary">Returns the length.</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Edge:getMidPoint">Edge:getMidPoint ()</a></td>
+	<td class="summary">Returns the midpoint coordinates.</td>
+	</tr>
+</table>
+<h2><a href="#Class_Point">Class Point </a></h2>
+<table class="function_list">
+	<tr>
+	<td class="name" nowrap><a href="#Point:new">Point:new (x, y)</a></td>
+	<td class="summary">Creates a new <a href="../index.html#Class_Point">Point</a> </td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Point:dist2">Point:dist2 (p)</a></td>
+	<td class="summary">Returns the square distance to another <a href="../index.html#Class_Point">Point</a> .</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Point:dist">Point:dist (p)</a></td>
+	<td class="summary">Returns the distance to another <a href="../index.html#Class_Point">Point</a> .</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Point:isInCircle">Point:isInCircle (cx, cy, r)</a></td>
+	<td class="summary">Checks if self lies into the bounds of a circle</td>
+	</tr>
+</table>
+<h2><a href="#Class_Triangle">Class Triangle </a></h2>
+<table class="function_list">
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:new">Triangle:new (p1, p2, p3)</a></td>
+	<td class="summary">Creates a new <a href="../index.html#Class_Triangle">Triangle</a> </td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:isCW">Triangle:isCW ()</a></td>
+	<td class="summary">Checks if the triangle is defined clockwise (sequence p1-p2-p3)</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:isCCW">Triangle:isCCW ()</a></td>
+	<td class="summary">Checks if the triangle is defined counter-clockwise (sequence p1-p2-p3)</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getSidesLength">Triangle:getSidesLength ()</a></td>
+	<td class="summary">Returns the length of the edges</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getCenter">Triangle:getCenter ()</a></td>
+	<td class="summary">Returns the coordinates of the center</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getCircumCircle">Triangle:getCircumCircle ()</a></td>
+	<td class="summary">Returns the coordinates of the circumcircle center and its radius</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getCircumCenter">Triangle:getCircumCenter ()</a></td>
+	<td class="summary">Returns the coordinates of the circumcircle center</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getCircumRadius">Triangle:getCircumRadius ()</a></td>
+	<td class="summary">Returns the radius of the circumcircle</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:getArea">Triangle:getArea ()</a></td>
+	<td class="summary">Returns the area</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Triangle:inCircumCircle">Triangle:inCircumCircle (p)</a></td>
+	<td class="summary">Checks if a given point lies into the triangle circumcircle</td>
+	</tr>
+</table>
+<h2><a href="#Delaunay_module">Delaunay module </a></h2>
+<table class="function_list">
+	<tr>
+	<td class="name" nowrap><a href="#Delaunay">Delaunay</a></td>
+	<td class="summary">Delaunay module</td>
+	</tr>
+	<tr>
+	<td class="name" nowrap><a href="#Delaunay.triangulate">Delaunay.triangulate (...)</a></td>
+	<td class="summary">Triangulates a set of given vertices</td>
+	</tr>
+</table>
+
+<br/>
+<br/>
+
+
+    <h2><a name="Class_Edge"></a>Class Edge </h2>
+
+    <dl class="function">
+    <dt>
+    <a name = "Edge:new"></a>
+    <strong>Edge:new (p1, p2)</strong>
+    </dt>
+    <dd>
+    Creates a new <a href="../index.html#Class_Edge">Edge</a>
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">p1</span>
+         a <a href="../index.html#Class_Point">Point</a>
+        </li>
+        <li><span class="parameter">p2</span>
+         a <a href="../index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        a new <a href="../index.html#Class_Edge">Edge</a>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> Delaunay = <span class="global">require</span> <span class="string">'Delaunay'</span>
+ <span class="keyword">local</span> Edge     = Delaunay.Edge
+ <span class="keyword">local</span> Point    = Delaunay.Point
+ <span class="keyword">local</span> e = Edge:new(Point(<span class="number">1</span>,<span class="number">1</span>), Point(<span class="number">2</span>,<span class="number">5</span>))
+ <span class="keyword">local</span> e = Edge(Point(<span class="number">1</span>,<span class="number">1</span>), Point(<span class="number">2</span>,<span class="number">5</span>)) <span class="comment">-- Alias to Edge.new
+</span> <span class="global">print</span>(e) <span class="comment">-- print the edge members p1 and p2
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Edge:same"></a>
+    <strong>Edge:same (otherEdge)</strong>
+    </dt>
+    <dd>
+    Test if <code>otherEdge</code> is similar to self.  It does not take into account the direction.
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">otherEdge</span>
+         an <a href="../index.html#Class_Edge">Edge</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        <code>true</code> or <code>false</code>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> e1 = Edge(Point(<span class="number">1</span>,<span class="number">1</span>), Point(<span class="number">2</span>,<span class="number">5</span>))
+ <span class="keyword">local</span> e2 = Edge(Point(<span class="number">2</span>,<span class="number">5</span>), Point(<span class="number">1</span>,<span class="number">1</span>))
+ <span class="global">print</span>(e1:same(e2)) <span class="comment">--&gt; true
+</span> <span class="global">print</span>(e1 == e2)) <span class="comment">--&gt; false, == operator considers the direction
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Edge:length"></a>
+    <strong>Edge:length ()</strong>
+    </dt>
+    <dd>
+    Returns the length.
+
+
+    <h3>Returns:</h3>
+    <ol>
+
+        the length of self
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> e = Edge(Point(), Point(<span class="number">10</span>,<span class="number">0</span>))
+ <span class="global">print</span>(e:length()) <span class="comment">--&gt; 10
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Edge:getMidPoint"></a>
+    <strong>Edge:getMidPoint ()</strong>
+    </dt>
+    <dd>
+    Returns the midpoint coordinates.
+
+
+    <h3>Returns:</h3>
+    <ol>
+        <li>
+        the x-coordinate of self midpoint</li>
+        <li>
+        the y-coordinate of self midpoint</li>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> e = Edge(Point(), Point(<span class="number">10</span>,<span class="number">0</span>))
+ <span class="global">print</span>(e:getMidPoint()) <span class="comment">--&gt; 5, 0
+</span></pre>
+    </ul>
+
+</dd>
+</dl>
+    <h2><a name="Class_Point"></a>Class Point </h2>
+
+    <dl class="function">
+    <dt>
+    <a name = "Point:new"></a>
+    <strong>Point:new (x, y)</strong>
+    </dt>
+    <dd>
+    Creates a new <a href="../index.html#Class_Point">Point</a>
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">x</span>
+         the x-coordinate
+        </li>
+        <li><span class="parameter">y</span>
+         the y-coordinate
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        a new <a href="../index.html#Class_Point">Point</a>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> Delaunay = <span class="global">require</span> <span class="string">'Delaunay'</span>
+ <span class="keyword">local</span> Point    = Delaunay.Point
+ <span class="keyword">local</span> p = Point:new(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> p = Point(<span class="number">1</span>,<span class="number">1</span>) <span class="comment">-- Alias to Point.new
+</span> <span class="global">print</span>(p) <span class="comment">-- print the point members x and y
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Point:dist2"></a>
+    <strong>Point:dist2 (p)</strong>
+    </dt>
+    <dd>
+    Returns the square distance to another <a href="../index.html#Class_Point">Point</a> .
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">p</span>
+         a <a href="../index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        the square distance from self to <code>p</code>.
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2 = Point(), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="global">print</span>(p1:dist2(p2)) <span class="comment">--&gt; 2
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Point:dist"></a>
+    <strong>Point:dist (p)</strong>
+    </dt>
+    <dd>
+    Returns the distance to another <a href="../index.html#Class_Point">Point</a> .
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">p</span>
+         a <a href="../index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        the distance from self to <code>p</code>.
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2 = Point(), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="global">print</span>(p1:dist2(p2)) <span class="comment">--&gt; 1.4142135623731
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Point:isInCircle"></a>
+    <strong>Point:isInCircle (cx, cy, r)</strong>
+    </dt>
+    <dd>
+    Checks if self lies into the bounds of a circle
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">cx</span>
+         the x-coordinate of the circle center
+        </li>
+        <li><span class="parameter">cy</span>
+         the y-coordinate of the circle center
+        </li>
+        <li><span class="parameter">r</span>
+         the radius of the circle
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        <code>true</code> or <code>false</code>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p = Point()
+ <span class="global">print</span>(p:isInCircle(<span class="number">0</span>,<span class="number">0</span>,<span class="number">1</span>)) <span class="comment">--&gt; true
+</span></pre>
+    </ul>
+
+</dd>
+</dl>
+    <h2><a name="Class_Triangle"></a>Class Triangle </h2>
+
+    <dl class="function">
+    <dt>
+    <a name = "Triangle:new"></a>
+    <strong>Triangle:new (p1, p2, p3)</strong>
+    </dt>
+    <dd>
+    Creates a new <a href="../index.html#Class_Triangle">Triangle</a>
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">p1</span>
+         a <a href="../index.html#Class_Point">Point</a>
+        </li>
+        <li><span class="parameter">p2</span>
+         a <a href="../index.html#Class_Point">Point</a>
+        </li>
+        <li><span class="parameter">p3</span>
+         a <a href="../index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        a new <a href="../index.html#Class_Triangle">Triangle</a>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> Delaunay = <span class="global">require</span> <span class="string">'Delaunay'</span>
+ <span class="keyword">local</span> Triangle = Delaunay.Triangle
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle:new(p1, p2, p3)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3) <span class="comment">-- Alias to Triangle.new
+</span> <span class="global">print</span>(t) <span class="comment">-- print the triangle members p1, p2 and p3
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:isCW"></a>
+    <strong>Triangle:isCW ()</strong>
+    </dt>
+    <dd>
+    Checks if the triangle is defined clockwise (sequence p1-p2-p3)
+
+
+    <h3>Returns:</h3>
+    <ol>
+
+        <code>true</code> or <code>false</code>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">1</span>,<span class="number">1</span>), Point(<span class="number">2</span>,<span class="number">0</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:isCW()) <span class="comment">--&gt; true
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:isCCW"></a>
+    <strong>Triangle:isCCW ()</strong>
+    </dt>
+    <dd>
+    Checks if the triangle is defined counter-clockwise (sequence p1-p2-p3)
+
+
+    <h3>Returns:</h3>
+    <ol>
+
+        <code>true</code> or <code>false</code>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:isCCW()) <span class="comment">--&gt; true
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getSidesLength"></a>
+    <strong>Triangle:getSidesLength ()</strong>
+    </dt>
+    <dd>
+    Returns the length of the edges
+
+
+    <h3>Returns:</h3>
+    <ol>
+        <li>
+        the length of the edge p1-p2</li>
+        <li>
+        the length of the edge p2-p3</li>
+        <li>
+        the length of the edge p3-p1</li>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getSidesLength()) <span class="comment">--&gt; 2  1.4142135623731  1.4142135623731
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getCenter"></a>
+    <strong>Triangle:getCenter ()</strong>
+    </dt>
+    <dd>
+    Returns the coordinates of the center
+
+
+    <h3>Returns:</h3>
+    <ol>
+        <li>
+        the x-coordinate of the center</li>
+        <li>
+        the y-coordinate of the center</li>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getCenter()) <span class="comment">--&gt; 1 0.33333333333333
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getCircumCircle"></a>
+    <strong>Triangle:getCircumCircle ()</strong>
+    </dt>
+    <dd>
+    Returns the coordinates of the circumcircle center and its radius
+
+
+    <h3>Returns:</h3>
+    <ol>
+        <li>
+        the x-coordinate of the circumcircle center</li>
+        <li>
+        the y-coordinate of the circumcircle center</li>
+        <li>
+        the radius of the circumcircle</li>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getCircumCircle()) <span class="comment">--&gt; 1	0	1
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getCircumCenter"></a>
+    <strong>Triangle:getCircumCenter ()</strong>
+    </dt>
+    <dd>
+    Returns the coordinates of the circumcircle center
+
+
+    <h3>Returns:</h3>
+    <ol>
+        <li>
+        the x-coordinate of the circumcircle center</li>
+        <li>
+        the y-coordinate of the circumcircle center</li>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getCircumCenter()) <span class="comment">--&gt; 1	0
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getCircumRadius"></a>
+    <strong>Triangle:getCircumRadius ()</strong>
+    </dt>
+    <dd>
+    Returns the radius of the circumcircle
+
+
+    <h3>Returns:</h3>
+    <ol>
+
+        the radius of the circumcircle
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getCircumRadius()) <span class="comment">--&gt; 1
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:getArea"></a>
+    <strong>Triangle:getArea ()</strong>
+    </dt>
+    <dd>
+    Returns the area
+
+
+    <h3>Returns:</h3>
+    <ol>
+
+        the area
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:getArea()) <span class="comment">--&gt; 1
+</span></pre>
+    </ul>
+
+</dd>
+    <dt>
+    <a name = "Triangle:inCircumCircle"></a>
+    <strong>Triangle:inCircumCircle (p)</strong>
+    </dt>
+    <dd>
+    Checks if a given point lies into the triangle circumcircle
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">p</span>
+         a <a href="../index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        <code>true</code> or <code>false</code>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> p1, p2, p3 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>)
+ <span class="keyword">local</span> t = Triangle(p1, p2, p3)
+ <span class="global">print</span>(t:inCircumCircle(Point(<span class="number">1</span>,-<span class="number">1</span>))) <span class="comment">--&gt; true
+</span></pre>
+    </ul>
+
+</dd>
+</dl>
+    <h2><a name="Delaunay_module"></a>Delaunay module </h2>
+
+    <dl class="function">
+    <dt>
+    <a name = "Delaunay"></a>
+    <strong>Delaunay</strong>
+    </dt>
+    <dd>
+    Delaunay module
+
+    <h3>Fields:</h3>
+    <ul>
+        <li><span class="parameter">Point</span>
+         reference to the <a href="../index.html#Class_Point">Point</a>  class
+        </li>
+        <li><span class="parameter">Edge</span>
+         reference to the <a href="../index.html#Class_Edge">Edge</a>  class
+        </li>
+        <li><span class="parameter">Triangle</span>
+         reference to the <a href="../index.html#Class_Triangle">Triangle</a>  class
+        </li>
+        <li><span class="parameter">_VERSION</span>
+         the version of the current module
+        </li>
+    </ul>
+
+
+
+
+
+</dd>
+    <dt>
+    <a name = "Delaunay.triangulate"></a>
+    <strong>Delaunay.triangulate (...)</strong>
+    </dt>
+    <dd>
+    Triangulates a set of given vertices
+
+    <h3>Parameters:</h3>
+    <ul>
+        <li><span class="parameter">...</span>
+         a <code>vargarg</code> list of objects of type <a href="../index.html#Class_Point">Point</a>
+        </li>
+    </ul>
+
+    <h3>Returns:</h3>
+    <ol>
+
+        a set of objects of type <a href="../index.html#Class_Triangle">Triangle</a>
+    </ol>
+
+
+
+    <h3>Usage:</h3>
+    <ul>
+        <pre class="example">
+ <span class="keyword">local</span> Delaunay = <span class="global">require</span> <span class="string">'Delaunay'</span>
+ <span class="keyword">local</span> Point    = Delaunay.Point
+ <span class="keyword">local</span> p1, p2, p3, p4 = Point(), Point(<span class="number">2</span>,<span class="number">0</span>), Point(<span class="number">1</span>,<span class="number">1</span>), Point(<span class="number">1</span>,-<span class="number">1</span>)
+ <span class="keyword">local</span> triangles = Delaunay.triangulate(p1, p2, p3, p4)
+ <span class="keyword">for</span> i = <span class="number">1</span>, #triangles <span class="keyword">do</span>
+   <span class="global">print</span>(triangles[i])
+ <span class="keyword">end</span></pre>
+    </ul>
+
+</dd>
+</dl>
+
+
+</div> <!-- id="content" -->
+</div> <!-- id="main" -->
+<div id="about">
+<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.0</a></i>
+</div> <!-- id="about" -->
+</div> <!-- id="container" -->
+</body>
+</html>

+ 38 - 0
performance/bench.lua

@@ -0,0 +1,38 @@
+local Delaunay = require ('Delaunay')
+local Point    = Delaunay.Point
+
+math.randomseed(os.time())
+
+local function newPoint()
+  local x, y = math.random(), math.random()
+  return Point(x * 1000, y * 1000)
+end
+
+local MAX_POINTS = 1e3
+local N_TESTS    = 10
+
+local function genPoints(n)
+  local points = {}
+  for i = 1, n do
+    points[i] = newPoint()
+  end
+  return points
+end
+
+local function time(f, p)
+  local start_time = os.clock()
+  local result = f(unpack(p))
+  local duration = (os.clock() - start_time) * 1000
+  assert(result~=nil, 'Unexpected output, returned nil')
+  return duration
+end
+
+local function main()
+  for i = 1, N_TESTS do
+    local p = genPoints(MAX_POINTS)
+    local duration = time(Delaunay.triangulate, p)
+    print(('Test %02d: triangulating %04d points in %.2f ms'):format(i, MAX_POINTS, duration))
+  end
+end
+
+main()

+ 82 - 0
specs/delaunay.lua

@@ -0,0 +1,82 @@
+local Delaunay       = (require "delaunay")
+local Point          = Delaunay.Point
+local Triangle       = Delaunay.Triangle
+
+context("Delaunay", function()
+
+  test('is a module containing binding to Point, Edge, Triangle primitives', function()
+    assert_true(type(Delaunay) == 'table')
+    assert_true(type(Delaunay.Point) == 'table')
+    assert_true(type(Delaunay.Edge) == 'table')
+    assert_true(type(Delaunay.Triangle) == 'table')
+  end)
+  
+  it('offers a triangulation function', function()
+    assert_true(type(Delaunay.triangulate) == 'function')
+  end)
+  
+  it('also have a _VERSION member', function()
+    assert_true(type(Delaunay._VERSION) == 'string')
+  end)  
+
+  should('throw an error when receiving a vertex', function()
+    local function triangulate1vertex()
+      Delaunay.triangulate(Point())
+    end
+    assert_error(triangulate1vertex)
+  end)    
+
+  should('throw an error when receiving two vertices', function()
+    local function triangulate2vertices()
+      Delaunay.triangulate(Point(), Point(1,1))
+    end
+    assert_error(triangulate2vertices)
+  end)
+  
+  should('return a unique triangle made when receiving 3 vertices', function()
+    local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+    local t = Delaunay.triangulate(p1, p2, p3)
+    assert_equal(#t, 1)
+    assert_equal(getmetatable(t[1]), Triangle)
+    assert_equal(t[1].p1, p1)
+    assert_equal(t[1].p2, p2)
+    assert_equal(t[1].p3, p3)
+  end)
+  
+  should('return 2 triangles for those 4 vertices', function()
+    local p1, p2, p3, p4 = Point(), Point(1,0), Point(1,1), Point(0,1)
+    local t = Delaunay.triangulate(p1, p2, p3, p4)
+    assert_equal(#t, 2)
+    assert_equal(getmetatable(t[1]), Triangle)    
+    assert_equal(t[1].p1, p2)
+    assert_equal(t[1].p2, p1)
+    assert_equal(t[1].p3, p4)
+    assert_equal(getmetatable(t[2]), Triangle)    
+    assert_equal(t[2].p1, p3)
+    assert_equal(t[2].p2, p2)
+    assert_equal(t[2].p3, p4)  
+  end)
+  
+  should('return 4 triangles for those 5 vertices', function()
+    local p1, p2, p3, p4, p5 = Point(), Point(1,0), Point(1,1), Point(0,1), Point(0.5, 0.5)
+    local t = Delaunay.triangulate(p1, p2, p3, p4, p5)
+    assert_equal(#t, 4)
+    assert_equal(getmetatable(t[1]), Triangle)    
+    assert_equal(t[1].p1, p3)
+    assert_equal(t[1].p2, p2)
+    assert_equal(t[1].p3, p5)
+    assert_equal(getmetatable(t[2]), Triangle)    
+    assert_equal(t[2].p1, p4)
+    assert_equal(t[2].p2, p3)
+    assert_equal(t[2].p3, p5)
+    assert_equal(getmetatable(t[3]), Triangle)    
+    assert_equal(t[3].p1, p2)
+    assert_equal(t[3].p2, p1)
+    assert_equal(t[3].p3, p5)
+    assert_equal(getmetatable(t[4]), Triangle)    
+    assert_equal(t[4].p1, p1)
+    assert_equal(t[4].p2, p4)
+    assert_equal(t[4].p3, p5)      
+  end)
+  
+end)

+ 53 - 0
specs/edge.lua

@@ -0,0 +1,53 @@
+local Point = (require "delaunay").Point
+local Edge  = (require "delaunay").Edge
+
+context("Edge", function()
+
+  test('an Edge is created passing two Points', function()
+    local e = Edge(Point(), Point(1,1))
+    assert_equal(getmetatable(e), Edge)
+  end)
+  
+  test('an edge has two members named p1 and p2, which are points', function()
+    local p1, p2 = Point(), Point(1,1)
+    local e = Edge(p1, p2)
+    assert_equal(e.p1, p1)
+    assert_equal(e.p2, p2)
+  end)
+  
+  it('can test if edges are equal without considering their orientation', function()
+    local p1, p2, p3 = Point(), Point(1,1), Point(1,2)
+    local e1 = Edge(p1, p2)
+    local e2 = Edge(p1, p2)
+    local e3 = Edge(p2, p1)
+    local e4 = Edge(p1, p3)
+    assert_true(e1:same(e2))
+    assert_true(e1:same(e3))
+    assert_false(e1:same(e4))
+  end)
+  
+  it('can also test if edges are strictly the same', function()
+    local p1, p2, p3 = Point(), Point(1,1), Point(1,2)
+    local e1 = Edge(p1, p2)
+    local e2 = Edge(p1, p2)
+    local e3 = Edge(p2, p1)
+    local e4 = Edge(p1, p3)
+    assert_true(e1 == e2)
+    assert_false(e1 == e3)
+    assert_false(e1 == e4)
+  end)  
+  
+  it('can evaluate the edge mid-point coordinates', function()
+    local e = Edge(Point(), Point(2,2))
+    local x, y = e:getMidPoint()
+    assert_equal(x, 1)
+    assert_equal(y, 1)
+  end)
+  
+  it('can evaluate the edge length', function()
+    local e = Edge(Point(), Point(1,1))
+    assert_equal(e:length(), math.sqrt(2))
+  end)  
+  
+
+end)

+ 49 - 0
specs/point.lua

@@ -0,0 +1,49 @@
+local Point = (require "delaunay").Point
+
+context("Point", function()
+      
+  test('a new point has x and y members which defaults to 0,0', function()
+    local p = Point()
+    assert_not_nil(p.x)
+    assert_not_nil(p.y)
+    assert_equal(p.x, 0)
+    assert_equal(p.y, 0)
+  end)
+  
+  it('can create a point via __call(...)', function()
+    local p = Point(0,0)
+    assert_equal(getmetatable(p), Point)
+    assert_equal(p.x, 0)
+    assert_equal(p.y, 0)
+  end)
+  
+  it('can create a point via new(...)', function()
+    local p = Point:new(1,2)
+    assert_equal(getmetatable(p), Point)
+    assert_equal(p.x, 1)
+    assert_equal(p.y, 2)
+  end)
+  
+  it('can test if two given points are equal points', function()
+    assert_equal(Point(), Point())
+    assert_not_equal(Point(1,1), Point(1,2))
+  end)
+  
+  it('can evaluate the distance between two points', function()
+    assert_equal((Point()):dist(Point(2,0)), 2)
+    assert_equal((Point()):dist(Point(1,1)), math.sqrt(2))
+  end)  
+  
+  it('can evaluate the square distance', function()
+    assert_equal((Point()):dist2(Point(2,0)), 4)
+    assert_equal((Point()):dist2(Point(1,1)), 2)
+  end)
+
+  it('can test if a point lies in a circle', function()
+    assert_true((Point()):isInCircle(0,0,1))
+    assert_true((Point()):isInCircle(1,1,math.sqrt(2)))
+    assert_false((Point()):isInCircle(1,1,1))
+    assert_false((Point()):isInCircle(1,1,0.99))
+  end)
+
+end)

+ 109 - 0
specs/triangle.lua

@@ -0,0 +1,109 @@
+local make_assertion = (require "telescope").make_assertion
+local Point          = (require "delaunay").Point
+local Edge           = (require "delaunay").Edge
+local Triangle       = (require "delaunay").Triangle
+
+make_assertion("fuzzy_equal", "%s to be almost equal to %s", function(a, b)
+ return math.abs(a - b) < 1e-8 
+end)
+ 
+context("Triangle", function()
+
+  test('a triangle is created passing three Points', function()
+    local t = Triangle(Point(), Point(2,0), Point(1,1))
+    assert_equal(getmetatable(t), Triangle)
+  end)
+  
+  test('a triangle has 3 Points as members : p1, p2 and p3', function()
+    local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+    local t = Triangle(p1, p2, p3)
+    assert_equal(t.p1, p1)
+    assert_equal(t.p2, p2)
+    assert_equal(t.p3, p3)
+  end)
+
+  test('a triangle has also 3 Edges as members : e1, e2 and e3', function()
+    local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+    local t = Triangle(p1, p2, p3)
+    assert_equal(t.e1, Edge(p1, p2))
+    assert_equal(t.e2, Edge(p2, p3))
+    assert_equal(t.e3, Edge(p3, p1))
+  end)
+  
+  test('a triangle cannot have a flat angle', function()
+    local p1, p2, p3 = Point(-1, 0), Point(0, 0), Point(1, 0)
+    local p4, p5, p6 = Point(0, 1), Point(0, 0), Point(0, -1)
+    local function makeFlat1() return Triangle(p1, p2, p3) end
+    local function makeFlat2() return Triangle(p4, p5, p6) end
+    assert_error(makeFlat1)
+    assert_error(makeFlat2)
+  end)  
+  
+  it('can evaluate the 3 sides length', function()
+    local p1, p2, p3 = Point(), Point(2,0), Point(1,1)
+    local t = Triangle(p1, p2, p3)
+    local a, b, c = t:getSidesLength()
+    assert_equal(a, 2)
+    assert_equal(b, math.sqrt(2))
+    assert_equal(c, math.sqrt(2))
+  end)
+  
+  it('can evaluate the coordinates of the triangle center', function()
+    local p1, p2, p3 = Point(-1,0), Point(1,0), Point(0,1)
+    local t = Triangle(p1, p2, p3)
+    local x, y = t:getCenter()
+    assert_equal(x, 0)
+    assert_equal(y, 1/3)
+  end)
+
+  it('can evaluate the coordinates of the triangle circumcenter', function()
+    local p1, p2, p3 = Point(5, 5), Point(10, 3), Point(9, 15)
+    local t = Triangle(p1, p2, p3)
+    local x, y = t:getCircumCenter()
+    assert_equal(x, 9.5)
+    assert_equal(y, 9)
+  end)
+  
+  it('can evaluate the radius of the triangle circumcircle', function()
+    local p1, p2, p3 = Point(5, 5), Point(10, 3), Point(9, 15)
+    local t = Triangle(p1, p2, p3)
+    assert_fuzzy_equal(t:getCircumRadius(), 6.0207972893961)
+  end)
+
+  it('can evaluate both circumcenter and circumradius', function()
+    local p1, p2, p3 = Point(5, 5), Point(10, 3), Point(9, 15)
+    local t = Triangle(p1, p2, p3)
+    local x, y, r = t:getCircumCircle()
+    assert_equal(x, 9.5)
+    assert_equal(y, 9)    
+    assert_fuzzy_equal(t:getCircumRadius(), 6.0207972893961)
+  end)
+  
+  it('can test if a given point lies in a triangle\'s circumcircle', function()
+    local p1, p2, p3 = Point(0, 0.5), Point(1, 1), Point(1.01, 1.01)
+    local t = Triangle(Point(-1,0), Point(1, 0), Point(1, 1))
+    assert_true(t:inCircumCircle(p1))
+    assert_true(t:inCircumCircle(p2))
+    assert_false(t:inCircumCircle(p3))
+  end)
+  
+  it('can evaluate the area of a triangle', function()
+    local p1, p2, p3 = Point(), Point(1, 0), Point(1, 1)
+    local t = Triangle(p1, p2, p3)
+    local x, y, r = t:getCircumCircle()
+    assert_equal(t:getArea(), 0.5)
+  end)
+
+  it('can evaluate if triangle is defined clockwise', function()
+    local p1, p2, p3 = Point(), Point(-1, 0), Point(1, 1)
+    assert_true((Triangle(p1, p2, p3)):isCW())
+    assert_false((Triangle(p1, p3, p2)):isCW())
+  end)
+  
+  it('can also evaluate if triangle is defined counter-clockwise', function()
+    local p1, p2, p3 = Point(), Point(1, 0), Point(1, 1)
+    assert_true((Triangle(p1, p2, p3)):isCCW())
+    assert_false((Triangle(p1, p3, p2)):isCCW())
+  end)  
+
+end)

+ 4 - 0
version_history.md

@@ -0,0 +1,4 @@
+#Version history#
+
+###0.1 (12/26/2013)
+* Initial release