mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2025-02-05 15:34:28 +01:00
parent
70ef5e7d5b
commit
a9241a45c6
@ -175,7 +175,7 @@ func drawArc(screen *ebiten.Image, count int) {
|
|||||||
|
|
||||||
theta2 := math.Pi * float64(count) / 180 / 3
|
theta2 := math.Pi * float64(count) / 180 / 3
|
||||||
path.MoveTo(550, 100)
|
path.MoveTo(550, 100)
|
||||||
path.Arc(550, 100, 50, float32(theta1), float32(theta2))
|
path.Arc(550, 100, 50, float32(theta1), float32(theta2), vector.Clockwise)
|
||||||
|
|
||||||
op := &ebiten.DrawTrianglesOptions{
|
op := &ebiten.DrawTrianglesOptions{
|
||||||
EvenOdd: true,
|
EvenOdd: true,
|
||||||
|
@ -23,6 +23,14 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Direction represents clockwise or countercolockwise.
|
||||||
|
type Direction int
|
||||||
|
|
||||||
|
const (
|
||||||
|
Clockwise Direction = iota
|
||||||
|
CounterClockwise
|
||||||
|
)
|
||||||
|
|
||||||
type point struct {
|
type point struct {
|
||||||
x float32
|
x float32
|
||||||
y float32
|
y float32
|
||||||
@ -139,6 +147,10 @@ func normalize(x, y float32) (float32, float32) {
|
|||||||
return x / len, y / len
|
return x / len, y / len
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func cross(x0, y0, x1, y1 float32) float32 {
|
||||||
|
return x0*y1 - x1*y0
|
||||||
|
}
|
||||||
|
|
||||||
// ArcTo adds an arc curve to the path. (x1, y1) is the control point, and (x2, y2) is the destination.
|
// ArcTo adds an arc curve to the path. (x1, y1) is the control point, and (x2, y2) is the destination.
|
||||||
//
|
//
|
||||||
// ArcTo updates the current position to (x2, y2).
|
// ArcTo updates the current position to (x2, y2).
|
||||||
@ -165,21 +177,22 @@ func (p *Path) ArcTo(x1, y1, x2, y2, radius float32) {
|
|||||||
ax0 := x1 + dx0*dist
|
ax0 := x1 + dx0*dist
|
||||||
ay0 := y1 + dy0*dist
|
ay0 := y1 + dy0*dist
|
||||||
|
|
||||||
// (ax1, ay1) is the end of the arc.
|
var cx, cy, a0, a1 float32
|
||||||
ax1 := x1 + dx1*dist
|
var dir Direction
|
||||||
ay1 := y1 + dy1*dist
|
if cross(dx0, dy0, dx1, dy1) >= 0 {
|
||||||
|
cx = ax0 - dy0*radius
|
||||||
p.LineTo(ax0, ay0)
|
cy = ay0 + dx0*radius
|
||||||
|
a0 = float32(math.Atan2(float64(-dx0), float64(dy0)))
|
||||||
// Calculate the control points for an approximated Bézier curve.
|
a1 = float32(math.Atan2(float64(dx1), float64(-dy1)))
|
||||||
// See https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/curves/beziers.
|
dir = CounterClockwise
|
||||||
alpha := math.Pi - theta
|
} else {
|
||||||
l := radius * float32(math.Tan(alpha/4)*4/3)
|
cx = ax0 + dy0*radius
|
||||||
cx0 := ax0 + l*(-dx0)
|
cy = ay0 - dx0*radius
|
||||||
cy0 := ay0 + l*(-dy0)
|
a0 = float32(math.Atan2(float64(dx0), float64(-dy0)))
|
||||||
cx1 := ax1 + l*(-dx1)
|
a1 = float32(math.Atan2(float64(-dx1), float64(dy1)))
|
||||||
cy1 := ay1 + l*(-dy1)
|
dir = Clockwise
|
||||||
p.CubicTo(cx0, cy0, cx1, cy1, ax1, ay1)
|
}
|
||||||
|
p.Arc(cx, cy, radius, a0, a1, dir)
|
||||||
|
|
||||||
p.LineTo(x2, y2)
|
p.LineTo(x2, y2)
|
||||||
}
|
}
|
||||||
@ -188,28 +201,51 @@ func (p *Path) ArcTo(x1, y1, x2, y2, radius float32) {
|
|||||||
// (x, y) is the center of the arc.
|
// (x, y) is the center of the arc.
|
||||||
//
|
//
|
||||||
// Arc updates the current position to the end of the arc.
|
// Arc updates the current position to the end of the arc.
|
||||||
func (p *Path) Arc(x, y, radius, startAngle, endAngle float32) {
|
func (p *Path) Arc(x, y, radius, startAngle, endAngle float32, dir Direction) {
|
||||||
// Adjust the angles.
|
// Adjust the angles.
|
||||||
|
var da float64
|
||||||
|
if dir == Clockwise {
|
||||||
for startAngle > endAngle {
|
for startAngle > endAngle {
|
||||||
endAngle += 2 * math.Pi
|
endAngle += 2 * math.Pi
|
||||||
}
|
}
|
||||||
da := float64(endAngle - startAngle)
|
da = float64(endAngle - startAngle)
|
||||||
|
} else {
|
||||||
|
for startAngle < endAngle {
|
||||||
|
startAngle += 2 * math.Pi
|
||||||
|
}
|
||||||
|
da = float64(startAngle - endAngle)
|
||||||
|
}
|
||||||
|
|
||||||
if da >= 2*math.Pi {
|
if da >= 2*math.Pi {
|
||||||
da = 2 * math.Pi
|
da = 2 * math.Pi
|
||||||
endAngle = startAngle + float32(da)
|
if dir == Clockwise {
|
||||||
|
endAngle = startAngle + 2*math.Pi
|
||||||
|
} else {
|
||||||
|
startAngle = endAngle + 2*math.Pi
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the angle is big, splict this into multiple Arc calls.
|
// If the angle is big, splict this into multiple Arc calls.
|
||||||
if da > math.Pi/2 {
|
if da > math.Pi/2 {
|
||||||
const delta = math.Pi / 3
|
const delta = math.Pi / 3
|
||||||
a := float64(startAngle)
|
a := float64(startAngle)
|
||||||
|
if dir == Clockwise {
|
||||||
for {
|
for {
|
||||||
p.Arc(x, y, radius, float32(a), float32(math.Min(a+delta, float64(endAngle))))
|
p.Arc(x, y, radius, float32(a), float32(math.Min(a+delta, float64(endAngle))), dir)
|
||||||
if a+delta >= float64(endAngle) {
|
if a+delta >= float64(endAngle) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
a += delta
|
a += delta
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
for {
|
||||||
|
p.Arc(x, y, radius, float32(a), float32(math.Max(a-delta, float64(endAngle))), dir)
|
||||||
|
if a-delta <= float64(endAngle) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
a -= delta
|
||||||
|
}
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,10 +261,18 @@ func (p *Path) Arc(x, y, radius, startAngle, endAngle float32) {
|
|||||||
// Calculate the control points for an approximated Bézier curve.
|
// Calculate the control points for an approximated Bézier curve.
|
||||||
// See https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/curves/beziers.
|
// See https://docs.microsoft.com/en-us/xamarin/xamarin-forms/user-interface/graphics/skiasharp/curves/beziers.
|
||||||
l := radius * float32(math.Tan(da/4)*4/3)
|
l := radius * float32(math.Tan(da/4)*4/3)
|
||||||
cx0 := x0 + l*float32(-sin0)
|
var cx0, cy0, cx1, cy1 float32
|
||||||
cy0 := y0 + l*float32(cos0)
|
if dir == Clockwise {
|
||||||
cx1 := x1 + l*float32(sin1)
|
cx0 = x0 + l*float32(-sin0)
|
||||||
cy1 := y1 + l*float32(-cos1)
|
cy0 = y0 + l*float32(cos0)
|
||||||
|
cx1 = x1 + l*float32(sin1)
|
||||||
|
cy1 = y1 + l*float32(-cos1)
|
||||||
|
} else {
|
||||||
|
cx0 = x0 + l*float32(sin0)
|
||||||
|
cy0 = y0 + l*float32(-cos0)
|
||||||
|
cx1 = x1 + l*float32(-sin1)
|
||||||
|
cy1 = y1 + l*float32(cos1)
|
||||||
|
}
|
||||||
p.CubicTo(cx0, cy0, cx1, cy1, x1, y1)
|
p.CubicTo(cx0, cy0, cx1, cy1, x1, y1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user