33#define BEZIERSUBDIVISION 20
37#define M_PI 3.14159265358979323846
39#define D2R(d) (M_PI*(d)/180.0)
40#define R2D(r) (180.0*(r)/M_PI)
44#define moveto(p,x,y) addto(p,x,y)
45#define lineto(p,x,y) addto(p,x,y)
61static double myatan (
double y,
double x)
74static double mymod (
double original,
double modulus)
77 if (original < 0 || original >= modulus) {
78 v = -floor(original/modulus);
79 return v * modulus + original;
101 vararr_append(arr, pt);
106printArr (vararr_t* arr, FILE* fp)
108 fprintf(fp,
"size %" PRISIZE_T "\n", vararr_size(arr));
109 for (
size_t i = 0; i < vararr_size(arr); i++) {
111 fprintf (fp,
" [%d] x %.02f y %.02f d %.02f\n", i, pt.
x, pt.
y, pt.
lengthsofar);
118 double delx = p0.
x - p1.
x;
119 double dely = p0.
y - p1.
y;
120 return hypot(delx, dely);
128 double seglen, linelen = 0;
131 const size_t n = bez->
size;
136 for (
size_t i = 0; i + 3 < n; i += 3) {
138 for (
size_t j = 1; j <= 3; j++)
156 printArr(&arr, stderr);
161static void drawbevel(
double x,
double lineout,
bool forward,
double dir,
170 lineto (p, x + lineout*cos(a2), x + lineout*sin(a2));
173typedef double (*
radfunc_t) (
double curlen,
double totallen,
double initwid);
182 double direction=0, direction_2=0;
184 pathpoint cur_point, last_point, next_point;
185 double x=0, y=0,
dist;
188 double lineout=0, linerad=0, linelen=0;
191 size_t pathcount = vararr_size(&arr);
192 pathpoint *pathpoints = vararr_detach(&arr);
196 for (
size_t i = 0; i < pathcount; i++) {
197 const size_t l = i == 0 ? pathcount - 1 : i - 1;
198 const size_t n = (i + 1) % pathcount;
200 cur_point = pathpoints[i];
205 next_point = pathpoints[n];
208 ndir =
myatan (ny-y, nx-x);
210 last_point = pathpoints[l];
213 ldir =
myatan (ly-y, lx-x);
219 linerad = radfunc(
dist, linelen, initwid);
221 if (i == 0 || i == pathcount-1) {
224 direction = ndir +
D2R(90);
226 direction = ldir -
D2R(90);
228 direction_2 = direction;
234 phi =
D2R(90) - theta / 2;
239 lineout = linerad / cos(phi);
242 direction = ndir+
D2R(90)+phi;
248 if (i == pathcount-1) {
252 direction_2 = direction;
258 pathpoints[i].
type =
'l';
259 pathpoints[i].
dir = direction;
260 pathpoints[i].
lout = lineout;
261 pathpoints[i].
bevel = bevel;
262 pathpoints[i].
dir2 = direction_2;
268 for (
size_t i = 0; i < pathcount; i++) {
269 cur_point = pathpoints[i];
272 direction = cur_point.
dir;
273 lineout = cur_point.
lout;
274 bool bevel = cur_point.
bevel;
275 direction_2 = cur_point.
dir2;
277 moveto(&p, x+cos(direction)*lineout, y+sin(direction)*lineout);
279 lineto(&p, x+cos(direction)*lineout, y+sin(direction)*lineout);
282 drawbevel(x, lineout,
true, direction, direction_2, &p);
286 direction +=
D2R(180);
287 lineto(&p, x+cos(direction)*lineout, y+sin(direction)*lineout);
289 assert(pathcount > 0);
290 for (
size_t i = pathcount - 2; i !=
SIZE_MAX; i--) {
291 cur_point = pathpoints[i];
294 direction = cur_point.
dir +
D2R(180);
295 lineout = cur_point.
lout;
296 bool bevel = cur_point.
bevel;
297 direction_2 = cur_point.
dir2 +
D2R(180);
298 lineto(&p, x+cos(direction_2)*lineout, y+sin(direction_2)*lineout);
300 drawbevel(x, lineout,
false, direction, direction_2, &p);
308static double halffunc (
double curlen,
double totallen,
double initwid)
310 return (1 - curlen / totallen) * initwid / 2.0;
327 sp =
taper(&bez, halffunc, 20.0);
328 printf (
"newpath\n");
330 for (
size_t i = 1; i < sp->
nvertices; i++)
332 printf (
"fill showpage\n");
Memory allocation wrappers that exit on failure.
static void * gv_recalloc(void *ptr, size_t old_nmemb, size_t new_nmemb, size_t size)
pointf Bezier(pointf *V, double t, pointf *Left, pointf *Right)
static double dist(int dim, double *x, double *y)
#define DEFINE_LIST(name, type)
#define PRISIZE_T
PRIu64 alike for printing size_t
size_t nvertices
number of points in the stroke
static void drawbevel(double x, double lineout, bool forward, double dir, double dir2, stroke_t *p)
static void addto(stroke_t *p, double x, double y)
static double l2dist(pointf p0, pointf p1)
static double myatan(double y, double x)
static vararr_t pathtolines(bezier *bez)
static double mymod(double original, double modulus)
double(* radfunc_t)(double curlen, double totallen, double initwid)
static double currentmiterlimit
static void insertArr(vararr_t *arr, pointf p, double l)
stroke_t taper(bezier *bez, radfunc_t radfunc, double initwid)
#define BEZIERSUBDIVISION
graphs, nodes and edges info: Agraphinfo_t, Agnodeinfo_t and Agedgeinfo_t