[
  {
    "path": "AUTHORS",
    "content": "Primary Contributors:\n\n  Mason Green <mason.green@gmail.com> (C++, Python)\n  Thomas hln <thahlen@gmail.com>    (Java)\n\nOther Contributors:\n\n  \n"
  },
  {
    "path": "LICENSE",
    "content": "Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\nhttp://code.google.com/p/poly2tri/\n\nAll rights reserved.\nRedistribution and use in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice,\n  this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n* Neither the name of Poly2Tri nor the names of its contributors may be\n  used to endorse or promote products derived from this software without specific\n  prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n\"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\nA PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\nPROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\nLIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n"
  },
  {
    "path": "README",
    "content": "﻿#####################################################################################\n###\n### Since there are no Input validation of the data given for triangulation you need \n### to think about this. Poly2Tri does not support repeat points within epsilon.\n### \n### * If you have a cyclic function that generates random points make sure you don't \n### add the same coordinate twice.\n###\n### * If you are given input and aren't sure same point exist twice you need to \n### check for this yourself.\n###      \n### * Only simple polygons are supported. You may add holes or interior Steiner points\n###\n### * Interior holes must not touch other holes, nor touch the polyline boundary\n###\n### * Use the library in this order:\n###\n### 1) Initialize CDT with a simple polyline (this defines the constrained edges)\n### 2) Add holes if necessary (also simple polylines)\n### 3) Add Steiner points\n### 4) Triangulate\n###\n### Make sure you understand the preceding notice before posting an issue. If you have \n### an issue not covered by the above, include your data-set with the problem.\n###\n### The only easy day was yesterday; have a nice day. <Mason Green>\n###\n######################################################################################\n\n===========================\nTESTBED INSTALLATION GUIDE\n===========================\n\n------------\nDependencies\n------------\n\n  Core poly2tri lib:\n  - Standard Template Library (STL)\n  \n  Testbed:\n  - gcc\n  - OpenGL\n  - GLFW (http://glfw.sf.net)\n  - Python\n \nwaf (http://code.google.com/p/waf/) is used to compile the testbed.   \nA waf script (86kb) is included in the repositoty.\n\n----------------------------------------------\nBuilding the Testbed\n----------------------------------------------\n\nPosix/MSYS environment:\n\n  ./waf configure\n  ./waf build\n\nWindows command line:\n\n  python waf configure\n  python waf build\n\n----------------------------------------------\nRunning the Examples\n----------------------------------------------\n\nLoad data points from a file:\np2t <filename> <center_x> <center_y> <zoom>\n\nRandom distribution of points inside a consrained box:\np2t random <num_points> <box_radius> <zoom>\n\nExamples:\n\n  ./p2t dude.dat 300 500 2\n  ./p2t nazca_monkey.dat 0 0 9\n  \n  ./p2t random 10 100 5.0\n  ./p2t random 1000 20000 0.025\n"
  },
  {
    "path": "poly2tri/common/shapes.cc",
    "content": "/* \n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\n * http://code.google.com/p/poly2tri/\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n * * Redistributions of source code must retain the above copyright notice,\n *   this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n *   this list of conditions and the following disclaimer in the documentation\n *   and/or other materials provided with the distribution.\n * * Neither the name of Poly2Tri nor the names of its contributors may be\n *   used to endorse or promote products derived from this software without specific\n *   prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"shapes.h\"\n#include <iostream>\n\nnamespace p2t {\n\nTriangle::Triangle(Point& a, Point& b, Point& c)\n{\n  points_[0] = &a; points_[1] = &b; points_[2] = &c;\n  neighbors_[0] = NULL; neighbors_[1] = NULL; neighbors_[2] = NULL;\n  constrained_edge[0] = constrained_edge[1] = constrained_edge[2] = false;\n  delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;\n  interior_ = false;\n}\n\n// Update neighbor pointers\nvoid Triangle::MarkNeighbor(Point* p1, Point* p2, Triangle* t)\n{\n  if ((p1 == points_[2] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[2]))\n    neighbors_[0] = t;\n  else if ((p1 == points_[0] && p2 == points_[2]) || (p1 == points_[2] && p2 == points_[0]))\n    neighbors_[1] = t;\n  else if ((p1 == points_[0] && p2 == points_[1]) || (p1 == points_[1] && p2 == points_[0]))\n    neighbors_[2] = t;\n  else\n    assert(0);\n}\n\n// Exhaustive search to update neighbor pointers\nvoid Triangle::MarkNeighbor(Triangle& t)\n{\n  if (t.Contains(points_[1], points_[2])) {\n    neighbors_[0] = &t;\n    t.MarkNeighbor(points_[1], points_[2], this);\n  } else if (t.Contains(points_[0], points_[2])) {\n    neighbors_[1] = &t;\n    t.MarkNeighbor(points_[0], points_[2], this);\n  } else if (t.Contains(points_[0], points_[1])) {\n    neighbors_[2] = &t;\n    t.MarkNeighbor(points_[0], points_[1], this);\n  }\n}\n\n/**\n * Clears all references to all other triangles and points\n */\nvoid Triangle::Clear()\n{\n    Triangle *t;\n    for( int i=0; i<3; i++ )\n    {\n        t = neighbors_[i];\n        if( t != NULL )\n        {\n            t->ClearNeighbor( this );\n        }\n    }\n    ClearNeighbors();\n    points_[0]=points_[1]=points_[2] = NULL;\n}\n\nvoid Triangle::ClearNeighbor(Triangle *triangle )\n{\n    if( neighbors_[0] == triangle )\n    {\n        neighbors_[0] = NULL;\n    }\n    else if( neighbors_[1] == triangle )\n    {\n        neighbors_[1] = NULL;            \n    }\n    else\n    {\n        neighbors_[2] = NULL;\n    }\n}\n    \nvoid Triangle::ClearNeighbors()\n{\n  neighbors_[0] = NULL;\n  neighbors_[1] = NULL;\n  neighbors_[2] = NULL;\n}\n\nvoid Triangle::ClearDelunayEdges()\n{\n  delaunay_edge[0] = delaunay_edge[1] = delaunay_edge[2] = false;\n}\n\nPoint* Triangle::OppositePoint(Triangle& t, Point& p)\n{\n  Point *cw = t.PointCW(p);\n  double x = cw->x;\n  double y = cw->y;\n  x = p.x;\n  y = p.y;\n  return PointCW(*cw);\n}\n\n// Legalized triangle by rotating clockwise around point(0)\nvoid Triangle::Legalize(Point& point)\n{\n  points_[1] = points_[0];\n  points_[0] = points_[2];\n  points_[2] = &point;\n}\n\n// Legalize triagnle by rotating clockwise around oPoint\nvoid Triangle::Legalize(Point& opoint, Point& npoint)\n{\n  if (&opoint == points_[0]) {\n    points_[1] = points_[0];\n    points_[0] = points_[2];\n    points_[2] = &npoint;\n  } else if (&opoint == points_[1]) {\n    points_[2] = points_[1];\n    points_[1] = points_[0];\n    points_[0] = &npoint;\n  } else if (&opoint == points_[2]) {\n    points_[0] = points_[2];\n    points_[2] = points_[1];\n    points_[1] = &npoint;\n  } else {\n    assert(0);\n  }\n}\n\nint Triangle::Index(const Point* p)\n{\n  if (p == points_[0]) {\n    return 0;\n  } else if (p == points_[1]) {\n    return 1;\n  } else if (p == points_[2]) {\n    return 2;\n  }\n  assert(0);\n}\n\nint Triangle::EdgeIndex(const Point* p1, const Point* p2)\n{\n  if (points_[0] == p1) {\n    if (points_[1] == p2) {\n      return 2;\n    } else if (points_[2] == p2) {\n      return 1;\n    }\n  } else if (points_[1] == p1) {\n    if (points_[2] == p2) {\n      return 0;\n    } else if (points_[0] == p2) {\n      return 2;\n    }\n  } else if (points_[2] == p1) {\n    if (points_[0] == p2) {\n      return 1;\n    } else if (points_[1] == p2) {\n      return 0;\n    }\n  }\n  return -1;\n}\n\nvoid Triangle::MarkConstrainedEdge(const int index)\n{\n  constrained_edge[index] = true;\n}\n\nvoid Triangle::MarkConstrainedEdge(Edge& edge)\n{\n  MarkConstrainedEdge(edge.p, edge.q);\n}\n\n// Mark edge as constrained\nvoid Triangle::MarkConstrainedEdge(Point* p, Point* q)\n{\n  if ((q == points_[0] && p == points_[1]) || (q == points_[1] && p == points_[0])) {\n    constrained_edge[2] = true;\n  } else if ((q == points_[0] && p == points_[2]) || (q == points_[2] && p == points_[0])) {\n    constrained_edge[1] = true;\n  } else if ((q == points_[1] && p == points_[2]) || (q == points_[2] && p == points_[1])) {\n    constrained_edge[0] = true;\n  }\n}\n\n// The point counter-clockwise to given point\nPoint* Triangle::PointCW(Point& point)\n{\n  if (&point == points_[0]) {\n    return points_[2];\n  } else if (&point == points_[1]) {\n    return points_[0];\n  } else if (&point == points_[2]) {\n    return points_[1];\n  }\n  assert(0);\n}\n\n// The point counter-clockwise to given point\nPoint* Triangle::PointCCW(Point& point)\n{\n  if (&point == points_[0]) {\n    return points_[1];\n  } else if (&point == points_[1]) {\n    return points_[2];\n  } else if (&point == points_[2]) {\n    return points_[0];\n  }\n  assert(0);\n}\n\n// The neighbor clockwise to given point\nTriangle* Triangle::NeighborCW(Point& point)\n{\n  if (&point == points_[0]) {\n    return neighbors_[1];\n  } else if (&point == points_[1]) {\n    return neighbors_[2];\n  }\n  return neighbors_[0];\n}\n\n// The neighbor counter-clockwise to given point\nTriangle* Triangle::NeighborCCW(Point& point)\n{\n  if (&point == points_[0]) {\n    return neighbors_[2];\n  } else if (&point == points_[1]) {\n    return neighbors_[0];\n  }\n  return neighbors_[1];\n}\n\nbool Triangle::GetConstrainedEdgeCCW(Point& p)\n{\n  if (&p == points_[0]) {\n    return constrained_edge[2];\n  } else if (&p == points_[1]) {\n    return constrained_edge[0];\n  }\n  return constrained_edge[1];\n}\n\nbool Triangle::GetConstrainedEdgeCW(Point& p)\n{\n  if (&p == points_[0]) {\n    return constrained_edge[1];\n  } else if (&p == points_[1]) {\n    return constrained_edge[2];\n  }\n  return constrained_edge[0];\n}\n\nvoid Triangle::SetConstrainedEdgeCCW(Point& p, bool ce)\n{\n  if (&p == points_[0]) {\n    constrained_edge[2] = ce;\n  } else if (&p == points_[1]) {\n    constrained_edge[0] = ce;\n  } else {\n    constrained_edge[1] = ce;\n  }\n}\n\nvoid Triangle::SetConstrainedEdgeCW(Point& p, bool ce)\n{\n  if (&p == points_[0]) {\n    constrained_edge[1] = ce;\n  } else if (&p == points_[1]) {\n    constrained_edge[2] = ce;\n  } else {\n    constrained_edge[0] = ce;\n  }\n}\n\nbool Triangle::GetDelunayEdgeCCW(Point& p)\n{\n  if (&p == points_[0]) {\n    return delaunay_edge[2];\n  } else if (&p == points_[1]) {\n    return delaunay_edge[0];\n  }\n  return delaunay_edge[1];\n}\n\nbool Triangle::GetDelunayEdgeCW(Point& p)\n{\n  if (&p == points_[0]) {\n    return delaunay_edge[1];\n  } else if (&p == points_[1]) {\n    return delaunay_edge[2];\n  }\n  return delaunay_edge[0];\n}\n\nvoid Triangle::SetDelunayEdgeCCW(Point& p, bool e)\n{\n  if (&p == points_[0]) {\n    delaunay_edge[2] = e;\n  } else if (&p == points_[1]) {\n    delaunay_edge[0] = e;\n  } else {\n    delaunay_edge[1] = e;\n  }\n}\n\nvoid Triangle::SetDelunayEdgeCW(Point& p, bool e)\n{\n  if (&p == points_[0]) {\n    delaunay_edge[1] = e;\n  } else if (&p == points_[1]) {\n    delaunay_edge[2] = e;\n  } else {\n    delaunay_edge[0] = e;\n  }\n}\n\n// The neighbor across to given point\nTriangle& Triangle::NeighborAcross(Point& opoint)\n{\n  if (&opoint == points_[0]) {\n    return *neighbors_[0];\n  } else if (&opoint == points_[1]) {\n    return *neighbors_[1];\n  }\n  return *neighbors_[2];\n}\n\nvoid Triangle::DebugPrint()\n{\n  using namespace std;\n  cout << points_[0]->x << \",\" << points_[0]->y << \" \";\n  cout << points_[1]->x << \",\" << points_[1]->y << \" \";\n  cout << points_[2]->x << \",\" << points_[2]->y << endl;\n}\n\n}\n\n"
  },
  {
    "path": "poly2tri/common/shapes.h",
    "content": "/*\n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\n * http://code.google.com/p/poly2tri/\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n * * Redistributions of source code must retain the above copyright notice,\n *   this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n *   this list of conditions and the following disclaimer in the documentation\n *   and/or other materials provided with the distribution.\n * * Neither the name of Poly2Tri nor the names of its contributors may be\n *   used to endorse or promote products derived from this software without specific\n *   prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n// Include guard\n#ifndef SHAPES_H\n#define SHAPES_H\n\n#include <vector>\n#include <cstddef>\n#include <assert.h>\n#include <cmath>\n\nnamespace p2t {\n\nstruct Edge;\n\nstruct Point {\n\n  double x, y;\n\n  /// Default constructor does nothing (for performance).\n  Point()\n  {\n    x = 0.0;\n    y = 0.0;\n  }\n\n  /// The edges this point constitutes an upper ending point\n  std::vector<Edge*> edge_list;\n\n  /// Construct using coordinates.\n  Point(double x, double y) : x(x), y(y) {}\n\n  /// Set this point to all zeros.\n  void set_zero()\n  {\n    x = 0.0;\n    y = 0.0;\n  }\n\n  /// Set this point to some specified coordinates.\n  void set(double x_, double y_)\n  {\n    x = x_;\n    y = y_;\n  }\n\n  /// Negate this point.\n  Point operator -() const\n  {\n    Point v;\n    v.set(-x, -y);\n    return v;\n  }\n\n  /// Add a point to this point.\n  void operator +=(const Point& v)\n  {\n    x += v.x;\n    y += v.y;\n  }\n\n  /// Subtract a point from this point.\n  void operator -=(const Point& v)\n  {\n    x -= v.x;\n    y -= v.y;\n  }\n\n  /// Multiply this point by a scalar.\n  void operator *=(double a)\n  {\n    x *= a;\n    y *= a;\n  }\n\n  /// Get the length of this point (the norm).\n  double Length() const\n  {\n    return sqrt(x * x + y * y);\n  }\n\n  /// Convert this point into a unit point. Returns the Length.\n  double Normalize()\n  {\n    double len = Length();\n    x /= len;\n    y /= len;\n    return len;\n  }\n\n};\n\n// Represents a simple polygon's edge\nstruct Edge {\n\n  Point* p, *q;\n\n  /// Constructor\n  Edge(Point& p1, Point& p2) : p(&p1), q(&p2)\n  {\n    if (p1.y > p2.y) {\n      q = &p1;\n      p = &p2;\n    } else if (p1.y == p2.y) {\n      if (p1.x > p2.x) {\n        q = &p1;\n        p = &p2;\n      } else if (p1.x == p2.x) {\n        // Repeat points\n        assert(false);\n      }\n    }\n\n    q->edge_list.push_back(this);\n  }\n};\n\n// Triangle-based data structures are know to have better performance than quad-edge structures\n// See: J. Shewchuk, \"Triangle: Engineering a 2D Quality Mesh Generator and Delaunay Triangulator\"\n//      \"Triangulations in CGAL\"\nclass Triangle {\npublic:\n\n/// Constructor\nTriangle(Point& a, Point& b, Point& c);\n\n/// Flags to determine if an edge is a Constrained edge\nbool constrained_edge[3];\n/// Flags to determine if an edge is a Delauney edge\nbool delaunay_edge[3];\n\nPoint* GetPoint(const int& index);\nPoint* PointCW(Point& point);\nPoint* PointCCW(Point& point);\nPoint* OppositePoint(Triangle& t, Point& p);\n\nTriangle* GetNeighbor(const int& index);\nvoid MarkNeighbor(Point* p1, Point* p2, Triangle* t);\nvoid MarkNeighbor(Triangle& t);\n\nvoid MarkConstrainedEdge(const int index);\nvoid MarkConstrainedEdge(Edge& edge);\nvoid MarkConstrainedEdge(Point* p, Point* q);\n\nint Index(const Point* p);\nint EdgeIndex(const Point* p1, const Point* p2);\n\nTriangle* NeighborCW(Point& point);\nTriangle* NeighborCCW(Point& point);\nbool GetConstrainedEdgeCCW(Point& p);\nbool GetConstrainedEdgeCW(Point& p);\nvoid SetConstrainedEdgeCCW(Point& p, bool ce);\nvoid SetConstrainedEdgeCW(Point& p, bool ce);\nbool GetDelunayEdgeCCW(Point& p);\nbool GetDelunayEdgeCW(Point& p);\nvoid SetDelunayEdgeCCW(Point& p, bool e);\nvoid SetDelunayEdgeCW(Point& p, bool e);\n\nbool Contains(Point* p);\nbool Contains(const Edge& e);\nbool Contains(Point* p, Point* q);\nvoid Legalize(Point& point);\nvoid Legalize(Point& opoint, Point& npoint);\n/**\n * Clears all references to all other triangles and points\n */\nvoid Clear();\nvoid ClearNeighbor(Triangle *triangle );\nvoid ClearNeighbors();\nvoid ClearDelunayEdges();\n\ninline bool IsInterior();\ninline void IsInterior(bool b);\n\nTriangle& NeighborAcross(Point& opoint);\n\nvoid DebugPrint();\n\nprivate:\n\n/// Triangle points\nPoint* points_[3];\n/// Neighbor list\nTriangle* neighbors_[3];\n\n/// Has this triangle been marked as an interior triangle?\nbool interior_;\n};\n\ninline bool cmp(const Point* a, const Point* b)\n{\n  if (a->y < b->y) {\n    return true;\n  } else if (a->y == b->y) {\n    // Make sure q is point with greater x value\n    if (a->x < b->x) {\n      return true;\n    }\n  }\n  return false;\n}\n\n/// Add two points_ component-wise.\ninline Point operator +(const Point& a, const Point& b)\n{\n  return Point(a.x + b.x, a.y + b.y);\n}\n\n/// Subtract two points_ component-wise.\ninline Point operator -(const Point& a, const Point& b)\n{\n  return Point(a.x - b.x, a.y - b.y);\n}\n\n/// Multiply point by scalar\ninline Point operator *(double s, const Point& a)\n{\n  return Point(s * a.x, s * a.y);\n}\n\ninline bool operator ==(const Point& a, const Point& b)\n{\n  return a.x == b.x && a.y == b.y;\n}\n\ninline bool operator !=(const Point& a, const Point& b)\n{\n  return !(a.x == b.x) || !(a.y == b.y);\n}\n\n/// Peform the dot product on two vectors.\ninline double Dot(const Point& a, const Point& b)\n{\n  return a.x * b.x + a.y * b.y;\n}\n\n/// Perform the cross product on two vectors. In 2D this produces a scalar.\ninline double Cross(const Point& a, const Point& b)\n{\n  return a.x * b.y - a.y * b.x;\n}\n\n/// Perform the cross product on a point and a scalar. In 2D this produces\n/// a point.\ninline Point Cross(const Point& a, double s)\n{\n  return Point(s * a.y, -s * a.x);\n}\n\n/// Perform the cross product on a scalar and a point. In 2D this produces\n/// a point.\ninline Point Cross(const double s, const Point& a)\n{\n  return Point(-s * a.y, s * a.x);\n}\n\ninline Point* Triangle::GetPoint(const int& index)\n{\n  return points_[index];\n}\n\ninline Triangle* Triangle::GetNeighbor(const int& index)\n{\n  return neighbors_[index];\n}\n\ninline bool Triangle::Contains(Point* p)\n{\n  return p == points_[0] || p == points_[1] || p == points_[2];\n}\n\ninline bool Triangle::Contains(const Edge& e)\n{\n  return Contains(e.p) && Contains(e.q);\n}\n\ninline bool Triangle::Contains(Point* p, Point* q)\n{\n  return Contains(p) && Contains(q);\n}\n\ninline bool Triangle::IsInterior()\n{\n  return interior_;\n}\n\ninline void Triangle::IsInterior(bool b)\n{\n  interior_ = b;\n}\n\n}\n\n#endif\n\n\n"
  },
  {
    "path": "poly2tri/common/utils.h",
    "content": "/* \r\n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\r\n * http://code.google.com/p/poly2tri/\r\n *\r\n * All rights reserved.\r\n *\r\n * Redistribution and use in source and binary forms, with or without modification,\r\n * are permitted provided that the following conditions are met:\r\n *\r\n * * Redistributions of source code must retain the above copyright notice,\r\n *   this list of conditions and the following disclaimer.\r\n * * Redistributions in binary form must reproduce the above copyright notice,\r\n *   this list of conditions and the following disclaimer in the documentation\r\n *   and/or other materials provided with the distribution.\r\n * * Neither the name of Poly2Tri nor the names of its contributors may be\r\n *   used to endorse or promote products derived from this software without specific\r\n *   prior written permission.\r\n *\r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n */\r\n \r\n#ifndef UTILS_H\r\n#define UTILS_H\r\n\r\n// Otherwise #defines like M_PI are undeclared under Visual Studio\r\n#define _USE_MATH_DEFINES\r\n\r\n#include <exception>\r\n#include <math.h>\r\n\r\nnamespace p2t {\r\n\r\nconst double PI_3div4 = 3 * M_PI / 4;\r\nconst double PI_div2 = 1.57079632679489661923;\r\nconst double EPSILON = 1e-12;\r\n\r\nenum Orientation { CW, CCW, COLLINEAR };\r\n\r\n/**\r\n * Forumla to calculate signed area<br>\r\n * Positive if CCW<br>\r\n * Negative if CW<br>\r\n * 0 if collinear<br>\r\n * <pre>\r\n * A[P1,P2,P3]  =  (x1*y2 - y1*x2) + (x2*y3 - y2*x3) + (x3*y1 - y3*x1)\r\n *              =  (x1-x3)*(y2-y3) - (y1-y3)*(x2-x3)\r\n * </pre>\r\n */\r\nOrientation Orient2d(Point& pa, Point& pb, Point& pc)\r\n{\r\n  double detleft = (pa.x - pc.x) * (pb.y - pc.y);\r\n  double detright = (pa.y - pc.y) * (pb.x - pc.x);\r\n  double val = detleft - detright;\r\n  if (val > -EPSILON && val < EPSILON) {\r\n    return COLLINEAR;\r\n  } else if (val > 0) {\r\n    return CCW;\r\n  }\r\n  return CW;\r\n}\r\n\r\n/*\r\nbool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)\r\n{\r\n  double pdx = pd.x;\r\n  double pdy = pd.y;\r\n  double adx = pa.x - pdx;\r\n  double ady = pa.y - pdy;\r\n  double bdx = pb.x - pdx;\r\n  double bdy = pb.y - pdy;\r\n\r\n  double adxbdy = adx * bdy;\r\n  double bdxady = bdx * ady;\r\n  double oabd = adxbdy - bdxady;\r\n\r\n  if (oabd <= EPSILON) {\r\n    return false;\r\n  }\r\n\r\n  double cdx = pc.x - pdx;\r\n  double cdy = pc.y - pdy;\r\n\r\n  double cdxady = cdx * ady;\r\n  double adxcdy = adx * cdy;\r\n  double ocad = cdxady - adxcdy;\r\n\r\n  if (ocad <= EPSILON) {\r\n    return false;\r\n  }\r\n\r\n  return true;\r\n}\r\n\r\n*/\r\n\r\nbool InScanArea(Point& pa, Point& pb, Point& pc, Point& pd)\r\n{\r\n  double oadb = (pa.x - pb.x)*(pd.y - pb.y) - (pd.x - pb.x)*(pa.y - pb.y);\r\n  if (oadb >= -EPSILON) {\r\n    return false;\r\n  }\r\n\r\n  double oadc = (pa.x - pc.x)*(pd.y - pc.y) - (pd.x - pc.x)*(pa.y - pc.y);\r\n  if (oadc <= EPSILON) {\r\n    return false;\r\n  }\r\n  return true;\r\n}\r\n\r\n}\r\n\r\n#endif\r\n\r\n"
  },
  {
    "path": "poly2tri/poly2tri.h",
    "content": "/* \n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\n * http://code.google.com/p/poly2tri/\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n * * Redistributions of source code must retain the above copyright notice,\n *   this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n *   this list of conditions and the following disclaimer in the documentation\n *   and/or other materials provided with the distribution.\n * * Neither the name of Poly2Tri nor the names of its contributors may be\n *   used to endorse or promote products derived from this software without specific\n *   prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef POLY2TRI_H\n#define POLY2TRI_H\n\n#include \"common/shapes.h\"\n#include \"sweep/cdt.h\"\n\n#endif\n\n"
  },
  {
    "path": "poly2tri/sweep/advancing_front.cc",
    "content": "/*\n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\n * http://code.google.com/p/poly2tri/\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n * * Redistributions of source code must retain the above copyright notice,\n *   this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n *   this list of conditions and the following disclaimer in the documentation\n *   and/or other materials provided with the distribution.\n * * Neither the name of Poly2Tri nor the names of its contributors may be\n *   used to endorse or promote products derived from this software without specific\n *   prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"advancing_front.h\"\n\nnamespace p2t {\n\nAdvancingFront::AdvancingFront(Node& head, Node& tail)\n{\n  head_ = &head;\n  tail_ = &tail;\n  search_node_ = &head;\n}\n\nNode* AdvancingFront::LocateNode(const double& x)\n{\n  Node* node = search_node_;\n\n  if (x < node->value) {\n    while ((node = node->prev) != NULL) {\n      if (x >= node->value) {\n        search_node_ = node;\n        return node;\n      }\n    }\n  } else {\n    while ((node = node->next) != NULL) {\n      if (x < node->value) {\n        search_node_ = node->prev;\n        return node->prev;\n      }\n    }\n  }\n  return NULL;\n}\n\nNode* AdvancingFront::FindSearchNode(const double& x)\n{\n  (void)x; // suppress compiler warnings \"unused parameter 'x'\"\n  // TODO: implement BST index\n  return search_node_;\n}\n\nNode* AdvancingFront::LocatePoint(const Point* point)\n{\n  const double px = point->x;\n  Node* node = FindSearchNode(px);\n  const double nx = node->point->x;\n\n  if (px == nx) {\n    if (point != node->point) {\n      // We might have two nodes with same x value for a short time\n      if (point == node->prev->point) {\n        node = node->prev;\n      } else if (point == node->next->point) {\n        node = node->next;\n      } else {\n        assert(0);\n      }\n    }\n  } else if (px < nx) {\n    while ((node = node->prev) != NULL) {\n      if (point == node->point) {\n        break;\n      }\n    }\n  } else {\n    while ((node = node->next) != NULL) {\n      if (point == node->point)\n        break;\n    }\n  }\n  if(node) search_node_ = node;\n  return node;\n}\n\nAdvancingFront::~AdvancingFront()\n{\n}\n\n}\n\n"
  },
  {
    "path": "poly2tri/sweep/advancing_front.h",
    "content": "/*\n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\n * http://code.google.com/p/poly2tri/\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n * * Redistributions of source code must retain the above copyright notice,\n *   this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n *   this list of conditions and the following disclaimer in the documentation\n *   and/or other materials provided with the distribution.\n * * Neither the name of Poly2Tri nor the names of its contributors may be\n *   used to endorse or promote products derived from this software without specific\n *   prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n#ifndef ADVANCED_FRONT_H\n#define ADVANCED_FRONT_H\n\n#include \"../common/shapes.h\"\n\nnamespace p2t {\n\nstruct Node;\n\n// Advancing front node\nstruct Node {\n  Point* point;\n  Triangle* triangle;\n\n  Node* next;\n  Node* prev;\n\n  double value;\n\n  Node(Point& p) : point(&p), triangle(NULL), next(NULL), prev(NULL), value(p.x)\n  {\n  }\n\n  Node(Point& p, Triangle& t) : point(&p), triangle(&t), next(NULL), prev(NULL), value(p.x)\n  {\n  }\n\n};\n\n// Advancing front\nclass AdvancingFront {\npublic:\n\nAdvancingFront(Node& head, Node& tail);\n// Destructor\n~AdvancingFront();\n\nNode* head();\nvoid set_head(Node* node);\nNode* tail();\nvoid set_tail(Node* node);\nNode* search();\nvoid set_search(Node* node);\n\n/// Locate insertion point along advancing front\nNode* LocateNode(const double& x);\n\nNode* LocatePoint(const Point* point);\n\nprivate:\n\nNode* head_, *tail_, *search_node_;\n\nNode* FindSearchNode(const double& x);\n};\n\ninline Node* AdvancingFront::head()\n{\n  return head_;\n}\ninline void AdvancingFront::set_head(Node* node)\n{\n  head_ = node;\n}\n\ninline Node* AdvancingFront::tail()\n{\n  return tail_;\n}\ninline void AdvancingFront::set_tail(Node* node)\n{\n  tail_ = node;\n}\n\ninline Node* AdvancingFront::search()\n{\n  return search_node_;\n}\n\ninline void AdvancingFront::set_search(Node* node)\n{\n  search_node_ = node;\n}\n\n}\n\n#endif\n"
  },
  {
    "path": "poly2tri/sweep/cdt.cc",
    "content": "/* \r\n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\r\n * http://code.google.com/p/poly2tri/\r\n *\r\n * All rights reserved.\r\n *\r\n * Redistribution and use in source and binary forms, with or without modification,\r\n * are permitted provided that the following conditions are met:\r\n *\r\n * * Redistributions of source code must retain the above copyright notice,\r\n *   this list of conditions and the following disclaimer.\r\n * * Redistributions in binary form must reproduce the above copyright notice,\r\n *   this list of conditions and the following disclaimer in the documentation\r\n *   and/or other materials provided with the distribution.\r\n * * Neither the name of Poly2Tri nor the names of its contributors may be\r\n *   used to endorse or promote products derived from this software without specific\r\n *   prior written permission.\r\n *\r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n */\r\n#include \"cdt.h\"\r\n\r\nnamespace p2t {\r\n\r\nCDT::CDT(std::vector<Point*> polyline)\r\n{\r\n  sweep_context_ = new SweepContext(polyline);\r\n  sweep_ = new Sweep;\r\n}\r\n\r\nvoid CDT::AddHole(std::vector<Point*> polyline)\r\n{\r\n  sweep_context_->AddHole(polyline);\r\n}\r\n\r\nvoid CDT::AddPoint(Point* point) {\r\n  sweep_context_->AddPoint(point);\r\n}\r\n\r\nvoid CDT::Triangulate()\r\n{\r\n  sweep_->Triangulate(*sweep_context_);\r\n}\r\n\r\nstd::vector<p2t::Triangle*> CDT::GetTriangles()\r\n{\r\n  return sweep_context_->GetTriangles();\r\n}\r\n\r\nstd::list<p2t::Triangle*> CDT::GetMap()\r\n{\r\n  return sweep_context_->GetMap();\r\n}\r\n\r\nCDT::~CDT()\r\n{\r\n  delete sweep_context_;\r\n  delete sweep_;\r\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "poly2tri/sweep/cdt.h",
    "content": "/* \r\n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\r\n * http://code.google.com/p/poly2tri/\r\n *\r\n * All rights reserved.\r\n *\r\n * Redistribution and use in source and binary forms, with or without modification,\r\n * are permitted provided that the following conditions are met:\r\n *\r\n * * Redistributions of source code must retain the above copyright notice,\r\n *   this list of conditions and the following disclaimer.\r\n * * Redistributions in binary form must reproduce the above copyright notice,\r\n *   this list of conditions and the following disclaimer in the documentation\r\n *   and/or other materials provided with the distribution.\r\n * * Neither the name of Poly2Tri nor the names of its contributors may be\r\n *   used to endorse or promote products derived from this software without specific\r\n *   prior written permission.\r\n *\r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n */\r\n \r\n#ifndef CDT_H\r\n#define CDT_H\r\n\r\n#include \"advancing_front.h\"\r\n#include \"sweep_context.h\"\r\n#include \"sweep.h\"\r\n\r\n/**\r\n * \r\n * @author Mason Green <mason.green@gmail.com>\r\n *\r\n */\r\n \r\nnamespace p2t {\r\n\r\nclass CDT\r\n{\r\npublic:\r\n\r\n  /**\r\n   * Constructor - add polyline with non repeating points\r\n   * \r\n   * @param polyline\r\n   */\r\n  CDT(std::vector<Point*> polyline);\r\n  \r\n   /**\r\n   * Destructor - clean up memory\r\n   */\r\n  ~CDT();\r\n  \r\n  /**\r\n   * Add a hole\r\n   * \r\n   * @param polyline\r\n   */\r\n  void AddHole(std::vector<Point*> polyline);\r\n  \r\n  /**\r\n   * Add a steiner point\r\n   * \r\n   * @param point\r\n   */\r\n  void AddPoint(Point* point);\r\n  \r\n  /**\r\n   * Triangulate - do this AFTER you've added the polyline, holes, and Steiner points\r\n   */\r\n  void Triangulate();\r\n  \r\n  /**\r\n   * Get CDT triangles\r\n   */\r\n  std::vector<Triangle*> GetTriangles();\r\n  \r\n  /**\r\n   * Get triangle map\r\n   */\r\n  std::list<Triangle*> GetMap();\r\n\r\n  private:\r\n\r\n  /**\r\n   * Internals\r\n   */\r\n   \r\n  SweepContext* sweep_context_;\r\n  Sweep* sweep_;\r\n\r\n};\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "poly2tri/sweep/sweep.cc",
    "content": "/*\r\n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\r\n * http://code.google.com/p/poly2tri/\r\n *\r\n * All rights reserved.\r\n *\r\n * Redistribution and use in source and binary forms, with or without modification,\r\n * are permitted provided that the following conditions are met:\r\n *\r\n * * Redistributions of source code must retain the above copyright notice,\r\n *   this list of conditions and the following disclaimer.\r\n * * Redistributions in binary form must reproduce the above copyright notice,\r\n *   this list of conditions and the following disclaimer in the documentation\r\n *   and/or other materials provided with the distribution.\r\n * * Neither the name of Poly2Tri nor the names of its contributors may be\r\n *   used to endorse or promote products derived from this software without specific\r\n *   prior written permission.\r\n *\r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n */\r\n#include <stdexcept>\r\n#include \"sweep.h\"\r\n#include \"sweep_context.h\"\r\n#include \"advancing_front.h\"\r\n#include \"../common/utils.h\"\r\n\r\nnamespace p2t {\r\n\r\n// Triangulate simple polygon with holes\r\nvoid Sweep::Triangulate(SweepContext& tcx)\r\n{\r\n  tcx.InitTriangulation();\r\n  tcx.CreateAdvancingFront(nodes_);\r\n  // Sweep points; build mesh\r\n  SweepPoints(tcx);\r\n  // Clean up\r\n  FinalizationPolygon(tcx);\r\n}\r\n\r\nvoid Sweep::SweepPoints(SweepContext& tcx)\r\n{\r\n  for (int i = 1; i < tcx.point_count(); i++) {\r\n    Point& point = *tcx.GetPoint(i);\r\n    Node* node = &PointEvent(tcx, point);\r\n    for (unsigned int i = 0; i < point.edge_list.size(); i++) {\r\n      EdgeEvent(tcx, point.edge_list[i], node);\r\n    }\r\n  }\r\n}\r\n\r\nvoid Sweep::FinalizationPolygon(SweepContext& tcx)\r\n{\r\n  // Get an Internal triangle to start with\r\n  Triangle* t = tcx.front()->head()->next->triangle;\r\n  Point* p = tcx.front()->head()->next->point;\r\n  while (!t->GetConstrainedEdgeCW(*p)) {\r\n    t = t->NeighborCCW(*p);\r\n  }\r\n\r\n  // Collect interior triangles constrained by edges\r\n  tcx.MeshClean(*t);\r\n}\r\n\r\nNode& Sweep::PointEvent(SweepContext& tcx, Point& point)\r\n{\r\n  Node& node = tcx.LocateNode(point);\r\n  Node& new_node = NewFrontTriangle(tcx, point, node);\r\n\r\n  // Only need to check +epsilon since point never have smaller\r\n  // x value than node due to how we fetch nodes from the front\r\n  if (point.x <= node.point->x + EPSILON) {\r\n    Fill(tcx, node);\r\n  }\r\n\r\n  //tcx.AddNode(new_node);\r\n\r\n  FillAdvancingFront(tcx, new_node);\r\n  return new_node;\r\n}\r\n\r\nvoid Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node)\r\n{\r\n  tcx.edge_event.constrained_edge = edge;\r\n  tcx.edge_event.right = (edge->p->x > edge->q->x);\r\n\r\n  if (IsEdgeSideOfTriangle(*node->triangle, *edge->p, *edge->q)) {\r\n    return;\r\n  }\r\n\r\n  // For now we will do all needed filling\r\n  // TODO: integrate with flip process might give some better performance\r\n  //       but for now this avoid the issue with cases that needs both flips and fills\r\n  FillEdgeEvent(tcx, edge, node);\r\n  EdgeEvent(tcx, *edge->p, *edge->q, node->triangle, *edge->q);\r\n}\r\n\r\nvoid Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point)\r\n{\r\n  if (IsEdgeSideOfTriangle(*triangle, ep, eq)) {\r\n    return;\r\n  }\r\n\r\n  Point* p1 = triangle->PointCCW(point);\r\n  Orientation o1 = Orient2d(eq, *p1, ep);\r\n  if (o1 == COLLINEAR) {\r\n    if( triangle->Contains(&eq, p1)) {\r\n      triangle->MarkConstrainedEdge(&eq, p1 );\r\n      // We are modifying the constraint maybe it would be better to \r\n      // not change the given constraint and just keep a variable for the new constraint\r\n      tcx.edge_event.constrained_edge->q = p1;\r\n      triangle = &triangle->NeighborAcross(point);\r\n      EdgeEvent( tcx, ep, *p1, triangle, *p1 );\r\n    } else {\r\n      std::runtime_error(\"EdgeEvent - collinear points not supported\");\r\n      assert(0);\r\n    }\r\n    return;\r\n  }\r\n\r\n  Point* p2 = triangle->PointCW(point);\r\n  Orientation o2 = Orient2d(eq, *p2, ep);\r\n  if (o2 == COLLINEAR) {\r\n    if( triangle->Contains(&eq, p2)) {\r\n      triangle->MarkConstrainedEdge(&eq, p2 );\r\n      // We are modifying the constraint maybe it would be better to \r\n      // not change the given constraint and just keep a variable for the new constraint\r\n      tcx.edge_event.constrained_edge->q = p2;\r\n      triangle = &triangle->NeighborAcross(point);\r\n      EdgeEvent( tcx, ep, *p2, triangle, *p2 );\r\n    } else {\r\n      std::runtime_error(\"EdgeEvent - collinear points not supported\");\r\n      assert(0);\r\n    }\r\n    return;\r\n  }\r\n\r\n  if (o1 == o2) {\r\n    // Need to decide if we are rotating CW or CCW to get to a triangle\r\n    // that will cross edge\r\n    if (o1 == CW) {\r\n      triangle = triangle->NeighborCCW(point);\r\n    }       else{\r\n      triangle = triangle->NeighborCW(point);\r\n    }\r\n    EdgeEvent(tcx, ep, eq, triangle, point);\r\n  } else {\r\n    // This triangle crosses constraint so lets flippin start!\r\n    FlipEdgeEvent(tcx, ep, eq, triangle, point);\r\n  }\r\n}\r\n\r\nbool Sweep::IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq)\r\n{\r\n  int index = triangle.EdgeIndex(&ep, &eq);\r\n\r\n  if (index != -1) {\r\n    triangle.MarkConstrainedEdge(index);\r\n    Triangle* t = triangle.GetNeighbor(index);\r\n    if (t) {\r\n      t->MarkConstrainedEdge(&ep, &eq);\r\n    }\r\n    return true;\r\n  }\r\n  return false;\r\n}\r\n\r\nNode& Sweep::NewFrontTriangle(SweepContext& tcx, Point& point, Node& node)\r\n{\r\n  Triangle* triangle = new Triangle(point, *node.point, *node.next->point);\r\n\r\n  triangle->MarkNeighbor(*node.triangle);\r\n  tcx.AddToMap(triangle);\r\n\r\n  Node* new_node = new Node(point);\r\n  nodes_.push_back(new_node);\r\n\r\n  new_node->next = node.next;\r\n  new_node->prev = &node;\r\n  node.next->prev = new_node;\r\n  node.next = new_node;\n\r\n  if (!Legalize(tcx, *triangle)) {\r\n    tcx.MapTriangleToNodes(*triangle);\r\n  }\r\n\r\n  return *new_node;\r\n}\r\n\r\nvoid Sweep::Fill(SweepContext& tcx, Node& node)\r\n{\r\n  Triangle* triangle = new Triangle(*node.prev->point, *node.point, *node.next->point);\r\n\r\n  // TODO: should copy the constrained_edge value from neighbor triangles\r\n  //       for now constrained_edge values are copied during the legalize\r\n  triangle->MarkNeighbor(*node.prev->triangle);\r\n  triangle->MarkNeighbor(*node.triangle);\r\n\r\n  tcx.AddToMap(triangle);\r\n\r\n  // Update the advancing front\r\n  node.prev->next = node.next;\r\n  node.next->prev = node.prev;\n\r\n  // If it was legalized the triangle has already been mapped\r\n  if (!Legalize(tcx, *triangle)) {\r\n    tcx.MapTriangleToNodes(*triangle);\r\n  }\r\n\r\n}\r\n\r\nvoid Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)\r\n{\n\r\n  // Fill right holes\r\n  Node* node = n.next;\r\n\r\n  while (node->next) {\r\n    // if HoleAngle exceeds 90 degrees then break.\r\n    if (LargeHole_DontFill(node)) break;\r\n    Fill(tcx, *node);\r\n    node = node->next;\r\n  }\r\n\r\n  // Fill left holes\r\n  node = n.prev;\r\n\r\n  while (node->prev) {\r\n    // if HoleAngle exceeds 90 degrees then break.\r\n    if (LargeHole_DontFill(node)) break;\r\n    Fill(tcx, *node);\r\n    node = node->prev;\r\n  }\r\n\r\n  // Fill right basins\r\n  if (n.next && n.next->next) {\r\n    double angle = BasinAngle(n);\r\n    if (angle < PI_3div4) {\r\n      FillBasin(tcx, n);\r\n    }\r\n  }\r\n}\r\n\r\n// True if HoleAngle exceeds 90 degrees.\r\n// LargeHole_DontFill checks if the advancing front has a large hole.\r\n// A \"Large hole\" is a triangle formed by a sequence of points in the advancing\r\n// front where three neighbor points form a triangle.\r\n// And angle between left-top, bottom, and right-top points is more than 90 degrees.\r\n// The first part of the algorithm reviews only three neighbor points, e.g. named A, B, C.\r\n// Additional part of this logic reviews a sequence of 5 points -\r\n// additionally reviews one point before and one after the sequence of three (A, B, C),\r\n// e.g. named X and Y.\r\n// In this case, angles are XBC and ABY and this if angles are negative or more\r\n// than 90 degrees LargeHole_DontFill returns true.\r\n// But there is a configuration when ABC has a negative angle but XBC or ABY is less\r\n// than 90 degrees and positive.\r\n// Then function LargeHole_DontFill return false and initiates filling.\r\n// This filling creates a triangle ABC and adds it to the advancing front.\r\n// But in the case when angle ABC is negative this triangle goes inside the advancing front\r\n// and can intersect previously created triangles.\r\n// This triangle leads to making wrong advancing front and problems in triangulation in the future.\r\n// Looks like such a triangle should not be created.\r\n// The simplest way to check and fix it is to check an angle ABC.\r\n// If it is negative LargeHole_DontFill should return true and\r\n// not initiate creating the ABC triangle in the advancing front.\r\n// X______A         Y\r\n//        \\        /\r\n//         \\      /\r\n//          \\ B  /\r\n//           |  /\r\n//           | /\r\n//           |/\r\n//           C\r\nbool Sweep::LargeHole_DontFill(Node* node) {\r\n  \r\n  Node* nextNode = node->next;\r\n  Node* prevNode = node->prev;\r\n  if (!AngleExceeds90Degrees(node->point, nextNode->point, prevNode->point))\r\n          return false;\r\n\r\n  if (AngleIsNegative(node->point, nextNode->point, prevNode->point))\r\n          return true;\r\n\r\n  // Check additional points on front.\r\n  Node* next2Node = nextNode->next;\r\n  // \"..Plus..\" because only want angles on same side as point being added.\r\n  if ((next2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, next2Node->point, prevNode->point))\r\n          return false;\r\n\r\n  Node* prev2Node = prevNode->prev;\r\n  // \"..Plus..\" because only want angles on same side as point being added.\r\n  if ((prev2Node != NULL) && !AngleExceedsPlus90DegreesOrIsNegative(node->point, nextNode->point, prev2Node->point))\r\n          return false;\r\n\r\n  return true;\r\n}\r\n\r\nbool Sweep::AngleIsNegative(Point* origin, Point* pa, Point* pb) {\n    const double angle = Angle(*origin, *pa, *pb);\n    return angle < 0;\r\n}\r\n\r\nbool Sweep::AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb) {\r\n  double angle = Angle(*origin, *pa, *pb);\r\n  bool exceeds90Degrees = ((angle > PI_div2) || (angle < -PI_div2));\r\n  return exceeds90Degrees;\r\n}\r\n\r\nbool Sweep::AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb) {\r\n  double angle = Angle(*origin, *pa, *pb);\r\n  bool exceedsPlus90DegreesOrIsNegative = (angle > PI_div2) || (angle < 0);\r\n  return exceedsPlus90DegreesOrIsNegative;\r\n}\r\n\r\ndouble Sweep::Angle(Point& origin, Point& pa, Point& pb) {\r\n  /* Complex plane\r\n   * ab = cosA +i*sinA\r\n   * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)\r\n   * atan2(y,x) computes the principal value of the argument function\r\n   * applied to the complex number x+iy\r\n   * Where x = ax*bx + ay*by\r\n   *       y = ax*by - ay*bx\r\n   */\r\n  double px = origin.x;\r\n  double py = origin.y;\r\n  double ax = pa.x- px;\r\n  double ay = pa.y - py;\r\n  double bx = pb.x - px;\r\n  double by = pb.y - py;\r\n  double x = ax * by - ay * bx;\r\n  double y = ax * bx + ay * by;\r\n  double angle = atan2(x, y);\r\n  return angle;\r\n}\r\n\r\ndouble Sweep::BasinAngle(Node& node)\r\n{\r\n  double ax = node.point->x - node.next->next->point->x;\r\n  double ay = node.point->y - node.next->next->point->y;\r\n  return atan2(ay, ax);\r\n}\r\n\r\ndouble Sweep::HoleAngle(Node& node)\r\n{\r\n  /* Complex plane\r\n   * ab = cosA +i*sinA\r\n   * ab = (ax + ay*i)(bx + by*i) = (ax*bx + ay*by) + i(ax*by-ay*bx)\r\n   * atan2(y,x) computes the principal value of the argument function\r\n   * applied to the complex number x+iy\r\n   * Where x = ax*bx + ay*by\r\n   *       y = ax*by - ay*bx\r\n   */\r\n  double ax = node.next->point->x - node.point->x;\r\n  double ay = node.next->point->y - node.point->y;\r\n  double bx = node.prev->point->x - node.point->x;\r\n  double by = node.prev->point->y - node.point->y;\r\n  return atan2(ax * by - ay * bx, ax * bx + ay * by);\r\n}\r\n\r\nbool Sweep::Legalize(SweepContext& tcx, Triangle& t)\r\n{\r\n  // To legalize a triangle we start by finding if any of the three edges\r\n  // violate the Delaunay condition\r\n  for (int i = 0; i < 3; i++) {\r\n    if (t.delaunay_edge[i])\r\n      continue;\r\n\r\n    Triangle* ot = t.GetNeighbor(i);\r\n\r\n    if (ot) {\r\n      Point* p = t.GetPoint(i);\r\n      Point* op = ot->OppositePoint(t, *p);\r\n      int oi = ot->Index(op);\r\n\r\n      // If this is a Constrained Edge or a Delaunay Edge(only during recursive legalization)\r\n      // then we should not try to legalize\r\n      if (ot->constrained_edge[oi] || ot->delaunay_edge[oi]) {\r\n        t.constrained_edge[i] = ot->constrained_edge[oi];\r\n        continue;\r\n      }\r\n\r\n      bool inside = Incircle(*p, *t.PointCCW(*p), *t.PointCW(*p), *op);\r\n\r\n      if (inside) {\r\n        // Lets mark this shared edge as Delaunay\r\n        t.delaunay_edge[i] = true;\r\n        ot->delaunay_edge[oi] = true;\r\n\r\n        // Lets rotate shared edge one vertex CW to legalize it\r\n        RotateTrianglePair(t, *p, *ot, *op);\r\n\r\n        // We now got one valid Delaunay Edge shared by two triangles\r\n        // This gives us 4 new edges to check for Delaunay\r\n\r\n        // Make sure that triangle to node mapping is done only one time for a specific triangle\r\n        bool not_legalized = !Legalize(tcx, t);\r\n        if (not_legalized) {\r\n          tcx.MapTriangleToNodes(t);\r\n        }\r\n\r\n        not_legalized = !Legalize(tcx, *ot);\r\n        if (not_legalized)\r\n          tcx.MapTriangleToNodes(*ot);\r\n\r\n        // Reset the Delaunay edges, since they only are valid Delaunay edges\r\n        // until we add a new triangle or point.\r\n        // XXX: need to think about this. Can these edges be tried after we\r\n        //      return to previous recursive level?\r\n        t.delaunay_edge[i] = false;\r\n        ot->delaunay_edge[oi] = false;\r\n\r\n        // If triangle have been legalized no need to check the other edges since\r\n        // the recursive legalization will handles those so we can end here.\r\n        return true;\r\n      }\r\n    }\r\n  }\r\n  return false;\r\n}\r\n\r\nbool Sweep::Incircle(Point& pa, Point& pb, Point& pc, Point& pd)\r\n{\r\n  double adx = pa.x - pd.x;\r\n  double ady = pa.y - pd.y;\r\n  double bdx = pb.x - pd.x;\r\n  double bdy = pb.y - pd.y;\r\n\r\n  double adxbdy = adx * bdy;\r\n  double bdxady = bdx * ady;\r\n  double oabd = adxbdy - bdxady;\r\n\r\n  if (oabd <= 0)\r\n    return false;\r\n\r\n  double cdx = pc.x - pd.x;\r\n  double cdy = pc.y - pd.y;\r\n\r\n  double cdxady = cdx * ady;\r\n  double adxcdy = adx * cdy;\r\n  double ocad = cdxady - adxcdy;\r\n\r\n  if (ocad <= 0)\r\n    return false;\r\n\r\n  double bdxcdy = bdx * cdy;\r\n  double cdxbdy = cdx * bdy;\r\n\r\n  double alift = adx * adx + ady * ady;\r\n  double blift = bdx * bdx + bdy * bdy;\r\n  double clift = cdx * cdx + cdy * cdy;\r\n\r\n  double det = alift * (bdxcdy - cdxbdy) + blift * ocad + clift * oabd;\r\n\r\n  return det > 0;\r\n}\r\n\r\nvoid Sweep::RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op)\r\n{\r\n  Triangle* n1, *n2, *n3, *n4;\r\n  n1 = t.NeighborCCW(p);\r\n  n2 = t.NeighborCW(p);\r\n  n3 = ot.NeighborCCW(op);\r\n  n4 = ot.NeighborCW(op);\r\n\r\n  bool ce1, ce2, ce3, ce4;\r\n  ce1 = t.GetConstrainedEdgeCCW(p);\r\n  ce2 = t.GetConstrainedEdgeCW(p);\r\n  ce3 = ot.GetConstrainedEdgeCCW(op);\r\n  ce4 = ot.GetConstrainedEdgeCW(op);\r\n\r\n  bool de1, de2, de3, de4;\r\n  de1 = t.GetDelunayEdgeCCW(p);\r\n  de2 = t.GetDelunayEdgeCW(p);\r\n  de3 = ot.GetDelunayEdgeCCW(op);\r\n  de4 = ot.GetDelunayEdgeCW(op);\r\n\r\n  t.Legalize(p, op);\r\n  ot.Legalize(op, p);\r\n\r\n  // Remap delaunay_edge\r\n  ot.SetDelunayEdgeCCW(p, de1);\r\n  t.SetDelunayEdgeCW(p, de2);\r\n  t.SetDelunayEdgeCCW(op, de3);\r\n  ot.SetDelunayEdgeCW(op, de4);\r\n\r\n  // Remap constrained_edge\r\n  ot.SetConstrainedEdgeCCW(p, ce1);\r\n  t.SetConstrainedEdgeCW(p, ce2);\r\n  t.SetConstrainedEdgeCCW(op, ce3);\r\n  ot.SetConstrainedEdgeCW(op, ce4);\r\n\r\n  // Remap neighbors\r\n  // XXX: might optimize the markNeighbor by keeping track of\r\n  //      what side should be assigned to what neighbor after the\r\n  //      rotation. Now mark neighbor does lots of testing to find\r\n  //      the right side.\r\n  t.ClearNeighbors();\r\n  ot.ClearNeighbors();\r\n  if (n1) ot.MarkNeighbor(*n1);\r\n  if (n2) t.MarkNeighbor(*n2);\r\n  if (n3) t.MarkNeighbor(*n3);\r\n  if (n4) ot.MarkNeighbor(*n4);\r\n  t.MarkNeighbor(ot);\r\n}\r\n\r\nvoid Sweep::FillBasin(SweepContext& tcx, Node& node)\r\n{\r\n  if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) {\r\n    tcx.basin.left_node = node.next->next;\r\n  } else {\r\n    tcx.basin.left_node = node.next;\r\n  }\r\n\r\n  // Find the bottom and right node\r\n  tcx.basin.bottom_node = tcx.basin.left_node;\r\n  while (tcx.basin.bottom_node->next\r\n         && tcx.basin.bottom_node->point->y >= tcx.basin.bottom_node->next->point->y) {\r\n    tcx.basin.bottom_node = tcx.basin.bottom_node->next;\r\n  }\r\n  if (tcx.basin.bottom_node == tcx.basin.left_node) {\r\n    // No valid basin\r\n    return;\r\n  }\r\n\r\n  tcx.basin.right_node = tcx.basin.bottom_node;\r\n  while (tcx.basin.right_node->next\r\n         && tcx.basin.right_node->point->y < tcx.basin.right_node->next->point->y) {\r\n    tcx.basin.right_node = tcx.basin.right_node->next;\r\n  }\r\n  if (tcx.basin.right_node == tcx.basin.bottom_node) {\r\n    // No valid basins\r\n    return;\r\n  }\r\n\r\n  tcx.basin.width = tcx.basin.right_node->point->x - tcx.basin.left_node->point->x;\r\n  tcx.basin.left_highest = tcx.basin.left_node->point->y > tcx.basin.right_node->point->y;\r\n\r\n  FillBasinReq(tcx, tcx.basin.bottom_node);\r\n}\r\n\r\nvoid Sweep::FillBasinReq(SweepContext& tcx, Node* node)\r\n{\r\n  // if shallow stop filling\r\n  if (IsShallow(tcx, *node)) {\r\n    return;\r\n  }\r\n\r\n  Fill(tcx, *node);\n\r\n  if (node->prev == tcx.basin.left_node && node->next == tcx.basin.right_node) {\r\n    return;\r\n  } else if (node->prev == tcx.basin.left_node) {\r\n    Orientation o = Orient2d(*node->point, *node->next->point, *node->next->next->point);\r\n    if (o == CW) {\r\n      return;\r\n    }\r\n    node = node->next;\r\n  } else if (node->next == tcx.basin.right_node) {\r\n    Orientation o = Orient2d(*node->point, *node->prev->point, *node->prev->prev->point);\r\n    if (o == CCW) {\r\n      return;\r\n    }\r\n    node = node->prev;\r\n  } else {\r\n    // Continue with the neighbor node with lowest Y value\r\n    if (node->prev->point->y < node->next->point->y) {\r\n      node = node->prev;\r\n    } else {\r\n      node = node->next;\r\n    }\r\n  }\r\n\r\n  FillBasinReq(tcx, node);\r\n}\r\n\r\nbool Sweep::IsShallow(SweepContext& tcx, Node& node)\r\n{\r\n  double height;\r\n\r\n  if (tcx.basin.left_highest) {\r\n    height = tcx.basin.left_node->point->y - node.point->y;\r\n  } else {\r\n    height = tcx.basin.right_node->point->y - node.point->y;\r\n  }\r\n\r\n  // if shallow stop filling\r\n  if (tcx.basin.width > height) {\r\n    return true;\r\n  }\r\n  return false;\r\n}\r\n\r\nvoid Sweep::FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node)\r\n{\r\n  if (tcx.edge_event.right) {\r\n    FillRightAboveEdgeEvent(tcx, edge, node);\r\n  } else {\r\n    FillLeftAboveEdgeEvent(tcx, edge, node);\r\n  }\r\n}\r\n\r\nvoid Sweep::FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node)\r\n{\r\n  while (node->next->point->x < edge->p->x) {\r\n    // Check if next node is below the edge\r\n    if (Orient2d(*edge->q, *node->next->point, *edge->p) == CCW) {\r\n      FillRightBelowEdgeEvent(tcx, edge, *node);\r\n    } else {\r\n      node = node->next;\r\n    }\r\n  }\r\n}\r\n\r\nvoid Sweep::FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)\r\n{\r\n  if (node.point->x < edge->p->x) {\r\n    if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) {\r\n      // Concave\r\n      FillRightConcaveEdgeEvent(tcx, edge, node);\r\n    } else{\r\n      // Convex\r\n      FillRightConvexEdgeEvent(tcx, edge, node);\r\n      // Retry this one\r\n      FillRightBelowEdgeEvent(tcx, edge, node);\r\n    }\r\n  }\r\n}\r\n\r\nvoid Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)\r\n{\r\n  Fill(tcx, *node.next);\r\n  if (node.next->point != edge->p) {\r\n    // Next above or below edge?\r\n    if (Orient2d(*edge->q, *node.next->point, *edge->p) == CCW) {\r\n      // Below\r\n      if (Orient2d(*node.point, *node.next->point, *node.next->next->point) == CCW) {\r\n        // Next is concave\r\n        FillRightConcaveEdgeEvent(tcx, edge, node);\r\n      } else {\r\n        // Next is convex\r\n      }\r\n    }\r\n  }\n\r\n}\r\n\r\nvoid Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)\r\n{\r\n  // Next concave or convex?\r\n  if (Orient2d(*node.next->point, *node.next->next->point, *node.next->next->next->point) == CCW) {\r\n    // Concave\r\n    FillRightConcaveEdgeEvent(tcx, edge, *node.next);\r\n  } else{\r\n    // Convex\r\n    // Next above or below edge?\r\n    if (Orient2d(*edge->q, *node.next->next->point, *edge->p) == CCW) {\r\n      // Below\r\n      FillRightConvexEdgeEvent(tcx, edge, *node.next);\r\n    } else{\r\n      // Above\r\n    }\r\n  }\r\n}\r\n\r\nvoid Sweep::FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node)\r\n{\r\n  while (node->prev->point->x > edge->p->x) {\r\n    // Check if next node is below the edge\r\n    if (Orient2d(*edge->q, *node->prev->point, *edge->p) == CW) {\r\n      FillLeftBelowEdgeEvent(tcx, edge, *node);\r\n    } else {\r\n      node = node->prev;\r\n    }\r\n  }\r\n}\r\n\r\nvoid Sweep::FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)\r\n{\r\n  if (node.point->x > edge->p->x) {\r\n    if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) {\r\n      // Concave\r\n      FillLeftConcaveEdgeEvent(tcx, edge, node);\r\n    } else {\r\n      // Convex\r\n      FillLeftConvexEdgeEvent(tcx, edge, node);\r\n      // Retry this one\r\n      FillLeftBelowEdgeEvent(tcx, edge, node);\r\n    }\r\n  }\r\n}\r\n\r\nvoid Sweep::FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)\r\n{\r\n  // Next concave or convex?\r\n  if (Orient2d(*node.prev->point, *node.prev->prev->point, *node.prev->prev->prev->point) == CW) {\r\n    // Concave\r\n    FillLeftConcaveEdgeEvent(tcx, edge, *node.prev);\r\n  } else{\r\n    // Convex\r\n    // Next above or below edge?\r\n    if (Orient2d(*edge->q, *node.prev->prev->point, *edge->p) == CW) {\r\n      // Below\r\n      FillLeftConvexEdgeEvent(tcx, edge, *node.prev);\r\n    } else{\r\n      // Above\r\n    }\r\n  }\r\n}\r\n\r\nvoid Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)\r\n{\r\n  Fill(tcx, *node.prev);\r\n  if (node.prev->point != edge->p) {\r\n    // Next above or below edge?\r\n    if (Orient2d(*edge->q, *node.prev->point, *edge->p) == CW) {\r\n      // Below\r\n      if (Orient2d(*node.point, *node.prev->point, *node.prev->prev->point) == CW) {\r\n        // Next is concave\r\n        FillLeftConcaveEdgeEvent(tcx, edge, node);\r\n      } else{\r\n        // Next is convex\r\n      }\r\n    }\r\n  }\r\n\r\n}\r\n\r\nvoid Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p)\r\n{\r\n  Triangle& ot = t->NeighborAcross(p);\r\n  Point& op = *ot.OppositePoint(*t, p);\r\n\r\n  if (&ot == NULL) {\r\n    // If we want to integrate the fillEdgeEvent do it here\r\n    // With current implementation we should never get here\r\n    //throw new RuntimeException( \"[BUG:FIXME] FLIP failed due to missing triangle\");\r\n    assert(0);\r\n  }\r\n\r\n  if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) {\r\n    // Lets rotate shared edge one vertex CW\r\n    RotateTrianglePair(*t, p, ot, op);\r\n    tcx.MapTriangleToNodes(*t);\r\n    tcx.MapTriangleToNodes(ot);\r\n\r\n    if (p == eq && op == ep) {\r\n      if (eq == *tcx.edge_event.constrained_edge->q && ep == *tcx.edge_event.constrained_edge->p) {\r\n        t->MarkConstrainedEdge(&ep, &eq);\r\n        ot.MarkConstrainedEdge(&ep, &eq);\r\n        Legalize(tcx, *t);\r\n        Legalize(tcx, ot);\r\n      } else {\r\n        // XXX: I think one of the triangles should be legalized here?\r\n      }\r\n    } else {\r\n      Orientation o = Orient2d(eq, op, ep);\r\n      t = &NextFlipTriangle(tcx, (int)o, *t, ot, p, op);\r\n      FlipEdgeEvent(tcx, ep, eq, t, p);\r\n    }\r\n  } else {\r\n    Point& newP = NextFlipPoint(ep, eq, ot, op);\r\n    FlipScanEdgeEvent(tcx, ep, eq, *t, ot, newP);\r\n    EdgeEvent(tcx, ep, eq, t, p);\r\n  }\r\n}\r\n\r\nTriangle& Sweep::NextFlipTriangle(SweepContext& tcx, int o, Triangle& t, Triangle& ot, Point& p, Point& op)\r\n{\r\n  if (o == CCW) {\r\n    // ot is not crossing edge after flip\r\n    int edge_index = ot.EdgeIndex(&p, &op);\r\n    ot.delaunay_edge[edge_index] = true;\r\n    Legalize(tcx, ot);\r\n    ot.ClearDelunayEdges();\r\n    return t;\r\n  }\r\n\r\n  // t is not crossing edge after flip\r\n  int edge_index = t.EdgeIndex(&p, &op);\r\n\r\n  t.delaunay_edge[edge_index] = true;\r\n  Legalize(tcx, t);\r\n  t.ClearDelunayEdges();\r\n  return ot;\r\n}\r\n\r\nPoint& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)\r\n{\r\n  Orientation o2d = Orient2d(eq, op, ep);\r\n  if (o2d == CW) {\r\n    // Right\r\n    return *ot.PointCCW(op);\r\n  } else if (o2d == CCW) {\r\n    // Left\r\n    return *ot.PointCW(op);\r\n  } else{\r\n    //throw new RuntimeException(\"[Unsupported] Opposing point on constrained edge\");\r\n    assert(0);\r\n  }\r\n}\r\n\r\nvoid Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,\r\n                              Triangle& t, Point& p)\r\n{\r\n  Triangle& ot = t.NeighborAcross(p);\r\n  Point& op = *ot.OppositePoint(t, p);\r\n\r\n  if (&t.NeighborAcross(p) == NULL) {\r\n    // If we want to integrate the fillEdgeEvent do it here\r\n    // With current implementation we should never get here\r\n    //throw new RuntimeException( \"[BUG:FIXME] FLIP failed due to missing triangle\");\r\n    assert(0);\r\n  }\r\n\r\n  if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) {\r\n    // flip with new edge op->eq\r\n    FlipEdgeEvent(tcx, eq, op, &ot, op);\r\n    // TODO: Actually I just figured out that it should be possible to\r\n    //       improve this by getting the next ot and op before the the above\r\n    //       flip and continue the flipScanEdgeEvent here\r\n    // set new ot and op here and loop back to inScanArea test\r\n    // also need to set a new flip_triangle first\r\n    // Turns out at first glance that this is somewhat complicated\r\n    // so it will have to wait.\r\n  } else{\r\n    Point& newP = NextFlipPoint(ep, eq, ot, op);\r\n    FlipScanEdgeEvent(tcx, ep, eq, flip_triangle, ot, newP);\r\n  }\r\n}\n\nSweep::~Sweep() {\n\n    // Clean up memory\n    for(int i = 0; i < nodes_.size(); i++) {\n        delete nodes_[i];\n    }\n\n}\r\n\r\n}\r\n\r\n"
  },
  {
    "path": "poly2tri/sweep/sweep.h",
    "content": "/*\n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\n * http://code.google.com/p/poly2tri/\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n * * Redistributions of source code must retain the above copyright notice,\n *   this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n *   this list of conditions and the following disclaimer in the documentation\n *   and/or other materials provided with the distribution.\n * * Neither the name of Poly2Tri nor the names of its contributors may be\n *   used to endorse or promote products derived from this software without specific\n *   prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n/**\n * Sweep-line, Constrained Delauney Triangulation (CDT) See: Domiter, V. and\n * Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',\n * International Journal of Geographical Information Science\n *\n * \"FlipScan\" Constrained Edge Algorithm invented by Thomas hln, thahlen@gmail.com\n */\n\n#ifndef SWEEP_H\n#define SWEEP_H\n\n#include <vector>\n\nnamespace p2t {\n\nclass SweepContext;\nstruct Node;\nstruct Point;\nstruct Edge;\nclass Triangle;\n\nclass Sweep \n{\npublic:\n\n  /**\n   * Triangulate\n   * \n   * @param tcx\n   */\n  void Triangulate(SweepContext& tcx);\n  \n  /**\n   * Destructor - clean up memory\n   */\n  ~Sweep();\n\nprivate:\n\n  /**\n   * Start sweeping the Y-sorted point set from bottom to top\n   * \n   * @param tcx\n   */\n  void SweepPoints(SweepContext& tcx);\n\n  /**\n   * Find closes node to the left of the new point and\n   * create a new triangle. If needed new holes and basins\n   * will be filled to.\n   *\n   * @param tcx\n   * @param point\n   * @return\n   */\n  Node& PointEvent(SweepContext& tcx, Point& point);\n\n   /**\n     * \n     * \n     * @param tcx\n     * @param edge\n     * @param node\n     */\n  void EdgeEvent(SweepContext& tcx, Edge* edge, Node* node);\n\n  void EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point);\n\n  /**\n   * Creates a new front triangle and legalize it\n   * \n   * @param tcx\n   * @param point\n   * @param node\n   * @return\n   */\n  Node& NewFrontTriangle(SweepContext& tcx, Point& point, Node& node);\n\n  /**\n   * Adds a triangle to the advancing front to fill a hole.\n   * @param tcx\n   * @param node - middle node, that is the bottom of the hole\n   */\n  void Fill(SweepContext& tcx, Node& node);\n\n  /**\n   * Returns true if triangle was legalized\n   */\n  bool Legalize(SweepContext& tcx, Triangle& t);\n\n  /**\n   * <b>Requirement</b>:<br>\n   * 1. a,b and c form a triangle.<br>\n   * 2. a and d is know to be on opposite side of bc<br>\n   * <pre>\n   *                a\n   *                +\n   *               / \\\n   *              /   \\\n   *            b/     \\c\n   *            +-------+\n   *           /    d    \\\n   *          /           \\\n   * </pre>\n   * <b>Fact</b>: d has to be in area B to have a chance to be inside the circle formed by\n   *  a,b and c<br>\n   *  d is outside B if orient2d(a,b,d) or orient2d(c,a,d) is CW<br>\n   *  This preknowledge gives us a way to optimize the incircle test\n   * @param a - triangle point, opposite d\n   * @param b - triangle point\n   * @param c - triangle point\n   * @param d - point opposite a\n   * @return true if d is inside circle, false if on circle edge\n   */\n  bool Incircle(Point& pa, Point& pb, Point& pc, Point& pd);\n\n  /**\n   * Rotates a triangle pair one vertex CW\n   *<pre>\n   *       n2                    n2\n   *  P +-----+             P +-----+\n   *    | t  /|               |\\  t |\n   *    |   / |               | \\   |\n   *  n1|  /  |n3           n1|  \\  |n3\n   *    | /   |    after CW   |   \\ |\n   *    |/ oT |               | oT \\|\n   *    +-----+ oP            +-----+\n   *       n4                    n4\n   * </pre>\n   */\n  void RotateTrianglePair(Triangle& t, Point& p, Triangle& ot, Point& op);\n\n  /**\n   * Fills holes in the Advancing Front\n   *\n   *\n   * @param tcx\n   * @param n\n   */\n  void FillAdvancingFront(SweepContext& tcx, Node& n);\n  \n  // Decision-making about when to Fill hole. \n  // Contributed by ToolmakerSteve2\n  bool LargeHole_DontFill(Node* node);\n  bool AngleIsNegative(Point* origin, Point* pa, Point* pb);\n  bool AngleExceeds90Degrees(Point* origin, Point* pa, Point* pb);\n  bool AngleExceedsPlus90DegreesOrIsNegative(Point* origin, Point* pa, Point* pb);\n  double Angle(Point& origin, Point& pa, Point& pb);\n\n  /**\n   *\n   * @param node - middle node\n   * @return the angle between 3 front nodes\n   */\n  double HoleAngle(Node& node);\n\n  /**\n   * The basin angle is decided against the horizontal line [1,0]\n   */\n  double BasinAngle(Node& node);\n\n  /**\n   * Fills a basin that has formed on the Advancing Front to the right\n   * of given node.<br>\n   * First we decide a left,bottom and right node that forms the\n   * boundaries of the basin. Then we do a reqursive fill.\n   *\n   * @param tcx\n   * @param node - starting node, this or next node will be left node\n   */\n  void FillBasin(SweepContext& tcx, Node& node);\n\n  /**\n   * Recursive algorithm to fill a Basin with triangles\n   *\n   * @param tcx\n   * @param node - bottom_node\n   * @param cnt - counter used to alternate on even and odd numbers\n   */\n  void FillBasinReq(SweepContext& tcx, Node* node);\n\n  bool IsShallow(SweepContext& tcx, Node& node);\n\n  bool IsEdgeSideOfTriangle(Triangle& triangle, Point& ep, Point& eq);\n\n  void FillEdgeEvent(SweepContext& tcx, Edge* edge, Node* node);\n\n  void FillRightAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node);\n\n  void FillRightBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);\n\n  void FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);\n\n  void FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);\n\n  void FillLeftAboveEdgeEvent(SweepContext& tcx, Edge* edge, Node* node);\n\n  void FillLeftBelowEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);\n\n  void FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);\n\n  void FillLeftConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node);\n\n  void FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p);\n\n  /**\n   * After a flip we have two triangles and know that only one will still be\n   * intersecting the edge. So decide which to contiune with and legalize the other\n   * \n   * @param tcx\n   * @param o - should be the result of an orient2d( eq, op, ep )\n   * @param t - triangle 1\n   * @param ot - triangle 2\n   * @param p - a point shared by both triangles \n   * @param op - another point shared by both triangles\n   * @return returns the triangle still intersecting the edge\n   */\n  Triangle& NextFlipTriangle(SweepContext& tcx, int o, Triangle&  t, Triangle& ot, Point& p, Point& op);\n\n   /**\n     * When we need to traverse from one triangle to the next we need \n     * the point in current triangle that is the opposite point to the next\n     * triangle. \n     * \n     * @param ep\n     * @param eq\n     * @param ot\n     * @param op\n     * @return\n     */\n  Point& NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op);\n\n   /**\n     * Scan part of the FlipScan algorithm<br>\n     * When a triangle pair isn't flippable we will scan for the next \n     * point that is inside the flip triangle scan area. When found \n     * we generate a new flipEdgeEvent\n     * \n     * @param tcx\n     * @param ep - last point on the edge we are traversing\n     * @param eq - first point on the edge we are traversing\n     * @param flipTriangle - the current triangle sharing the point eq with edge\n     * @param t\n     * @param p\n     */\n  void FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle, Triangle& t, Point& p);\n\n  void FinalizationPolygon(SweepContext& tcx);\n\n  std::vector<Node*> nodes_;\n\n};\n\n}\n\n#endif\n"
  },
  {
    "path": "poly2tri/sweep/sweep_context.cc",
    "content": "/*\n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\n * http://code.google.com/p/poly2tri/\n *\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without modification,\n * are permitted provided that the following conditions are met:\n *\n * * Redistributions of source code must retain the above copyright notice,\n *   this list of conditions and the following disclaimer.\n * * Redistributions in binary form must reproduce the above copyright notice,\n *   this list of conditions and the following disclaimer in the documentation\n *   and/or other materials provided with the distribution.\n * * Neither the name of Poly2Tri nor the names of its contributors may be\n *   used to endorse or promote products derived from this software without specific\n *   prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n#include \"sweep_context.h\"\n#include <algorithm>\n#include \"advancing_front.h\"\n\nnamespace p2t {\n\nSweepContext::SweepContext(std::vector<Point*> polyline) :\n  front_(0),\n  head_(0),\n  tail_(0),\n  af_head_(0),\n  af_middle_(0),\n  af_tail_(0)\n{\n  basin = Basin();\n  edge_event = EdgeEvent();\n\n  points_ = polyline;\n\n  InitEdges(points_);\n}\n\nvoid SweepContext::AddHole(std::vector<Point*> polyline)\n{\n  InitEdges(polyline);\n  for(unsigned int i = 0; i < polyline.size(); i++) {\n    points_.push_back(polyline[i]);\n  }\n}\n\nvoid SweepContext::AddPoint(Point* point) {\n  points_.push_back(point);\n}\n\nstd::vector<Triangle*> SweepContext::GetTriangles()\n{\n  return triangles_;\n}\n\nstd::list<Triangle*> SweepContext::GetMap()\n{\n  return map_;\n}\n\nvoid SweepContext::InitTriangulation()\n{\n  double xmax(points_[0]->x), xmin(points_[0]->x);\n  double ymax(points_[0]->y), ymin(points_[0]->y);\n\n  // Calculate bounds.\n  for (unsigned int i = 0; i < points_.size(); i++) {\n    Point& p = *points_[i];\n    if (p.x > xmax)\n      xmax = p.x;\n    if (p.x < xmin)\n      xmin = p.x;\n    if (p.y > ymax)\n      ymax = p.y;\n    if (p.y < ymin)\n      ymin = p.y;\n  }\n\n  double dx = kAlpha * (xmax - xmin);\n  double dy = kAlpha * (ymax - ymin);\n  head_ = new Point(xmax + dx, ymin - dy);\n  tail_ = new Point(xmin - dx, ymin - dy);\n\n  // Sort points along y-axis\n  std::sort(points_.begin(), points_.end(), cmp);\n\n}\n\nvoid SweepContext::InitEdges(std::vector<Point*> polyline)\n{\n  int num_points = polyline.size();\n  for (int i = 0; i < num_points; i++) {\n    int j = i < num_points - 1 ? i + 1 : 0;\n    edge_list.push_back(new Edge(*polyline[i], *polyline[j]));\n  }\n}\n\nPoint* SweepContext::GetPoint(const int& index)\n{\n  return points_[index];\n}\n\nvoid SweepContext::AddToMap(Triangle* triangle)\n{\n  map_.push_back(triangle);\n}\n\nNode& SweepContext::LocateNode(Point& point)\n{\n  // TODO implement search tree\n  return *front_->LocateNode(point.x);\n}\n\nvoid SweepContext::CreateAdvancingFront(std::vector<Node*> nodes)\n{\n\n  (void) nodes;\n  // Initial triangle\n  Triangle* triangle = new Triangle(*points_[0], *tail_, *head_);\n\n  map_.push_back(triangle);\n\n  af_head_ = new Node(*triangle->GetPoint(1), *triangle);\n  af_middle_ = new Node(*triangle->GetPoint(0), *triangle);\n  af_tail_ = new Node(*triangle->GetPoint(2));\n  front_ = new AdvancingFront(*af_head_, *af_tail_);\n\n  // TODO: More intuitive if head is middles next and not previous?\n  //       so swap head and tail\n  af_head_->next = af_middle_;\n  af_middle_->next = af_tail_;\n  af_middle_->prev = af_head_;\n  af_tail_->prev = af_middle_;\n}\n\nvoid SweepContext::RemoveNode(Node* node)\n{\n  delete node;\n}\n\nvoid SweepContext::MapTriangleToNodes(Triangle& t)\n{\n  for (int i = 0; i < 3; i++) {\n    if (!t.GetNeighbor(i)) {\n      Node* n = front_->LocatePoint(t.PointCW(*t.GetPoint(i)));\n      if (n)\n        n->triangle = &t;\n    }\n  }\n}\n\nvoid SweepContext::RemoveFromMap(Triangle* triangle)\n{\n  map_.remove(triangle);\n}\n\nvoid SweepContext::MeshClean(Triangle& triangle)\n{\n  std::vector<Triangle *> triangles;\n  triangles.push_back(&triangle);\n\n  while(!triangles.empty()){\n\tTriangle *t = triangles.back();\n\ttriangles.pop_back();\n\n    if (t != NULL && !t->IsInterior()) {\n      t->IsInterior(true);\n      triangles_.push_back(t);\n      for (int i = 0; i < 3; i++) {\n        if (!t->constrained_edge[i])\n          triangles.push_back(t->GetNeighbor(i));\n      }\n    }\n  }\n}\n\nSweepContext::~SweepContext()\n{\n\n    // Clean up memory\n\n    delete head_;\n    delete tail_;\n    delete front_;\n    delete af_head_;\n    delete af_middle_;\n    delete af_tail_;\n\n    typedef std::list<Triangle*> type_list;\n\n    for(type_list::iterator iter = map_.begin(); iter != map_.end(); ++iter) {\n        Triangle* ptr = *iter;\n        delete ptr;\n    }\n\n     for(unsigned int i = 0; i < edge_list.size(); i++) {\n        delete edge_list[i];\n    }\n\n}\n\n}\n"
  },
  {
    "path": "poly2tri/sweep/sweep_context.h",
    "content": "/*\r\n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\r\n * http://code.google.com/p/poly2tri/\r\n *\r\n * All rights reserved.\r\n *\r\n * Redistribution and use in source and binary forms, with or without modification,\r\n * are permitted provided that the following conditions are met:\r\n *\r\n * * Redistributions of source code must retain the above copyright notice,\r\n *   this list of conditions and the following disclaimer.\r\n * * Redistributions in binary form must reproduce the above copyright notice,\r\n *   this list of conditions and the following disclaimer in the documentation\r\n *   and/or other materials provided with the distribution.\r\n * * Neither the name of Poly2Tri nor the names of its contributors may be\r\n *   used to endorse or promote products derived from this software without specific\r\n *   prior written permission.\r\n *\r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n */\r\n\r\n#ifndef SWEEP_CONTEXT_H\r\n#define SWEEP_CONTEXT_H\r\n\r\n#include <list>\r\n#include <vector>\r\n#include <cstddef>\r\n\r\nnamespace p2t {\r\n\r\n// Inital triangle factor, seed triangle will extend 30% of\r\n// PointSet width to both left and right.\r\nconst double kAlpha = 0.3;\r\n\r\nstruct Point;\r\nclass Triangle;\r\nstruct Node;\r\nstruct Edge;\r\nclass AdvancingFront;\r\n\r\nclass SweepContext {\r\npublic:\r\n\r\n/// Constructor\r\nSweepContext(std::vector<Point*> polyline);\r\n/// Destructor\r\n~SweepContext();\r\n\r\nvoid set_head(Point* p1);\r\n\r\nPoint* head();\r\n\r\nvoid set_tail(Point* p1);\r\n\r\nPoint* tail();\r\n\r\nint point_count();\r\n\r\nNode& LocateNode(Point& point);\r\n\r\nvoid RemoveNode(Node* node);\r\n\r\nvoid CreateAdvancingFront(std::vector<Node*> nodes);\r\n\r\n/// Try to map a node to all sides of this triangle that don't have a neighbor\r\nvoid MapTriangleToNodes(Triangle& t);\r\n\r\nvoid AddToMap(Triangle* triangle);\r\n\r\nPoint* GetPoint(const int& index);\r\n\r\nPoint* GetPoints();\r\n\r\nvoid RemoveFromMap(Triangle* triangle);\r\n\r\nvoid AddHole(std::vector<Point*> polyline);\r\n\r\nvoid AddPoint(Point* point);\r\n\r\nAdvancingFront* front();\r\n\r\nvoid MeshClean(Triangle& triangle);\r\n\r\nstd::vector<Triangle*> GetTriangles();\r\nstd::list<Triangle*> GetMap();\n\r\nstd::vector<Edge*> edge_list;\r\n\r\nstruct Basin {\r\n  Node* left_node;\r\n  Node* bottom_node;\r\n  Node* right_node;\r\n  double width;\r\n  bool left_highest;\r\n\r\n  Basin() : left_node(NULL), bottom_node(NULL), right_node(NULL), width(0.0), left_highest(false)\r\n  {\r\n  }\r\n\r\n  void Clear()\r\n  {\r\n    left_node = NULL;\r\n    bottom_node = NULL;\r\n    right_node = NULL;\r\n    width = 0.0;\r\n    left_highest = false;\r\n  }\r\n};\r\n\r\nstruct EdgeEvent {\r\n  Edge* constrained_edge;\r\n  bool right;\r\n\r\n  EdgeEvent() : constrained_edge(NULL), right(false)\r\n  {\r\n  }\r\n};\r\n\r\nBasin basin;\r\nEdgeEvent edge_event;\r\n\r\nprivate:\r\n\r\nfriend class Sweep;\r\n\r\nstd::vector<Triangle*> triangles_;\r\nstd::list<Triangle*> map_;\r\nstd::vector<Point*> points_;\r\n\r\n// Advancing front\r\nAdvancingFront* front_;\r\n// head point used with advancing front\r\nPoint* head_;\r\n// tail point used with advancing front\r\nPoint* tail_;\r\n\r\nNode *af_head_, *af_middle_, *af_tail_;\r\n\r\nvoid InitTriangulation();\r\nvoid InitEdges(std::vector<Point*> polyline);\r\n\r\n};\r\n\r\ninline AdvancingFront* SweepContext::front()\r\n{\r\n  return front_;\r\n}\r\n\r\ninline int SweepContext::point_count()\r\n{\r\n  return points_.size();\r\n}\r\n\r\ninline void SweepContext::set_head(Point* p1)\r\n{\r\n  head_ = p1;\r\n}\r\n\r\ninline Point* SweepContext::head()\r\n{\r\n  return head_;\r\n}\r\n\r\ninline void SweepContext::set_tail(Point* p1)\r\n{\r\n  tail_ = p1;\r\n}\r\n\r\ninline Point* SweepContext::tail()\r\n{\r\n  return tail_;\r\n}\r\n\r\n}\r\n\r\n#endif\r\n"
  },
  {
    "path": "testbed/data/polygon.dae",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\" ?>\r\n<COLLADA xmlns=\"http://www.collada.org/2005/11/COLLADASchema\" version=\"1.4.1\">\r\n    <asset>\r\n        <contributor>\r\n            <authoring_tool>Google SketchUp 7.1.4871</authoring_tool>\r\n        </contributor>\r\n        <created>2009-12-21T01:51:00Z</created>\r\n        <modified>2009-12-21T01:51:00Z</modified>\r\n        <unit meter=\"0.0254\" name=\"inch\" />\r\n        <up_axis>Z_UP</up_axis>\r\n    </asset>\r\n    <library_visual_scenes>\r\n        <visual_scene id=\"ID1\">\r\n            <node name=\"SketchUp\">\r\n                <instance_geometry url=\"#ID2\">\r\n                    <bind_material>\r\n                        <technique_common>\r\n                            <instance_material symbol=\"Material2\" target=\"#ID4\">\r\n                                <bind_vertex_input semantic=\"UVSET0\" input_semantic=\"TEXCOORD\" input_set=\"0\" />\r\n                            </instance_material>\r\n                        </technique_common>\r\n                    </bind_material>\r\n                </instance_geometry>\r\n            </node>\r\n        </visual_scene>\r\n    </library_visual_scenes>\r\n    <library_geometries>\r\n        <geometry id=\"ID2\">\r\n            <mesh>\r\n                <source id=\"ID5\">\r\n                    <float_array id=\"ID8\" count=\"324\">-112.9393 -5.134218 -5.952325e-030 -115.783 -26.39329 -4.065249e-030 -116.1693 -15.52189 -5.174618e-030 -111.8239 -36.52552 -2.74901e-030 -106.4564 3.601217 -6.310887e-030 -104.7373 -44.7788 -1.373963e-030 -66.76277 70.05491 -5.637993e-014 -68.21937 53.83701 -4.127297e-014 -68.55863 62.04185 -5.054886e-014 -65.7681 45.99956 -2.91844e-014 -62.95416 77.33014 -5.83688e-014 -61.37187 39.0636 -1.510696e-014 -57.39237 83.37173 -5.637993e-014 -55.33028 33.5018 0 -50.4564 87.76796 -5.054886e-014 -54.18848 31.40854 0 -52.54381 29.68213 0 -50.50835 28.44022 0 -48.22082 27.76744 0 -42.61895 90.21923 -4.127297e-014 -45.8371 27.70964 0 -43.51965 28.27076 0 -41.4264 29.41256 0 -34.41412 90.55849 -2.91844e-014 -38.42946 47.11159 0 -39.69999 31.05723 0 -38.45807 33.09269 0 -36.86605 53.9672 0 -33.69118 60.24126 0 -26.40105 88.76263 -1.510696e-014 -29.09332 65.56134 0 -23.3454 69.61164 0 -19.12582 84.95402 1.877284e-029 -16.7886 72.15173 0 -13.74167 81.56284 1.269697e-029 -9.81216 73.03084 0 -8.03964 78.73864 7.636926e-030 -2.830188 72.19677 0 -2.079244 76.51087 3.64551e-030 3.742859 69.69904 0 4.077324 74.9028 7.643719e-031 9.516804 65.68592 0 10.36582 73.93119 -9.764253e-031 14.1489 60.39562 0 16.72063 73.60619 -1.558716e-030 17.36419 54.14218 0 23.07544 73.93119 -9.764253e-031 19.14039 41.22425 0 92.15467 80.62257 -5.238305e-014 88.83104 50.24595 2.085226e-030 88.0531 85.73196 -5.423092e-014 92.70476 55.53018 -1.403599e-014 94.79408 74.62572 -4.696535e-014 95.07883 61.63694 -2.711546e-014 95.79146 68.15007 -3.834705e-014 -138.3173 50.47565 -5.441105e-014 -137.432 24.73624 -3.697808e-014 -140.3168 37.52194 -4.746962e-014 -131.7115 61.79639 -5.68373e-014 -130.0639 13.89615 -2.439509e-014 -121.4177 69.91023 -5.441105e-014 -119.2369 6.508783 -1.147007e-014 -108.8671 73.6891 -4.746962e-014 -95.8047 72.60761 -3.697808e-014 -95.3204 -50.22474 -9.478654e-032 -84.0465 66.81613 -2.439509e-014 -84.63247 -52.25073 9.446271e-031 -73.87579 -50.62886 1.627355e-030 -75.22729 57.11985 -1.147007e-014 -70.57319 44.86685 0 -64.26037 -45.54158 1.876598e-030 -69.61521 31.86262 0 -64.96236 19.68153 0 -57.00677 9.350201 0 -56.86785 -37.56115 1.664318e-030 -51.7342 -16.73615 -6.04464e-035 -46.41893 1.739326 0 -52.52979 -27.58529 1.014396e-030 -43.24859 -39.15101 -3.163366e-031 -34.09116 -2.50966 0 -28.50562 -58.04747 -5.308165e-031 -21.06243 -3.038659 0 -8.827904 -71.73027 -6.242584e-031 -8.430764 0.1969107 0 14.01921 -78.97189 -5.882796e-031 2.739249 6.924362 0 11.50623 16.57672 0 17.1313 28.34049 0 37.98603 -79.12265 -4.261077e-031 29.36394 74.9028 7.643719e-031 35.52051 76.51087 3.64551e-030 41.48091 78.73864 7.636926e-030 60.92244 -72.16905 -1.522917e-031 47.18293 81.56284 1.269697e-029 52.56709 84.95402 1.877284e-029 57.67648 89.0556 -1.403599e-014 63.67333 91.69501 -2.711546e-014 80.77074 -58.7349 2.086037e-031 70.14898 92.69238 -3.834705e-014 76.66211 91.97975 -4.696535e-014 82.76887 89.60568 -5.238305e-014 95.75028 -40.02542 6.242015e-031 100.8951 29.53631 1.822036e-030 104.5172 -17.71909 1.057217e-030 106.285 6.182927 1.468804e-030 -38.28861 40.08139 0 -37.78529 35.38022 0 -37.72749 37.76394 0</float_array>\r\n                    <technique_common>\r\n                        <accessor count=\"108\" source=\"#ID8\" stride=\"3\">\r\n                            <param name=\"X\" type=\"float\" />\r\n                            <param name=\"Y\" type=\"float\" />\r\n                            <param name=\"Z\" type=\"float\" />\r\n                        </accessor>\r\n                    </technique_common>\r\n                </source>\r\n                <source id=\"ID6\">\r\n                    <float_array id=\"ID9\" count=\"324\">5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1 5.652422e-017 -2.025185e-016 -1</float_array>\r\n                    <technique_common>\r\n                        <accessor count=\"108\" source=\"#ID9\" stride=\"3\">\r\n                            <param name=\"X\" type=\"float\" />\r\n                            <param name=\"Y\" type=\"float\" />\r\n                            <param name=\"Z\" type=\"float\" />\r\n                        </accessor>\r\n                    </technique_common>\r\n                </source>\r\n                <vertices id=\"ID7\">\r\n                    <input semantic=\"POSITION\" source=\"#ID5\" />\r\n                    <input semantic=\"NORMAL\" source=\"#ID6\" />\r\n                </vertices>\r\n                <triangles count=\"106\" material=\"Material2\">\r\n                    <input offset=\"0\" semantic=\"VERTEX\" source=\"#ID7\" />\r\n                    <p>0 1 2 1 0 3 3 0 4 3 4 5 6 7 8 7 6 9 9 6 10 9 10 11 11 10 12 11 12 13 13 12 14 13 14 15 15 14 16 16 14 17 17 14 18 18 14 19 18 19 20 20 19 21 21 19 22 22 19 23 22 23 24 22 24 25 25 24 26 24 23 27 27 23 28 28 23 29 28 29 30 30 29 31 31 29 32 31 32 33 33 32 34 33 34 35 35 34 36 35 36 37 37 36 38 37 38 39 39 38 40 39 40 41 41 40 42 41 42 43 43 42 44 43 44 45 45 44 46 45 46 47 48 49 50 49 48 51 51 48 52 51 52 53 53 52 54 55 56 57 56 55 58 56 58 59 59 58 60 59 60 61 61 60 62 61 62 4 4 62 63 4 63 5 5 63 64 64 63 65 64 65 66 66 65 67 67 65 68 67 68 69 67 69 70 70 69 71 70 71 72 70 72 73 70 73 74 74 73 75 75 73 76 74 75 77 75 76 78 78 76 79 78 79 80 80 79 81 80 81 82 82 81 83 82 83 84 84 83 85 84 85 86 84 86 87 84 87 88 88 87 47 88 47 46 88 46 89 88 89 90 88 90 91 88 91 92 92 91 93 92 93 94 92 94 95 92 95 96 92 96 97 97 96 98 97 98 99 97 99 100 97 100 101 101 100 49 49 100 50 101 49 102 101 102 103 103 102 104 26 105 106 105 26 24 106 105 107</p>\r\n                </triangles>\r\n            </mesh>\r\n        </geometry>\r\n    </library_geometries>\r\n    <library_materials>\r\n        <material id=\"ID4\" name=\"material_0\">\r\n            <instance_effect url=\"#ID3\" />\r\n        </material>\r\n    </library_materials>\r\n    <library_effects>\r\n        <effect id=\"ID3\">\r\n            <profile_COMMON>\r\n                <technique sid=\"COMMON\">\r\n                    <lambert>\r\n                        <diffuse>\r\n                            <color>1 1 1 1</color>\r\n                        </diffuse>\r\n                    </lambert>\r\n                </technique>\r\n            </profile_COMMON>\r\n        </effect>\r\n    </library_effects>\r\n    <scene>\r\n        <instance_visual_scene url=\"#ID1\" />\r\n    </scene>\r\n</COLLADA>\r\n"
  },
  {
    "path": "testbed/main.cc",
    "content": "/*\r\n * Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors\r\n * http://code.google.com/p/poly2tri/\r\n *\r\n * All rights reserved.\r\n *\r\n * Redistribution and use in source and binary forms, with or without modification,\r\n * are permitted provided that the following conditions are met:\r\n *\r\n * * Redistributions of source code must retain the above copyright notice,\r\n *   this list of conditions and the following disclaimer.\r\n * * Redistributions in binary form must reproduce the above copyright notice,\r\n *   this list of conditions and the following disclaimer in the documentation\r\n *   and/or other materials provided with the distribution.\r\n * * Neither the name of Poly2Tri nor the names of its contributors may be\r\n *   used to endorse or promote products derived from this software without specific\r\n *   prior written permission.\r\n *\r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\r\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\r\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\r\n * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r\n * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r\n * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r\n * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR\r\n * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r\n * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r\n * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r\n * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r\n */\r\n#include <cstdlib>\r\n#include <GL/glfw.h>\r\n#include <time.h>\r\n#include <fstream>\r\n#include <string>\r\n#include <sstream>\r\n#include <algorithm>\r\n#include <iterator>\r\n#include <iostream>\r\nusing namespace std;\r\n\r\n#include \"../poly2tri/poly2tri.h\"\r\nusing namespace p2t;\r\n\r\nvoid Init();\r\nvoid ShutDown(int return_code);\r\nvoid MainLoop(const double zoom);\r\nvoid Draw(const double zoom);\r\nvoid DrawMap(const double zoom);\r\nvoid ConstrainedColor(bool constrain);\r\ndouble StringToDouble(const std::string& s);\r\ndouble Random(double (*fun)(double), double xmin, double xmax);\r\ndouble Fun(double x);\r\n\r\n/// Dude hole examples\r\nvector<Point*> CreateHeadHole();\r\nvector<Point*> CreateChestHole();\r\n\r\n/// Stalactite hole example\r\nvector<Point*> CreateStalactiteHole();\r\n\r\nfloat rotate_y = 0,\r\n      rotate_z = 0;\r\nconst float rotations_per_tick = .2;\r\n\r\n/// Screen center x\r\ndouble cx = 0.0;\r\n/// Screen center y\r\ndouble cy = 0.0;\r\n\r\n/// Constrained triangles\r\nvector<Triangle*> triangles;\r\n/// Triangle map\r\nlist<Triangle*> map;\r\n/// Polylines\r\nvector< vector<Point*> > polylines;\r\n\r\n/// Draw the entire triangle map?\r\nbool draw_map = false;\r\n/// Create a random distribution of points?\r\nbool random_distribution = false;\r\n\r\ntemplate <class C> void FreeClear( C & cntr ) {\r\n    for ( typename C::iterator it = cntr.begin(); \r\n              it != cntr.end(); ++it ) {\r\n        delete * it;\r\n    }\r\n    cntr.clear();\r\n}\r\n\r\nint main(int argc, char* argv[])\r\n{\r\n\r\n  int num_points = 0;\r\n  double max, min;\r\n  double zoom;\r\n\r\n  if (argc != 5) {\r\n    cout << \"-== USAGE ==-\" << endl;\r\n    cout << \"Load Data File: p2t filename center_x center_y zoom\" << endl;\r\n    cout << \"Example: ./build/p2t testbed/data/dude.dat 500 500 1\" << endl;\r\n    return 1;\r\n  }\r\n\r\n  if(string(argv[1]) == \"random\") {\r\n    num_points = atoi(argv[2]);\r\n    random_distribution = true;\r\n    char* pEnd;\r\n    max = strtod(argv[3], &pEnd);\r\n    min = -max;\r\n    cx = cy = 0;\r\n    zoom = atof(argv[4]);\r\n  } else {\r\n    zoom = atof(argv[4]);\r\n    cx = atof(argv[2]);\r\n    cy = atof(argv[3]);\r\n  }\r\n\r\n  vector<p2t::Point*> polyline;\r\n    \r\n  if(random_distribution) {\r\n    // Create a simple bounding box\r\n    polyline.push_back(new Point(min,min));\r\n    polyline.push_back(new Point(min,max));\r\n    polyline.push_back(new Point(max,max));\r\n    polyline.push_back(new Point(max,min));\r\n  } else {\r\n    // Load pointset from file\r\n\r\n    // Parse and tokenize data file\r\n    string line;\r\n    ifstream myfile(argv[1]);\r\n    if (myfile.is_open()) {\r\n      while (!myfile.eof()) {\r\n        getline(myfile, line);\r\n        if (line.size() == 0) {\r\n          break;\r\n        }\r\n        istringstream iss(line);\r\n        vector<string> tokens;\r\n        copy(istream_iterator<string>(iss), istream_iterator<string>(),\r\n             back_inserter<vector<string> >(tokens));\r\n        double x = StringToDouble(tokens[0]);\r\n        double y = StringToDouble(tokens[1]);\r\n        polyline.push_back(new Point(x, y));\r\n        num_points++;\r\n      }\r\n      myfile.close();\r\n    } else {\r\n      cout << \"File not opened\" << endl;\r\n    }\r\n  }\r\n  \r\n  cout << \"Number of constrained edges = \" << polyline.size() << endl;\r\n  polylines.push_back(polyline);\r\n\r\n  Init();\r\n\r\n  /*\r\n   * Perform triangulation!\r\n   */\r\n\r\n  double init_time = glfwGetTime();\r\n\r\n  /*\r\n   * STEP 1: Create CDT and add primary polyline\r\n   * NOTE: polyline must be a simple polygon. The polyline's points\r\n   * constitute constrained edges. No repeat points!!!\r\n   */\r\n  CDT* cdt = new CDT(polyline);\r\n\r\n  /*\r\n   * STEP 2: Add holes or Steiner points if necessary\r\n   */\r\n      \r\n  string s(argv[1]);\r\n  if(s.find(\"dude.dat\", 0) != string::npos) {\r\n    // Add head hole\r\n    vector<Point*> head_hole = CreateHeadHole();\r\n    num_points += head_hole.size();\r\n    cdt->AddHole(head_hole);\r\n    // Add chest hole\r\n    vector<Point*> chest_hole = CreateChestHole();\r\n    num_points += chest_hole.size();\r\n    cdt->AddHole(chest_hole);\r\n    polylines.push_back(head_hole);\r\n    polylines.push_back(chest_hole);\r\n  } else if (s.find(\"stalactite.dat\", 0) != string::npos) {\r\n    vector<Point*> stalactite_hole = CreateStalactiteHole();\r\n    num_points += stalactite_hole.size();\r\n    cdt->AddHole(stalactite_hole);\r\n    polylines.push_back(stalactite_hole);\r\n  } else if (random_distribution) {\r\n    max-=(1e-4);\r\n    min+=(1e-4);\r\n    for(int i = 0; i < num_points; i++) {\r\n      double x = Random(Fun, min, max);\r\n      double y = Random(Fun, min, max);\r\n      cdt->AddPoint(new Point(x, y));\r\n    }\r\n  }\r\n  \r\n  /*\r\n   * STEP 3: Triangulate!\r\n   */\r\n  cdt->Triangulate();\r\n\r\n  double dt = glfwGetTime() - init_time;\r\n\r\n  triangles = cdt->GetTriangles();\r\n  map = cdt->GetMap();\r\n\r\n  cout << \"Number of points = \" << num_points << endl;\r\n  cout << \"Number of triangles = \" << triangles.size() << endl;\r\n  cout << \"Elapsed time (ms) = \" << dt*1000.0 << endl;\r\n\r\n  MainLoop(zoom);\r\n\r\n  // Cleanup\r\n  \n  delete cdt;\r\n  \r\n  // Free points\r\n  for(int i = 0; i < polylines.size(); i++) {\r\n    vector<Point*> poly = polylines[i];\r\n    FreeClear(poly);\r\n  }\r\n  \r\n  ShutDown(0);\r\n  return 0;\r\n}\r\n\r\nvoid Init()\r\n{\r\n  const int window_width = 800,\r\n            window_height = 600;\r\n\r\n  if (glfwInit() != GL_TRUE)\r\n    ShutDown(1);\r\n  // 800 x 600, 16 bit color, no depth, alpha or stencil buffers, windowed\r\n  if (glfwOpenWindow(window_width, window_height, 5, 6, 5, 0, 0, 0, GLFW_WINDOW) != GL_TRUE)\r\n    ShutDown(1);\r\n\r\n  glfwSetWindowTitle(\"Poly2Tri - C++\");\r\n  glfwSwapInterval(1);\r\n\r\n  glEnable(GL_BLEND);\r\n  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);\r\n  glClearColor(0.0, 0.0, 0.0, 0.0);\r\n  glHint(GL_LINE_SMOOTH_HINT, GL_NICEST);\r\n}\r\n\r\nvoid ShutDown(int return_code)\r\n{\r\n  glfwTerminate();\r\n  exit(return_code);\r\n}\r\n\r\nvoid MainLoop(const double zoom)\r\n{\r\n  // the time of the previous frame\r\n  double old_time = glfwGetTime();\r\n  // this just loops as long as the program runs\r\n  bool running = true;\r\n\r\n  while (running) {\r\n    // calculate time elapsed, and the amount by which stuff rotates\r\n    double current_time = glfwGetTime(),\r\n           delta_rotate = (current_time - old_time) * rotations_per_tick * 360;\r\n    old_time = current_time;\r\n\r\n    // escape to quit, arrow keys to rotate view\r\n    // Check if ESC key was pressed or window was closed\r\n    running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam(GLFW_OPENED);\r\n\r\n    if (glfwGetKey(GLFW_KEY_LEFT) == GLFW_PRESS)\r\n      rotate_y += delta_rotate;\r\n    if (glfwGetKey(GLFW_KEY_RIGHT) == GLFW_PRESS)\r\n      rotate_y -= delta_rotate;\r\n    // z axis always rotates\r\n    rotate_z += delta_rotate;\r\n\r\n    // Draw the scene\r\n    if (draw_map) {\r\n      DrawMap(zoom);\r\n    } else {\r\n      Draw(zoom);\r\n    }\r\n\r\n    // swap back and front buffers\r\n    glfwSwapBuffers();\r\n  }\r\n}\r\n\r\nvoid ResetZoom(double zoom, double cx, double cy, double width, double height)\r\n{\r\n  double left = -width / zoom;\r\n  double right = width / zoom;\r\n  double bottom = -height / zoom;\r\n  double top = height / zoom;\r\n\r\n  // Reset viewport\r\n  glLoadIdentity();\r\n  glMatrixMode(GL_PROJECTION);\r\n  glLoadIdentity();\r\n\r\n  // Reset ortho view\r\n  glOrtho(left, right, bottom, top, 1, -1);\r\n  glTranslatef(-cx, -cy, 0);\r\n  glMatrixMode(GL_MODELVIEW);\r\n  glDisable(GL_DEPTH_TEST);\r\n  glLoadIdentity();\r\n\r\n  // Clear the screen\r\n  glClear(GL_COLOR_BUFFER_BIT);\r\n}\r\n\r\nvoid Draw(const double zoom)\r\n{\r\n  // reset zoom\r\n  Point center = Point(cx, cy);\r\n\r\n  ResetZoom(zoom, center.x, center.y, 800, 600);\r\n\r\n  for (int i = 0; i < triangles.size(); i++) {\r\n    Triangle& t = *triangles[i];\r\n    Point& a = *t.GetPoint(0);\r\n    Point& b = *t.GetPoint(1);\r\n    Point& c = *t.GetPoint(2);\r\n\r\n    // Red\r\n    glColor3f(1, 0, 0);\r\n\r\n    glBegin(GL_LINE_LOOP);\r\n    glVertex2f(a.x, a.y);\r\n    glVertex2f(b.x, b.y);\r\n    glVertex2f(c.x, c.y);\r\n    glEnd();\r\n  }\r\n\r\n  // green\r\n  glColor3f(0, 1, 0);\r\n\r\n  for(int i = 0; i < polylines.size(); i++) {\r\n    vector<Point*> poly = polylines[i];\r\n    glBegin(GL_LINE_LOOP);\r\n      for(int j = 0; j < poly.size(); j++) {\r\n        glVertex2f(poly[j]->x, poly[j]->y);\r\n      }\r\n    glEnd();\r\n  }\r\n}\r\n\r\nvoid DrawMap(const double zoom)\r\n{\r\n  // reset zoom\r\n  Point center = Point(cx, cy);\r\n\r\n  ResetZoom(zoom, center.x, center.y, 800, 600);\r\n\r\n  list<Triangle*>::iterator it;\r\n  for (it = map.begin(); it != map.end(); it++) {\r\n    Triangle& t = **it;\r\n    Point& a = *t.GetPoint(0);\r\n    Point& b = *t.GetPoint(1);\r\n    Point& c = *t.GetPoint(2);\r\n\r\n    ConstrainedColor(t.constrained_edge[2]);\r\n    glBegin(GL_LINES);\r\n    glVertex2f(a.x, a.y);\r\n    glVertex2f(b.x, b.y);\r\n    glEnd( );\r\n\r\n    ConstrainedColor(t.constrained_edge[0]);\r\n    glBegin(GL_LINES);\r\n    glVertex2f(b.x, b.y);\r\n    glVertex2f(c.x, c.y);\r\n    glEnd( );\r\n\r\n    ConstrainedColor(t.constrained_edge[1]);\r\n    glBegin(GL_LINES);\r\n    glVertex2f(c.x, c.y);\r\n    glVertex2f(a.x, a.y);\r\n    glEnd( );\r\n  }\r\n}\r\n\r\nvoid ConstrainedColor(bool constrain)\r\n{\r\n  if (constrain) {\r\n    // Green\r\n    glColor3f(0, 1, 0);\r\n  } else {\r\n    // Red\r\n    glColor3f(1, 0, 0);\r\n  }\r\n}\r\n\r\nvector<Point*> CreateHeadHole() {\r\n\r\n  vector<Point*> head_hole;\r\n  head_hole.push_back(new Point(325, 437));\r\n  head_hole.push_back(new Point(320, 423));\r\n  head_hole.push_back(new Point(329, 413));\r\n  head_hole.push_back(new Point(332, 423));\r\n\r\n  return head_hole;\r\n}\r\n\r\nvector<Point*> CreateChestHole() {\r\n\r\n  vector<Point*> chest_hole;\r\n  chest_hole.push_back(new Point(320.72342,480));\r\n  chest_hole.push_back(new Point(338.90617,465.96863));\r\n  chest_hole.push_back(new Point(347.99754,480.61584));\r\n  chest_hole.push_back(new Point(329.8148,510.41534));\r\n  chest_hole.push_back(new Point(339.91632,480.11077));\r\n  chest_hole.push_back(new Point(334.86556,478.09046));\r\n\r\n  return chest_hole;\r\n\r\n}\r\n\r\nvector<Point*> CreateStalactiteHole() {\r\n  vector<Point*> hole;\r\n  hole.push_back(new Point(980, 1636));\r\n  hole.push_back(new Point(950, 1600));\r\n  hole.push_back(new Point(650, 1230));\r\n  hole.push_back(new Point(625, 1247));\r\n  hole.push_back(new Point(600, 1250));\r\n  hole.push_back(new Point(591, 1350));\r\n  hole.push_back(new Point(550, 2050));\r\n\r\n  return hole;\r\n}\r\n\r\ndouble StringToDouble(const std::string& s)\r\n{\r\n  std::istringstream i(s);\r\n  double x;\r\n  if (!(i >> x))\r\n    return 0;\r\n  return x;\r\n}\r\n\r\ndouble Fun(double x)\r\n{\r\n  return 2.5 + sin(10 * x) / x;\r\n}\r\n\r\ndouble Random(double (*fun)(double), double xmin = 0, double xmax = 1)\r\n{\r\n  static double (*Fun)(double) = NULL, YMin, YMax;\r\n  static bool First = true;\r\n\r\n  // Initialises random generator for first call\r\n  if (First)\r\n  {\r\n    First = false;\r\n    srand((unsigned) time(NULL));\r\n  }\r\n\r\n  // Evaluates maximum of function\r\n  if (fun != Fun)\r\n  {\r\n    Fun = fun;\r\n    YMin = 0, YMax = Fun(xmin);\r\n    for (int iX = 1; iX < RAND_MAX; iX++)\r\n    {\r\n      double X = xmin + (xmax - xmin) * iX / RAND_MAX;\r\n      double Y = Fun(X);\r\n      YMax = Y > YMax ? Y : YMax;\r\n    }\r\n  }\r\n\r\n  // Gets random values for X & Y\r\n  double X = xmin + (xmax - xmin) * rand() / RAND_MAX;\r\n  double Y = YMin + (YMax - YMin) * rand() / RAND_MAX;\r\n\r\n  // Returns if valid and try again if not valid\r\n  return Y < fun(X) ? X : Random(Fun, xmin, xmax);\r\n}\r\n"
  },
  {
    "path": "wscript",
    "content": "#! /usr/bin/env python\r\n# encoding: utf-8\r\n# waf 1.6.10\r\n\r\nVERSION='0.3.3'\r\nimport sys\r\nAPPNAME='p2t'\r\ntop = '.'\r\nout = 'build'\r\n\r\nCPP_SOURCES = ['poly2tri/common/shapes.cc',\r\n               'poly2tri/sweep/cdt.cc',\r\n               'poly2tri/sweep/advancing_front.cc',\r\n               'poly2tri/sweep/sweep_context.cc',\r\n               'poly2tri/sweep/sweep.cc',\r\n               'testbed/main.cc']\r\n\r\nfrom waflib.Tools.compiler_cxx import cxx_compiler\r\ncxx_compiler['win32'] = ['g++']\r\n\r\n#Platform specific libs\r\nif sys.platform == 'win32':\r\n    # MS Windows\r\n    sys_libs = ['glfw', 'opengl32']\r\nelif sys.platform == 'darwin':\r\n    # Apple OSX\r\n    sys_libs = ['glfw', 'OpenGL']\r\nelse:\r\n    # GNU/Linux, BSD, etc\r\n    sys_libs = ['glfw', 'GL']\r\n\r\ndef options(opt):\r\n  print('  set_options')\r\n  opt.load('compiler_cxx')\r\n\r\ndef configure(conf):\r\n  print('  calling the configuration')\r\n  conf.load('compiler_cxx')\r\n  conf.env.CXXFLAGS = ['-O3', '-ffast-math']\r\n  conf.env.DEFINES_P2T = ['P2T']\r\n  conf.env.LIB_P2T = sys_libs\r\n\r\ndef build(bld):\r\n  print('  building')\r\n  bld.program(features = 'cxx cxxprogram', source=CPP_SOURCES, target = 'p2t', uselib = 'P2T')\r\n"
  }
]