several more modules
[?]
May 18, 2022, 4:18 AM
VHQCNMARPMNBSIUFLJG7HVK4QGDNPCGNVFLHS3I4IGNVSV5MRLYQCDependencies
- [2]
JRLBUB6Lmore intuitive point delete from polygons - [3]
SYS67ZEJload/save remaining shapes - [4]
PLLSUOCIsome missing transitions - [5]
AVDRMDDBbugfix - [6]
XJ5J7LDIstart imposing some organization - [7]
BLWAYPKVextract a module - [8]
7IKRRESBlonger names for indices in long loops - [9]
JVRL5TWLstore device-independent coordinates inside drawings - [10]
KVHUFUFVreorg - [11]
FJ4L6N74draw lines by default - [12]
6PUNJS5Bbackspace - [13]
O2UFJ6G3switch from freehand to just straight lines - [14]
IFGAJAF7add a level of indirection to vertices of shapes - [15]
GP56QHRHbugfix - [16]
5T2E3PDVcouple of bugfixes to file-handling - [17]
VVXVV2D2change data model; text can now have metadata - [18]
5TIFKJ7Shandle space key - [19]
6LJZN727handle chords - [20]
FBDRL6LHdelete points or shapes - [21]
KCIM5UTVrevert: back to freehand - [22]
YKRF5V3Zstarting to load/save - [23]
Z4KNS42Nto open a file without a terminal, drag it on! - [24]
V5TP27FPctrl-+ and ctrl-- to adjust font size - [25]
NW7X4AGMmuch better help color and copy - [26]
MGOQ5XAVstart uppercasing globals - [27]
HWPK4SMPnew mode: manhattan - [28]
MNWHXPBLmore lightweight; select just the stroke at the mouse - [29]
CXCAERTBicons for current_mode - [30]
7Q4B6M2Desc to cancel a shape mid-click - [31]
T76KKDWZturn strokes into horizontal and vertical lines - [32]
FMQ74DP3new mode: circle - [33]
T664AOUGmake points easier to acquire - [34]
G77XIN7Mselecting a stroke - [35]
4NDYV4WDfix 2 bugs in line selection - [36]
OFA3PRBSautosave on keystrokes - [37]
2C7CTIQYmake space for multiple kinds of width - [38]
RJGZD4INbinary search to most natural up/down with proportional fonts - [39]
JCSLDGAHbeginnings of support for multiple shapes - [40]
SNDZOK6Qslightly less strange now that we have the same two ways to move points as any other operation - [41]
ICIIP4DBslightly better default sizing of drawings - [42]
3XD6M3CFrefactor - [43]
6J6EEUAYrespect zoom when printing online help - [44]
ZOOY3ME4new mode: circle arc - [45]
JS6JSYOTonline contextual help - [46]
3SYFA5JQshow cursor even on empty lines - [47]
RXE6NQTNchanging your mind mid-shape - [48]
K6HMLFLZcolor close to drawing - [49]
UTF73CBLreorg - [50]
YHQC72JXslightly tweak boundary between concerns - [51]
EDY3RQULgracefully handle a non-existent filename at the commandline - [52]
FI6IK76Msnap lines to nearby points - [53]
POT3XFCTrename - [54]
BULPIBEGbeginnings of a module for the text editor - [55]
VXORMHMEdelete experimental REPL - [56]
TRCAEE2Aclip drawings inside the border - [57]
ZD63LJ2Tbugfix: keep the click to create a new drawing from creating a new shape in the drawing - [58]
2FMZNSD7experiment: only show drawing borders when they can be edited - [59]
Z2CJVAPVlighter border for figures - [60]
ZUOL7X6Vmove - [61]
HDCVGN6Gsave each line's y coordinate, whether it's a drawing or not - [62]
OTIBCAUJlove2d scaffold - [63]
R3WSFYGYspacing - [64]
HRWN5V6JDevine's suggestion to try to live with just freehand - [65]
IK3N7J3Breset zoom - [66]
GCUARQ2Gbugfix: clipping in line and manhattan mode - [67]
XX7G2FFJintermingle freehand line drawings with text - [68]
2INHXC3Kposition cursor by clicking on text - [69]
H7OEU6WPexperimental approach to combining keyboard and mouse while drawing - [70]
IHG5RXP5allow text to be typed while mouse hovers over drawing - [71]
L5USRTY2inline - [72]
WAZVXUV2simplest possible way to straighten strokes - [73]
NL5J7Z5Hnew mode: polygon - [74]
IZZVOCLBconfirm that we have access to all of the love API - [75]
WDWXNW7Vslightly strange way to move points - [76]
LBQAAJN4load/save freehand strokes - [77]
3CS5KKCIup/down cursor movement - [78]
M36DBSDEbit more polish to help screen - [79]
D2GCFTTTclean up repl functionality - [80]
AVQ5MC5Dfinish uppercasing all globals - [81]
EFMLTMZGbugfix: restrict strokes to the drawing they started in - [82]
6Q6XGOFLlittle Lua repl on hitting ctrl-r - [83]
634QBFQXctrl- and alt- combinations - [*]
R5QXEHUIsomebody stop me
Change contents
- edit in main.lua at line 3
require 'file' - edit in main.lua at line 7
local geom = require 'geom'require 'help'require 'icons' - replacement in main.lua at line 49
Current_mode = 'line'Previous_mode = nilCurrent_drawing_mode = 'line'Previous_drawing_mode = nil - edit in main.lua at line 55[9.28]→[9.168:207](∅→∅),[9.257]→[9.168:207](∅→∅),[9.168]→[9.168:207](∅→∅),[9.207]→[9.258:287](∅→∅),[9.287]→[9.231:273](∅→∅),[9.231]→[9.231:273](∅→∅),[9.273]→[9.288:329](∅→∅),[9.329]→[9.309:313](∅→∅),[9.309]→[9.309:313](∅→∅)
function pixels(n) -- parts to pixelsreturn n*Drawing_width/256endfunction coord(n) -- pixels to partsreturn math.floor(n*256/Drawing_width)end - replacement in main.lua at line 119
y = y+pixels(line.h)y = y+Drawing.pixels(line.h) - replacement in main.lua at line 133
if y >= drawing.y and y < drawing.y + pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenif y >= drawing.y and y < drawing.y + Drawing.pixels(drawing.h) and x >= 16 and x < 16+Drawing_width then - replacement in main.lua at line 135
table.insert(drawing.pending.points, {x=coord(love.mouse.getX()-16), y=coord(love.mouse.getY()-drawing.y)})table.insert(drawing.pending.points, {x=Drawing.coord(love.mouse.getX()-16), y=Drawing.coord(love.mouse.getY()-drawing.y)}) - replacement in main.lua at line 137
local mx,my = coord(x-16), coord(y-drawing.y)local mx,my = Drawing.coord(x-16), Drawing.coord(y-drawing.y) - replacement in main.lua at line 144
elseif Current_mode == 'move' thenelseif Current_drawing_mode == 'move' then - replacement in main.lua at line 147
if y >= drawing.y and y < drawing.y + pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenlocal mx,my = coord(x-16), coord(y-drawing.y)if y >= drawing.y and y < drawing.y + Drawing.pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenlocal mx,my = Drawing.coord(x-16), Drawing.coord(y-drawing.y) - replacement in main.lua at line 168[9.132]→[9.2016:2333](∅→∅),[9.2333]→[9.444:526](∅→∅),[9.444]→[9.444:526](∅→∅),[9.526]→[9.2334:2434](∅→∅),[9.2434]→[9.626:708](∅→∅),[9.626]→[9.626:708](∅→∅),[9.708]→[9.2435:2542](∅→∅),[9.2542]→[9.815:897](∅→∅),[9.815]→[9.815:897](∅→∅),[9.897]→[9.2543:2601](∅→∅)
if y >= drawing.y and y < drawing.y + pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenif Current_mode == 'freehand' thendrawing.pending = {mode=Current_mode, points={{x=coord(x-16), y=coord(y-drawing.y)}}}elseif Current_mode == 'line' or Current_mode == 'manhattan' thenlocal j = insert_point(drawing.points, coord(x-16), coord(y-drawing.y))drawing.pending = {mode=Current_mode, p1=j}elseif Current_mode == 'polygon' thenlocal j = insert_point(drawing.points, coord(x-16), coord(y-drawing.y))drawing.pending = {mode=Current_mode, vertices={j}}elseif Current_mode == 'circle' thenlocal j = insert_point(drawing.points, coord(x-16), coord(y-drawing.y))drawing.pending = {mode=Current_mode, center=j}if y >= drawing.y and y < drawing.y + Drawing.pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenif Current_drawing_mode == 'freehand' thendrawing.pending = {mode=Current_drawing_mode, points={{x=Drawing.coord(x-16), y=Drawing.coord(y-drawing.y)}}}elseif Current_drawing_mode == 'line' or Current_drawing_mode == 'manhattan' thenlocal j = Drawing.insert_point(drawing.points, Drawing.coord(x-16), Drawing.coord(y-drawing.y))drawing.pending = {mode=Current_drawing_mode, p1=j}elseif Current_drawing_mode == 'polygon' thenlocal j = Drawing.insert_point(drawing.points, Drawing.coord(x-16), Drawing.coord(y-drawing.y))drawing.pending = {mode=Current_drawing_mode, vertices={j}}elseif Current_drawing_mode == 'circle' thenlocal j = Drawing.insert_point(drawing.points, Drawing.coord(x-16), Drawing.coord(y-drawing.y))drawing.pending = {mode=Current_drawing_mode, center=j} - replacement in main.lua at line 188
if Current_mode == 'move' thenCurrent_mode = Previous_modePrevious_mode = nilif Current_drawing_mode == 'move' thenCurrent_drawing_mode = Previous_drawing_modePrevious_drawing_mode = nil - replacement in main.lua at line 197
local mx,my = coord(x-16), coord(y-Lines.current.y)local mx,my = Drawing.coord(x-16), Drawing.coord(y-Lines.current.y) - replacement in main.lua at line 199
local j = insert_point(Lines.current.points, mx,my)local j = Drawing.insert_point(Lines.current.points, mx,my) - replacement in main.lua at line 205
local mx,my = coord(x-16), coord(y-Lines.current.y)local mx,my = Drawing.coord(x-16), Drawing.coord(y-Lines.current.y) - replacement in main.lua at line 208
local j = insert_point(Lines.current.points, mx, p1.y)local j = Drawing.insert_point(Lines.current.points, mx, p1.y) - replacement in main.lua at line 211
local j = insert_point(Lines.current.points, p1.x, my)local j = Drawing.insert_point(Lines.current.points, p1.x, my) - replacement in main.lua at line 215
love.mouse.setPosition(16+pixels(p2.x), Lines.current.y+pixels(p2.y))love.mouse.setPosition(16+Drawing.pixels(p2.x), Lines.current.y+Drawing.pixels(p2.y)) - replacement in main.lua at line 219
local mx,my = coord(x-16), coord(y-Lines.current.y)local mx,my = Drawing.coord(x-16), Drawing.coord(y-Lines.current.y) - replacement in main.lua at line 221
local j = insert_point(Lines.current.points, mx,my)local j = Drawing.insert_point(Lines.current.points, mx,my) - replacement in main.lua at line 226
local mx,my = coord(x-16), coord(y-Lines.current.y)local mx,my = Drawing.coord(x-16), Drawing.coord(y-Lines.current.y) - replacement in main.lua at line 233
local mx,my = coord(x-16), coord(y-Lines.current.y)local mx,my = Drawing.coord(x-16), Drawing.coord(y-Lines.current.y) - replacement in main.lua at line 236
Lines.current.pending.end_angle = angle_with_hint(center.x,center.y, mx,my, Lines.current.pending.end_angle)Lines.current.pending.end_angle = geom.angle_with_hint(center.x,center.y, mx,my, Lines.current.pending.end_angle) - edit in main.lua at line 246[9.2746]→[9.55:61](∅→∅),[9.3157]→[9.55:61](∅→∅),[9.55]→[9.55:61](∅→∅),[9.61]→[9.2109:2114](∅→∅),[9.190]→[9.2109:2114](∅→∅),[9.2109]→[9.2109:2114](∅→∅),[9.469]→[9.762:797](∅→∅),[9.39]→[9.797:832](∅→∅),[9.797]→[9.797:832](∅→∅),[9.832]→[9.35:64](∅→∅),[9.64]→[9.874:955](∅→∅),[9.142]→[9.874:955](∅→∅),[9.874]→[9.874:955](∅→∅),[9.955]→[9.65:229](∅→∅),[9.229]→[9.955:1006](∅→∅),[9.955]→[9.955:1006](∅→∅),[9.1006]→[9.2424:2688](∅→∅),[9.2424]→[9.2424:2688](∅→∅),[9.2688]→[9.696:760](∅→∅),[9.760]→[9.1007:1182](∅→∅),[9.2723]→[9.1007:1182](∅→∅),[9.1182]→[9.595:1078](∅→∅),[9.1078]→[9.614:798](∅→∅),[9.798]→[9.467:694](∅→∅),[9.694]→[9.341:379](∅→∅),[9.379]→[9.694:741](∅→∅),[9.694]→[9.694:741](∅→∅),[9.741]→[9.2834:2845](∅→∅),[9.798]→[9.2834:2845](∅→∅),[9.1078]→[9.2834:2845](∅→∅),[9.1182]→[9.2834:2845](∅→∅),[9.2834]→[9.2834:2845](∅→∅),[9.2845]→[9.1183:1262](∅→∅),[9.1262]→[9.2890:2925](∅→∅),[9.2890]→[9.2890:2925](∅→∅),[9.2925]→[9.1263:1304](∅→∅),[9.1304]→[9.2957:2992](∅→∅),[9.2957]→[9.2957:2992](∅→∅),[9.2992]→[9.1305:1345](∅→∅),[9.1345]→[9.1045:1300](∅→∅),[9.1300]→[9.761:923](∅→∅),[9.1441]→[9.761:923](∅→∅),[9.923]→[9.1301:1383](∅→∅),[9.1383]→[9.923:1180](∅→∅),[9.923]→[9.923:1180](∅→∅),[9.1180]→[9.1079:1535](∅→∅),[9.1535]→[9.799:1205](∅→∅),[9.1205]→[9.742:1239](∅→∅)
endendfunction insert_point(points, x,y)for i,point in ipairs(points) doif near(point, x,y) thenreturn iendendtable.insert(points, {x=x, y=y})return #pointsendfunction near(point, x,y)local px,py = pixels(x),pixels(y)local cx,cy = pixels(point.x), pixels(point.y)return (cx-px)*(cx-px) + (cy-py)*(cy-py) < 16endfunction draw_shape(left,top, drawing, shape)if shape.mode == 'freehand' thenlocal prev = nilfor _,point in ipairs(shape.points) doif prev thenlove.graphics.line(pixels(prev.x)+left,pixels(prev.y)+top, pixels(point.x)+left,pixels(point.y)+top)endprev = pointendelseif shape.mode == 'line' or shape.mode == 'manhattan' thenlocal p1 = drawing.points[shape.p1]local p2 = drawing.points[shape.p2]love.graphics.line(pixels(p1.x)+left,pixels(p1.y)+top, pixels(p2.x)+left,pixels(p2.y)+top)elseif shape.mode == 'polygon' thenlocal prev = nilfor _,point in ipairs(shape.vertices) dolocal curr = drawing.points[point]if prev thenlove.graphics.line(pixels(prev.x)+left,pixels(prev.y)+top, pixels(curr.x)+left,pixels(curr.y)+top)endprev = currend-- close the looplocal curr = drawing.points[shape.vertices[1]]love.graphics.line(pixels(prev.x)+left,pixels(prev.y)+top, pixels(curr.x)+left,pixels(curr.y)+top)elseif shape.mode == 'circle' thenlocal center = drawing.points[shape.center]love.graphics.circle('line', pixels(center.x)+left,pixels(center.y)+top, pixels(shape.radius))elseif shape.mode == 'arc' thenlocal center = drawing.points[shape.center]love.graphics.arc('line', 'open', pixels(center.x)+left,pixels(center.y)+top, pixels(shape.radius), shape.start_angle, shape.end_angle, 360)elseif shape.mode == 'deleted' thenelseprint(shape.mode)assert(false)endendfunction draw_pending_shape(left,top, drawing)local shape = drawing.pendingif shape.mode == 'freehand' thendraw_shape(left,top, drawing, shape)elseif shape.mode == 'line' thenlocal p1 = drawing.points[shape.p1]local mx,my = coord(love.mouse.getX()-16), coord(love.mouse.getY()-drawing.y)if mx < 0 or mx >= 256 or my < 0 or my >= drawing.h thenreturnendlove.graphics.line(pixels(p1.x)+left,pixels(p1.y)+top, pixels(mx)+left,pixels(my)+top)elseif shape.mode == 'manhattan' thenlocal p1 = drawing.points[shape.p1]local mx,my = coord(love.mouse.getX()-16), coord(love.mouse.getY()-drawing.y)if mx < 0 or mx >= 256 or my < 0 or my >= drawing.h thenreturnendif math.abs(mx-p1.x) > math.abs(my-p1.y) thenlove.graphics.line(pixels(p1.x)+left,pixels(p1.y)+top, pixels(mx)+left,pixels(p1.y)+top)elselove.graphics.line(pixels(p1.x)+left,pixels(p1.y)+top, pixels(p1.x)+left,pixels(my)+top)endelseif shape.mode == 'polygon' then-- don't close the loop on a pending polygonlocal prev = nilfor _,point in ipairs(shape.vertices) dolocal curr = drawing.points[point]if prev thenlove.graphics.line(pixels(prev.x)+left,pixels(prev.y)+top, pixels(curr.x)+left,pixels(curr.y)+top)endprev = currendlove.graphics.line(pixels(prev.x)+left,pixels(prev.y)+top, love.mouse.getX(),love.mouse.getY())elseif shape.mode == 'circle' thenlocal center = drawing.points[shape.center]local mx,my = coord(love.mouse.getX()-16), coord(love.mouse.getY()-drawing.y)if mx < 0 or mx >= 256 or my < 0 or my >= drawing.h thenreturnendlocal cx,cy = pixels(center.x)+left, pixels(center.y)+toplove.graphics.circle('line', cx,cy, math.dist(cx,cy, love.mouse.getX(),love.mouse.getY()))elseif shape.mode == 'arc' thenlocal center = drawing.points[shape.center]local mx,my = coord(love.mouse.getX()-16), coord(love.mouse.getY()-drawing.y)if mx < 0 or mx >= 256 or my < 0 or my >= drawing.h thenreturnendshape.end_angle = angle_with_hint(center.x,center.y, mx,my, shape.end_angle)local cx,cy = pixels(center.x)+left, pixels(center.y)+toplove.graphics.arc('line', 'open', cx,cy, pixels(shape.radius), shape.start_angle, shape.end_angle, 360) - edit in main.lua at line 249[9.3121]→[9.1442:1481](∅→∅),[9.1481]→[9.3151:3186](∅→∅),[9.3151]→[9.3151:3186](∅→∅),[9.3186]→[9.1482:1526](∅→∅),[9.1526]→[9.3221:3256](∅→∅),[9.3221]→[9.3221:3256](∅→∅),[9.3256]→[9.1527:1567](∅→∅),[9.1567]→[9.1181:1299](∅→∅),[9.1299]→[9.1536:1617](∅→∅),[9.1617]→[9.1206:1352](∅→∅),[9.1352]→[9.1240:1549](∅→∅),[9.1549]→[9.380:418](∅→∅),[9.418]→[9.3287:3294](∅→∅),[9.1299]→[9.3287:3294](∅→∅),[9.1352]→[9.3287:3294](∅→∅),[9.1549]→[9.3287:3294](∅→∅),[9.1567]→[9.3287:3294](∅→∅),[9.1617]→[9.3287:3294](∅→∅),[9.3287]→[9.3287:3294](∅→∅),[9.3294]→[9.1300:1322](∅→∅),[9.1322]→[9.3294:3323](∅→∅),[9.3294]→[9.3294:3323](∅→∅),[9.3323]→[9.1568:1610](∅→∅),[9.1610]→[9.442:455](∅→∅),[9.442]→[9.442:455](∅→∅),[9.455]→[9.3324:3361](∅→∅),[9.3361]→[9.485:502](∅→∅),[9.485]→[9.485:502](∅→∅),[9.502]→[9.1611:1664](∅→∅),[9.1664]→[9.567:644](∅→∅),[9.567]→[9.567:644](∅→∅),[9.644]→[9.1665:1927](∅→∅),[9.1927]→[9.74:101](∅→∅),[9.74]→[9.74:101](∅→∅),[9.101]→[9.1928:1956](∅→∅),[9.1956]→[9.740:760](∅→∅),[9.740]→[9.740:760](∅→∅),[9.760]→[9.102:122](∅→∅),[9.122]→[9.780:864](∅→∅),[9.780]→[9.780:864](∅→∅),[9.864]→[9.1957:2030](∅→∅),[9.2030]→[9.961:1044](∅→∅),[9.961]→[9.961:1044](∅→∅),[9.1044]→[9.2031:2066](∅→∅),[9.2066]→[9.1091:1128](∅→∅),[9.1091]→[9.1091:1128](∅→∅),[9.1128]→[9.1618:1934](∅→∅),[9.1934]→[9.1550:1633](∅→∅),[9.1691]→[9.1691:2004](∅→∅)
function on_shape(x,y, drawing, shape)if shape.mode == 'freehand' thenreturn on_freehand(x,y, drawing, shape)elseif shape.mode == 'line' thenreturn on_line(x,y, drawing, shape)elseif shape.mode == 'manhattan' thenreturn x == drawing.points[shape.p1].x or y == drawing.points[shape.p1].yelseif shape.mode == 'polygon' thenreturn on_polygon(x,y, drawing, shape)elseif shape.mode == 'circle' thenlocal center = drawing.points[shape.center]return math.dist(center.x,center.y, x,y) == shape.radiuselseif shape.mode == 'arc' thenlocal center = drawing.points[shape.center]local dist = math.dist(center.x,center.y, x,y)if dist < shape.radius*0.95 or dist > shape.radius*1.05 thenreturn falseendreturn angle_between(center.x,center.y, x,y, shape.start_angle,shape.end_angle)elseif shape.mode == 'deleted' thenelseprint(shape.mode)assert(false)endendfunction on_freehand(x,y, drawing, shape)local prevfor _,p in ipairs(shape.points) doif prev thenif on_line(x,y, drawing, {p1=prev, p2=p}) thenreturn trueendendprev = pendreturn falseendfunction on_line(x,y, drawing, shape)local p1,p2if type(shape.p1) == 'number' thenp1 = drawing.points[shape.p1]p2 = drawing.points[shape.p2]elsep1 = shape.p1p2 = shape.p2endif p1.x == p2.x thenif math.abs(p1.x-x) > 5 thenreturn falseendlocal y1,y2 = p1.y,p2.yif y1 > y2 theny1,y2 = y2,y1endreturn y >= y1 and y <= y2end-- has the right slope and interceptlocal m = (p2.y - p1.y) / (p2.x - p1.x)local yp = p1.y + m*(x-p1.x)if yp < 0.95*y or yp > 1.05*y thenreturn falseend-- between endpointslocal k = (x-p1.x) / (p2.x-p1.x)return k > -0.05 and k < 1.05endfunction on_polygon(x,y, drawing, shape)local prevfor _,p in ipairs(shape.vertices) doif prev thenif on_line(x,y, drawing, {p1=prev, p2=p}) thenreturn trueendendprev = pendreturn on_line(x,y, drawing, {p1=shape.vertices[1], p2=shape.vertices[#shape.vertices]})endfunction angle_between(x1,y1, x2,y2, s,e)local angle = math.angle(x1,y1, x2,y2)if s > e thens,e = e,send-- I'm not sure this is right or ideal..angle = angle-math.pi*2if s <= angle and angle <= e thenreturn trueendangle = angle+math.pi*2if s <= angle and angle <= e thenreturn trueendangle = angle+math.pi*2return s <= angle and angle <= eend - replacement in main.lua at line 359
local drawing = current_drawing()local drawing = Drawing.current_drawing() - replacement in main.lua at line 362
Current_mode = 'freehand'Current_drawing_mode = 'freehand' - replacement in main.lua at line 364
Current_mode = 'polygon'Current_drawing_mode = 'polygon' - replacement in main.lua at line 366
Current_mode = 'polygon'local drawing = current_drawing()Current_drawing_mode = 'polygon'local drawing = Drawing.current_drawing() - replacement in main.lua at line 369
drawing.pending.vertices = {insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)}drawing.pending.vertices = {Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)} - replacement in main.lua at line 378
elseif love.mouse.isDown('1') and chord == 'p' and Current_mode == 'polygon' thenlocal drawing = current_drawing()local mx,my = coord(love.mouse.getX()-16), coord(love.mouse.getY()-drawing.y)local j = insert_point(drawing.points, mx,my)elseif love.mouse.isDown('1') and chord == 'p' and Current_drawing_mode == 'polygon' thenlocal drawing = Drawing.current_drawing()local mx,my = Drawing.coord(love.mouse.getX()-16), Drawing.coord(love.mouse.getY()-drawing.y)local j = Drawing.insert_point(drawing.points, mx,my) - replacement in main.lua at line 384
Current_mode = 'circle'elseif love.mouse.isDown('1') and chord == 'a' and Current_mode == 'circle' thenlocal drawing = current_drawing()Current_drawing_mode = 'circle'elseif love.mouse.isDown('1') and chord == 'a' and Current_drawing_mode == 'circle' thenlocal drawing = Drawing.current_drawing() - replacement in main.lua at line 388
local mx,my = coord(love.mouse.getX()-16), coord(love.mouse.getY()-drawing.y)local j = insert_point(drawing.points, mx,my)local mx,my = Drawing.coord(love.mouse.getX()-16), Drawing.coord(love.mouse.getY()-drawing.y)local j = Drawing.insert_point(drawing.points, mx,my) - replacement in main.lua at line 392
drawing.pending.start_angle = math.angle(center.x,center.y, mx,my)drawing.pending.start_angle = geom.angle(center.x,center.y, mx,my) - replacement in main.lua at line 394
Current_mode = 'circle'local drawing = current_drawing()Current_drawing_mode = 'circle'local drawing = Drawing.current_drawing() - replacement in main.lua at line 397
drawing.pending.center = insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)drawing.pending.center = Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y) - replacement in main.lua at line 405
Current_mode = 'line'local drawing = current_drawing()Current_drawing_mode = 'line'local drawing = Drawing.current_drawing() - replacement in main.lua at line 408
drawing.pending.p1 = insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)drawing.pending.p1 = Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y) - replacement in main.lua at line 416
Current_mode = 'line'local drawing,_,shape = select_shape_at_mouse()Current_drawing_mode = 'line'local drawing,_,shape = Drawing.select_shape_at_mouse() - replacement in main.lua at line 422
Current_mode = 'manhattan'local drawing = select_drawing_at_mouse()Current_drawing_mode = 'manhattan'local drawing = Drawing.select_drawing_at_mouse() - replacement in main.lua at line 425
drawing.pending.p1 = insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y)drawing.pending.p1 = Drawing.insert_point(drawing.points, drawing.pending.points[1].x, drawing.pending.points[1].y) - replacement in main.lua at line 435
Current_mode = 'manhattan'local drawing,_,shape = select_shape_at_mouse()Current_drawing_mode = 'manhattan'local drawing,_,shape = Drawing.select_shape_at_mouse() - replacement in main.lua at line 441
local drawing,_,shape = select_shape_at_mouse()local drawing,_,shape = Drawing.select_shape_at_mouse() - replacement in main.lua at line 446
local drawing,_,p = select_point_at_mouse()local drawing,_,p = Drawing.select_point_at_mouse() - replacement in main.lua at line 448
Previous_mode = Current_modeCurrent_mode = 'move'drawing.pending = {mode=Current_mode, target_point=p}Previous_drawing_mode = Current_drawing_modeCurrent_drawing_mode = 'move'drawing.pending = {mode=Current_drawing_mode, target_point=p} - replacement in main.lua at line 454
local drawing,_,p = select_point_at_mouse()local drawing,_,p = Drawing.select_point_at_mouse() - replacement in main.lua at line 456
Previous_mode = Current_modeCurrent_mode = 'move'drawing.pending = {mode=Current_mode, target_point=p}Previous_drawing_mode = Current_drawing_modeCurrent_drawing_mode = 'move'drawing.pending = {mode=Current_drawing_mode, target_point=p} - replacement in main.lua at line 462
local drawing,i,p = select_point_at_mouse()local drawing,i,p = Drawing.select_point_at_mouse() - replacement in main.lua at line 465
if contains_point(shape, i) thenif Drawing.contains_point(shape, i) then - replacement in main.lua at line 480
local drawing,_,shape = select_shape_at_mouse()local drawing,_,shape = Drawing.select_shape_at_mouse() - replacement in main.lua at line 485
local drawing = select_drawing_at_mouse()local drawing = Drawing.select_drawing_at_mouse() - edit in main.lua at line 493[9.146]→[9.146:156](∅→∅),[9.156]→[9.533:552](∅→∅),[9.576]→[9.533:552](∅→∅),[9.803]→[9.803:882](∅→∅),[9.882]→[9.5377:5413](∅→∅),[9.5413]→[9.3056:3094](∅→∅),[9.918]→[9.3056:3094](∅→∅),[9.3094]→[9.6279:6383](∅→∅),[9.994]→[9.1054:1087](∅→∅),[9.6383]→[9.1054:1087](∅→∅),[9.1054]→[9.1054:1087](∅→∅),[9.1087]→[9.126:134](∅→∅),[9.126]→[9.126:134](∅→∅),[9.134]→[9.119:125](∅→∅),[9.119]→[9.119:125](∅→∅),[9.125]→[9.1088:1101](∅→∅),[9.1101]→[9.125:163](∅→∅),[9.125]→[9.125:163](∅→∅),[9.163]→[9.5414:5450](∅→∅),[9.5450]→[9.3095:3133](∅→∅),[9.199]→[9.3095:3133](∅→∅),[9.3133]→[9.236:292](∅→∅),[9.236]→[9.236:292](∅→∅),[9.292]→[9.6384:6488](∅→∅),[9.6488]→[9.1094:1180](∅→∅),[9.1094]→[9.1094:1180](∅→∅),[9.1180]→[9.384:433](∅→∅),[9.1354]→[9.384:433](∅→∅),[9.384]→[9.384:433](∅→∅),[9.433]→[9.1384:1408](∅→∅),[9.1408]→[9.975:1025](∅→∅),[9.766]→[9.507:542](∅→∅),[9.1025]→[9.507:542](∅→∅),[9.1067]→[9.507:542](∅→∅),[9.1399]→[9.507:542](∅→∅),[9.3460]→[9.507:542](∅→∅),[9.507]→[9.507:542](∅→∅),[9.542]→[9.1073:1161](∅→∅),[9.1161]→[9.5451:5487](∅→∅),[9.5487]→[9.3134:3172](∅→∅),[9.1197]→[9.3134:3172](∅→∅),[9.3172]→[9.1234:1290](∅→∅),[9.1234]→[9.1234:1290](∅→∅),[9.1290]→[9.6489:6593](∅→∅),[9.6593]→[9.1389:1475](∅→∅),[9.1389]→[9.1389:1475](∅→∅),[9.1475]→[9.1026:1075](∅→∅),[9.1075]→[9.1524:1585](∅→∅),[9.1524]→[9.1524:1585](∅→∅),[9.1585]→[9.1076:1111](∅→∅),[9.542]→[9.448:492](∅→∅),[9.1111]→[9.448:492](∅→∅),[9.1618]→[9.448:492](∅→∅),[9.448]→[9.448:492](∅→∅),[9.185]→[9.601:607](∅→∅),[9.324]→[9.601:607](∅→∅),[9.492]→[9.601:607](∅→∅),[9.1135]→[9.601:607](∅→∅),[9.601]→[9.601:607](∅→∅),[9.607]→[9.1068:1073](∅→∅),[9.1073]→[9.1526:1561](∅→∅),[9.1561]→[9.5488:5524](∅→∅),[9.5524]→[9.3173:3211](∅→∅),[9.1597]→[9.3173:3211](∅→∅),[9.3211]→[9.1634:1690](∅→∅),[9.1634]→[9.1634:1690](∅→∅),[9.1690]→[9.6594:6698](∅→∅),[9.6698]→[9.1789:1812](∅→∅),[9.1789]→[9.1789:1812](∅→∅)
endendendendfunction current_drawing()local x, y = love.mouse.getX(), love.mouse.getY()for _,drawing in ipairs(Lines) doif drawing.mode == 'drawing' thenif y >= drawing.y and y < drawing.y + pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenreturn drawingendendendreturn nilendfunction select_shape_at_mouse()for _,drawing in ipairs(Lines) doif drawing.mode == 'drawing' thenlocal x, y = love.mouse.getX(), love.mouse.getY()if y >= drawing.y and y < drawing.y + pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenlocal mx,my = coord(love.mouse.getX()-16), coord(love.mouse.getY()-drawing.y)for i,shape in ipairs(drawing.shapes) doassert(shape)if on_shape(mx,my, drawing, shape) thenreturn drawing,i,shapeendendendendendendfunction select_point_at_mouse()for _,drawing in ipairs(Lines) doif drawing.mode == 'drawing' thenlocal x, y = love.mouse.getX(), love.mouse.getY()if y >= drawing.y and y < drawing.y + pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenlocal mx,my = coord(love.mouse.getX()-16), coord(love.mouse.getY()-drawing.y)for i,point in ipairs(drawing.points) doassert(point)if near(point, mx,my) thenreturn drawing,i,pointendendendendendendfunction select_drawing_at_mouse()for _,drawing in ipairs(Lines) doif drawing.mode == 'drawing' thenlocal x, y = love.mouse.getX(), love.mouse.getY()if y >= drawing.y and y < drawing.y + pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenreturn drawing - edit in main.lua at line 494[9.1822]→[9.1822:1841](∅→∅),[9.1841]→[9.1112:1202](∅→∅),[9.1202]→[5.2:66](∅→∅),[5.66]→[9.1270:1619](∅→∅),[9.1270]→[9.1270:1619](∅→∅),[9.1619]→[5.67:89](∅→∅),[5.89]→[9.1619:1648](∅→∅),[9.1619]→[9.1619:1648](∅→∅),[9.1648]→[9.2255:2293](∅→∅),[9.1841]→[9.2255:2293](∅→∅),[9.1073]→[9.2255:2293](∅→∅),[9.2293]→[9.1114:1353](∅→∅),[9.3490]→[9.1114:1353](∅→∅),[9.1114]→[9.1114:1353](∅→∅),[9.1353]→[9.3491:3548](∅→∅),[9.3548]→[9.2294:2480](∅→∅),[9.1401]→[9.152:157](∅→∅),[9.2480]→[9.152:157](∅→∅),[9.3696]→[9.152:157](∅→∅),[9.826]→[9.152:157](∅→∅),[9.157]→[9.3697:3742](∅→∅),[9.3742]→[9.2481:2522](∅→∅),[9.2522]→[9.3774:3870](∅→∅),[9.3774]→[9.3774:3870](∅→∅),[9.3870]→[9.2523:2667](∅→∅),[9.859]→[9.445:452](∅→∅),[9.1587]→[9.445:452](∅→∅),[9.2667]→[9.445:452](∅→∅),[9.3962]→[9.445:452](∅→∅),[9.445]→[9.445:452](∅→∅),[9.452]→[9.2668:2684](∅→∅),[9.884]→[9.505:511](∅→∅),[9.1641]→[9.505:511](∅→∅),[9.2684]→[9.505:511](∅→∅),[9.3987]→[9.505:511](∅→∅),[9.505]→[9.505:511](∅→∅),[9.511]→[9.325:330](∅→∅),[9.826]→[9.325:330](∅→∅),[9.607]→[9.325:330](∅→∅),[9.330]→[9.135:160](∅→∅),[9.160]→[9.3988:4023](∅→∅),[9.4023]→[9.160:175](∅→∅),[9.160]→[9.160:175](∅→∅),[9.175]→[9.4024:4155](∅→∅),[9.4155]→[9.278:342](∅→∅),[9.278]→[9.278:342](∅→∅)
endendendfunction contains_point(shape, p)if shape.mode == 'freehand' then-- not supportedelseif shape.mode == 'line' or shape.mode == 'manhattan' thenreturn shape.p1 == p or shape.p2 == pelseif shape.mode == 'polygon' thenreturn table.find(shape.vertices, p)elseif shape.mode == 'circle' thenreturn shape.center == pelseif shape.mode == 'arc' thenreturn shape.center == p-- ugh, how to support angleselseif shape.mode == 'deleted' then-- already doneelseprint(shape.mode)assert(false)endendfunction convert_line(drawing, shape)-- Perhaps we should do a more sophisticated "simple linear regression"-- here:-- https://en.wikipedia.org/wiki/Linear_regression#Simple_and_multiple_linear_regression-- But this works well enough for close-to-linear strokes.assert(shape.mode == 'freehand')shape.mode = 'line'shape.p1 = insert_point(drawing.points, shape.points[1].x, shape.points[1].y)local n = #shape.pointsshape.p2 = insert_point(drawing.points, shape.points[n].x, shape.points[n].y)end-- turn a line either horizontal or verticalfunction convert_horvert(drawing, shape)if shape.mode == 'freehand' thenconvert_line(shape)endassert(shape.mode == 'line')local p1 = drawing.points[shape.p1]local p2 = drawing.points[shape.p2]if math.abs(p1.x-p2.x) > math.abs(p1.y-p2.y) thenp2.y = p1.yelsep2.x = p1.xendendfunction smoothen(shape)assert(shape.mode == 'freehand')for _=1,7 dofor i=2,#shape.points-1 dolocal a = shape.points[i-1]local b = shape.points[i]local c = shape.points[i+1]b.x = (a.x + b.x + c.x)/3b.y = (a.y + b.y + c.y)/3 - edit in main.lua at line 505[2.417]→[2.417:431](∅→∅),[2.431]→[9.2486:3164](∅→∅),[9.371]→[9.2486:3164](∅→∅),[9.116]→[9.460:464](∅→∅),[9.2055]→[9.460:464](∅→∅),[9.3164]→[9.460:464](∅→∅),[9.460]→[9.460:464](∅→∅),[9.464]→[9.1411:1482](∅→∅),[9.1482]→[9.191:226](∅→∅),[9.226]→[9.120:155](∅→∅),[9.155]→[9.17:57](∅→∅),[9.57]→[9.68:104](∅→∅),[9.104]→[9.223:276](∅→∅),[9.223]→[9.223:276](∅→∅),[9.276]→[9.226:246](∅→∅),[9.226]→[9.226:246](∅→∅),[9.281]→[9.281:298](∅→∅),[9.298]→[9.277:402](∅→∅),[9.402]→[9.298:316](∅→∅),[9.298]→[9.298:316](∅→∅),[9.316]→[9.403:441](∅→∅),[9.441]→[9.349:492](∅→∅),[9.349]→[9.349:492](∅→∅),[9.492]→[9.442:503](∅→∅),[9.503]→[9.543:554](∅→∅),[9.543]→[9.543:554](∅→∅),[9.554]→[9.3212:3267](∅→∅),[9.3267]→[9.589:613](∅→∅),[9.589]→[9.589:613](∅→∅),[9.613]→[9.105:128](∅→∅),[9.128]→[9.3268:3317](∅→∅),[9.3317]→[9.157:163](∅→∅),[9.157]→[9.157:163](∅→∅),[9.163]→[9.613:747](∅→∅),[9.613]→[9.613:747](∅→∅),[9.747]→[9.3318:3353](∅→∅),[9.3353]→[9.781:825](∅→∅),[9.781]→[9.781:825](∅→∅),[9.825]→[9.3354:3391](∅→∅)
endendendfunction angle_with_hint(x1, y1, x2, y2, hint)local result = math.angle(x1,y1, x2,y2)if hint then-- Smooth the discontinuity where angle goes from positive to negative.-- The hint is a memory of which way we drew it last time.while result > hint+math.pi/10 doresult = result-math.pi*2endwhile result < hint-math.pi/10 doresult = result+math.pi*2endendreturn resultend-- result is from -π/2 to 3π/2, approximately adding math.atan2 from Lua 5.3-- (LÖVE is Lua 5.1)function math.angle(x1,y1, x2,y2)local result = math.atan((y2-y1)/(x2-x1))if x2 < x1 thenresult = result+math.piendreturn resultendfunction math.dist(x1,y1, x2,y2) return ((x2-x1)^2+(y2-y1)^2)^0.5 endfunction load_from_disk(filename)local infile = io.open(filename)local result = load_from_file(infile)if infile then infile:close() endreturn resultendfunction load_from_file(infile)local result = {}if infile thenlocal infile_next_line = infile:lines() -- works with both Lua files and LÖVE Files (https://www.love2d.org/wiki/File)while true dolocal line = infile_next_line()if line == nil then break endif line == '```lines' then -- inflexible with whitespace since these files are always autogeneratedtable.insert(result, load_drawing(infile_next_line))elsetable.insert(result, {mode='text', data=line})endendendif #result == 0 thentable.insert(result, {mode='text', data=''})endreturn resultendfunction save_to_disk(lines, filename)local outfile = io.open(filename, 'w')for _,line in ipairs(lines) doif line.mode == 'drawing' thenstore_drawing(outfile, line)elseoutfile:write(line.data..'\n') - edit in main.lua at line 507
outfile:close() - edit in main.lua at line 508[9.875]→[9.875:898](∅→∅),[9.898]→[9.504:544](∅→∅),[9.544]→[9.3392:3470](∅→∅),[9.3470]→[9.990:1006](∅→∅),[9.990]→[9.990:1006](∅→∅),[9.1006]→[9.545:581](∅→∅),[9.581]→[9.1037:1126](∅→∅),[9.1037]→[9.1037:1126](∅→∅),[9.1126]→[3.3:65](∅→∅),[3.65]→[9.1159:1299](∅→∅),[9.1159]→[9.1159:1299](∅→∅),[9.1299]→[3.66:368](∅→∅),[3.368]→[9.1299:1489](∅→∅),[9.1299]→[9.1299:1489](∅→∅),[9.1489]→[9.119:156](∅→∅),[9.489]→[9.489:535](∅→∅),[9.535]→[3.369:435](∅→∅),[3.435]→[9.1522:1630](∅→∅),[9.572]→[9.1522:1630](∅→∅),[9.1522]→[9.1522:1630](∅→∅),[9.1630]→[3.436:700](∅→∅),[3.700]→[9.1630:1662](∅→∅),[9.1630]→[9.1630:1662](∅→∅),[9.1662]→[9.573:612](∅→∅),[9.612]→[3.701:1027](∅→∅),[9.612]→[9.1662:1701](∅→∅),[3.1027]→[9.1662:1701](∅→∅),[9.1662]→[9.1662:1701](∅→∅),[9.1701]→[9.56:71](∅→∅),[9.71]→[6.38:268](∅→∅),[6.268]→[9.71:501](∅→∅),[9.71]→[9.71:501](∅→∅),[9.501]→[9.1701:1705](∅→∅),[9.1701]→[9.1701:1705](∅→∅),[9.1705]→[9.502:1086](∅→∅),[9.1086]→[9.585:674](∅→∅),[9.750]→[9.750:775](∅→∅),[9.775]→[9.6699:7418](∅→∅),[9.693]→[9.1414:1420](∅→∅),[9.7418]→[9.1414:1420](∅→∅),[9.1414]→[9.1414:1420](∅→∅),[9.1420]→[9.7419:7559](∅→∅),[9.801]→[9.1546:1552](∅→∅),[9.7559]→[9.1546:1552](∅→∅),[9.1546]→[9.1546:1552](∅→∅),[9.1552]→[9.7560:7725](∅→∅),[9.929]→[9.1703:1709](∅→∅),[9.7725]→[9.1703:1709](∅→∅),[9.1703]→[9.1703:1709](∅→∅),[9.1709]→[9.7726:7875](∅→∅),[9.1044]→[9.1844:1850](∅→∅),[9.7875]→[9.1844:1850](∅→∅),[9.1844]→[9.1844:1850](∅→∅),[9.1850]→[9.7876:8022](∅→∅),[9.1155]→[9.1982:1988](∅→∅),[9.8022]→[9.1982:1988](∅→∅),[9.1982]→[9.1982:1988](∅→∅),[9.1988]→[9.8023:8329](∅→∅),[9.8329]→[9.107:146](∅→∅),[9.1372]→[9.107:146](∅→∅),[9.146]→[9.8330:8434](∅→∅),[9.245]→[9.1988:2074](∅→∅),[9.256]→[9.1988:2074](∅→∅),[9.376]→[9.1988:2074](∅→∅),[9.1372]→[9.1988:2074](∅→∅),[9.8434]→[9.1988:2074](∅→∅),[9.1988]→[9.1988:2074](∅→∅),[9.2150]→[9.2150:2175](∅→∅),[9.2175]→[9.8435:9016](∅→∅),[9.9016]→[9.2699:2744](∅→∅),[9.2699]→[9.2699:2744](∅→∅),[9.2744]→[9.9017:9231](∅→∅),[9.2029]→[9.2938:2947](∅→∅),[9.9231]→[9.2938:2947](∅→∅),[9.2938]→[9.2938:2947](∅→∅),[9.2947]→[9.9232:9332](∅→∅),[9.756]→[9.3037:3045](∅→∅),[9.2129]→[9.3037:3045](∅→∅),[9.9332]→[9.3037:3045](∅→∅),[9.3037]→[9.3037:3045](∅→∅),[9.3045]→[9.9333:9617](∅→∅),[9.2373]→[9.3294:3300](∅→∅),[9.9617]→[9.3294:3300](∅→∅),[9.3294]→[9.3294:3300](∅→∅),[9.3300]→[9.9618:9900](∅→∅),[9.2624]→[9.3432:3438](∅→∅),[9.9900]→[9.3432:3438](∅→∅),[9.3432]→[9.3432:3438](∅→∅),[9.3438]→[9.9901:10061](∅→∅),[9.2747]→[9.3584:3590](∅→∅),[9.10061]→[9.3584:3590](∅→∅),[9.3584]→[9.3584:3590](∅→∅),[9.3590]→[9.10062:10206](∅→∅),[9.2857]→[9.3720:3726](∅→∅),[9.10206]→[9.3720:3726](∅→∅),[9.3720]→[9.3720:3726](∅→∅),[9.3726]→[9.10207:10348](∅→∅),[9.2963]→[9.3853:3859](∅→∅),[9.10348]→[9.3853:3859](∅→∅),[9.3853]→[9.3853:3859](∅→∅),[9.3859]→[9.860:899](∅→∅),[9.899]→[9.10349:10453](∅→∅),[9.998]→[9.3859:3864](∅→∅),[9.10453]→[9.3859:3864](∅→∅),[9.3859]→[9.3859:3864](∅→∅),[9.3864]→[9.999:1029](∅→∅),[9.1029]→[9.10454:10491](∅→∅),[9.10491]→[9.3935:3964](∅→∅),[9.3935]→[9.3935:3964](∅→∅),[9.3964]→[9.10492:10529](∅→∅),[9.10529]→[9.4001:4028](∅→∅),[9.4001]→[9.4001:4028](∅→∅),[9.4028]→[9.10530:10572](∅→∅),[9.10572]→[9.4070:4108](∅→∅),[9.4070]→[9.4070:4108](∅→∅),[9.4108]→[9.10573:10644](∅→∅),[9.10644]→[9.1101:1118](∅→∅),[9.1101]→[9.1101:1118](∅→∅),[9.1118]→[9.4108:4115](∅→∅),[9.4108]→[9.4108:4115](∅→∅),[9.4115]→[9.10645:10669](∅→∅),[9.10669]→[9.4139:4150](∅→∅),[9.4139]→[9.4139:4150](∅→∅),[9.4230]→[9.4230:4445](∅→∅),[9.4445]→[9.1086:1090](∅→∅),[9.1086]→[9.1086:1090](∅→∅)
json = require 'json'function load_drawing(infile_next_line)local drawing = {mode='drawing', h=256/2, points={}, shapes={}, pending={}}while true dolocal line = infile_next_line()assert(line)if line == '```' then break endlocal shape = json.decode(line)if shape.mode == 'line' or shape.mode == 'manhattan' thenshape.p1 = insert_point(drawing.points, shape.p1.x, shape.p1.y)shape.p2 = insert_point(drawing.points, shape.p2.x, shape.p2.y)elseif shape.mode == 'polygon' thenfor i,p in ipairs(shape.vertices) doshape.vertices[i] = insert_point(drawing.points, p.x,p.y)endelseif shape.mode == 'circle' or shape.mode == 'arc' thenshape.center = insert_point(drawing.points, shape.center.x,shape.center.y)endtable.insert(drawing.shapes, shape)endreturn drawingendfunction store_drawing(outfile, drawing)outfile:write('```lines\n')for _,shape in ipairs(drawing.shapes) doif shape.mode == 'freehand' thenoutfile:write(json.encode(shape)..'\n')elseif shape.mode == 'line' or shape.mode == 'manhattan' thenlocal line = json.encode({mode=shape.mode, p1=drawing.points[shape.p1], p2=drawing.points[shape.p2]})outfile:write(line..'\n')elseif shape.mode == 'polygon' thenlocal obj = {mode=shape.mode, vertices={}}for _,p in ipairs(shape.vertices) dotable.insert(obj.vertices, drawing.points[p])endlocal line = json.encode(obj)outfile:write(line..'\n')elseif shape.mode == 'circle' thenoutfile:write(json.encode({mode=shape.mode, center=drawing.points[shape.center], radius=shape.radius})..'\n')elseif shape.mode == 'arc' thenoutfile:write(json.encode({mode=shape.mode, center=drawing.points[shape.center], radius=shape.radius, start_angle=shape.start_angle, end_angle=shape.end_angle})..'\n')endendoutfile:write('```\n')endicon = {}function icon.insert_drawing(x, y)love.graphics.setColor(0.7,0.7,0.7)love.graphics.rectangle('line', x,y, 12,12)love.graphics.line(4,y+6, 16,y+6)love.graphics.line(10,y, 10,y+12)love.graphics.setColor(0, 0, 0)endfunction icon.freehand(x, y)love.graphics.line(x+4,y+7,x+5,y+5)love.graphics.line(x+5,y+5,x+7,y+4)love.graphics.line(x+7,y+4,x+9,y+3)love.graphics.line(x+9,y+3,x+10,y+5)love.graphics.line(x+10,y+5,x+12,y+6)love.graphics.line(x+12,y+6,x+13,y+8)love.graphics.line(x+13,y+8,x+13,y+10)love.graphics.line(x+13,y+10,x+14,y+12)love.graphics.line(x+14,y+12,x+15,y+14)love.graphics.line(x+15,y+14,x+15,y+16)endfunction icon.line(x, y)love.graphics.line(x+4,y+2, x+16,y+18)endfunction icon.manhattan(x, y)love.graphics.line(x+4,y+20, x+4,y+2)love.graphics.line(x+4,y+2, x+10,y+2)love.graphics.line(x+10,y+2, x+10,y+10)love.graphics.line(x+10,y+10, x+18,y+10)endfunction icon.polygon(x, y)love.graphics.line(x+8,y+2, x+14,y+2)love.graphics.line(x+14,y+2, x+18,y+10)love.graphics.line(x+18,y+10, x+10,y+18)love.graphics.line(x+10,y+18, x+4,y+12)love.graphics.line(x+4,y+12, x+8,y+2)endfunction icon.circle(x, y)love.graphics.circle('line', x+10,y+10, 8)endfunction draw_help_without_mouse_pressed(drawing)love.graphics.setColor(0,0.5,0)local y = drawing.y+10love.graphics.print("Things you can do:", 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Press the mouse button to start drawing a "..current_shape(), 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Hover on a point and press 'ctrl+v' to start moving it,", 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("then press the mouse button to finish", 16+30+bullet_indent(),y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Hover on a point or shape and press 'ctrl+d' to delete it", 16+30,y, 0, Zoom)y = y+15*Zoomy = y+15*Zoomif Current_mode ~= 'freehand' thenlove.graphics.print("* Press 'ctrl+f' to switch to drawing freehand strokes", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_mode ~= 'line' thenlove.graphics.print("* Press 'ctrl+l' to switch to drawing lines", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_mode ~= 'manhattan' thenlove.graphics.print("* Press 'ctrl+m' to switch to drawing horizontal/vertical lines", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_mode ~= 'circle' thenlove.graphics.print("* Press 'ctrl+c' to switch to drawing circles/arcs", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_mode ~= 'polygon' thenlove.graphics.print("* Press 'ctrl+g' to switch to drawing polygons", 16+30,y, 0, Zoom)y = y+15*Zoomendlove.graphics.print("* Press 'ctrl+=' or 'ctrl+-' to Zoom in or out", 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Press 'ctrl+0' to reset Zoom", 16+30,y, 0, Zoom)y = y+15*Zoomy = y+15*Zoomlove.graphics.print("Hit 'esc' now to hide this message", 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.setColor(0,0.5,0, 0.1)love.graphics.rectangle('fill', 16,drawing.y, Drawing_width, math.max(pixels(drawing.h),y-drawing.y))endfunction draw_help_with_mouse_pressed(drawing)love.graphics.setColor(0,0.5,0)local y = drawing.y+10love.graphics.print("You're currently drawing a "..current_shape(drawing.pending), 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print('Things you can do now:', 16+30,y, 0, Zoom)y = y+15*Zoomif Current_mode == 'freehand' thenlove.graphics.print('* Release the mouse button to finish drawing the stroke', 16+30,y, 0, Zoom)y = y+15*Zoomelseif Current_mode == 'line' or Current_mode == 'manhattan' thenlove.graphics.print('* Release the mouse button to finish drawing the line', 16+30,y, 0, Zoom)y = y+15*Zoomelseif Current_mode == 'circle' thenif drawing.pending.mode == 'circle' thenlove.graphics.print('* Release the mouse button to finish drawing the circle', 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Press 'a' to draw just an arc of a circle", 16+30,y, 0, Zoom)elselove.graphics.print('* Release the mouse button to finish drawing the arc', 16+30,y, 0, Zoom)endy = y+15*Zoomelseif Current_mode == 'polygon' thenlove.graphics.print('* Release the mouse button to finish drawing the polygon', 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Press 'p' to add a vertex to the polygon", 16+30,y, 0, Zoom)y = y+15*Zoomendlove.graphics.print("* Press 'esc' then release the mouse button to cancel the current shape", 16+30,y, 0, Zoom)y = y+15*Zoomy = y+15*Zoomif Current_mode ~= 'line' thenlove.graphics.print("* Press 'l' to switch to drawing lines", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_mode ~= 'manhattan' thenlove.graphics.print("* Press 'm' to switch to drawing horizontal/vertical lines", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_mode ~= 'circle' thenlove.graphics.print("* Press 'c' to switch to drawing circles/arcs", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_mode ~= 'polygon' thenlove.graphics.print("* Press 'g' to switch to drawing polygons", 16+30,y, 0, Zoom)y = y+15*Zoomendlove.graphics.setColor(0,0.5,0, 0.1)love.graphics.rectangle('fill', 16,drawing.y, Drawing_width, math.max(pixels(drawing.h),y-drawing.y))endfunction current_shape(shape)if Current_mode == 'freehand' thenreturn 'freehand stroke'elseif Current_mode == 'line' thenreturn 'straight line'elseif Current_mode == 'manhattan' thenreturn 'horizontal/vertical line'elseif Current_mode == 'circle' and shape and shape.start_angle thenreturn 'arc'elsereturn Current_modeendend_bullet_indent = nilfunction bullet_indent()if _bullet_indent == nil thenlocal text = love.graphics.newText(love.graphics.getFont(), '* ')_bullet_indent = text:getWidth()endreturn _bullet_indentend - file addition: icons.lua[85.2]
icon = {}function icon.insert_drawing(x, y)love.graphics.setColor(0.7,0.7,0.7)love.graphics.rectangle('line', x,y, 12,12)love.graphics.line(4,y+6, 16,y+6)love.graphics.line(10,y, 10,y+12)love.graphics.setColor(0, 0, 0)endfunction icon.freehand(x, y)love.graphics.line(x+4,y+7,x+5,y+5)love.graphics.line(x+5,y+5,x+7,y+4)love.graphics.line(x+7,y+4,x+9,y+3)love.graphics.line(x+9,y+3,x+10,y+5)love.graphics.line(x+10,y+5,x+12,y+6)love.graphics.line(x+12,y+6,x+13,y+8)love.graphics.line(x+13,y+8,x+13,y+10)love.graphics.line(x+13,y+10,x+14,y+12)love.graphics.line(x+14,y+12,x+15,y+14)love.graphics.line(x+15,y+14,x+15,y+16)endfunction icon.line(x, y)love.graphics.line(x+4,y+2, x+16,y+18)endfunction icon.manhattan(x, y)love.graphics.line(x+4,y+20, x+4,y+2)love.graphics.line(x+4,y+2, x+10,y+2)love.graphics.line(x+10,y+2, x+10,y+10)love.graphics.line(x+10,y+10, x+18,y+10)endfunction icon.polygon(x, y)love.graphics.line(x+8,y+2, x+14,y+2)love.graphics.line(x+14,y+2, x+18,y+10)love.graphics.line(x+18,y+10, x+10,y+18)love.graphics.line(x+10,y+18, x+4,y+12)love.graphics.line(x+4,y+12, x+8,y+2)endfunction icon.circle(x, y)love.graphics.circle('line', x+10,y+10, 8)end - file addition: help.lua[85.2]
function draw_help_without_mouse_pressed(drawing)love.graphics.setColor(0,0.5,0)local y = drawing.y+10love.graphics.print("Things you can do:", 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Press the mouse button to start drawing a "..current_shape(), 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Hover on a point and press 'ctrl+v' to start moving it,", 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("then press the mouse button to finish", 16+30+bullet_indent(),y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Hover on a point or shape and press 'ctrl+d' to delete it", 16+30,y, 0, Zoom)y = y+15*Zoomy = y+15*Zoomif Current_drawing_mode ~= 'freehand' thenlove.graphics.print("* Press 'ctrl+f' to switch to drawing freehand strokes", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_drawing_mode ~= 'line' thenlove.graphics.print("* Press 'ctrl+l' to switch to drawing lines", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_drawing_mode ~= 'manhattan' thenlove.graphics.print("* Press 'ctrl+m' to switch to drawing horizontal/vertical lines", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_drawing_mode ~= 'circle' thenlove.graphics.print("* Press 'ctrl+c' to switch to drawing circles/arcs", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_drawing_mode ~= 'polygon' thenlove.graphics.print("* Press 'ctrl+g' to switch to drawing polygons", 16+30,y, 0, Zoom)y = y+15*Zoomendlove.graphics.print("* Press 'ctrl+=' or 'ctrl+-' to Zoom in or out", 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Press 'ctrl+0' to reset Zoom", 16+30,y, 0, Zoom)y = y+15*Zoomy = y+15*Zoomlove.graphics.print("Hit 'esc' now to hide this message", 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.setColor(0,0.5,0, 0.1)love.graphics.rectangle('fill', 16,drawing.y, Drawing_width, math.max(Drawing.pixels(drawing.h),y-drawing.y))endfunction draw_help_with_mouse_pressed(drawing)love.graphics.setColor(0,0.5,0)local y = drawing.y+10love.graphics.print("You're currently drawing a "..current_shape(drawing.pending), 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print('Things you can do now:', 16+30,y, 0, Zoom)y = y+15*Zoomif Current_drawing_mode == 'freehand' thenlove.graphics.print('* Release the mouse button to finish drawing the stroke', 16+30,y, 0, Zoom)y = y+15*Zoomelseif Current_drawing_mode == 'line' or Current_drawing_mode == 'manhattan' thenlove.graphics.print('* Release the mouse button to finish drawing the line', 16+30,y, 0, Zoom)y = y+15*Zoomelseif Current_drawing_mode == 'circle' thenif drawing.pending.mode == 'circle' thenlove.graphics.print('* Release the mouse button to finish drawing the circle', 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Press 'a' to draw just an arc of a circle", 16+30,y, 0, Zoom)elselove.graphics.print('* Release the mouse button to finish drawing the arc', 16+30,y, 0, Zoom)endy = y+15*Zoomelseif Current_drawing_mode == 'polygon' thenlove.graphics.print('* Release the mouse button to finish drawing the polygon', 16+30,y, 0, Zoom)y = y+15*Zoomlove.graphics.print("* Press 'p' to add a vertex to the polygon", 16+30,y, 0, Zoom)y = y+15*Zoomendlove.graphics.print("* Press 'esc' then release the mouse button to cancel the current shape", 16+30,y, 0, Zoom)y = y+15*Zoomy = y+15*Zoomif Current_drawing_mode ~= 'line' thenlove.graphics.print("* Press 'l' to switch to drawing lines", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_drawing_mode ~= 'manhattan' thenlove.graphics.print("* Press 'm' to switch to drawing horizontal/vertical lines", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_drawing_mode ~= 'circle' thenlove.graphics.print("* Press 'c' to switch to drawing circles/arcs", 16+30,y, 0, Zoom)y = y+15*Zoomendif Current_drawing_mode ~= 'polygon' thenlove.graphics.print("* Press 'g' to switch to drawing polygons", 16+30,y, 0, Zoom)y = y+15*Zoomendlove.graphics.setColor(0,0.5,0, 0.1)love.graphics.rectangle('fill', 16,drawing.y, Drawing_width, math.max(Drawing.pixels(drawing.h),y-drawing.y))endfunction current_shape(shape)if Current_drawing_mode == 'freehand' thenreturn 'freehand stroke'elseif Current_drawing_mode == 'line' thenreturn 'straight line'elseif Current_drawing_mode == 'manhattan' thenreturn 'horizontal/vertical line'elseif Current_drawing_mode == 'circle' and shape and shape.start_angle thenreturn 'arc'elsereturn Current_drawing_modeendend_bullet_indent = nilfunction bullet_indent()if _bullet_indent == nil thenlocal text = love.graphics.newText(love.graphics.getFont(), '* ')_bullet_indent = text:getWidth()endreturn _bullet_indentend - file addition: geom.lua[85.2]
local geom = {}function geom.on_shape(x,y, drawing, shape)if shape.mode == 'freehand' thenreturn geom.on_freehand(x,y, drawing, shape)elseif shape.mode == 'line' thenreturn geom.on_line(x,y, drawing, shape)elseif shape.mode == 'manhattan' thenreturn x == drawing.points[shape.p1].x or y == drawing.points[shape.p1].yelseif shape.mode == 'polygon' thenreturn geom.on_polygon(x,y, drawing, shape)elseif shape.mode == 'circle' thenlocal center = drawing.points[shape.center]return math.dist(center.x,center.y, x,y) == shape.radiuselseif shape.mode == 'arc' thenlocal center = drawing.points[shape.center]local dist = math.dist(center.x,center.y, x,y)if dist < shape.radius*0.95 or dist > shape.radius*1.05 thenreturn falseendreturn geom.angle_between(center.x,center.y, x,y, shape.start_angle,shape.end_angle)elseif shape.mode == 'deleted' thenelseprint(shape.mode)assert(false)endendfunction geom.on_freehand(x,y, drawing, shape)local prevfor _,p in ipairs(shape.points) doif prev thenif geom.on_line(x,y, drawing, {p1=prev, p2=p}) thenreturn trueendendprev = pendreturn falseendfunction geom.on_line(x,y, drawing, shape)local p1,p2if type(shape.p1) == 'number' thenp1 = drawing.points[shape.p1]p2 = drawing.points[shape.p2]elsep1 = shape.p1p2 = shape.p2endif p1.x == p2.x thenif math.abs(p1.x-x) > 5 thenreturn falseendlocal y1,y2 = p1.y,p2.yif y1 > y2 theny1,y2 = y2,y1endreturn y >= y1 and y <= y2end-- has the right slope and interceptlocal m = (p2.y - p1.y) / (p2.x - p1.x)local yp = p1.y + m*(x-p1.x)if yp < 0.95*y or yp > 1.05*y thenreturn falseend-- between endpointslocal k = (x-p1.x) / (p2.x-p1.x)return k > -0.05 and k < 1.05endfunction geom.on_polygon(x,y, drawing, shape)local prevfor _,p in ipairs(shape.vertices) doif prev thenif geom.on_line(x,y, drawing, {p1=prev, p2=p}) thenreturn trueendendprev = pendreturn geom.on_line(x,y, drawing, {p1=shape.vertices[1], p2=shape.vertices[#shape.vertices]})endfunction geom.angle_with_hint(x1, y1, x2, y2, hint)local result = geom.angle(x1,y1, x2,y2)if hint then-- Smooth the discontinuity where angle goes from positive to negative.-- The hint is a memory of which way we drew it last time.while result > hint+math.pi/10 doresult = result-math.pi*2endwhile result < hint-math.pi/10 doresult = result+math.pi*2endendreturn resultend-- result is from -π/2 to 3π/2, approximately adding math.atan2 from Lua 5.3-- (LÖVE is Lua 5.1)function geom.angle(x1,y1, x2,y2)local result = math.atan((y2-y1)/(x2-x1))if x2 < x1 thenresult = result+math.piendreturn resultend-- is the line between x,y and cx,cy at an angle between s and e?function geom.angle_between(ox,oy, x,y, s,e)local angle = math.angle(ox,oy, x,y)if s > e thens,e = e,send-- I'm not sure this is right or ideal..angle = angle-math.pi*2if s <= angle and angle <= e thenreturn trueendangle = angle+math.pi*2if s <= angle and angle <= e thenreturn trueendangle = angle+math.pi*2return s <= angle and angle <= eendfunction geom.dist(x1,y1, x2,y2) return ((x2-x1)^2+(y2-y1)^2)^0.5 endreturn geom - file addition: file.lua[85.2]
-- primitives for saving to file and loading from fileDrawing = require 'drawing'function load_from_disk(filename)local infile = io.open(filename)local result = load_from_file(infile)if infile then infile:close() endreturn resultendfunction load_from_file(infile)local result = {}if infile thenlocal infile_next_line = infile:lines() -- works with both Lua files and LÖVE Files (https://www.love2d.org/wiki/File)while true dolocal line = infile_next_line()if line == nil then break endif line == '```lines' then -- inflexible with whitespace since these files are always autogeneratedtable.insert(result, load_drawing(infile_next_line))elsetable.insert(result, {mode='text', data=line})endendendif #result == 0 thentable.insert(result, {mode='text', data=''})endreturn resultendfunction save_to_disk(lines, filename)local outfile = io.open(filename, 'w')for _,line in ipairs(lines) doif line.mode == 'drawing' thenstore_drawing(outfile, line)elseoutfile:write(line.data..'\n')endendoutfile:close()endjson = require 'json'function load_drawing(infile_next_line)local drawing = {mode='drawing', h=256/2, points={}, shapes={}, pending={}}while true dolocal line = infile_next_line()assert(line)if line == '```' then break endlocal shape = json.decode(line)if shape.mode == 'line' or shape.mode == 'manhattan' thenshape.p1 = Drawing.insert_point(drawing.points, shape.p1.x, shape.p1.y)shape.p2 = Drawing.insert_point(drawing.points, shape.p2.x, shape.p2.y)elseif shape.mode == 'polygon' thenfor i,p in ipairs(shape.vertices) doshape.vertices[i] = Drawing.insert_point(drawing.points, p.x,p.y)endelseif shape.mode == 'circle' or shape.mode == 'arc' thenshape.center = Drawing.insert_point(drawing.points, shape.center.x,shape.center.y)endtable.insert(drawing.shapes, shape)endreturn drawingendfunction store_drawing(outfile, drawing)outfile:write('```lines\n')for _,shape in ipairs(drawing.shapes) doif shape.mode == 'freehand' thenoutfile:write(json.encode(shape)..'\n')elseif shape.mode == 'line' or shape.mode == 'manhattan' thenlocal line = json.encode({mode=shape.mode, p1=drawing.points[shape.p1], p2=drawing.points[shape.p2]})outfile:write(line..'\n')elseif shape.mode == 'polygon' thenlocal obj = {mode=shape.mode, vertices={}}for _,p in ipairs(shape.vertices) dotable.insert(obj.vertices, drawing.points[p])endlocal line = json.encode(obj)outfile:write(line..'\n')elseif shape.mode == 'circle' thenoutfile:write(json.encode({mode=shape.mode, center=drawing.points[shape.center], radius=shape.radius})..'\n')elseif shape.mode == 'arc' thenoutfile:write(json.encode({mode=shape.mode, center=drawing.points[shape.center], radius=shape.radius, start_angle=shape.start_angle, end_angle=shape.end_angle})..'\n')endendoutfile:write('```\n')end - edit in drawing.lua at line 3
geom = require 'geom' - replacement in drawing.lua at line 7
if pmx < 16+Drawing_width and pmy > line.y and pmy < line.y+pixels(line.h) thenif pmx < 16+Drawing_width and pmy > line.y and pmy < line.y+Drawing.pixels(line.h) then - replacement in drawing.lua at line 9
love.graphics.rectangle('line', 16,line.y, Drawing_width,pixels(line.h))if icon[Current_mode] thenicon[Current_mode](16+Drawing_width-20, line.y+4)love.graphics.rectangle('line', 16,line.y, Drawing_width,Drawing.pixels(line.h))if icon[Current_drawing_mode] thenicon[Current_drawing_mode](16+Drawing_width-20, line.y+4) - replacement in drawing.lua at line 13
icon[Previous_mode](16+Drawing_width-20, line.y+4)icon[Previous_drawing_mode](16+Drawing_width-20, line.y+4) - replacement in drawing.lua at line 27
local mx,my = coord(love.mouse.getX()-16), coord(love.mouse.getY()-line.y)local mx,my = Drawing.coord(love.mouse.getX()-16), Drawing.coord(love.mouse.getY()-line.y) - replacement in drawing.lua at line 31
if on_shape(mx,my, line, shape) thenif geom.on_shape(mx,my, line, shape) then - replacement in drawing.lua at line 36
draw_shape(16,line.y, line, shape)Drawing.draw_shape(16,line.y, line, shape) - replacement in drawing.lua at line 40
if near(p, mx,my) thenif Drawing.near(p, mx,my) then - replacement in drawing.lua at line 42
love.graphics.circle('line', pixels(p.x)+16,pixels(p.y)+line.y, 4)love.graphics.circle('line', Drawing.pixels(p.x)+16,Drawing.pixels(p.y)+line.y, 4) - replacement in drawing.lua at line 45
love.graphics.circle('fill', pixels(p.x)+16,pixels(p.y)+line.y, 2)love.graphics.circle('fill', Drawing.pixels(p.x)+16,Drawing.pixels(p.y)+line.y, 2) - replacement in drawing.lua at line 49
draw_pending_shape(16,line.y, line)Drawing.draw_pending_shape(16,line.y, line)endfunction Drawing.current_drawing()local x, y = love.mouse.getX(), love.mouse.getY()for _,drawing in ipairs(Lines) doif drawing.mode == 'drawing' thenif y >= drawing.y and y < drawing.y + Drawing.pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenreturn drawingendendendreturn nilendfunction Drawing.select_shape_at_mouse()for _,drawing in ipairs(Lines) doif drawing.mode == 'drawing' thenlocal x, y = love.mouse.getX(), love.mouse.getY()if y >= drawing.y and y < drawing.y + Drawing.pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenlocal mx,my = Drawing.coord(love.mouse.getX()-16), Drawing.coord(love.mouse.getY()-drawing.y)for i,shape in ipairs(drawing.shapes) doassert(shape)if geom.on_shape(mx,my, drawing, shape) thenreturn drawing,i,shapeendendendendendendfunction Drawing.select_point_at_mouse()for _,drawing in ipairs(Lines) doif drawing.mode == 'drawing' thenlocal x, y = love.mouse.getX(), love.mouse.getY()if y >= drawing.y and y < drawing.y + Drawing.pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenlocal mx,my = Drawing.coord(love.mouse.getX()-16), Drawing.coord(love.mouse.getY()-drawing.y)for i,point in ipairs(drawing.points) doassert(point)if Drawing.near(point, mx,my) thenreturn drawing,i,pointendendendendendendfunction Drawing.select_drawing_at_mouse()for _,drawing in ipairs(Lines) doif drawing.mode == 'drawing' thenlocal x, y = love.mouse.getX(), love.mouse.getY()if y >= drawing.y and y < drawing.y + Drawing.pixels(drawing.h) and x >= 16 and x < 16+Drawing_width thenreturn drawingendendendendfunction Drawing.contains_point(shape, p)if shape.mode == 'freehand' then-- not supportedelseif shape.mode == 'line' or shape.mode == 'manhattan' thenreturn shape.p1 == p or shape.p2 == pelseif shape.mode == 'polygon' thenreturn table.find(shape.vertices, p)elseif shape.mode == 'circle' thenreturn shape.center == pelseif shape.mode == 'arc' thenreturn shape.center == p-- ugh, how to support angleselseif shape.mode == 'deleted' then-- already doneelseprint(shape.mode)assert(false)endendfunction Drawing.convert_line(drawing, shape)-- Perhaps we should do a more sophisticated "simple linear regression"-- here:-- https://en.wikipedia.org/wiki/Linear_regression#Simple_and_multiple_linear_regression-- But this works well enough for close-to-linear strokes.assert(shape.mode == 'freehand')shape.mode = 'line'shape.p1 = insert_point(drawing.points, shape.points[1].x, shape.points[1].y)local n = #shape.pointsshape.p2 = insert_point(drawing.points, shape.points[n].x, shape.points[n].y)end-- turn a line either horizontal or verticalfunction Drawing.convert_horvert(drawing, shape)if shape.mode == 'freehand' thenconvert_line(shape)endassert(shape.mode == 'line')local p1 = drawing.points[shape.p1]local p2 = drawing.points[shape.p2]if math.abs(p1.x-p2.x) > math.abs(p1.y-p2.y) thenp2.y = p1.yelsep2.x = p1.xendendfunction Drawing.smoothen(shape)assert(shape.mode == 'freehand')for _=1,7 dofor i=2,#shape.points-1 dolocal a = shape.points[i-1]local b = shape.points[i]local c = shape.points[i+1]b.x = (a.x + b.x + c.x)/3b.y = (a.y + b.y + c.y)/3endendendfunction Drawing.insert_point(points, x,y)for i,point in ipairs(points) doif Drawing.near(point, x,y) thenreturn iendendtable.insert(points, {x=x, y=y})return #pointsendfunction Drawing.near(point, x,y)local px,py = Drawing.pixels(x),Drawing.pixels(y)local cx,cy = Drawing.pixels(point.x), Drawing.pixels(point.y)return (cx-px)*(cx-px) + (cy-py)*(cy-py) < 16endfunction Drawing.draw_shape(left,top, drawing, shape)if shape.mode == 'freehand' thenlocal prev = nilfor _,point in ipairs(shape.points) doif prev thenlove.graphics.line(Drawing.pixels(prev.x)+left,Drawing.pixels(prev.y)+top, Drawing.pixels(point.x)+left,Drawing.pixels(point.y)+top)endprev = pointendelseif shape.mode == 'line' or shape.mode == 'manhattan' thenlocal p1 = drawing.points[shape.p1]local p2 = drawing.points[shape.p2]love.graphics.line(Drawing.pixels(p1.x)+left,Drawing.pixels(p1.y)+top, Drawing.pixels(p2.x)+left,Drawing.pixels(p2.y)+top)elseif shape.mode == 'polygon' thenlocal prev = nilfor _,point in ipairs(shape.vertices) dolocal curr = drawing.points[point]if prev thenlove.graphics.line(Drawing.pixels(prev.x)+left,Drawing.pixels(prev.y)+top, Drawing.pixels(curr.x)+left,Drawing.pixels(curr.y)+top)endprev = currend-- close the looplocal curr = drawing.points[shape.vertices[1]]love.graphics.line(Drawing.pixels(prev.x)+left,Drawing.pixels(prev.y)+top, Drawing.pixels(curr.x)+left,Drawing.pixels(curr.y)+top)elseif shape.mode == 'circle' thenlocal center = drawing.points[shape.center]love.graphics.circle('line', Drawing.pixels(center.x)+left,Drawing.pixels(center.y)+top, Drawing.pixels(shape.radius))elseif shape.mode == 'arc' thenlocal center = drawing.points[shape.center]love.graphics.arc('line', 'open', Drawing.pixels(center.x)+left,Drawing.pixels(center.y)+top, Drawing.pixels(shape.radius), shape.start_angle, shape.end_angle, 360)elseif shape.mode == 'deleted' thenelseprint(shape.mode)assert(false)endendfunction Drawing.draw_pending_shape(left,top, drawing)local shape = drawing.pendingif shape.mode == 'freehand' thendraw_shape(left,top, drawing, shape)elseif shape.mode == 'line' thenlocal p1 = drawing.points[shape.p1]local mx,my = Drawing.coord(love.mouse.getX()-16), Drawing.coord(love.mouse.getY()-drawing.y)if mx < 0 or mx >= 256 or my < 0 or my >= drawing.h thenreturnendlove.graphics.line(Drawing.pixels(p1.x)+left,Drawing.pixels(p1.y)+top, Drawing.pixels(mx)+left,Drawing.pixels(my)+top)elseif shape.mode == 'manhattan' thenlocal p1 = drawing.points[shape.p1]local mx,my = Drawing.coord(love.mouse.getX()-16), Drawing.coord(love.mouse.getY()-drawing.y)if mx < 0 or mx >= 256 or my < 0 or my >= drawing.h thenreturnendif math.abs(mx-p1.x) > math.abs(my-p1.y) thenlove.graphics.line(Drawing.pixels(p1.x)+left,Drawing.pixels(p1.y)+top, Drawing.pixels(mx)+left,Drawing.pixels(p1.y)+top)elselove.graphics.line(Drawing.pixels(p1.x)+left,Drawing.pixels(p1.y)+top, Drawing.pixels(p1.x)+left,Drawing.pixels(my)+top)endelseif shape.mode == 'polygon' then-- don't close the loop on a pending polygonlocal prev = nilfor _,point in ipairs(shape.vertices) dolocal curr = drawing.points[point]if prev thenlove.graphics.line(Drawing.pixels(prev.x)+left,Drawing.pixels(prev.y)+top, Drawing.pixels(curr.x)+left,Drawing.pixels(curr.y)+top)endprev = currendlove.graphics.line(Drawing.pixels(prev.x)+left,Drawing.pixels(prev.y)+top, love.mouse.getX(),love.mouse.getY())elseif shape.mode == 'circle' thenlocal center = drawing.points[shape.center]local mx,my = Drawing.coord(love.mouse.getX()-16), Drawing.coord(love.mouse.getY()-drawing.y)if mx < 0 or mx >= 256 or my < 0 or my >= drawing.h thenreturnendlocal cx,cy = Drawing.pixels(center.x)+left, Drawing.pixels(center.y)+toplove.graphics.circle('line', cx,cy, math.dist(cx,cy, love.mouse.getX(),love.mouse.getY()))elseif shape.mode == 'arc' thenlocal center = drawing.points[shape.center]local mx,my = Drawing.coord(love.mouse.getX()-16), Drawing.coord(love.mouse.getY()-drawing.y)if mx < 0 or mx >= 256 or my < 0 or my >= drawing.h thenreturnendshape.end_angle = geom.angle_with_hint(center.x,center.y, mx,my, shape.end_angle)local cx,cy = Drawing.pixels(center.x)+left, Drawing.pixels(center.y)+toplove.graphics.arc('line', 'open', cx,cy, Drawing.pixels(shape.radius), shape.start_angle, shape.end_angle, 360)endendfunction Drawing.pixels(n) -- parts to pixelsreturn n*Drawing_width/256endfunction Drawing.coord(n) -- pixels to partsreturn math.floor(n*256/Drawing_width)