about summary refs log tree commit diff stats
path: root/main.lua
diff options
context:
space:
mode:
Diffstat (limited to 'main.lua')
-rw-r--r--main.lua81
1 files changed, 81 insertions, 0 deletions
diff --git a/main.lua b/main.lua
index f1b19ae..9f60a25 100644
--- a/main.lua
+++ b/main.lua
@@ -182,6 +182,13 @@ function love.mousereleased(x,y, button)
           lines.current.pending.radius = math.dist(center.x,center.y, mx,my)
           table.insert(lines.current.shapes, lines.current.pending)
         end
+      elseif lines.current.pending.mode == 'arc' then
+        local mx,my = coord(x-16), coord(y-lines.current.y)
+        if mx >= 0 and mx < 256 and my >= 0 and my < lines.current.h then
+          local center = lines.current.points[lines.current.pending.center]
+          lines.current.pending.end_angle = angle_with_hint(center.x,center.y, mx,my, lines.current.pending.end_angle)
+          table.insert(lines.current.shapes, lines.current.pending)
+        end
       end
       lines.current.pending = {}
       lines.current = nil
@@ -256,6 +263,12 @@ function draw_shape(left,top, drawing, shape)
   elseif shape.mode == 'circle' then
     local center = drawing.points[shape.center]
     love.graphics.circle('line', pixels(center.x)+left,pixels(center.y)+top, pixels(shape.radius))
+  elseif shape.mode == 'arc' then
+    local 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)
+  else
+    print(shape.mode)
+    assert(false)
   end
 end
 
@@ -300,6 +313,15 @@ function draw_pending_shape(left,top, drawing)
     end
     local cx,cy = pixels(center.x)+left, pixels(center.y)+top
     love.graphics.circle('line', cx,cy, math.dist(cx,cy, love.mouse.getX(),love.mouse.getY()))
+  elseif shape.mode == 'arc' then
+    local 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 then
+      return
+    end
+    shape.end_angle = angle_with_hint(center.x,center.y, mx,my, shape.end_angle)
+    local cx,cy = pixels(center.x)+left, pixels(center.y)+top
+    love.graphics.arc('line', 'open', cx,cy, pixels(shape.radius), shape.start_angle, shape.end_angle, 360)
   end
 end
 
@@ -315,6 +337,13 @@ function on_shape(x,y, drawing, shape)
   elseif shape.mode == 'circle' then
     local center = drawing.points[shape.center]
     return math.dist(center.x,center.y, x,y) == shape.radius
+  elseif shape.mode == 'arc' then
+    local 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 then
+      return false
+    end
+    return angle_between(center.x,center.y, x,y, shape.start_angle,shape.end_angle)
   else
     print(shape.mode)
     assert(false)
@@ -377,6 +406,25 @@ function on_polygon(x,y, drawing, shape)
   return on_line(x,y, drawing, {p1=shape.vertices[1], p2=shape.vertices[#shape.vertices]})
 end
 
+function angle_between(x1,y1, x2,y2, s,e)
+  local angle = math.angle(x1,y1, x2,y2)
+--?   print(s,e, angle-math.pi*2, angle, angle+math.pi*2)
+  if s > e then
+    s,e = e,s
+  end
+  -- I'm not sure this is right or ideal..
+  angle = angle-math.pi*2
+  if s <= angle and angle <= e then
+    return true
+  end
+  angle = angle+math.pi*2
+  if s <= angle and angle <= e then
+    return true
+  end
+  angle = angle+math.pi*2
+  return s <= angle and angle <= e
+end
+
 function love.textinput(t)
   if love.mouse.isDown('1') then return end
   if in_drawing() then return end
@@ -412,6 +460,14 @@ function keychord_pressed(chord)
     table.insert(drawing.pending.vertices, j)
   elseif chord == 'C-c' then
     current_mode = 'circle'
+  elseif love.mouse.isDown('1') and chord == 'a' and current_mode == 'circle' then
+    local drawing = current_drawing()
+    drawing.pending.mode = 'arc'
+    local mx,my = coord(love.mouse.getX()-16), coord(love.mouse.getY()-drawing.y)
+    local j = insert_point(drawing.points, mx,my)
+    local center = drawing.points[drawing.pending.center]
+    drawing.pending.radius = math.dist(center.x,center.y, mx,my)
+    drawing.pending.start_angle = math.angle(center.x,center.y, mx,my)
   elseif love.mouse.isDown('1') and chord == 'l' then
     current_mode = 'line'
     local drawing = current_drawing()
@@ -537,4 +593,29 @@ end
 function love.keyreleased(key, scancode)
 end
 
+function 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 do
+      result = result-math.pi*2
+    end
+    while result < hint-math.pi/10 do
+      result = result+math.pi*2
+    end
+  end
+  return result
+end
+
+-- 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 then
+    result = result+math.pi
+  end
+  return result
+end
+
 function math.dist(x1,y1, x2,y2) return ((x2-x1)^2+(y2-y1)^2)^0.5 end