39#define BEZIERSUBDIVISION 20
43#define M_PI 3.14159265358979323846
45#define D2R(d) (M_PI*(d)/180.0)
46#define R2D(r) (180.0*(r)/M_PI)
50#define moveto(p,x,y) addto(p,x,y)
51#define lineto(p,x,y) addto(p,x,y)
67static double myatan (
double y,
double x)
80static double mymod (
double original,
double modulus)
83 if (original < 0 || original >= modulus) {
84 v = -floor(original/modulus);
85 return v * modulus + original;
104insertArr (vararr_t* arr,
pointf p,
double l)
114 for (
size_t i = 0; i <
LIST_SIZE(arr); i++) {
116 fprintf(fp,
" [%" PRISIZE_T "] x %.02f y %.02f d %.02f\n", i, pt.
x, pt.
y,
123 double delx = p0.
x - p1.
x;
124 double dely = p0.
y - p1.
y;
125 return hypot(delx, dely);
133 double seglen, linelen = 0;
136 const size_t n = bez->
size;
139 insertArr(&arr,
A[0], 0);
141 for (
size_t i = 0; i + 3 < n; i += 3) {
143 for (
size_t j = 1; j <= 3; j++)
155 insertArr(&arr, p1, linelen);
166static void drawbevel(
double x,
double lineout,
bool forward,
double dir,
175 lineto (p, x + lineout*cos(a2), x + lineout*sin(a2));
178typedef double (*
radfunc_t) (
double curlen,
double totallen,
double initwid);
187 double direction=0, direction_2=0;
189 pathpoint cur_point, last_point, next_point;
190 double x=0, y=0,
dist;
193 double lineout=0, linerad=0, linelen=0;
202 for (
size_t i = 0; i < pathcount; i++) {
203 const size_t l = i == 0 ? pathcount - 1 : i - 1;
204 const size_t n = (i + 1) % pathcount;
206 cur_point = pathpoints[i];
211 next_point = pathpoints[n];
214 ndir =
myatan (ny-y, nx-x);
216 last_point = pathpoints[l];
219 ldir =
myatan (ly-y, lx-x);
225 linerad = radfunc(
dist, linelen, initwid);
227 if (i == 0 || i == pathcount-1) {
230 direction = ndir +
D2R(90);
232 direction = ldir -
D2R(90);
234 direction_2 = direction;
240 phi =
D2R(90) - theta / 2;
245 lineout = linerad / cos(phi);
248 direction = ndir+
D2R(90)+phi;
254 if (i == pathcount-1) {
258 direction_2 = direction;
264 pathpoints[i].
type =
'l';
265 pathpoints[i].
dir = direction;
266 pathpoints[i].
lout = lineout;
267 pathpoints[i].
bevel = bevel;
268 pathpoints[i].
dir2 = direction_2;
274 for (
size_t i = 0; i < pathcount; i++) {
275 cur_point = pathpoints[i];
278 direction = cur_point.
dir;
279 lineout = cur_point.
lout;
280 bool bevel = cur_point.
bevel;
281 direction_2 = cur_point.
dir2;
283 moveto(&p, x+cos(direction)*lineout, y+sin(direction)*lineout);
285 lineto(&p, x+cos(direction)*lineout, y+sin(direction)*lineout);
288 drawbevel(x, lineout,
true, direction, direction_2, &p);
292 direction +=
D2R(180);
293 lineto(&p, x+cos(direction)*lineout, y+sin(direction)*lineout);
295 assert(pathcount > 0);
296 for (
size_t i = pathcount - 2; i !=
SIZE_MAX; i--) {
297 cur_point = pathpoints[i];
300 direction = cur_point.
dir +
D2R(180);
301 lineout = cur_point.
lout;
302 bool bevel = cur_point.
bevel;
303 direction_2 = cur_point.
dir2 +
D2R(180);
304 lineto(&p, x+cos(direction_2)*lineout, y+sin(direction_2)*lineout);
306 drawbevel(x, lineout,
false, direction, direction_2, &p);
314static double halffunc (
double curlen,
double totallen,
double initwid)
316 return (1 - curlen / totallen) * initwid / 2.0;
333 sp =
taper(&bez, halffunc, 20.0);
334 printf (
"newpath\n");
336 for (
size_t i = 1; i < sp->
nvertices; i++)
338 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)
type-generic dynamically expanding list
#define LIST_DETACH(list, datap, sizep)
#define LIST_APPEND(list, item)
#define LIST_GET(list, index)
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
stroke_t taper(bezier *bez, radfunc_t radfunc, double initwid)
static void printArr(vararr_t *arr, FILE *fp)
#define BEZIERSUBDIVISION
graphs, nodes and edges info: Agraphinfo_t, Agnodeinfo_t and Agedgeinfo_t