fixed the line intersection calculation; splitting polygons at self-intersections now works
This commit is contained in:
parent
a7c6f10541
commit
31c2eb204e
2 changed files with 33 additions and 17 deletions
23
paths.go
23
paths.go
|
@ -289,8 +289,8 @@ func (cv *Canvas) lineJoint(p pathPoint, p0, p1, p2, l0p0, l0p1, l0p2, l0p3 lm.V
|
||||||
l1p2 := p2.Add(v3)
|
l1p2 := p2.Add(v3)
|
||||||
l1p3 := p1.Add(v3)
|
l1p3 := p1.Add(v3)
|
||||||
|
|
||||||
ip0, _ := lineIntersection(l0p0, l0p1, l1p1, l1p0)
|
ip0, _, _ := lineIntersection(l0p0, l0p1, l1p1, l1p0)
|
||||||
ip1, _ := lineIntersection(l0p2, l0p3, l1p3, l1p2)
|
ip1, _, _ := lineIntersection(l0p2, l0p3, l1p3, l1p2)
|
||||||
|
|
||||||
tris = append(tris,
|
tris = append(tris,
|
||||||
p1[0], p1[1], l0p1[0], l0p1[1], ip0[0], ip0[1],
|
p1[0], p1[1], l0p1[0], l0p1[1], ip0[0], ip0[1],
|
||||||
|
@ -328,17 +328,22 @@ func (cv *Canvas) addCircleTris(center lm.Vec2, radius float32, tris []float32)
|
||||||
return tris
|
return tris
|
||||||
}
|
}
|
||||||
|
|
||||||
func lineIntersection(a0, a1, b0, b1 lm.Vec2) (lm.Vec2, float32) {
|
func lineIntersection(a0, a1, b0, b1 lm.Vec2) (lm.Vec2, float32, float32) {
|
||||||
va := a1.Sub(a0)
|
va := a1.Sub(a0)
|
||||||
vb := b1.Sub(b0)
|
vb := b1.Sub(b0)
|
||||||
|
|
||||||
if vb[1] == 0 {
|
if (va[0] == 0 && vb[0] == 0) || (va[1] == 0 && vb[1] == 0) || (va[0] == 0 && va[1] == 0) || (vb[0] == 0 && vb[1] == 0) {
|
||||||
r := (b0[1] + (a0[0]-b0[0])*(vb[1]/vb[0]) - a0[1]) / (va[1] - va[0]*(vb[1]/vb[0]))
|
return lm.Vec2{}, float32(math.Inf(1)), float32(math.Inf(1))
|
||||||
return a0.Add(va.MulF(r)), r
|
}
|
||||||
|
p := (vb[1]*(a0[0]-b0[0]) - a0[1]*vb[0] + b0[1]*vb[0]) / (va[1]*vb[0] - va[0]*vb[1])
|
||||||
|
var q float32
|
||||||
|
if vb[0] == 0 {
|
||||||
|
q = (a0[1] + p*va[1] - b0[1]) / vb[1]
|
||||||
|
} else {
|
||||||
|
q = (a0[0] + p*va[0] - b0[0]) / vb[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
r := (b0[0] + (a0[1]-b0[1])*(vb[0]/vb[1]) - a0[0]) / (va[0] - va[1]*(vb[0]/vb[1]))
|
return a0.Add(va.MulF(p)), p, q
|
||||||
return a0.Add(va.MulF(r)), r
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cv *Canvas) Fill() {
|
func (cv *Canvas) Fill() {
|
||||||
|
@ -353,7 +358,7 @@ func (cv *Canvas) Fill() {
|
||||||
if len(path) < 3 {
|
if len(path) < 3 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//path = cv.cutIntersections(path)
|
path = cv.cutIntersections(path)
|
||||||
|
|
||||||
cv.activate()
|
cv.activate()
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,7 @@ func triangulatePath(path []pathPoint, target []float32) []float32 {
|
||||||
if !polygonContainsPoint(polygon, center) {
|
if !polygonContainsPoint(polygon, center) {
|
||||||
continue triangles
|
continue triangles
|
||||||
}
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
target = append(target, a[0], a[1], b[0], b[1], c[0], c[1])
|
target = append(target, a[0], a[1], b[0], b[1], c[0], c[1])
|
||||||
break
|
break
|
||||||
|
@ -101,6 +102,8 @@ func triangulatePath(path []pathPoint, target []float32) []float32 {
|
||||||
func (cv *Canvas) cutIntersections(path []pathPoint) []pathPoint {
|
func (cv *Canvas) cutIntersections(path []pathPoint) []pathPoint {
|
||||||
type cut struct {
|
type cut struct {
|
||||||
from, to int
|
from, to int
|
||||||
|
j int
|
||||||
|
b bool
|
||||||
ratio float32
|
ratio float32
|
||||||
point lm.Vec2
|
point lm.Vec2
|
||||||
}
|
}
|
||||||
|
@ -109,26 +112,34 @@ func (cv *Canvas) cutIntersections(path []pathPoint) []pathPoint {
|
||||||
cuts := cutBuf[:0]
|
cuts := cutBuf[:0]
|
||||||
|
|
||||||
for i := 0; i < len(cv.polyPath); i++ {
|
for i := 0; i < len(cv.polyPath); i++ {
|
||||||
a0 := cv.polyPath[(i+len(cv.polyPath)-1)%len(cv.polyPath)].pos
|
ip := (i + len(cv.polyPath) - 1) % len(cv.polyPath)
|
||||||
|
a0 := cv.polyPath[ip].pos
|
||||||
a1 := cv.polyPath[i].pos
|
a1 := cv.polyPath[i].pos
|
||||||
for j := i + 1; j < len(cv.polyPath); j++ {
|
for j := i + 1; j < len(cv.polyPath); j++ {
|
||||||
b0 := cv.polyPath[(j+len(cv.polyPath)-1)%len(cv.polyPath)].pos
|
jp := (j + len(cv.polyPath) - 1) % len(cv.polyPath)
|
||||||
|
if ip == j || jp == i {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
b0 := cv.polyPath[jp].pos
|
||||||
b1 := cv.polyPath[j].pos
|
b1 := cv.polyPath[j].pos
|
||||||
p, r := lineIntersection(a0, a1, b0, b1)
|
p, r1, r2 := lineIntersection(a0, a1, b0, b1)
|
||||||
if r <= 0 || r >= 1 {
|
if r1 <= 0 || r1 >= 1 || r2 <= 0 || r2 >= 1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
cuts = append(cuts, cut{
|
cuts = append(cuts, cut{
|
||||||
from: (i + len(cv.polyPath) - 1) % len(cv.polyPath),
|
from: ip,
|
||||||
to: i,
|
to: i,
|
||||||
ratio: r,
|
ratio: r1,
|
||||||
point: p,
|
point: p,
|
||||||
|
j: j,
|
||||||
})
|
})
|
||||||
cuts = append(cuts, cut{
|
cuts = append(cuts, cut{
|
||||||
from: (j + len(cv.polyPath) - 1) % len(cv.polyPath),
|
from: jp,
|
||||||
to: j,
|
to: j,
|
||||||
ratio: p.Sub(b0).Len() / b1.Sub(b0).Len(),
|
ratio: r2,
|
||||||
point: p,
|
point: p,
|
||||||
|
j: i,
|
||||||
|
b: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue