added new circumcenter test

This commit is contained in:
zzzzrrr 2009-08-24 20:07:36 -04:00
parent 5811c2c0d1
commit daa7b135c8
4 changed files with 107 additions and 4 deletions

View File

@ -210,6 +210,13 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
g.draw(triangle)
})
//slCDT.cList.foreach(c => {
for(i <- 0 until 7) {
val circ = new Circle(slCDT.cList(i).x, slCDT.cList(i).y, 0.5f)
g.setColor(blue); g.draw(circ); g.fill(circ)
}
//})
}
if(drawSegs) {
@ -243,6 +250,11 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
mousePressed = true
mousePosOld = mousePos
mousePos = Point(x, y)
/*
val point = mousePos/scaleFactor + Point(deltaX, deltaY)
slCDT.addPoint(point)
slCDT.triangulate
*/
}
/**
@ -424,6 +436,15 @@ class Poly2TriDemo extends BasicGame("Poly2Tri") {
slCDT triangulate
val runTime = System.nanoTime - t1
if(slCDT.cList.size > 1) {
//slCDT.addPoint(slCDT.cList(0))
//slCDT.addPoint(slCDT.cList(1))
println(slCDT.cList.size)
for(i <- 0 until 7)
slCDT.addPoint(slCDT.cList(i))
slCDT.triangulate
}
println("CDT average (ms) = " + runTime*1e-6)
println("Number of triangles = " + slCDT.triangles.size)
println

View File

@ -53,6 +53,9 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
def triangleMesh = mesh.map
def debugTriangles = mesh.debug
val cList = new ArrayBuffer[Point]
var refine = false
// Initialize edges
initEdges(polyLine)
@ -62,9 +65,20 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
points = points ++ holePolyLine.toList
}
// Add an internal point
// Good for manually refining the mesh. Use this when you want to eliminate
// skinny triangles
def addPoint(point: Point) {
points = point :: points
}
// Triangulate simple polygon with holes
def triangulate {
mesh.map.clear
mesh.triangles.clear
mesh.debug.clear
var xmax, xmin = points.first.x
var ymax, ymin = points.first.y
@ -125,7 +139,6 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
if(p1.x > p2.x) {
return List(p2, p1)
} else if(p1.x == p2.x) {
println(p1 + "," + p2)
throw new Exception("Duplicate point")
}
}
@ -139,8 +152,10 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
// Implement sweep-line
private def sweep {
// 48 67
val size = if(refine) 68 else points.size
for(i <- 1 until points.size) {
for(i <- 1 until size) {
val point = points(i)
// Process Point event
@ -167,6 +182,17 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
})
// Collect interior triangles constrained by edges
mesh clean cleanTri
mesh.triangles.foreach(t => {
if(t.thin) {
val center = Util.circumcenter(t.points(0), t.points(1), t.points(2))
cList += center
refine = true
//addPoint(center)
//mesh.debug += t
}
})
}
// Point event
@ -286,12 +312,24 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
nTriangles += pNode.triangle
pNode = pNode.next
while(pNode.point != point2 && edge > pNode.point) {
while(pNode.point != point2) {
points += pNode.point
nTriangles += pNode.triangle
pNode = pNode.next
}
val s = new Segment(first.point, first.next.point)
if(s > point1) {
mesh.map -= first.triangle
first.triangle = first.triangle.neighborCW(first.point)
val t = first.triangle.neighborAcross(first.point)
val n = new Node(point1, t)
first.next = n
n.prev = first
n.next = first.next.next
n.next.prev = n
}
// Triangulate empty areas.
val T = new ArrayBuffer[Triangle]
triangulate(points.toArray, List(point1, point2), T)
@ -305,6 +343,11 @@ class CDT(polyLine: Array[Point], clearPoint: Point) {
// Mark constrained edge
T.last markEdge(point1, point2)
if(pNode.point != edge.p) {
println("span")
//edgeEvent(edge, pNode)
}
} else if(firstTriangle.contains(edge.q, edge.p)) {
// Constrained edge lies on the side of a triangle
// Mark constrained edge

View File

@ -353,7 +353,8 @@ class Triangle(val points: Array[Point]) {
val b = points(0).x - points(1).x
val h = points(2).y - points(1).y
(b*h*0.5f)
Math.abs((b*h*0.5f))
}
def centroid: Point = {
@ -363,4 +364,18 @@ class Triangle(val points: Array[Point]) {
Point(cx, cy)
}
def thin: Boolean = {
val a1 = (points(1) - points(0))
val b1 = (points(2) - points(0))
val a2 = (points(0) - points(1))
val b2 = (points(2) - points(1))
val angle1 = Math.abs(Math.atan2(a1 cross b1, a1 dot b1))
val angle2 = Math.abs(Math.atan2(a2 cross b2, a2 dot b2))
val angle3 = Math.Pi - angle1 - angle2
// 30 degrees
val minAngle = Math.Pi/6
//println(angle1 + "," + angle2 + "," + angle3)
(angle1 <= minAngle || angle2 <= minAngle || angle3 <= minAngle)
}
}

View File

@ -131,6 +131,30 @@ object Util {
return orient2d(pa, pb, c)
}
}
// Original by Jonathan Shewchuk
// http://www.ics.uci.edu/~eppstein/junkyard/circumcenter.html
def circumcenter(a: Point, b: Point, c: Point): Point = {
/* Use coordinates relative to point `a' of the triangle. */
val xba = b.x - a.x
val yba = b.y - a.y
val xca = c.x - a.x
val yca = c.y - a.y
/* Squares of lengths of the edges incident to `a'. */
val balength = xba * xba + yba * yba
val calength = xca * xca + yca * yca
/* Calculate the denominator of the formulae. */
val denominator = 0.5 / orient2d(b, c, a)
/* Calculate offset (from `a') of circumcenter. */
val xcirca = (yca * balength - yba * calength) * denominator
val ycirca = (xba * calength - xca * balength) * denominator
a + Point(xcirca.toFloat, ycirca.toFloat)
}
// Returns triangle circumcircle point and radius