#include "art.h" Image *color; /* * return the closest point on arc ip to point testp. */ Dpoint neararc(Item *ip, Dpoint testp){ Flt d; Dpoint p, cen; cen=circumcenter(ip->p[0], ip->p[1], ip->p[2]); p=dsub(testp, cen); d=dlen(p); if(d!=0){ p=dlerp(cen, p, dist(ip->p[0], cen)/d); if(triarea(ip->p[0], p, ip->p[2])*triarea(ip->p[0], ip->p[1], ip->p[2])>0) return p; } if(dist(testp, ip->p[0])p[2])) return ip->p[0]; return ip->p[2]; } /* * given three points, p[0], p[1], p[2] which indicate the points on the circle. * p[0] and p[2] makes two end points, and p[1] indicates inner point in the arc */ void drawarc(Item *ip, Image *b, Image *color){ Dpoint cen; int alpha, phi, p0, p2; if(pldist(ip->p[1], ip->p[0], ip->p[2])p[0]), D2P(ip->p[2]), Endsquare, Endsquare, 0, color, ZP); if(ip->style&ARROW0) line(b, D2P(ip->p[0]), D2P(ip->p[2]), Endsquare, Endarrow, 0, color, ZP); if(ip->style&ARROW1) line(b, D2P(ip->p[0]), D2P(ip->p[2]), Endarrow, Endsquare, 0, color, ZP); return; } cen=circumcenter(ip->p[0], ip->p[1], ip->p[2]); p0 = datan2((ip->p[0].y - cen.y), (ip->p[0].x - cen.x)); p2 = datan2((ip->p[2].y - cen.y), (ip->p[2].x - cen.x)); if(p2 > p0) { /* phi > 0 */ alpha = p0; phi = p2 - p0; }else { alpha = p2; phi = p0 - p2; } arc(b, D2P(cen), (int)(dist(cen, ip->p[0])*DPI), (int)(dist(cen, ip->p[0])*DPI), 0, color, ZP, alpha, phi); if(ip->style&ARROW0) { line(b, D2P(cen), D2P(ip->p[0]), Endsquare, Endarrow, 0, color, ZP); line(b, D2P(cen), D2P(ip->p[2]), Endsquare, Endarrow, 0, color, ZP); }else if(ip->style&ARROW1){ line(b, D2P(cen), D2P(ip->p[0]), Endarrow, Endsquare, 0, color, ZP); line(b, D2P(cen), D2P(ip->p[2]), Endarrow, Endsquare, 0, color, ZP); }else{ line(b, D2P(cen), D2P(ip->p[0]), Endsquare, Endsquare, 0, color, ZP); line(b, D2P(cen), D2P(ip->p[2]), Endsquare, Endsquare, 0, color, ZP); } } void editarc(void){ Flt l0=dist(arg[0], selection->p[0]); Flt l1=dist(arg[0], selection->p[1]); Flt l2=dist(arg[0], selection->p[2]); if(l0p[1]); hotpoint(selection->p[2]); track(movep, 0, selection); } else if(l1p[0]); hotpoint(selection->p[2]); track(movep, 1, selection); } else{ hotpoint(selection->p[0]); hotpoint(selection->p[1]); track(movep, 2, selection); } } void translatearc(Item *ip, Dpoint delta){ ip->p[0]=dadd(ip->p[0], delta); ip->p[1]=dadd(ip->p[1], delta); ip->p[2]=dadd(ip->p[2], delta); } void deletearc(Item *ip){ } void writearc(Item *ip, int f){ fprint(f, "a %.3f %.3f %.3f %.3f %.3f %.3f", ip->p[0].x, ip->p[0].y, ip->p[1].x, ip->p[1].y, ip->p[2].x, ip->p[2].y); writestyle(f, ip->style); fprint(f, "\n"); } void activatearc(Item *ip){ hotarc(ip->p[0], ip->p[1], ip->p[2]); } int inboxarc(Item *ip, Drectangle r){ Dpoint i[2]; return dptinrect(ip->p[0], r) || seginterarc(r.min, Dpt(r.min.x, r.max.y), ip->p[0], ip->p[1], ip->p[2], i) || seginterarc(r.min, Dpt(r.max.x, r.min.y), ip->p[0], ip->p[1], ip->p[2], i) || seginterarc(r.max, Dpt(r.min.x, r.max.y), ip->p[0], ip->p[1], ip->p[2], i) || seginterarc(r.max, Dpt(r.max.x, r.min.y), ip->p[0], ip->p[1], ip->p[2], i); } /* * This can overestimate the size of the box. */ Drectangle bboxarc(Item *ip){ Drectangle r; r.min=dsub(ip->p[0], Dpt(ip->r, ip->r)); r.max=dadd(ip->p[0], Dpt(ip->r, ip->r)); return r; } Dpoint nearvertarc(Item *ip, Dpoint testp){ if(dist(ip->p[0], testp)p[2], testp)) return ip->p[0]; return ip->p[2]; } Itemfns arcfns={ deletearc, writearc, activatearc, neararc, drawarc, editarc, translatearc, inboxarc, bboxarc, nearvertarc, }; Item *addarc(Item *head, Dpoint p0, Dpoint p1, Dpoint p2){ return additem(head, ARC, 0., 0, 0, 0, &arcfns, 3, p0, p1, p2); }