mirror of
				https://github.com/jhasse/poly2tri.git
				synced 2025-11-04 06:09:31 +01:00 
			
		
		
		
	updated comments; optimizations
This commit is contained in:
		@@ -413,9 +413,10 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
 | 
			
		||||
    
 | 
			
		||||
          headSegs = new ArrayBuffer[Segment]
 | 
			
		||||
	      for(i <- 0 until headHole.size-1)
 | 
			
		||||
	        chestSegs += new Segment(headHole(i), headHole(i+1))
 | 
			
		||||
	      chestSegs += new Segment(headHole.first, headHole.last)
 | 
			
		||||
	        headSegs += new Segment(headHole(i), headHole(i+1))
 | 
			
		||||
	      headSegs += new Segment(headHole.first, headHole.last)
 | 
			
		||||
       
 | 
			
		||||
          // Add the holes
 | 
			
		||||
          slCDT.addHole(headHole)
 | 
			
		||||
          slCDT.addHole(chestHole)
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -99,6 +99,7 @@ class AFront(iTriangle: Triangle) {
 | 
			
		||||
    val point2 = edge.p
 | 
			
		||||
    
 | 
			
		||||
    // Scan the advancing front and update Node triangle pointers
 | 
			
		||||
    // TODO: Make this more efficient
 | 
			
		||||
    while(node != null && node != eNode.next) {
 | 
			
		||||
      T2.foreach(t => {
 | 
			
		||||
        if(t.contains(node.point, node.next.point))
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,7 @@ import utils.Util
 | 
			
		||||
// and triangle traversal respectively. See figure 14(a) from Domiter et al.
 | 
			
		||||
// Although it may not be necessary for simple polygons....
 | 
			
		||||
 | 
			
		||||
// clearPoint is any interior point inside the polygon                                                      
 | 
			
		||||
class CDT(polyLine: Array[Point], clearPoint: Point) {
 | 
			
		||||
        
 | 
			
		||||
  // Triangle list
 | 
			
		||||
@@ -140,6 +141,7 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
 | 
			
		||||
  private def sweep {
 | 
			
		||||
    
 | 
			
		||||
    for(i <- 1 until points.size) {
 | 
			
		||||
      
 | 
			
		||||
      val point = points(i)
 | 
			
		||||
      // Process Point event
 | 
			
		||||
      val node = pointEvent(point)
 | 
			
		||||
@@ -149,18 +151,21 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
 | 
			
		||||
    
 | 
			
		||||
  }  
 | 
			
		||||
  
 | 
			
		||||
  // Final step in the sweep-line CDT algo
 | 
			
		||||
  // Final step in the sweep-line CDT 
 | 
			
		||||
  // Clean exterior triangles
 | 
			
		||||
  private def finalization {
 | 
			
		||||
    
 | 
			
		||||
    var found = false
 | 
			
		||||
    mesh.map.foreach(m => {
 | 
			
		||||
      if(!found)
 | 
			
		||||
        // Mark the originating clean triangle
 | 
			
		||||
        if(m.pointIn(clearPoint)) {
 | 
			
		||||
          found = true
 | 
			
		||||
          cleanTri = m
 | 
			
		||||
         }
 | 
			
		||||
      m.markNeighborEdges
 | 
			
		||||
    })
 | 
			
		||||
    // Collect interior triangles constrained by edges
 | 
			
		||||
    mesh clean cleanTri
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
@@ -367,7 +372,7 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
 | 
			
		||||
      do {
 | 
			
		||||
        angle = fill(node1)
 | 
			
		||||
        node1 = node1.next
 | 
			
		||||
      } while(angle <= PI_2 && node1.next != null) 
 | 
			
		||||
      } while(angle <= PI_2 && angle >= -PI_2 && node1.next != null) 
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    var node2 = n.prev
 | 
			
		||||
@@ -377,17 +382,19 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
 | 
			
		||||
      do {
 | 
			
		||||
	    angle = fill(node2)
 | 
			
		||||
        node2 = node2.prev
 | 
			
		||||
      } while(angle <= PI_2 && node2.prev != null)
 | 
			
		||||
      } while(angle <= PI_2 && angle >= -PI_2 && node2.prev != null)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Fill empty space with a triangle
 | 
			
		||||
  private def fill(node: Node): Double = {
 | 
			
		||||
    
 | 
			
		||||
	  val a = (node.prev.point - node.point)
 | 
			
		||||
	  val b = (node.next.point - node.point)
 | 
			
		||||
	  val angle = Math.abs(Math.atan2(a cross b, a dot b))
 | 
			
		||||
	  if(angle <= PI_2) {
 | 
			
		||||
	  val angle = Math.atan2(a cross b, a dot b)
 | 
			
		||||
      // Is the angle acute?
 | 
			
		||||
	  if(angle <= PI_2 && angle >= -PI_2) {
 | 
			
		||||
	    val points = Array(node.prev.point, node.point, node.next.point)
 | 
			
		||||
	    val triangle = new Triangle(points)
 | 
			
		||||
        // Update neighbor pointers
 | 
			
		||||
 
 | 
			
		||||
@@ -30,20 +30,23 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.poly2tri.cdt
 | 
			
		||||
 | 
			
		||||
import scala.collection.mutable.{HashSet, ArrayBuffer}
 | 
			
		||||
import scala.collection.mutable.ArrayBuffer
 | 
			
		||||
 | 
			
		||||
import shapes.{Point, Triangle}
 | 
			
		||||
 | 
			
		||||
class Mesh {
 | 
			
		||||
  
 | 
			
		||||
  // Triangles that constitute the mesh
 | 
			
		||||
  val map = HashSet.empty[Triangle]
 | 
			
		||||
  val map = new ArrayBuffer[Triangle]
 | 
			
		||||
  // Debug triangles
 | 
			
		||||
  val debug = HashSet.empty[Triangle]
 | 
			
		||||
  val debug = new ArrayBuffer[Triangle]
 | 
			
		||||
  val triangles = new ArrayBuffer[Triangle]
 | 
			
		||||
  
 | 
			
		||||
  // Recursively collect triangles
 | 
			
		||||
  // Recursively collect interior triangles and clean the mesh
 | 
			
		||||
  // Excludes exterior triangles outside constrained edges
 | 
			
		||||
  // TODO: Investigate depth first search as an alternative
 | 
			
		||||
  def clean(triangle: Triangle) {
 | 
			
		||||
    
 | 
			
		||||
    if(triangle != null && !triangle.interior) {
 | 
			
		||||
      triangle.interior = true
 | 
			
		||||
      triangles += triangle
 | 
			
		||||
 
 | 
			
		||||
@@ -30,7 +30,6 @@
 | 
			
		||||
 */
 | 
			
		||||
package org.poly2tri.shapes
 | 
			
		||||
 | 
			
		||||
import scala.collection.mutable.HashSet
 | 
			
		||||
import scala.collection.mutable.ArrayBuffer
 | 
			
		||||
 | 
			
		||||
import utils.Util
 | 
			
		||||
@@ -80,6 +79,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
      neighbors(2) = t
 | 
			
		||||
      t.markNeighbor(points(0), points(1), this)
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  def clearNeighbors {
 | 
			
		||||
@@ -87,6 +87,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  def oppositePoint(t: Triangle): Point = {
 | 
			
		||||
    
 | 
			
		||||
    assert(t != this, "self-pointer error")
 | 
			
		||||
    if(points(0) == t.points(1)) 
 | 
			
		||||
      points(1)
 | 
			
		||||
@@ -123,6 +124,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
 | 
			
		||||
  // Locate first triangle crossed by constrained edge
 | 
			
		||||
  def locateFirst(edge: Segment): Triangle = {
 | 
			
		||||
    
 | 
			
		||||
    if(contains(edge)) this
 | 
			
		||||
    if(edge.q == points(0)) 
 | 
			
		||||
      search(points(1), points(2), edge, neighbors(2))
 | 
			
		||||
@@ -171,6 +173,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  
 | 
			
		||||
  // The neighbor clockwise to given point
 | 
			
		||||
  def neighborCW(point: Point): Triangle = {
 | 
			
		||||
    
 | 
			
		||||
    if(point == points(0)) {
 | 
			
		||||
      neighbors(1)
 | 
			
		||||
    }else if(point == points(1)) {
 | 
			
		||||
@@ -181,6 +184,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  
 | 
			
		||||
  // The neighbor counter-clockwise to given point
 | 
			
		||||
  def neighborCCW(oPoint: Point): Triangle = {
 | 
			
		||||
    
 | 
			
		||||
    if(oPoint == points(0)) {
 | 
			
		||||
      neighbors(2)
 | 
			
		||||
    }else if(oPoint == points(1)) {
 | 
			
		||||
@@ -191,6 +195,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  
 | 
			
		||||
  // The neighbor clockwise to given point
 | 
			
		||||
  def neighborAcross(point: Point): Triangle = {
 | 
			
		||||
    
 | 
			
		||||
    if(point == points(0)) {
 | 
			
		||||
      neighbors(0)
 | 
			
		||||
    }else if(point == points(1)) {
 | 
			
		||||
@@ -201,6 +206,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  
 | 
			
		||||
  // The point counter-clockwise to given point
 | 
			
		||||
  def pointCCW(point: Point): Point = {
 | 
			
		||||
    
 | 
			
		||||
    if(point == points(0)) {
 | 
			
		||||
      points(1)
 | 
			
		||||
    } else if(point == points(1)) {
 | 
			
		||||
@@ -214,6 +220,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  
 | 
			
		||||
  // The point counter-clockwise to given point
 | 
			
		||||
  def pointCW(point: Point): Point = {
 | 
			
		||||
    
 | 
			
		||||
    if(point == points(0)) {
 | 
			
		||||
      points(2)
 | 
			
		||||
    } else if(point == points(1)) {
 | 
			
		||||
@@ -227,6 +234,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  
 | 
			
		||||
  // Legalized triangle by rotating clockwise around point(0)
 | 
			
		||||
  def legalize(oPoint: Point) {
 | 
			
		||||
    
 | 
			
		||||
	points(1) = points(0)
 | 
			
		||||
	points(0) = points(2)
 | 
			
		||||
	points(2) = oPoint
 | 
			
		||||
@@ -234,6 +242,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  
 | 
			
		||||
  // Legalize triagnle by rotating clockwise around oPoint
 | 
			
		||||
  def legalize(oPoint: Point, nPoint: Point) {
 | 
			
		||||
    
 | 
			
		||||
    if(oPoint == points(0)) {
 | 
			
		||||
      points(1) = points(0)
 | 
			
		||||
      points(0) = points(2)
 | 
			
		||||
@@ -257,6 +266,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  
 | 
			
		||||
  // Check if legalized triangle will be collinear
 | 
			
		||||
  def collinear(oPoint: Point, nPoint: Point): Boolean = {
 | 
			
		||||
    
 | 
			
		||||
    if(oPoint == points(0)) {
 | 
			
		||||
      Util.collinear(points(0), points(2), nPoint)
 | 
			
		||||
    } else if (oPoint == points(1)) {
 | 
			
		||||
@@ -268,6 +278,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  
 | 
			
		||||
  // Rotate neighbors clockwise around give point. Share diagnal with triangle
 | 
			
		||||
  def rotateNeighborsCW(oPoint: Point, triangle: Triangle) {
 | 
			
		||||
    
 | 
			
		||||
    if(oPoint == points(0)) {
 | 
			
		||||
      neighbors(2) = neighbors(1)
 | 
			
		||||
      neighbors(1) = null
 | 
			
		||||
@@ -289,6 +300,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
 | 
			
		||||
  // Finalize edge marking
 | 
			
		||||
  def markNeighborEdges {
 | 
			
		||||
    
 | 
			
		||||
    for(i <- 0 to 2) 
 | 
			
		||||
      if(edges(i)) 
 | 
			
		||||
        i match {
 | 
			
		||||
@@ -299,6 +311,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  def markEdge(triangle: Triangle) {
 | 
			
		||||
    
 | 
			
		||||
    for(i <- 0 to 2) 
 | 
			
		||||
      if(edges(i)) 
 | 
			
		||||
        i match {
 | 
			
		||||
@@ -309,6 +322,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  def markEdge(T: ArrayBuffer[Triangle]) {
 | 
			
		||||
    
 | 
			
		||||
    for(t <- T) {
 | 
			
		||||
	    for(i <- 0 to 2) 
 | 
			
		||||
	      if(t.edges(i)) 
 | 
			
		||||
@@ -322,6 +336,7 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  
 | 
			
		||||
  // Mark edge as constrained
 | 
			
		||||
  def markEdge(p: Point, q: Point) {
 | 
			
		||||
    
 | 
			
		||||
    if((q == points(0) && p == points(1)) || (q == points(1) && p == points(0))) {
 | 
			
		||||
      finalized = true
 | 
			
		||||
      edges(2) = true
 | 
			
		||||
@@ -335,12 +350,14 @@ class Triangle(val points: Array[Point]) {
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  def area = {
 | 
			
		||||
    
 | 
			
		||||
    val b = points(0).x - points(1).x
 | 
			
		||||
    val h = points(2).y - points(1).y
 | 
			
		||||
    (b*h*0.5f)
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  def centroid: Point = {
 | 
			
		||||
    
 | 
			
		||||
    val cx = (points(0).x + points(1).x + points(2).x)/3f
 | 
			
		||||
    val cy = (points(0).y + points(1).y + points(2).y)/3f
 | 
			
		||||
    Point(cx, cy)
 | 
			
		||||
 
 | 
			
		||||
@@ -14,7 +14,7 @@ object Util {
 | 
			
		||||
  val ccwerrboundA = (3.0 + 16.0 * epsilon) * epsilon
 | 
			
		||||
  val iccerrboundA = (10.0 + 96.0 * epsilon) * epsilon
 | 
			
		||||
  
 | 
			
		||||
  // From "Scala By Example," by Martin Odersky
 | 
			
		||||
  // Refursive merge sort, from "Scala By Example," by Martin Odersky
 | 
			
		||||
  def msort[A](less: (A, A) => Boolean)(xs: List[A]): List[A] = {
 | 
			
		||||
    def merge(xs1: List[A], xs2: List[A]): List[A] =
 | 
			
		||||
      if (xs1.isEmpty) xs2
 | 
			
		||||
@@ -26,6 +26,7 @@ object Util {
 | 
			
		||||
      else merge(msort(less)(xs take n), msort(less)(xs drop n))
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  // Insertion sort - best for lists <= 10 elements
 | 
			
		||||
  def insertSort[A](less: (A, A) => Boolean)(xs: ArrayBuffer[A]): ArrayBuffer[A] = {    
 | 
			
		||||
    var j = 1
 | 
			
		||||
    while(j < xs.size){   
 | 
			
		||||
@@ -46,7 +47,7 @@ object Util {
 | 
			
		||||
 | 
			
		||||
    val d = Math.abs((p2-p1) cross (p1-p3))
 | 
			
		||||
    
 | 
			
		||||
    if(Math.abs(d) <= COLLINEAR_SLOP) 
 | 
			
		||||
    if(d <= COLLINEAR_SLOP) 
 | 
			
		||||
      true
 | 
			
		||||
    else 
 | 
			
		||||
      false
 | 
			
		||||
@@ -157,7 +158,7 @@ object Util {
 | 
			
		||||
     (center, radius)
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
   def det(p1: Point, p2: Point, p3: Point): Float = {
 | 
			
		||||
   private def det(p1: Point, p2: Point, p3: Point): Float = {
 | 
			
		||||
     
 | 
			
		||||
     val a11 = p1.x
 | 
			
		||||
     val a12 = p1.y
 | 
			
		||||
@@ -171,7 +172,7 @@ object Util {
 | 
			
		||||
     
 | 
			
		||||
   }
 | 
			
		||||
   
 | 
			
		||||
   def detC(p1: Point, p2: Point, p3: Point): Float = {
 | 
			
		||||
   private def detC(p1: Point, p2: Point, p3: Point): Float = {
 | 
			
		||||
     
 | 
			
		||||
     val a11 = p1.x*p1.x + p1.y*p1.y
 | 
			
		||||
     val a12 = p1.x
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user