mirror of
				https://github.com/jhasse/poly2tri.git
				synced 2025-11-04 06:09:31 +01:00 
			
		
		
		
	fixed pointer bug
This commit is contained in:
		@@ -43,8 +43,6 @@ class MonotoneMountain {
 | 
				
			|||||||
	val monoPoly = new ArrayBuffer[Point]
 | 
						val monoPoly = new ArrayBuffer[Point]
 | 
				
			||||||
    // Triangles that constitute the mountain
 | 
					    // Triangles that constitute the mountain
 | 
				
			||||||
	val triangles = new ArrayBuffer[Array[Point]]
 | 
						val triangles = new ArrayBuffer[Array[Point]]
 | 
				
			||||||
	      
 | 
					 | 
				
			||||||
	var angle = 0f
 | 
					 | 
				
			||||||
 
 | 
					 
 | 
				
			||||||
	// Append a point to the list
 | 
						// Append a point to the list
 | 
				
			||||||
	def +=(point: Point) {
 | 
						def +=(point: Point) {
 | 
				
			||||||
@@ -123,16 +121,17 @@ class MonotoneMountain {
 | 
				
			|||||||
	private def convex(p: Point) = {
 | 
						private def convex(p: Point) = {
 | 
				
			||||||
	  val a = (p.next - p) 
 | 
						  val a = (p.next - p) 
 | 
				
			||||||
	  val b = (p.prev - p) 
 | 
						  val b = (p.prev - p) 
 | 
				
			||||||
      angle = Math.atan2(b.y,b.x).toFloat - Math.atan2(a.y,a.x).toFloat
 | 
					      var angle = Math.atan2(b.y,b.x) - Math.atan2(a.y,a.x)
 | 
				
			||||||
      if(angle < 0) while(angle < -Math.Pi) angle += Math.Pi.toFloat
 | 
					      if(angle < 0) while(angle < -Math.Pi) angle += Math.Pi
 | 
				
			||||||
      if(angle > 0) while(angle > Math.Pi) angle -= Math.Pi.toFloat
 | 
					      if(angle > 0) while(angle > Math.Pi) angle -= Math.Pi
 | 
				
			||||||
      // For numerical robustness....
 | 
					      // For numerical robustness....
 | 
				
			||||||
      angle = 0.01f * Math.round( angle * 10.0f)
 | 
					      angle = 0.1 * Math.round( angle * 10.0)
 | 
				
			||||||
 | 
					      val cvx = (angle < 0)
 | 
				
			||||||
      if(p.y >= head.y) {
 | 
					      if(p.y >= head.y) {
 | 
				
			||||||
        (angle < 0)
 | 
					        cvx
 | 
				
			||||||
      } else {
 | 
					      } else {
 | 
				
			||||||
        !(angle < 0)
 | 
					        !cvx
 | 
				
			||||||
      }
 | 
					      } 
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	private def lastTriangle {
 | 
						private def lastTriangle {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -59,6 +59,7 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
 | 
				
			|||||||
  var quit = false
 | 
					  var quit = false
 | 
				
			||||||
  var debug = false
 | 
					  var debug = false
 | 
				
			||||||
  var drawMap = false
 | 
					  var drawMap = false
 | 
				
			||||||
 | 
					  var hiLighter = 0
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  def init(container: GameContainer) {
 | 
					  def init(container: GameContainer) {
 | 
				
			||||||
    snake
 | 
					    snake
 | 
				
			||||||
@@ -92,11 +93,14 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
 | 
				
			|||||||
   }
 | 
					   }
 | 
				
			||||||
   
 | 
					   
 | 
				
			||||||
   if(!debug) {
 | 
					   if(!debug) {
 | 
				
			||||||
 | 
					    var i = 0
 | 
				
			||||||
    for(t <- tesselator.triangles) {
 | 
					    for(t <- tesselator.triangles) {
 | 
				
			||||||
        val triangle = new Polygon
 | 
					        val triangle = new Polygon
 | 
				
			||||||
        t.foreach(p => triangle.addPoint(p.x, p.y))
 | 
					        t.foreach(p => triangle.addPoint(p.x, p.y))
 | 
				
			||||||
        g.setColor(red)
 | 
					        val color = if(i == hiLighter) blue else red
 | 
				
			||||||
 | 
					        g.setColor(color)
 | 
				
			||||||
        g.draw(triangle)
 | 
					        g.draw(triangle)
 | 
				
			||||||
 | 
					        i += 1
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
   } else {
 | 
					   } else {
 | 
				
			||||||
    for(mp <- tesselator.monoPolies) {
 | 
					    for(mp <- tesselator.monoPolies) {
 | 
				
			||||||
@@ -110,12 +114,27 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  override def keyPressed(key:Int, c:Char) {
 | 
					  override def keyPressed(key:Int, c:Char) {
 | 
				
			||||||
 | 
					    // ESC
 | 
				
			||||||
    if(key == 1) quit = true
 | 
					    if(key == 1) quit = true
 | 
				
			||||||
 | 
					    // SPACE
 | 
				
			||||||
    if(key == 57) debug = !debug
 | 
					    if(key == 57) debug = !debug
 | 
				
			||||||
 | 
					    // UP
 | 
				
			||||||
 | 
					    if(key == 200) {
 | 
				
			||||||
 | 
					      hiLighter += 1
 | 
				
			||||||
 | 
					      if (hiLighter == tesselator.triangles.size)
 | 
				
			||||||
 | 
					        hiLighter = 0
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    // DOWN
 | 
				
			||||||
 | 
					    if(key == 208) {
 | 
				
			||||||
 | 
					      hiLighter -= 1
 | 
				
			||||||
 | 
					      if (hiLighter == -1)
 | 
				
			||||||
 | 
					        hiLighter = tesselator.triangles.size-1
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
    if(c == 'm') drawMap = !drawMap
 | 
					    if(c == 'm') drawMap = !drawMap
 | 
				
			||||||
    if(c == '1') poly
 | 
					    if(c == '1') {poly; hiLighter = 0}
 | 
				
			||||||
    if(c == '2') snake
 | 
					    if(c == '2') {snake; hiLighter = 0}
 | 
				
			||||||
    if(c == '3') star
 | 
					    if(c == '3') {star; hiLighter = 0}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Test #1
 | 
					  // Test #1
 | 
				
			||||||
@@ -143,18 +162,16 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
 | 
				
			|||||||
  
 | 
					  
 | 
				
			||||||
  def star {
 | 
					  def star {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	val scale = 1.0f
 | 
					    val p1 = new Point(350,75)
 | 
				
			||||||
    val displace = 0f
 | 
					    val p2 = new Point(379,161)
 | 
				
			||||||
    val p1 = new Point(350,75)*scale+displace
 | 
					    val p3 = new Point(469,161)
 | 
				
			||||||
    val p2 = new Point(379,161)*scale+displace
 | 
					    val p4 = new Point(397,215)
 | 
				
			||||||
    val p3 = new Point(469,161)*scale+displace
 | 
					    val p5 = new Point(423,301)
 | 
				
			||||||
    val p4 = new Point(397,215)*scale+displace
 | 
					    val p6 = new Point(350,250)
 | 
				
			||||||
    val p5 = new Point(423,301)*scale+displace
 | 
					    val p7 = new Point(277,301)
 | 
				
			||||||
    val p6 = new Point(350,250)*scale+displace
 | 
					    val p8 = new Point(303,215)
 | 
				
			||||||
    val p7 = new Point(277,301)*scale+displace
 | 
					    val p9 = new Point(231,161)
 | 
				
			||||||
    val p8 = new Point(303,215)*scale+displace
 | 
					    val p10 = new Point(321,161)
 | 
				
			||||||
    val p9 = new Point(231,161)*scale+displace
 | 
					 | 
				
			||||||
    val p10 = new Point(321,161)*scale+displace
 | 
					 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    val segments = new ArrayBuffer[Segment]
 | 
					    val segments = new ArrayBuffer[Segment]
 | 
				
			||||||
    segments += new Segment(p1, p2)
 | 
					    segments += new Segment(p1, p2)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -48,7 +48,7 @@ class QueryGraph(var head: Node) {
 | 
				
			|||||||
	      if(s > trapezoids(j).rightPoint) {
 | 
						      if(s > trapezoids(j).rightPoint) {
 | 
				
			||||||
	        trapezoids += trapezoids(j).upperRight
 | 
						        trapezoids += trapezoids(j).upperRight
 | 
				
			||||||
	      } else {
 | 
						      } else {
 | 
				
			||||||
	        trapezoids += trapezoids(j).lowerRight
 | 
						          trapezoids += trapezoids(j).lowerRight
 | 
				
			||||||
	      }
 | 
						      }
 | 
				
			||||||
	      j += 1
 | 
						      j += 1
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,18 +41,21 @@ class Trapezoid(val leftPoint: Point, var rightPoint: Point, val top: Segment, v
 | 
				
			|||||||
  var upperRight: Trapezoid = null
 | 
					  var upperRight: Trapezoid = null
 | 
				
			||||||
  var lowerRight: Trapezoid = null
 | 
					  var lowerRight: Trapezoid = null
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  def updateNeighbors(ul: Trapezoid, ll: Trapezoid, ur: Trapezoid, lr: Trapezoid) {
 | 
					  def updateLeftNeighbors(ul: Trapezoid, ll: Trapezoid) {
 | 
				
			||||||
    if(upperLeft != null && upperLeft.top == top) upperLeft.upperRight = ul
 | 
					    if(upperLeft != null && upperLeft.top == top) upperLeft.upperRight = ul
 | 
				
			||||||
    if(lowerLeft != null && lowerLeft.bottom == bottom) lowerLeft.lowerRight = ll
 | 
					    if(lowerLeft != null && lowerLeft.bottom == bottom) lowerLeft.lowerRight = ll
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
 | 
					  def updateRightNeighbors(ur: Trapezoid, lr: Trapezoid) {
 | 
				
			||||||
    if(upperRight != null && upperRight.top == top) upperRight.upperLeft = ur
 | 
					    if(upperRight != null && upperRight.top == top) upperRight.upperLeft = ur
 | 
				
			||||||
    if(lowerRight != null && lowerRight.bottom == bottom) lowerRight.lowerLeft = lr
 | 
					    if(lowerRight != null && lowerRight.bottom == bottom) lowerRight.lowerLeft = lr
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  def update(ul: Trapezoid, ll: Trapezoid, ur: Trapezoid, lr: Trapezoid) {
 | 
					  def update(ul: Trapezoid, ll: Trapezoid, ur: Trapezoid, lr: Trapezoid) {
 | 
				
			||||||
    upperLeft = ul
 | 
					    upperLeft = ul; if(ul != null) ul.upperRight = this
 | 
				
			||||||
    lowerLeft = ll
 | 
					    lowerLeft = ll; if(ll != null) ll.lowerRight = this
 | 
				
			||||||
    upperRight = ur
 | 
					    upperRight = ur; if(ur != null) ur.upperLeft = this
 | 
				
			||||||
    lowerRight = lr
 | 
					    lowerRight = lr; if(lr != null) lr.lowerLeft = this    
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  def markNeighbors {
 | 
					  def markNeighbors {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -81,7 +81,6 @@ class TrapezoidalMap {
 | 
				
			|||||||
    s.above = trapezoids(1)
 | 
					    s.above = trapezoids(1)
 | 
				
			||||||
    s.below = trapezoids(2)
 | 
					    s.below = trapezoids(2)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    t.updateNeighbors(trapezoids(0), trapezoids(0), trapezoids(3), trapezoids(3))
 | 
					 | 
				
			||||||
    trapezoids
 | 
					    trapezoids
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -105,7 +104,6 @@ class TrapezoidalMap {
 | 
				
			|||||||
    s.above = trapezoids(1)
 | 
					    s.above = trapezoids(1)
 | 
				
			||||||
    s.below = trapezoids(2)
 | 
					    s.below = trapezoids(2)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    t.updateNeighbors(trapezoids(0), trapezoids(0), trapezoids(1), trapezoids(2))
 | 
					 | 
				
			||||||
    trapezoids
 | 
					    trapezoids
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
@@ -126,18 +124,18 @@ class TrapezoidalMap {
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    if(topCross) {
 | 
					    if(topCross) {
 | 
				
			||||||
      trapezoids(0).upperRight = t.upperRight
 | 
					      trapezoids(0).upperRight = t.upperRight
 | 
				
			||||||
      trapezoids(0).rightPoint = t.rightPoint
 | 
					      if(t.upperRight != null) t.upperRight.upperLeft = trapezoids(0)
 | 
				
			||||||
 | 
					      trapezoids(0).rightPoint = rp
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      trapezoids(0).update(t.upperLeft, s.above, t.upperRight, null)
 | 
					      trapezoids(0).update(t.upperLeft, s.above, t.upperRight, null)
 | 
				
			||||||
      if(s.above != null) s.above.lowerRight = trapezoids(0)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if(bottomCross) {
 | 
					    if(bottomCross) {
 | 
				
			||||||
      trapezoids(1).lowerRight = t.lowerRight
 | 
					      trapezoids(1).lowerRight = t.lowerRight
 | 
				
			||||||
      trapezoids(1).rightPoint = t.rightPoint
 | 
					      if(t.lowerRight != null) t.lowerRight.lowerLeft = trapezoids(1)
 | 
				
			||||||
 | 
					      trapezoids(1).rightPoint = rp
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      trapezoids(1).update(s.below, t.lowerLeft, null, t.lowerRight)
 | 
					      trapezoids(1).update(s.below, t.lowerLeft, null, t.lowerRight)
 | 
				
			||||||
      if(s.below != null) s.below.upperRight = trapezoids(1)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    bCross = t.bottom
 | 
					    bCross = t.bottom
 | 
				
			||||||
@@ -145,7 +143,6 @@ class TrapezoidalMap {
 | 
				
			|||||||
    s.above = trapezoids(0)
 | 
					    s.above = trapezoids(0)
 | 
				
			||||||
    s.below = trapezoids(1)
 | 
					    s.below = trapezoids(1)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    t.updateNeighbors(trapezoids(0), trapezoids(1), trapezoids(0), trapezoids(1))
 | 
					 | 
				
			||||||
    trapezoids
 | 
					    trapezoids
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
@@ -168,7 +165,6 @@ class TrapezoidalMap {
 | 
				
			|||||||
      trapezoids(0).rightPoint = s.q
 | 
					      trapezoids(0).rightPoint = s.q
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      trapezoids(0).update(t.upperLeft, s.above, trapezoids(2), null)
 | 
					      trapezoids(0).update(t.upperLeft, s.above, trapezoids(2), null)
 | 
				
			||||||
      if(s.above != null) s.above.lowerRight = trapezoids(0)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    if(bottomCross) {
 | 
					    if(bottomCross) {
 | 
				
			||||||
@@ -176,14 +172,10 @@ class TrapezoidalMap {
 | 
				
			|||||||
      trapezoids(1).rightPoint = s.q
 | 
					      trapezoids(1).rightPoint = s.q
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
      trapezoids(1).update(s.below, t.lowerLeft, null, trapezoids(2))
 | 
					      trapezoids(1).update(s.below, t.lowerLeft, null, trapezoids(2))
 | 
				
			||||||
      if(s.below != null) s.below.upperRight = trapezoids(1)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
    trapezoids(2).update(trapezoids(0), trapezoids(1), t.upperRight, t.lowerRight)
 | 
					    trapezoids(2).update(trapezoids(0), trapezoids(1), t.upperRight, t.lowerRight)
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    s.above = trapezoids(0)
 | 
					 | 
				
			||||||
    s.below = trapezoids(1)
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    t.updateNeighbors(trapezoids(0), trapezoids(1), trapezoids(2), trapezoids(2))
 | 
					 | 
				
			||||||
    trapezoids
 | 
					    trapezoids
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,11 +36,12 @@ import scala.collection.mutable.ArrayBuffer
 | 
				
			|||||||
// algorithm for computing trapezoidal decompositions and for triangulating polygons"
 | 
					// algorithm for computing trapezoidal decompositions and for triangulating polygons"
 | 
				
			||||||
class Triangulator(var segments: ArrayBuffer[Segment]) {
 | 
					class Triangulator(var segments: ArrayBuffer[Segment]) {
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // Trapezoid decomposition list
 | 
					 | 
				
			||||||
  var trapezoids : ArrayBuffer[Trapezoid] = null
 | 
					 | 
				
			||||||
  // Triangle decomposition list
 | 
					  // Triangle decomposition list
 | 
				
			||||||
  var triangles = new ArrayBuffer[Array[Point]]
 | 
					  var triangles = new ArrayBuffer[Array[Point]]
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
 | 
					  // Order and randomize the segments
 | 
				
			||||||
 | 
					  segments = orderSegments
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
  // Build the trapezoidal map and query graph
 | 
					  // Build the trapezoidal map and query graph
 | 
				
			||||||
  def process {
 | 
					  def process {
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
@@ -81,10 +82,14 @@ class Triangulator(var segments: ArrayBuffer[Segment]) {
 | 
				
			|||||||
    for(i <- 0 until xMonoPoly.size)
 | 
					    for(i <- 0 until xMonoPoly.size)
 | 
				
			||||||
      for(t <- xMonoPoly(i).triangles)
 | 
					      for(t <- xMonoPoly(i).triangles)
 | 
				
			||||||
    	  triangles += t
 | 
					    	  triangles += t
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					    println("# triangles = " + triangles.size)
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  
 | 
					  
 | 
				
			||||||
  // For debugging
 | 
					  // The trapezoidal map 
 | 
				
			||||||
  def trapezoidMap = trapezoidalMap.map
 | 
					  def trapezoidMap = trapezoidalMap.map
 | 
				
			||||||
 | 
					  // Trapezoid decomposition list
 | 
				
			||||||
 | 
					  var trapezoids : ArrayBuffer[Trapezoid] = null
 | 
				
			||||||
  // Monotone polygons - these are monotone mountains
 | 
					  // Monotone polygons - these are monotone mountains
 | 
				
			||||||
  def monoPolies: ArrayBuffer[ArrayBuffer[Point]] = {
 | 
					  def monoPolies: ArrayBuffer[ArrayBuffer[Point]] = {
 | 
				
			||||||
    val polies = new ArrayBuffer[ArrayBuffer[Point]]
 | 
					    val polies = new ArrayBuffer[ArrayBuffer[Point]]
 | 
				
			||||||
@@ -99,8 +104,6 @@ class Triangulator(var segments: ArrayBuffer[Segment]) {
 | 
				
			|||||||
  private val queryGraph = new QueryGraph(new Sink(boundingBox))
 | 
					  private val queryGraph = new QueryGraph(new Sink(boundingBox))
 | 
				
			||||||
  private val xMonoPoly = new ArrayBuffer[MonotoneMountain]
 | 
					  private val xMonoPoly = new ArrayBuffer[MonotoneMountain]
 | 
				
			||||||
                                        
 | 
					                                        
 | 
				
			||||||
  segments = orderSegments
 | 
					 | 
				
			||||||
  
 | 
					 | 
				
			||||||
  // Build a list of x-monotone mountains
 | 
					  // Build a list of x-monotone mountains
 | 
				
			||||||
  private def createMountains {
 | 
					  private def createMountains {
 | 
				
			||||||
    for(s <- segments) {
 | 
					    for(s <- segments) {
 | 
				
			||||||
@@ -143,9 +146,8 @@ class Triangulator(var segments: ArrayBuffer[Segment]) {
 | 
				
			|||||||
        s.p = s.q
 | 
					        s.p = s.q
 | 
				
			||||||
        s.q = tmp
 | 
					        s.q = tmp
 | 
				
			||||||
        segs += s
 | 
					        segs += s
 | 
				
			||||||
      } else if(s.p.x < s.q.x) {
 | 
					      } else if(s.p.x < s.q.x)
 | 
				
			||||||
        segs += s
 | 
					          segs += s
 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    // This is actually important: See Seidel's paper
 | 
					    // This is actually important: See Seidel's paper
 | 
				
			||||||
    Random.shuffle(segs)
 | 
					    Random.shuffle(segs)
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user