#include "art.h" /* * code to maintain alignment data structure (global variable active). */ void activateprim(Item *ip, Item *op){ if(op->flags&HOT) (*ip->fn->activate)(ip); } void activate(Item *ip){ walk(ip, scoffs, activateprim); } void hotline(Dpoint p, Dpoint q, int ep){ Dpoint d, r; int i; Flt ang, l; if(ep&L) hotpoint(p); if(ep&R) hotpoint(q); d=dsub(q, p); l=dlen(d); if(ltype){ default: return 0; case LINE: return deqpt(ip->p[0], p) && deqpt(ip->p[1], q) || deqpt(ip->p[0], q) && deqpt(ip->p[1], p); case HEAD: for(cp=ip->next;cp!=ip;cp=cp->next) if(findline(cp, p, q)) return 1; return 0; } } int findcircle(Item *ip, Dpoint p, Flt r){ Item *cp; switch(ip->type){ default: return 0; case CIRCLE: return deqpt(ip->p[0], p) && same(ip->r, r); case HEAD: for(cp=ip->next;cp!=ip;cp=cp->next) if(findcircle(cp, p, r)) return 1; return 0; } } #define code(p) ((p->xx>xr?2:0)|(p->y>yt?4:p->yx #define y0 p0->y #define x1 p1->x #define y1 p1->y int dclipline(Drectangle r, Dpoint *p0, Dpoint *p1){ int c0=code(p0), c1=code(p1), c; Dpoint t; while(c0|c1){ if(c0&c1) return 0; c=c0?c0:c1; if(c&1) t.y=y0+(y1-y0)*(xl-x0)/(x1-x0), t.x=xl; else if(c&2)t.y=y0+(y1-y0)*(xr-x0)/(x1-x0), t.x=xr; else if(c&4)t.x=x0+(x1-x0)*(yt-y0)/(y1-y0), t.y=yt; else t.x=x0+(x1-x0)*(yb-y0)/(y1-y0), t.y=yb; if(c==c0) *p0=t, c0=code(p0); else *p1=t, c1=code(p1); } return 1; } void Oheat(void){ if(selection){ heat(selection); activate(selection); } else msg("heat: nothing selected"); } /* * turn a's HOT flags on */ void heat(Item *a){ Item *ip; if(a->type==HEAD) for(ip=a->next;ip!=a;ip=ip->next) heat(ip); else a->flags|=HOT; } void Ocoolall(void){ cool(scene); delete(active); active=addhead(); redraw(); reheat(); } /* * turn a's HOT flags off */ void cool(Item *a){ Item *p; a->flags&=~HOT; if(a->type==HEAD){ for(p=a->next;p!=a;p=p->next) cool(p); } } /* * get intersections of two objects * Missing cases: * spline-circle * spline-arc */ int itemxitem(Item *p, Item *q, Dpoint *i){ Item r, *t; int n; Dpoint pt[2]; if(p==q && p->type!=SPLINE) return 0; if(q->type==BOX){ t=p; p=q; q=t; } switch(p->type){ case BOX: r.type=LINE; r.p=pt; r.np=2; r.p[0]=p->p[0]; r.p[1]=Dpt(p->p[0].x, p->p[1].y); n=itemxitem(q, &r, i); r.p[0]=p->p[1]; n+=itemxitem(q, &r, i+n); r.p[1]=Dpt(p->p[1].x, p->p[0].y); n+=itemxitem(q, &r, i+n); r.p[0]=p->p[0]; return n+itemxitem(q, &r, i+n); case LINE: switch(q->type){ case LINE: return seginterseg(p->p[0], p->p[1], q->p[0], q->p[1], i); case CIRCLE: return segintercircle(p->p[0], p->p[1], q->p[0], q->r, i); case ARC: return seginterarc(p->p[0], p->p[1], q->p[0], q->p[1], q->p[2], i); case SPLINE: return seginterspline(p->p[0], p->p[1], q, i); } break; case CIRCLE: switch(q->type){ case LINE: return segintercircle(q->p[0], q->p[1], p->p[0], p->r, i); case CIRCLE: return circintercirc(p->p[0], p->r, q->p[0], q->r, i); case ARC: return circinterarc(p->p[0], p->r, q->p[0], q->p[1], q->p[2], i); } break; case ARC: switch(q->type){ case LINE: return seginterarc(q->p[0], q->p[1], p->p[0], p->p[1], p->p[2], i); case CIRCLE: return circinterarc(q->p[0], q->r, p->p[0], p->p[1], p->p[2], i); case ARC: return arcinterarc(p->p[0],p->p[1],p->p[2], q->p[0],q->p[1],q->p[2], i); } case SPLINE: switch(q->type){ case LINE: return seginterspline(q->p[0], q->p[1], p, i); case SPLINE: return splineinterspline(p, q, i); } } return 0; /* missing cases behave as if no intersection */ } void reheat(void){ delete(active); active=addhead(); redraw(); activate(scene); } void flatten(Item *ip, Item *op){ ip=additemv(active, ip->type, ip->r, ip->face, ip->text, ip->group, ip->fn, ip->np, ip->p, Dpt(0., 0.)); ip->flags|=FLAT|INVIS; /* INVIS because the originals are already visible */ ip->orig=op; } void realign(void){ Item *ip, *next; for(ip=active->next;ip!=active;ip=next){ next=ip->next; if(ip->flags&FLAT) delete(ip); } mwalk(scene, scoffs, flatten); }