#!/usr/local/bin/cz --
use b

# TODO try with GL

struct arc:
	num x0, y0, x1, y1, angle, bend, shear

struct shape:
	int n_arcs
	arc *arcs

shape_calc(polygon *p, shape *s):
	for(i, 0, s->n_arcs):
		arc_calc(p, &s->arcs[i])

const num pi2 = M_PI * 2

#def trig_unit deg

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

	# 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

	if angle == 0:
		polygon_point(p, x0, y0)
		return

	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(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)
	for(a, -angle/2, angle/2, da):
		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)

Main:
	space()
	zoom(100)
	shape *s = &(shape){2, (arc[]){{-1,0,1,0.5,90,1,0},{1,0.5,-1,0,180,0.75,0}}}
	new(p, polygon, 240)
	bm()
	int rep = 1000
	repeat(rep):
		shape_calc(p, s)
		blue()
		polygon_fill(p)
		yellow()
		polygon_draw(p)
		polygon_clear(p)
	polygon_end(p)
	bm("drew it", rep)

