-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathpath2d_svgarc_demo.lua
109 lines (86 loc) · 3.13 KB
/
path2d_svgarc_demo.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
local player = require'cplayer'
local arc = require'path2d_arc'
local svgarc = require'path2d_svgarc'
local matrix = require'affine2d'
local world_rotation = 0
local rotation = 0
local scale = 1
function player:on_render(cr)
world_rotation = self:slider{id = 'world_rotation',
x = 10, y = 10, w = 300, h = 24, text = 'world rotation',
i0 = 0, i1 = 360, step = 1, i = world_rotation,
}
rotation = self:slider{id = 'rotation',
x = 10, y = 40, w = 300, h = 24, text = 'arc rotation',
i0 = 0, i1 = 360, step = 1, i = rotation,
}
scale = self:slider{id = 'scale',
x = 10, y = 70, w = 300, h = 24, text = 'scale',
i0 = 0.1, i1 = 5, step = 0.01, i = scale,
}
cr:identity_matrix()
cr:translate(400, 500)
cr:scale(scale, scale)
cr:translate(-400, -500)
local cpx, cpy
local function write(_, x2, y2, x3, y3, x4, y4)
cpx, cpy = cr:current_point()
cr:circle(cpx, cpy, 2)
cr:circle(x4, y4, 2)
cr:move_to(cpx, cpy)
cr:curve_to(x2, y2, x3, y3, x4, y4)
end
local world_center_x, world_center_y = 600, 300
local mt = matrix():rotate_around(world_center_x, world_center_y, math.rad(world_rotation))
local function draw(x1, y1, rx, ry, rotation, large, sweep, x2, y2, r, g, b, a)
if not svgarc.valid(x1, y1, x2, y2, rx, ry) then return end
cr:move_to(mt(x1, y1))
arc.to_bezier3(write, svgarc.to_arc(x1, y1, rx, ry, rotation, large, sweep, x2, y2, mt))
cr:rgba(r, g, b, a)
cr:stroke()
end
cr:line_width(2)
local mind, minx, miny, mint
local function hit(x1, y1, rx, ry, rotation, large, sweep, x2, y2)
if not svgarc.valid(x1, y1, x2, y2, rx, ry) then return end
local x, y = cr:device_to_user(self.mousex, self.mousey)
local d, x, y, t = arc.hit(x, y, svgarc.to_arc(x1, y1, rx, ry, rotation, large, sweep, x2, y2, mt))
if not mind or d < mind then
mind, minx, miny, mint = d, x, y, t
end
local
x11, y11, rx1, ry1, rotation1, large1, sweep1, x12, y12,
x21, y21, rx2, ry2, rotation2, large2, sweep2, x22, y22 =
svgarc.split(t, x1, y1, rx, ry, rotation, large, sweep, x2, y2)
draw(x11, y11, rx1, ry1, rotation1, large1, sweep1, x12, y12, 1, 0, 0, 1)
draw(x21, y21, rx2, ry2, rotation2, large2, sweep2, x22, y22, 0.3, 0.3, 1, 1)
end
--the four svg elliptic arcs from http://www.w3.org/TR/SVG/images/paths/arcs02.svg
local function ellipses(tx, ty, large, sweep)
local x1, y1, rx, ry, x2, y2 = tx+125, ty+75, 100, 50, tx+125+100, ty+75+50
local cx, cy, crx, cry = svgarc.to_arc(x1, y1, rx, ry, rotation, large, sweep, x2, y2, mt)
local cmt = cr:matrix()
cr:rotate_around(world_center_x, world_center_y, math.rad(world_rotation))
cr:translate(cx, cy)
cr:rotate(math.rad(rotation))
cr:translate(-125, -125)
cr:ellipse(125, 125, crx, cry)
cr:matrix(cmt)
cr:rgba(0,1,0,0.3)
cr:stroke()
hit(x1, y1, rx, ry, rotation, large, sweep, x2, y2)
end
ellipses(200, 100, 0, 0)
ellipses(600, 100, 0, 1)
ellipses(600, 400, 1, 0)
ellipses(200, 400, 1, 1)
--degenerate arcs
hit(700, 100, 100, 0, 0, 0, 0, 800, 200) --zero radius
hit(800, 100, 100, 100, 0, 0, 0, 800, 100) --conincident endpoints
--closest hit point
cr:line_width(1)
cr:rgb(1,1,1)
cr:circle(minx, miny, 5)
cr:stroke()
end
player:play()