From d39dbc6a88840e1e18d0f0d023ef6bd892e19582 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Sat, 28 Dec 2019 14:57:50 +0900 Subject: [PATCH] vector: Add QuadraticCurve Updates #741 --- examples/vector/main.go | 9 +++++- vector/internal/math/triangulate.go | 8 ++--- vector/internal/math/triangulate_test.go | 37 +++++++++++++++++++++++- vector/path.go | 16 +++++++++- 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/examples/vector/main.go b/examples/vector/main.go index 2bcefc41f..e4ba634d6 100644 --- a/examples/vector/main.go +++ b/examples/vector/main.go @@ -46,7 +46,14 @@ func drawEbitenText(screen *ebiten.Image) { path.LineTo(70, 30) path.LineTo(70, 20) - // TODO: Draw other letters like B, I, T, E, N + // B + path.MoveTo(80, 20) + path.LineTo(80, 70) + path.LineTo(100, 70) + path.QuadraticCurveTo(130, 57.5, 100, 45) + path.QuadraticCurveTo(130, 32.5, 100, 20) + + // TODO: Draw other letters like I, T, E, N path.Fill(screen, color.White) } diff --git a/vector/internal/math/triangulate.go b/vector/internal/math/triangulate.go index 53cc0b66a..3cc6fa161 100644 --- a/vector/internal/math/triangulate.go +++ b/vector/internal/math/triangulate.go @@ -34,7 +34,7 @@ func InTriangle(pt, pt0, pt1, pt2 Point) bool { c0 := cross(Vector{pt.X - pt0.X, pt.Y - pt0.Y}, Vector{pt1.X - pt0.X, pt1.Y - pt0.Y}) c1 := cross(Vector{pt.X - pt1.X, pt.Y - pt1.Y}, Vector{pt2.X - pt1.X, pt2.Y - pt1.Y}) c2 := cross(Vector{pt.X - pt2.X, pt.Y - pt2.Y}, Vector{pt0.X - pt2.X, pt0.Y - pt2.Y}) - return (c0 < 0 && c1 < 0 && c2 < 0) || (c0 > 0 && c1 > 0 && c2 > 0) + return (c0 <= 0 && c1 <= 0 && c2 <= 0) || (c0 >= 0 && c1 >= 0 && c2 >= 0) } func Triangulate(pts []Point) []uint16 { @@ -60,12 +60,12 @@ dup: // Determine the direction of the polygon from the upper-left point. var upperLeft int - for _, i := range currentIndices { + for ci, i := range currentIndices { if pts[upperLeft].X < pts[i].X { - upperLeft = int(i) + upperLeft = int(ci) } if pts[upperLeft].X == pts[i].X && pts[upperLeft].Y < pts[i].Y { - upperLeft = int(i) + upperLeft = int(ci) } } i0, i1, i2 := adjacentIndices(currentIndices, upperLeft) diff --git a/vector/internal/math/triangulate_test.go b/vector/internal/math/triangulate_test.go index a1d2f07db..e4815981b 100644 --- a/vector/internal/math/triangulate_test.go +++ b/vector/internal/math/triangulate_test.go @@ -145,6 +145,15 @@ func TestTriangulate(t *testing.T) { }, Out: []uint16{2, 0, 1}, }, + { + In: []Point{ + {0, 0}, + {1, 1}, + {0, 1}, + {0, 0.5}, + }, + Out: []uint16{2, 0, 1}, + }, { In: []Point{ {0, 0}, @@ -178,7 +187,33 @@ func TestTriangulate(t *testing.T) { {3, 4}, {3, 3}, }, - Out: []uint16{9, 0, 1, 1, 2, 3, 1, 3, 4, 9, 1, 4, 8, 5, 6, 8, 6, 7}, + Out: []uint16{9, 0, 1, 1, 2, 3, 1, 3, 4, 1, 4, 5, 5, 6, 7, 5, 7, 8, 9, 1, 5}, + }, + { + In: []Point{ + {0, 0}, + {0, 5}, + {2, 5}, + {3, 3}, + {2, 2}, + {3, 1}, + {2, 0}, + }, + Out: []uint16{6, 0, 1, 1, 2, 3, 1, 3, 4, 6, 1, 4, 6, 4, 5}, + }, + { + In: []Point{ + {0, 0}, + {0, 5}, + {2, 5}, + {2, 5}, + {3, 3}, + {2, 2}, + {2, 2}, + {3, 1}, + {2, 0}, + }, + Out: []uint16{8, 0, 1, 1, 2, 4, 1, 4, 5, 8, 1, 5, 8, 5, 7}, }, } for _, tc := range tests { diff --git a/vector/path.go b/vector/path.go index a21ad5aee..bfc1e021a 100644 --- a/vector/path.go +++ b/vector/path.go @@ -48,12 +48,26 @@ func (p *Path) MoveTo(x, y float32) { // LineTo updates the current position to (x, y). func (p *Path) LineTo(x, y float32) { if len(p.segs) == 0 { - p.segs = append(p.segs, []math.Point{{X: 0, Y: 0}}) + p.segs = append(p.segs, []math.Point{p.cur}) } p.segs[len(p.segs)-1] = append(p.segs[len(p.segs)-1], math.Point{X: x, Y: y}) p.cur = math.Point{X: x, Y: y} } +func (p *Path) QuadraticCurveTo(cpx, cpy, x, y float32) { + c := p.cur + dist := float64((x-c.X)*(x-c.X) + (y-c.Y)*(y-c.Y)) + num := 1.0 + for num*num < dist { + num *= 2 + } + for t := float32(0.0); t <= 1; t += 1.0 / 128.0 { + xf := t*t*x + 2*t*(1-t)*cpx + (1-t)*(1-t)*c.X + yf := t*t*y + 2*t*(1-t)*cpy + (1-t)*(1-t)*c.Y + p.LineTo(xf, yf) + } +} + func (p *Path) Fill(dst *ebiten.Image, clr color.Color) { var vertices []ebiten.Vertex var indices []uint16