--math for 2D circular arcs defined as (x1, y1, xp, yp, x2, y2) where (x1, y1) and (x2, y2) are its end points, --and (xp, yp) is a third point on the arc. if the 3 points are collinear, then the arc is the line between --(x1, y1) and (x2, y2), regardless of where (xp, yp) is. local circle_3p_to_circle = require'path2d_circle_3p'.to_circle local point_angle = require'path2d_point'.point_angle local sweep_between = require'path2d_arc'.sweep_between local arc_split = require'path2d_arc'.split local arc_to_arc_3p = require'path2d_arc'.to_arc_3p local function to_arc(x1, y1, xp, yp, x2, y2) local cx, cy, r = circle_3p_to_circle(x1, y1, xp, yp, x2, y2) if not cx then return end local start_angle = point_angle(x1, y1, cx, cy) local end_angle = point_angle(x2, y2, cx, cy) local ctl_angle = point_angle(xp, yp, cx, cy) local sweep_angle = sweep_between(start_angle, end_angle) local ctl_sweep = sweep_between(start_angle, ctl_angle) if ctl_sweep > sweep_angle then --control point is outside the positive sweep, must be inside the negative sweep then. sweep_angle = sweep_between(start_angle, end_angle, false) end return cx, cy, r, r, start_angle, sweep_angle, 0, x2, y2 end local function split(t, x1, y1, xp, yp, x2, y2) local cx, cy, r, r, start_angle, sweep_angle = to_arc(x1, y1, xp, yp, x2, y2) if not cx then return end local cx1, cy1, r1, r1, start_angle1, sweep_angle1, _, cx2, cy2, r2, r2, start_angle2, sweep_angle2 = arc_split(t, cx, cy, r, r, start_angle, sweep_angle, 0, x2, y2) local ax1, ay1, axp, ayp, ax2, ay2 = arc_to_arc_3p(cx1, cy1, r1, r1, start_angle1, sweep_angle1) local bx1, by1, bxp, byp, bx2, by2 = arc_to_arc_3p(cx2, cy2, r2, r2, start_angle2, sweep_angle2) --overide arcs' end points for numerical stability ax1, ay1 = x1, y1 bx2, by2 = x2, y2 bx1, by1 = ax2, ay2 return ax1, ay1, axp, ayp, ax2, ay2, --first arc bx1, by1, bxp, byp, bx2, by2 --second arc end if not ... then require'path2d_arc_3p_demo' end return { to_arc = to_arc, split = split, }