1: #include <X/mit-copyright.h> 2: 3: /* Copyright Massachusetts Institute of Technology 1984, 1985 */ 4: 5: #include "gedit.h" 6: 7: #ifndef lint 8: static char *rcsid_garc_c = "$Header: garc.c,v 10.5 86/02/01 16:18:41 tony Rel $"; 9: #endif lint 10: 11: /* arc drawing routines */ 12: 13: double sqrt(),atan2(),sin(),cos(); 14: char *malloc(); 15: 16: /* construct a line object */ 17: gptr mline(x1,y1,x2,y2,next) 18: gptr next; 19: { register gptr p; 20: 21: if ((p = (gptr)malloc(sizeof(struct segment))) == NULL) { 22: msg("out of room!"); 23: return(next); 24: } 25: p->s.type = SEGMENT; 26: p->s.next = next; 27: p->s.parent = NULL; 28: p->s.x1 = x1; 29: p->s.y1 = y1; 30: p->s.x2 = x2; 31: p->s.y2 = y2; 32: p->s.angle = 0; 33: p->s.cache = NULL; 34: return(p); 35: } 36: 37: /* rounds the double x off to an integer */ 38: int round(x) 39: double x; 40: { register int i; 41: if (x >= 0.0) i = x+0.5; else i = x-0.5; 42: return(i); 43: } 44: 45: /* compute center from arc end point and radius */ 46: circcent(ang,fx,fy,tx,ty,xcp,ycp,rp) 47: int ang,fx,fy,tx,ty,*xcp,*ycp; 48: double *rp; 49: { double xx,yy,ss,dd,x1,y1; 50: 51: xx = tx - fx; yy = ty - fy; 52: dd = sqrt(xx*xx + yy*yy); /* length of chord */ 53: if (dd == 0) { *xcp = fx; *ycp = fy; *rp = 0; return; } 54: 55: /* radius of arc */ 56: *rp = dd / (2.0 * sin(3.141592653 * ang / 2048.0)); 57: 58: /* length of perpendicular to chord */ 59: ss = sqrt((*rp)*(*rp) - dd*dd/4.0); 60: 61: if (ang > 1024) ss = -ss; 62: x1 = (tx + fx) / 2.0; /* compute center point of chord */ 63: y1 = (ty + fy) / 2.0; 64: x1 -= yy*ss/dd; /* now compute center of circle */ 65: y1 += xx*ss/dd; 66: 67: *xcp = round(x1); *ycp = round(y1); 68: } 69: 70: /* calculate new arc list */ 71: newalist(p,xa,ya,xb,yb) 72: register struct segment *p; 73: { double xx,yy,aa,bb; 74: double ainc,r; 75: int ix,iy,xc,yc; 76: int wherex,wherey; 77: 78: if (p->cache != NULL) { 79: rmalist(p->cache); 80: p->cache = NULL; 81: } 82: 83: if (p->angle == 0) return; 84: circcent(p->angle,xa,ya,xb,yb,&xc,&yc,&r); 85: 86: if (r < 2.0) { 87: p->cache = mline(xa-1,ya-1,xa+1,ya-1,p->cache); 88: p->cache = mline(xa-1,ya,xa+1,ya,p->cache); 89: p->cache = mline(xa-1,ya+1,xa+1,ya+1,p->cache); 90: return; 91: } 92: 93: xx = xa-xc; yy = ya-yc; 94: aa = atan2(yy,xx); 95: xx = xb-xc; yy = yb-yc; 96: bb = atan2(yy,xx); 97: 98: /* put aa and bb into proper relationship */ 99: /* if (p->angle <= 1024) { 100: */ if (aa > bb) bb += 2*3.141592653; 101: /* } else { 102: if (bb > aa) aa += 2*3.141592653; 103: } 104: */ 105: /* usually 32 lines/arc, but use enough to ensure that there would 106: * be at least 100 segments for a full circle. 107: */ 108: ainc = (bb - aa)/32.0; 109: if (ainc > 0.628) ainc = 0.628; 110: else if (ainc < -0.628) ainc = -0.628; 111: 112: wherex = xa; wherey = ya; 113: while (1) { 114: ix = xc + r*cos(aa); 115: iy = yc + r*sin(aa); 116: p->cache = mline(wherex,wherey,ix,iy,p->cache); 117: wherex = ix; wherey = iy; 118: aa += ainc; 119: if ((ainc<0 && aa<=bb) || (ainc>=0 && aa>=bb)) break; 120: }; 121: p->cache = mline(wherex,wherey,xb,yb,p->cache); 122: }