henesyinit from p9fce6d0435 years agoHistory
248 lines · 5.7 KB · C
RawDownload
#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(l<SMALL){ msg("tiny line"); return; }	ang=datan2(d.y, d.x);	for(i=0;i!=nalign[ANGLE];i++) if(align[ANGLE][i].active){		if(ep&L) alline(p, ang+align[ANGLE][i].value);		if(ep&R) alline(q, ang+align[ANGLE][i].value);	}	for(i=0;i!=nalign[PARA];i++) if(align[PARA][i].active){		r.x=d.y*align[PARA][i].value/l;		r.y=-d.x*align[PARA][i].value/l;		alline(dadd(p, r), ang);		alline(dsub(p, r), ang);	}}void hotarc(Dpoint p, Dpoint q, Dpoint r){	Dpoint cen, d;	int i;	Flt pang, rang;	if(pldist(p, q, r)<CLOSE){		hotline(p, r, L|R);		return;	}	hotpoint(p);	hotpoint(q);	cen=circumcenter(p, q, r);	d=dsub(p, cen);	pang=datan2(d.x, -d.y);	d=dsub(r, cen);	rang=datan2(d.x, -d.y);	for(i=0;i!=nalign[ANGLE];i++) if(align[ANGLE][i].active){		alline(p, pang+align[ANGLE][i].value);		alline(r, rang+align[ANGLE][i].value);	}}void hotpoint(Dpoint p){	int i;	for(i=0;i!=nalign[SLOPE];i++) if(align[SLOPE][i].active)		alline(p, align[SLOPE][i].value);	for(i=0;i!=nalign[CIRC];i++)		if(align[CIRC][i].active)			alcirc(p, align[CIRC][i].value);}/* * add an alignment line through p at angle t */void alline(Dpoint p, Flt t){	Dpoint p0, p1, d;	Item *ip;	d.x=2000.*cos(radians(t));	d.y=2000.*sin(radians(t));	p0=dsub(p, d);	p1=dadd(p, d);	if(dclipline(dwgdrect, &p0, &p1) && !findline(active, p0, p1)){		ip=addline(active, p0, p1);		draw(ip, Dpt(0., 0.), faint, S|D);	}}/* * add an alignment circle through p with radius r */void alcirc(Dpoint p, Flt r){	Item *ip;	if(!findcircle(active, p, r)){		ip=addcircle(active, p, r);		draw(ip, Dpt(0., 0.), faint, S|D);	}}int findline(Item *ip, Dpoint p, Dpoint q){	Item *cp;	switch(ip->type){	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->x<xl?1:p->x>xr?2:0)|(p->y>yt?4:p->y<yb?8:0))#define	xl r.min.x#define	yb r.min.y#define	xr r.max.x#define yt r.max.y#define	x0 p0->x#define	y0 p0->y#define	x1 p1->x#define	y1 p1->yint 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);}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t