3 function geom
.on_shape(x
,y
, drawing
, shape
)
4 if shape
.mode
== 'freehand' then
5 return geom
.on_freehand(x
,y
, drawing
, shape
)
6 elseif shape
.mode
== 'line' then
7 return geom
.on_line(x
,y
, drawing
, shape
)
8 elseif shape
.mode
== 'manhattan' then
9 local p1
= drawing
.points
[shape
.p1
]
10 local p2
= drawing
.points
[shape
.p2
]
12 if x
~= p1
.x
then return false end
13 local y1
,y2
= p1
.y
, p2
.y
17 return y
>= y1
-2 and y
<= y2
+2
18 elseif p1
.y
== p2
.y
then
19 if y
~= p1
.y
then return false end
20 local x1
,x2
= p1
.x
, p2
.x
24 return x
>= x1
-2 and x
<= x2
+2
26 elseif shape
.mode
== 'polygon' or shape
.mode
== 'rectangle' or shape
.mode
== 'square' then
27 return geom
.on_polygon(x
,y
, drawing
, shape
)
28 elseif shape
.mode
== 'circle' then
29 local center
= drawing
.points
[shape
.center
]
30 local dist
= geom
.dist(center
.x
,center
.y
, x
,y
)
31 return dist
> shape
.radius
*0.95 and dist
< shape
.radius
*1.05
32 elseif shape
.mode
== 'arc' then
33 local center
= drawing
.points
[shape
.center
]
34 local dist
= geom
.dist(center
.x
,center
.y
, x
,y
)
35 if dist
< shape
.radius
*0.95 or dist
> shape
.radius
*1.05 then
38 return geom
.angle_between(center
.x
,center
.y
, x
,y
, shape
.start_angle
,shape
.end_angle
)
39 elseif shape
.mode
== 'deleted' then
46 function geom
.on_freehand(x
,y
, drawing
, shape
)
48 for _
,p
in ipairs(shape
.points
) do
50 if geom
.on_line(x
,y
, drawing
, {p1
=prev
, p2
=p
}) then
59 function geom
.on_line(x
,y
, drawing
, shape
)
61 if type(shape
.p1
) == 'number' then
62 p1
= drawing
.points
[shape
.p1
]
63 p2
= drawing
.points
[shape
.p2
]
69 if math
.abs(p1
.x
-x
) > 2 then
72 local y1
,y2
= p1
.y
,p2
.y
76 return y
>= y1
-2 and y
<= y2
+2
78 -- has the right slope and intercept
79 local m
= (p2
.y
- p1
.y
) / (p2
.x
- p1
.x
)
80 local yp
= p1
.y
+ m
*(x
-p1
.x
)
81 if yp
< y
-2 or yp
> y
+2 then
85 local k
= (x
-p1
.x
) / (p2
.x
-p1
.x
)
86 return k
> -0.005 and k
< 1.005
89 function geom
.on_polygon(x
,y
, drawing
, shape
)
91 for _
,p
in ipairs(shape
.vertices
) do
93 if geom
.on_line(x
,y
, drawing
, {p1
=prev
, p2
=p
}) then
99 return geom
.on_line(x
,y
, drawing
, {p1
=shape
.vertices
[1], p2
=shape
.vertices
[#shape
.vertices
]})
102 -- are (x3,y3) and (x4,y4) on the same side of the line between (x1,y1) and (x2,y2)
103 function geom
.same_side(x1
,y1
, x2
,y2
, x3
,y3
, x4
,y4
)
105 return math
.sign(x3
-x1
) == math
.sign(x4
-x1
)
108 return math
.sign(y3
-y1
) == math
.sign(y4
-y1
)
110 local m
= (y2
-y1
)/(x2
-x1
)
111 return math
.sign(m
*(x3
-x1
) + y1
-y3
) == math
.sign(m
*(x4
-x1
) + y1
-y4
)
114 function math
.sign(x
)
124 function geom
.angle_with_hint(x1
, y1
, x2
, y2
, hint
)
125 local result
= geom
.angle(x1
,y1
, x2
,y2
)
127 -- Smooth the discontinuity where angle goes from positive to negative.
128 -- The hint is a memory of which way we drew it last time.
129 while result
> hint
+math
.pi
/10 do
130 result
= result
-math
.pi
*2
132 while result
< hint
-math
.pi
/10 do
133 result
= result
+math
.pi
*2
139 -- result is from -π/2 to 3π/2, approximately adding math.atan2 from Lua 5.3
141 function geom
.angle(x1
,y1
, x2
,y2
)
142 local result
= math
.atan((y2
-y1
)/(x2
-x1
))
144 result
= result
+math
.pi
149 -- is the line between x,y and cx,cy at an angle between s and e?
150 function geom
.angle_between(ox
,oy
, x
,y
, s
,e
)
151 local angle
= geom
.angle(ox
,oy
, x
,y
)
155 -- I'm not sure this is right or ideal..
156 angle
= angle
-math
.pi
*2
157 if s
<= angle
and angle
<= e
then
160 angle
= angle
+math
.pi
*2
161 if s
<= angle
and angle
<= e
then
164 angle
= angle
+math
.pi
*2
165 return s
<= angle
and angle
<= e
168 function geom
.dist(x1
,y1
, x2
,y2
) return ((x2
-x1
)^
2+(y2
-y1
)^
2)^
0.5 end