class nape.geom.GeomPoly

Available on all platforms

Polygon class with various geometric methods *

* This class represents a general Polygon, rather than the Polygon class * which is physics shape. *

* Internally this polygon is stored as a circularly linked list of special * vertex types that are exposed via a Vec2 that is lazily constructed whenever * necessary to the API.

Class Fields

static function get(?vertices:Dynamic = null):GeomPoly

Allocate GeomPoly from object pool. *

* The vertices argument is typed Dynamic ( in AS3), and is permitted * to be one of: Array<Vec2>, flash.Vector<Vec2>, Vec2List, GeomPoly *

* The input will be used to initialise the vertices of the polygon with * the head of the polygon pointing to the first vertex in input with vertices * inserted in forward order.
*

vertices

Vertex data to initialise polygon, or null for empty polygon. *

returns

New GeomPoly representing input vertex data, allocated from object pool. *

Instance Fields

var zpp_disp:Bool

@private

var zpp_pool:GeomPoly

@private

function new(?vertices:Dynamic = null):Void

Create a new GeomPoly polygon. *

* The vertices argument is typed Dynamic ( in AS3), and is permitted * to be one of: Array<Vec2>, flash.Vector<Vec2>, Vec2List, GeomPoly *

* The input will be used to initialise the vertices of the polygon with * the head of the polygon pointing to the first vertex in input with vertices * inserted in forward order. *

* You should use the static 'get' method in preference to make use of object pool.
*

vertices

Vertex data to initialise polygon, or null for empty polygon. *

returns

New GeomPoly representing input vertex data. *

function area():Float

Compute area of weakly-simple polygon. *

* For complex polygons, this function will return an underestimate * to the true area. * *

returns

The area of the polygon. *

function backwardsIterator():GeomVertexIterator

Haxe iterator over vertices of polygon. * *

returns

A Haxe iterator over the vertices of the polygon. Iterating in a backwards direction.

function bottom():Vec2

Find bottom most vertex of polygon. *

* If there is more than one such vertex then the result is indeterminate. *

* The Vec2 returned is intrinsically tied to the inner vertex like that * returned by current(). This method will not alter the current vertex. * This Vec2 is not able to be disposed of. * *

returns

A Vec2 representing the bottom most vertex. *

function bounds():AABB

Determine bounds of polygon. * *

returns

A new AABB representing bounds of polygon. *

function clear():GeomPoly

Clear all vertices from polygon. *

* All of the vertices will be released to the global object pool. * *

returns

A reference to this polygon. *

function contains(point:Vec2):Bool

Determine if point is contained in polygon. *

* Polygon containment is performed with a ray cast through polygon * from the vertex and counting the number of intersections. In this * way containment will be defined for self-intersecting polygons based * on how such a polygon would be rendered with areas of self-intersection * treat as being 'outside' the polygon. *

* This algorithm operates in O(n) time. * *

point

The point to test for containment. *

returns

True if point is contained in the polygon. *

function convexDecomposition(?delaunay:Bool = false, ?output:GeomPolyList = null):GeomPolyList

Produce a decomposition of weakly-simple polygon into convex components. *

* This algorithm 'should' be 100% robust and has been well test on for * example, the output of the Marching Squars utility which produces many * degenerate cases of weakly-simple polygons that have not yet broken this * algorithm!. *

* This algorithm operates in O(n.log(n)) time and will produce no more than * 4 times the number of convex poylgons in a minimal decomposition in the * worst case scenario. *

* Vertices may be stripped from the polygon that are found to not be * necessary as part of making this algorithm robust. * *

delaunay

This algorithm first performs a triangulation, if this field * is true, then this triangulation will be made delaunay and may * produce better convex polygons resultanly (default false). *

output

If supplied, polygons will be appended to this list via 'add' * instead of a new list being constructed. *

returns

A Nape list of GeomPoly's defining the decomposition. *

function copy():GeomPoly

Copy this polygon. *

* The copy will have its vertices in the same order as 'this' polygon. * It will also have its current vertex at head, as the same vertex * this polygon has. *

* This polygon will not be modified in any way. *

     * poly := -> A <-> B <-> C <-> D <-> E <-
     *                (head)
     
     * poly2 = poly.copy();
     
     * poly2 := -> A' <-> B' <-> C' <-> D' <-> E' <-
     *                  (head)
     * 
* *

returns

The new GeomPoly representing the copy. *

function current():Vec2

Current vertex at head of polygon. *

* The current vertex will not be changed by this access. *

* This function returns a Vec2 which will be intrinsically tied * to the values of the internal vertex so that modifications to * this Vec2 will be reflected in the vertex of the polygon. *

* If invoked again with the head of the polygon pointing to the * same vertex, then the same Vec2 will be returned; this Vec2 is * not able to be disposed of. * *

returns

A Vec2 representing the current vertex of polygon. *

function cut(start:Vec2, end:Vec2, ?boundedStart:Bool = false, ?boundedEnd:Bool = false, ?output:GeomPolyList = null):GeomPolyList

Cut simple polygon with line. *

* The result of this operation will be a list of new GeomPoly representing * the connected regions of the polygon after an imaginary cut is made. *

     * (Result of cut assuming
     *  boundedStart = true)       
     *   /\    _             /\   / \
     *  /  \  / \           /  \ '---'
     * / o--\/---\-->  =>  /    \,---,
     * \/         \_/
     * 
* This algorithm runs in average case O(n.log(n)) time and worst case O(n^2). * For convex polygons, this algorithm runs in guaranteed O(n) time. * *

start

The start point for line segment *

end

The end point for line segment. *

boundedStart

If true, then the cut will not extend * beyond the start of the line segment. * (default false) *

boundedEnd

If true, then the cut will not extend * beyond the end of the line segment. * (default false) *

output

A GeomPolyList to append results to if supplied, * otherwise a new list is created (default null) *

returns

A list of GeomPoly representing the result of the cut. *

function dispose():Void

Release this GeomPoly to global object pool. *

* Once disposed this GeomPoly will be accessible to Nape internals for re-allocation * and should not be touched (Good practice would be to set any references to this * GeomPoly to null to help ensure this). *

* In debug mode, should you attempt to access this GeomPoly after disposal * and the GeomPoly is still in the object pool, you will be given an Error. * The object pool operates on a First-In-Last-Out principal in debug mode to help * catch these sort of errors. *

function empty():Bool

Determine if polygon is empty. * *

returns

True if polygon is empty. *

function erase(count:Int):GeomPoly

Erase count number of elements *

* For positive values of count, this is equivalent to successive * unshift operations. *

* For negative values of count, this is equivalent to successive * pop operations. *

     * poly := -> A <-> B <-> C <-> D <-> E <-> F <-> G <-
     *                (head)
     
     * poly.erase(2);
     
     * poly := -> A <-> D <-> E <-> F <-> G <-
     *                (head)
     
     * poly.erase(-3);
     
     * poly := -> E <-> F <-
     *                (head)
     * 
* In this case that the specified number of elements to erase is * greater than the size of the polygon, the method will simply * terminate with the polygon being empty. * *

count

The number of vertices to erase, with sign indicating * the direction for erasing. *

returns

A reference to this polygon. *

function forwardIterator():GeomVertexIterator

Haxe iterator over vertices of polygon. * *

returns

A Haxe iterator over the vertices of the polygon. Iterating in a forward direction.

function inflate(inflation:Float):GeomPoly

Inflate/Deflate polygon. *

* This algorithm does not attempt to deal with any self-intersections which may * result from the process. Gaps are joined with a miter joint. *

* This algorithm will work for self-intersecting polygons, though the results * may not be what you expect; some parts will be inflated, and some deflated * depending on the local winding. You should probably avoid using this on * self-intersecting polygons. * *

inflation

The number of pixels to inflate polygon by. To deflate * use a negative value. *

returns

The inflated polygon. *

function isClockwise():Bool

Determine if polygon is clockwise wound. *

* This is equivalent to poly.winding() == Winding.CLOCKWISE. * *

returns

True if polygon is clockwise wound. *

function isConvex():Bool

Determine if weakly-simple polygon is convex. *

* This algorithm assumes that the polygon is weakly-simple. Otherwise it may * fail (It is very easy to construct a self intersecting polygon which * will return True for isConvex()). *

* You may wish to instead use isSimple() && isConvex() if * you cannot be sure of the polygon being simple, noting that this will * of course return false in the case of a weakly-simple polygon. *

     *  
     * |     |
     * |     |  <-- convex
     * |/
     *  
     * |  \
     * |     /  <-- concave
     * |/
     * 
* This algorithm operates in O(n) time. * *

returns

True if polygon is found to be convex. *

function isDegenerate():Bool

Determine if weakly-simple polygon is degenerate. *

* Degeneracy is determined by having a zero area, if polygon is complex, * then this function may report degeneracy erroneously. * *

returns

True if polygon is degenerate. *

function isMonotone():Bool

Determine if polygon is y-monotone. *

* To be classed as y-monotone, the polygon must be such that any horizontal * line intersects the polygon in at most 2 intersections. *

     *  
     * |   |
     * |   |  <-- y-monotone
     * ||
     
     * |\
     * | \/|  <-- not y-monotone, offending vertex at bottom of the V.
     * |___|
     * 
* This algorithm operates in O(n) time. *

returns

True if polygon is y-monotone. *

function isSimple():Bool

Determine if polygon is strictly simple. *

* By strict simplicity, we refer to not permitting 'glancing' * self intersections (where boundary of polygon 'touches' but does not * pass through another area of the polygon's boundary). This property * is instead referred to as being 'weakly simple' for which there is no * easy test! *

     *  
     * |     |  <-- strictly simple polygon.
     * |   \ \|
     *  \/
     *  
     * |   |   |
     * |  /\  | <-- weakly simple polygon.
     *  \/
     *  
     * | /
     *  X     <-- complex polygon.
     * |  \/  \
     * \/\__|
     * 
* This algorithm operates in O(n.log(n)) time. * *

returns

True if polygon is strictly simple. *

function iterator():GeomVertexIterator

Haxe iterator over vertices of polygon. * *

returns

A Haxe iterator over the vertices of the polygon. *

function left():Vec2

Find left most vertex of polygon. *

* If there is more than one such vertex then the result is indeterminate. *

* The Vec2 returned is intrinsically tied to the inner vertex like that * returned by current(). This method will not alter the current vertex. * This Vec2 is not able to be disposed of. * *

returns

A Vec2 representing the left most vertex. *

function monotoneDecomposition(?output:GeomPolyList = null):GeomPolyList

Produce a decomposition of weakly-simple polygon into monotone components. *

* This algorithm 'should' be 100% robust and has been well tested on for * example, the output of the Marching Squares utility which produces many * degenerate cases of weakly-simple polygons that have not yet broken this * algorithm!. *

* This algorithm operates in O(n.log(n)) time and may strip vertices from * the polygon in degenerate cases where vertex is not needed to define the * polygon. *

* This algorithm is an improved version of the one presented in: Mark de * Berg, Marc van Kreveld, Mark Overmars, and Otfried Schwarzkopf. * Computational Geometry: Algorithms and Applications. Springer-Verlag, * Berlin, 1997. *

output

If supplied, polygons will be appended to this list via 'add' * instead of a new list being constructed. *

returns

A Nape list of GeomPoly's defining the decomposition. *

function pop():GeomPoly

Pop vertex from polygon. *

* Pop the current vertex at head of polygon, retreating the 'current' * vertex to point to the previous vertex in polygon. This inner vertex * will be released to the global object pool. *

* In this way a pop which follows a push will act to reset the push. *

     * poly := -> A <-> B <-> C <-> D <-> E <-
     *                (head)
     
     * poly.pop();
     
     * poly := -> A <-> C <-> D <-> E <-
     *          (head)
     * 
* *

returns

A reference to this polygon. *

function push(vertex:Vec2):GeomPoly

Push vertex to polygon. *

* A vertex will be allocated from a global object pool, and initialised * with the values of the given Vec2. *

* This vertex will be inserted after the current head, and the head * advanced to the newly inserted vertex, in this way successive pushes * will insert elements in order. *

* Note that the Vec2 supplied as argument is only used to initialise the * inner Vertex. *

     * poly := -> A <-> B <-> C <-> D <-> E <-
     *                (head)
     
     * poly.push(X);
     
     * poly := -> A <-> B <-> X <-> C <-> D <-> E <-
     *                      (head)
     * 
* *

vertex

The Vec2 to be used in initialising the inner vertex. *

returns

A reference to this polygon. *

function right():Vec2

Find right most vertex of polygon. *

* If there is more than one such vertex then the result is indeterminate. *

* The Vec2 returned is intrinsically tied to the inner vertex like that * returned by current(). This method will not alter the current vertex. * This Vec2 is not able to be disposed of. * *

returns

A Vec2 representing the right most vertex. *

function shift():GeomPoly

Shift vertex from polygon. *

* Shift the current vertex at head of polygon, advancing the 'current' * vertex to point to the next vertex in polygon. This inner vertex * will be released to the global object pool. *

* In this way a shift which follows an unshift will act to reset the * unshift operation. *

     * poly := -> A <-> B <-> C <-> D <-> E <-
     *                (head)
     
     * poly.shift();
     
     * poly := -> A <-> C <-> D <-> E <-
     *                (head)
     * 
* *

returns

A reference to this polygon. *

function simpleDecomposition(?output:GeomPolyList = null):GeomPolyList

Produce a decomposition of complex polygon into simple components. *

* WARNING: This method is 'not' 100% robust. It may fail! *

* Produce a decomposition of a self intersecting, complex polygon into * a set of weakly-simple components. *

* This algorithm operates in O(n.log(n)) time and is based on the * Bentley-Ottmann algorithm. * *

output

If supplied, polygons will be appended to this list via 'add' * instead of a new list being constructed. *

returns

A Nape list of GeomPoly's representing the decomposition. *

function simplify(epsilon:Float):GeomPoly

Simplify polygon. *

* Simplification is performed with an implementation of the Ramer-Douglas-Peucker * algorithm. The output polygon is formed via subset of the vertices in * the input polygon such that any discarded vertex is at most 'epsilon' pixels * away from the local output polygon. *

* This algorithm works on both simple and complex polygons, but please note * that this algorithm makes no guarantees on a simple polygon remaining simple * after simplification. This should not generally be a problem unless the epsilon * value is large with respect to the size of the features on the polygon. *

* Many of the geometric algorithms will mark vertices as important, such that * they will be guaranteed to exist after simplification (Such as preventing * gaps from opening up in marching squares when simplifying output polygons). *

* The average runtime of this algorithm is O(n.log(n)). This algorithm is * not stable in the sense that adding a new vertex to the polygon may drastically * change the result of simplifying the polygon. * *

epsilon

The distance from polygon at which vertices are ignored. *

returns

A new GeomPoly representing the result of the simplification. *

function size():Int

Determine number of vertices in polygon * *

returns

The number of vertices. *

function skipBackwards(times:Int):GeomPoly

Advance head of polygon backwards. *

* The current head of polygon will be moved backwards * the given number of times, with a negative value * being equivalent to performing a forwards advance. *

* poly.skipbackwards(times) is equivalent to * poly.skipforwards(-times) *

     * poly := -> A <-> B <-> C <-> D <-> E <-
     *                (head)
     
     * poly.skipBackwards(2);
     
     * poly := -> A <-> B <-> C <-> D <-> E <-
     *                                  (head)
     * 
* * @params times The number of times to advance head backwards. * This value can be negative indicating a forwards * advance. *

returns

A reference to this polygon. *

function skipForward(times:Int):GeomPoly

Advance head of polygon forward. *

* The current head of polygon will be moved forwards * the given number of times, with a negative value * being equivalent to performing a backwards advance. *

* poly.skipforwards(times) is equivalent to * poly.skipbackwards(-times) *

     * poly := -> A <-> B <-> C <-> D <-> E <-
     *                (head)
     
     * poly.skipForwards(2);
     
     * poly := -> A <-> B <-> C <-> D <-> E <-
     *                            (head)
     * 
* * @params times The number of times to advance head forward. * This value can be negative indicating a backwards * advance. *

returns

A reference to this polygon. *

function toString():String

@private

function top():Vec2

Find top most vertex of polygon. *

* If there is more than one such vertex then the result is indeterminate. *

* The Vec2 returned is intrinsically tied to the inner vertex like that * returned by current(). This method will not alter the current vertex. * This Vec2 is not able to be disposed of. * *

returns

A Vec2 representing the top most vertex. *

function transform(matrix:Mat23):GeomPoly

Transform polygon by given matrix. *

* Any transformation (not just equiorthogonal ones) are permitted, though * a transformation that causes polygon to be come degenerate is a bit * pointless. * *

matrix

The matrix to transform polygon by. *

returns

A reference to this polygon. *

function triangularDecomposition(?delaunay:Bool = false, ?output:GeomPolyList = null):GeomPolyList

Produce a decomposition of weakly-simple polygon into triangles. *

* This algorithm 'should' be 100% robust and has been well test on for * example, the output of the Marching Squars utility which produces many * degenerate cases of weakly-simple polygons that have not yet broken this * algorithm!. *

* This algorithm operates in O(n.log(n)) time. *

* Vertices may be stripped from the polygon that are found to not be * necessary as part of making this algorithm robust. * *

delaunay

If true, then an O(n^2) pass will be made to mutate the original * triangulation to push it into a delanuay triangulation. (default false) *

output

If supplied, polygons will be appended to this list via 'add' * instead of a new list being constructed. *

returns

A Nape list of GeomPoly's defining the decomposition. *

function unshift(vertex:Vec2):GeomPoly

Unshift vertex to polygon. *

* A vertex will be allocated from a global object pool, and initialised * with the values of the given Vec2. *

* This vertex will be inserted before the current head, and the head * retreated to the newly inserted vertex, in this way successive unshifts * will insert elements in the expected reverse order. *

* Note that the Vec2 supplied as argument is only used to initialise the * inner Vertex. *

     * poly := -> A <-> B <-> C <-> D <-> E <-
     *                (head)
     
     * poly.unshift(X);
     
     * poly := -> A <-> X <-> B <-> C <-> D <-> E <-
     *                (head)
     * 
* *

vertex

The Vec2 to be used in initialising the inner vertex. *

returns

A reference to this polygon. *

function winding():Winding

Compute the winding order for this polygon. *

* The winding order can be conceptualised by thinking of an analog * clock face, if your polygon is the numbers on the clock then a * clockwise winding would have your polygon's vertices in numerical * order. *

* In the case of a non-simple polygon with self intersections then the * winding order is decided by how 'much' of the polygon is locally * clockwise wound, and how much is locally anti-clockwise wound. *
* (Think of a figure 8 style polygon where one loop is larger than the * other. This larger loop will dictate the winding of the polygon.) *

* If no winding can be computed, then Winding.UNDEFINED * will be returned. * *

returns

The winding of the polygon. *