use m gr # draw a circular curve from (lx,ly) to (x,y) having arc-angle a def draw(x, y, a) draw3(x, y, a) draw3(num x, num y, num a): if a == 0: draw(x, y) return new(p, polygon, 240) # TODO use a static, quicker arc_calc(p, &(arc){lx, ly, x, y, a, 1, 0}) polygon_point(p, x, y) # arc_calc may exclude the destination point polygon_draw_curve(p) # polygon_clear(p) # TODO if static polygon_end(p) move(x, y) struct arc: num x0, y0, x1, y1, angle, bend, shear #def pi2 M_PI * 2 #def tau M_PI * 2 arc_calc(polygon *p, arc *a): calc_arc(p, a->x0, a->y0, a->x1, a->y1, a->angle, a->bend, a->shear) # max number of pixels error num calc_arc_dev = 0.25 calc_arc(polygon *p, num x0, num y0, num x1, num y1, num angle, num bend, num shear): num dx, dy, d, hf, ox, oy, r, da, x, y, s, c, x_, y_, altx, alty, alt # this is pretty messy, fix it up? but it does work! # TODO try it with GL/GLES - GL_POLYGON / GL_TRIANGLE_FAN; compare the performance to X11 polygons. # TODO put the GL and GLES support in libb, and configured in BRACE_USE # TODO use transformation matrix for X11 if not using GL. But, should use GL. # TODO apply shear use(shear) if angle == 0: polygon_point(p, x0, y0) return # +ve angle -> bend to the right angle = -angle dx = (x1 - x0)/2 dy = (y1 - y0)/2 d = hypot(dx, dy) # calc origin hf = 1 / Tan(angle / 2) ox = x0 + dx + dy*hf * bend oy = y0 + dy - dx*hf * bend # radius r = d / Sin(fabs(angle)/2) # length # l = pi2*r * angle / 360 # delta angle # r * (1 - Cos(da/2)) == calc_arc_dev da = Acos(1 - calc_arc_dev * a_pixel / r) * 2 # warn("da = %f old_da(3) = %f old_da(16) = %f", da, angle / l * 3 * a_pixel, angle / l * 16 * a_pixel) # da = angle / l * calc_arc_d * a_pixel altx = dy * hf alty = -dx * hf alt = hypot(altx, alty) altx /= alt alty /= alt polygon_point(p, x0, y0) int steps = fabs(angle) / da for(i, 0, steps): num a = angle * i / steps - angle / 2 s = Sin(a) c = Cos(a) * bend x_ = s * r y_ = c * r x = dy * hf x = ox - x_ * alty - y_ * altx y = oy + x_ * altx - y_ * alty polygon_point(p, x, y) # curve, with arc support boolean curve_at_start = 1 num curve0_x, curve0_y, curve0_a def curve() curve_at_start = 1 def curve(x, y) curve(x, y, 0) curve(num x, num y, num a) if curve_at_start move(x, y) curve0_x = x curve0_y = y curve0_a = a curve_at_start = 0 else draw(x, y, a) curve_close() if !curve_at_start: curve(curve0_x, curve0_y, curve0_a) curve_at_start = 1 def curve_end() curve_at_start = 1 # TODO curve_fill?