20 #define ARROW_LENGTH 10.
22 #define NUMB_OF_ARROW_HEADS 4
25 #define BITS_PER_ARROW 8
27 #define BITS_PER_ARROW_TYPE 4
29 #define ARR_TYPE_NONE (ARR_NONE)
30 #define ARR_TYPE_NORM 1
31 #define ARR_TYPE_CROW 2
32 #define ARR_TYPE_TEE 3
33 #define ARR_TYPE_BOX 4
34 #define ARR_TYPE_DIAMOND 5
35 #define ARR_TYPE_DOT 6
36 #define ARR_TYPE_CURVE 7
37 #define ARR_TYPE_GAP 8
41 #define ARR_MOD_OPEN (1<<(BITS_PER_ARROW_TYPE+0))
42 #define ARR_MOD_INV (1<<(BITS_PER_ARROW_TYPE+1))
43 #define ARR_MOD_LEFT (1<<(BITS_PER_ARROW_TYPE+2))
44 #define ARR_MOD_RIGHT (1<<(BITS_PER_ARROW_TYPE+3))
117 static void arrow_type_normal(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag);
118 static void arrow_type_crow(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag);
119 static void arrow_type_tee(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag);
120 static void arrow_type_box(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag);
121 static void arrow_type_diamond(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag);
122 static void arrow_type_dot(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag);
123 static void arrow_type_curve(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag);
124 static void arrow_type_gap(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag);
138 static char *arrow_match_name_frag(
char *name,
arrowname_t * arrownames,
int *flag)
144 for (arrowname = arrownames; arrowname->
name; arrowname++) {
145 namelen = strlen(arrowname->
name);
146 if (strncmp(name, arrowname->
name, namelen) == 0) {
147 *flag |= arrowname->
type;
155 static char *arrow_match_shape(
char *name,
int *flag)
160 rest = arrow_match_name_frag(name, Arrowsynonyms, &f);
164 rest = arrow_match_name_frag(next, Arrowmods, &f);
165 }
while (next != rest);
166 rest = arrow_match_name_frag(rest, Arrownames, &f);
174 static void arrow_match_name(
char *name,
int *flag)
184 rest = arrow_match_shape(next, &f);
186 agerr(
AGWARN,
"Arrow type \"%s\" unknown - ignoring\n", next);
206 for (arrowdir = Arrowdirs; arrowdir->
dir; arrowdir++) {
208 *sflag = arrowdir->
sflag;
209 *eflag = arrowdir->
eflag;
215 arrow_match_name(attr, eflag);
217 arrow_match_name(attr, sflag);
224 *eflag = *eflag | s0;
225 *sflag = *sflag | e0;
232 double lenfact = 0.0;
238 for (arrowtype = Arrowtypes; arrowtype->
gen; arrowtype++) {
239 if (f == arrowtype->
type) {
253 return DIST2(p, inside_context->
a.
p[0]) <= inside_context->
a.
r[0];
257 int endp,
bezier * spl,
int eflag)
265 spl->
eflag = eflag, spl->
ep = ps[endp + 3];
266 if (endp > startp &&
DIST2(ps[endp], ps[endp + 3]) < elen2) {
270 sp[2] = ps[endp + 1];
271 sp[1] = ps[endp + 2];
274 inside_context.
a.
p = &sp[0];
275 inside_context.
a.
r = &elen2;
279 ps[endp + 1] = sp[2];
280 ps[endp + 2] = sp[1];
281 ps[endp + 3] = sp[0];
286 int endp,
bezier * spl,
int sflag)
294 spl->
sflag = sflag, spl->
sp = ps[startp];
295 if (endp > startp &&
DIST2(ps[startp], ps[startp + 3]) < slen2) {
298 sp[0] = ps[startp + 3];
299 sp[1] = ps[startp + 2];
300 sp[2] = ps[startp + 1];
303 inside_context.
a.
p = &sp[3];
304 inside_context.
a.
r = &slen2;
308 ps[startp + 1] = sp[2];
309 ps[startp + 2] = sp[1];
310 ps[startp + 3] = sp[0];
326 double d, tlen, hlen, maxd;
328 if (sflag && eflag && (endp == startp)) {
334 if (hlen + tlen >= d) {
359 ps[endp] = ps[endp + 1] = s;
360 ps[endp + 2] = ps[endp + 3] = t;
361 spl->
eflag = eflag, spl->
ep = p;
362 spl->
sflag = sflag, spl->
sp = q;
376 if (p.
x < q.
x) r.
x = q.
x - hlen;
377 else r.
x = q.
x + hlen;
381 if (p.
y < q.
y) r.
y = q.
y - hlen;
382 else r.
y = q.
y + hlen;
385 ps[endp + 2] = ps[endp + 3] = r;
400 if (p.
x < q.
x) r.
x = p.
x + tlen;
401 else r.
x = p.
x - tlen;
405 if (p.
y < q.
y) r.
y = p.
y + tlen;
406 else r.
y = p.
y - tlen;
408 ps[startp] = ps[startp + 1] = r;
415 static void arrow_type_normal(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag)
422 arrowwidth *= penwidth / 4;
424 v.
x = -u.
y * arrowwidth;
425 v.
y = u.
x * arrowwidth;
451 static void arrow_type_crow(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag)
454 double arrowwidth, shaftwidth;
457 if (penwidth > (4 * arrowsize) && (flag & ARR_MOD_INV))
458 arrowwidth *= penwidth / (4 * arrowsize);
461 if (penwidth > 1 && (flag & ARR_MOD_INV))
462 shaftwidth = 0.05 * (penwidth - 1) / arrowsize;
464 v.
x = -u.
y * arrowwidth;
465 v.
y = u.
x * arrowwidth;
466 w.
x = -u.
y * shaftwidth;
467 w.
y = u.
x * shaftwidth;
470 m.
x = p.
x + u.
x * 0.5;
471 m.
y = p.
y + u.
y * 0.5;
472 if (flag & ARR_MOD_INV) {
503 if (flag & ARR_MOD_LEFT)
505 else if (flag & ARR_MOD_RIGHT)
511 static void arrow_type_gap(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag)
522 static void arrow_type_tee(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag)
530 m.
x = p.
x + u.
x * 0.2;
531 m.
y = p.
y + u.
y * 0.2;
532 n.
x = p.
x + u.
x * 0.6;
533 n.
y = p.
y + u.
y * 0.6;
542 if (flag & ARR_MOD_LEFT) {
545 }
else if (flag & ARR_MOD_RIGHT) {
555 static void arrow_type_box(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag)
561 m.
x = p.
x + u.
x * 0.8;
562 m.
y = p.
y + u.
y * 0.8;
573 if (flag & ARR_MOD_LEFT) {
576 }
else if (flag & ARR_MOD_RIGHT) {
586 static void arrow_type_diamond(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag)
592 r.
x = p.
x + u.
x / 2.;
593 r.
y = p.
y + u.
y / 2.;
602 if (flag & ARR_MOD_LEFT)
604 else if (flag & ARR_MOD_RIGHT)
610 static void arrow_type_dot(
GVJ_t * job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag)
615 r = sqrt(u.
x * u.
x + u.
y * u.
y) / 2.;
616 AF[0].
x = p.
x + u.
x / 2. - r;
617 AF[0].
y = p.
y + u.
y / 2. - r;
618 AF[1].
x = p.
x + u.
x / 2. + r;
619 AF[1].
y = p.
y + u.
y / 2. + r;
627 static void arrow_type_curve(
GVJ_t* job,
pointf p,
pointf u,
double arrowsize,
double penwidth,
int flag)
629 double arrowwidth = penwidth > 4 ? 0.5 * penwidth / 4 : 0.5;
635 v.
x = -u.
y * arrowwidth;
636 v.
y = u.
x * arrowwidth;
642 AF[0].
x = p.
x + v.
x + w.
x;
643 AF[0].
y = p.
y + v.
y + w.
y;
645 AF[3].
x = p.
x - v.
x + w.
x;
646 AF[3].
y = p.
y - v.
y + w.
y;
648 if (flag & ARR_MOD_INV) {
649 AF[1].
x = p.
x + 0.95 * v.
x + w.
x + w.
x * 4.0 / 3.0;
650 AF[1].
y = AF[0].
y + w.
y * 4.0 / 3.0;
652 AF[2].
x = p.
x - 0.95 * v.
x + w.
x + w.
x * 4.0 / 3.0;
653 AF[2].
y = AF[3].
y + w.
y * 4.0 / 3.0;
656 AF[1].
x = p.
x + 0.95 * v.
x + w.
x - w.
x * 4.0 / 3.0;
657 AF[1].
y = AF[0].
y - w.
y * 4.0 / 3.0;
659 AF[2].
x = p.
x - 0.95 * v.
x + w.
x - w.
x * 4.0 / 3.0;
660 AF[2].
y = AF[3].
y - w.
y * 4.0 / 3.0;
664 if (flag & ARR_MOD_LEFT)
666 else if (flag & ARR_MOD_RIGHT)
678 for (arrowtype = Arrowtypes; arrowtype->
type; arrowtype++) {
679 if (f == arrowtype->type) {
680 u.
x *= arrowtype->lenfact * arrowsize;
681 u.
y *= arrowtype->lenfact * arrowsize;
682 (arrowtype->gen) (job, p, u, arrowsize, penwidth, flag);
695 double ax,ay,bx,by,cx,cy,dx,dy;
760 p = arrow_gen_type(job, p, u, arrowsize, penwidth, f);
void gvrender_polygon(GVJ_t *job, pointf *af, int n, int filled)
CGRAPH_API int agisdirected(Agraph_t *g)
void(* gen)(GVJ_t *job, pointf p, pointf u, double arrowsize, double penwidth, int flag)
int agerr(agerrlevel_t level, const char *fmt,...)
#define BITS_PER_ARROW_TYPE
void arrow_flags(Agedge_t *e, int *sflag, int *eflag)
int arrowEndClip(edge_t *e, pointf *ps, int startp, int endp, bezier *spl, int eflag)
double arrow_length(edge_t *e, int flag)
#define ED_conc_opp_flag(e)
CGRAPH_API Agraph_t * agraphof(void *obj)
CGRAPH_API Agnode_t * agtail(Agedge_t *e)
CGRAPH_API Agnode_t * aghead(Agedge_t *e)
#define NUMB_OF_ARROW_HEADS
EXTERN Agsym_t * E_arrowhead
EXTERN Agsym_t * E_arrowtail
void gvrender_set_style(GVJ_t *job, char **s)
void gvrender_set_penwidth(GVJ_t *job, double penwidth)
pointf Bezier(pointf *V, int degree, double t, pointf *Left, pointf *Right)
void arrowOrthoClip(edge_t *e, pointf *ps, int startp, int endp, bezier *spl, int sflag, int eflag)
boxf arrow_bb(pointf p, pointf u, double arrowsize, int flag)
double late_double(void *obj, attrsym_t *attr, double def, double low)
struct arrowtype_t arrowtype_t
struct arrowname_t arrowname_t
#define agfindedge(g, t, h)
void gvrender_ellipse(GVJ_t *job, pointf *AF, int n, int filled)
void arrow_gen(GVJ_t *job, emit_state_t emit_state, pointf p, pointf u, double arrowsize, double penwidth, int flag)
void gvrender_beziercurve(GVJ_t *job, pointf *AF, int n, int arrow_at_start, int arrow_at_end, boolean filled)
char * agxget(void *obj, Agsym_t *sym)
EXTERN Agsym_t * E_arrowsz
struct arrowdir_t arrowdir_t
void bezier_clip(inside_t *inside_context, boolean(*insidefn)(inside_t *inside_context, pointf p), pointf *sp, boolean left_inside)
int arrowStartClip(edge_t *e, pointf *ps, int startp, int endp, bezier *spl, int sflag)
void gvrender_polyline(GVJ_t *job, pointf *AF, int n)