vector: Implement miter limit

Fixes #843
This commit is contained in:
Hajime Hoshi 2019-04-20 23:08:18 +09:00
parent 7d9bc8586e
commit 020cba22c5
2 changed files with 93 additions and 85 deletions

View File

@ -19,7 +19,6 @@ package main
import (
"image/color"
"log"
"math"
"github.com/hajimehoshi/ebiten"
"github.com/hajimehoshi/ebiten/vector"
@ -84,79 +83,28 @@ func drawEbitenText(screen *ebiten.Image) {
path.Draw(screen, op)
}
type roundingPoint struct {
cx float32
cy float32
r float32
degree int
}
func (r *roundingPoint) Update() {
r.degree++
r.degree %= 360
}
func (r *roundingPoint) Position() (float32, float32) {
s, c := math.Sincos(float64(r.degree) / 360 * 2 * math.Pi)
return r.cx + r.r*float32(c), r.cy + r.r*float32(s)
}
func drawLinesByRoundingPoints(screen *ebiten.Image, points []*roundingPoint) {
if len(points) == 0 {
return
}
func drawLines(screen *ebiten.Image) {
var path vector.Path
path.MoveTo(points[0].Position())
for i := 1; i < len(points); i++ {
path.LineTo(points[i].Position())
}
path.MoveTo(20, 80+float32(counter%320)/4)
path.LineTo(60, 120)
path.LineTo(20, 160-float32(counter%320)/4)
op := &vector.DrawPathOptions{}
op.LineWidth = 4
op.LineWidth = 16
op.StrokeColor = color.White
path.Draw(screen, op)
}
var points = []*roundingPoint{
{
cx: 100,
cy: 120,
r: 10,
degree: 0,
},
{
cx: 120,
cy: 120,
r: 10,
degree: 90,
},
{
cx: 100,
cy: 140,
r: 10,
degree: 180,
},
{
cx: 120,
cy: 140,
r: 10,
degree: 270,
},
}
var counter = 0
func update(screen *ebiten.Image) error {
for _, p := range points {
p.Update()
}
counter++
if ebiten.IsDrawingSkipped() {
return nil
}
drawEbitenText(screen)
drawLinesByRoundingPoints(screen, points)
drawLines(screen)
return nil
}

View File

@ -63,6 +63,8 @@ func (p *Path) LineTo(x, y float32) {
}
func (p *Path) strokeVertices(lineWidth float32, clr color.Color) (vertices []ebiten.Vertex, indices []uint16) {
const miterLimit = 10
if len(p.segs) == 0 {
return nil, nil
}
@ -103,35 +105,93 @@ func (p *Path) strokeVertices(lineWidth float32, clr color.Color) (vertices []eb
v2 := s0.P1
v3 := s1.P1
cut := false
if i != len(ss)-1 {
ns := ss[i+1]
v2 = ns.Translate(-lineWidth / 2).IntersectionAsLines(s0)
v3 = ns.Translate(lineWidth / 2).IntersectionAsLines(s1)
nv2 := ns.Translate(-lineWidth / 2).IntersectionAsLines(s0)
nv3 := ns.Translate(lineWidth / 2).IntersectionAsLines(s1)
l := lineWidth / 2 * miterLimit
if (nv2.X-nv3.X)*(nv2.X-nv3.X)+(nv2.Y-nv3.Y)*(nv2.Y-nv3.Y) < l*l {
v2 = nv2
v3 = nv3
} else {
cut = true
}
}
vertices = append(vertices,
ebiten.Vertex{
DstX: v2.X,
DstY: v2.Y,
SrcX: v2.X,
SrcY: v2.Y,
ColorR: rf,
ColorG: gf,
ColorB: bf,
ColorA: af,
},
ebiten.Vertex{
DstX: v3.X,
DstY: v3.Y,
SrcX: v3.X,
SrcY: v3.Y,
ColorR: rf,
ColorG: gf,
ColorB: bf,
ColorA: af,
})
indices = append(indices, idx, idx+1, idx+2, idx+1, idx+2, idx+3)
idx += 2
if cut {
ns := ss[i+1]
s2 := ns.Translate(-lineWidth / 2)
s3 := ns.Translate(lineWidth / 2)
vertices = append(vertices,
ebiten.Vertex{
DstX: s0.P1.X,
DstY: s0.P1.Y,
SrcX: s0.P1.X,
SrcY: s0.P1.Y,
ColorR: rf,
ColorG: gf,
ColorB: bf,
ColorA: af,
},
ebiten.Vertex{
DstX: s1.P1.X,
DstY: s1.P1.Y,
SrcX: s1.P1.X,
SrcY: s1.P1.Y,
ColorR: rf,
ColorG: gf,
ColorB: bf,
ColorA: af,
},
ebiten.Vertex{
DstX: s2.P0.X,
DstY: s2.P0.Y,
SrcX: s2.P0.X,
SrcY: s2.P0.Y,
ColorR: rf,
ColorG: gf,
ColorB: bf,
ColorA: af,
},
ebiten.Vertex{
DstX: s3.P0.X,
DstY: s3.P0.Y,
SrcX: s3.P0.X,
SrcY: s3.P0.Y,
ColorR: rf,
ColorG: gf,
ColorB: bf,
ColorA: af,
})
indices = append(indices, idx, idx+1, idx+2, idx+1, idx+2, idx+3,
idx+2, idx+3, idx+4, idx+3, idx+4, idx+5)
idx += 4
} else {
vertices = append(vertices,
ebiten.Vertex{
DstX: v2.X,
DstY: v2.Y,
SrcX: v2.X,
SrcY: v2.Y,
ColorR: rf,
ColorG: gf,
ColorB: bf,
ColorA: af,
},
ebiten.Vertex{
DstX: v3.X,
DstY: v3.Y,
SrcX: v3.X,
SrcY: v3.Y,
ColorR: rf,
ColorG: gf,
ColorB: bf,
ColorA: af,
})
indices = append(indices, idx, idx+1, idx+2, idx+1, idx+2, idx+3)
idx += 2
}
}
}