void tab() { putchar('\t'); } void tab(unsigned n) { for (unsigned i=0; i void translate(const T &c) { translate(c.cur); translate(c.sub); } #if 0 void printconnect(const COOROBJ::COOR &coor) { printf ("\t// printconnect\n"); tab(); translate(coor); openbrace(); tab(2); sphere(10,40); tab(2); cylinder(4,100,40); tab(); closebrace(); } #endif template void printconnect(const T &coor) { printf ("\t// printconnect\n"); tab(); translate(coor); openbrace(); tab(2); sphere(10,40); tab(2); cylinder(4,100,40); tab(); closebrace(); } using FOLLOW = COOROBJ::COOR; static void apply_angle (double angle, double &x, double &y, double &z) { if (angle != 0){ // |cos θ −sin θ 0| |x| |x cos θ − y sin θ| |x'| // |sin θ cos θ 0| |y| = |x sin θ + y cos θ| = |y'| // | 0 0 1| |z| | z | |z'| angle = angle/180*M_PI; double cosa = cos(angle); double sina = sin(angle); double newx = x*cosa-y*sina; double newy = x*sina+y*cosa; x = newx; y = newy; } } FOLLOW followpath_xyz (FOLLOW f, const COOROBJ::COOR &c) { FOLLOW ret; //fprintf (stderr,"\tfollow f=[%lf,%lf,%lf %lf,%lf,%lf] c=[%lf,%lf,%lf %lf,%lf,%lf]\n" // ,f.x,f.y,f.z,f.angle_x,f.angle_y,f.angle_z // ,c.x,c.y,c.z,c.angle_x,c.angle_y,c.angle_z); ret.angle_x = f.angle_x + c.angle_x; ret.angle_y = f.angle_y + c.angle_y; ret.angle_z = f.angle_z + c.angle_z; // On travaille des cylindre qui monte en suivant l'axe Z. // Pour un orientation de 0,0,0, on monte verticalement. // On corrige donc angle_x de 90 degrés. double x = c.x; double y = c.y; double z = c.z; apply_angle (ret.angle_x,y,z,x); apply_angle (ret.angle_y,z,x,y); apply_angle (ret.angle_z,x,y,z); #if 0 double sin_x = sin(ret.angle_x+M_PI_2); double cos_x = cos(ret.angle_x+M_PI_2); double sin_y = sin(ret.angle_y); double cos_y = cos(ret.angle_y); double sin_z = sin(ret.angle_z); double cos_z = cos(ret.angle_z); ret.x = f.x + cos_y*c.x+sin_z*c.x; ret.y = f.y + cos_z*c.y+sin_x*c.y; ret.z = f.z + cos_y*c.z+sin_x*c.z; #endif ret.x = f.x + x; ret.y = f.y + y; ret.z = f.z + z; //fprintf (stderr,"\t ret=[%lf,%lf,%lf -> %lf,%lf,%lf %lf,%lf,%lf]\n",x,y,z,ret.x,ret.y,ret.z,ret.angle_x,ret.angle_y,ret.angle_z); return ret; } template FOLLOW followpath_xyz(FOLLOW xyz, const T &c) { FOLLOW xyz1 = followpath_xyz (xyz,c.cur); FOLLOW xyz2 = followpath_xyz (xyz1,c.sub); return xyz2; } template FOLLOW followpath(const T &c) { //fprintf (stderr,"follow:\n"); FOLLOW xyz; return followpath_xyz(xyz,c); } template class SCAD_COMMON{ //using ID = typename T::ID; public: template auto getfcoor(ID id){ return followpath(static_cast(this)->getcoor(id)); } template double getx(ID id){ return followpath(static_cast(this)->getcoor(id)).x; } template double gety(ID id){ return followpath(static_cast(this)->getcoor(id)).y; } template double getz(ID id){ return followpath(static_cast(this)->getcoor(id)).z; } }; template class TRANSLATE: public SCAD_COMMON>{ T obj; double x,y,z; public: struct COOR{ typename T::COOR sub; COOROBJ::COOR cur; }; using ID = typename T::ID; TRANSLATE(T _obj, double _x, double _y, double _z) : obj(_obj), x(_x),y(_y),z(_z) { } TRANSLATE(T _obj, const COOROBJ::COOR &c) : obj(_obj), x(c.x),y(c.y),z(c.z) { } void print () const{ translate(x,y,z); printf ("{\n"); obj.print(); printf ("}\n"); } COOR getcoor (ID id) const{ COOR c; c.sub = obj.getcoor(id); c.cur.x = x; c.cur.y = y; c.cur.z = z; return c; } }; template class TRANSLATEC: public SCAD_COMMON>{ T obj; C c; public: struct COOR{ typename T::COOR sub; C cur; }; using ID = typename T::ID; TRANSLATEC(T _obj, const C &_c) : obj(_obj), c(_c) { } void print () const{ translate(c); printf ("{\n"); obj.print(); printf ("}\n"); } COOR getcoor (ID id) const{ COOR ret; ret.sub = obj.getcoor(id); ret.cur = c; return ret; } }; template class ROTATE: public SCAD_COMMON{ T obj; double angle_x,angle_y,angle_z; public: struct COOR{ typename T::COOR sub; COOROBJ::COOR cur; }; using ID = typename T::ID; ROTATE(T _obj, double _angle_x, double _angle_y, double _angle_z) : obj(_obj), angle_x(_angle_x),angle_y(_angle_y),angle_z(_angle_z) { } void print () const{ rotate(angle_x,angle_y,angle_z); printf ("{\n"); obj.print(); printf ("}\n"); } COOR getcoor (ID id) const{ COOR c; c.sub = obj.getcoor(id); c.cur.angle_x = angle_x; c.cur.angle_y = angle_y; c.cur.angle_z = angle_z; //apply_angle (angle_x,c.y,c.z); return c; } }; void printcoor (const char *title, const COOROBJ::COOR &c) { fprintf (stderr,"%-10s: translate %7.3lf %7.3lf %7.3lf rotate %7.3lf %7.3lf %7.3lf\n",title,c.x,c.y,c.z,c.angle_x,c.angle_y,c.angle_z); } template void printcoor (const char *title, const T &c) { printcoor (title,c.sub); printcoor (title,c.cur); } // Section d'un tube. On indique le changement d'angle et la longueur class SECTION{ public: double angle_x,angle_y,angle_z; double len; SECTION(double _angle_x, double _angle_y, double _angle_z, double _len) : angle_x(_angle_x), angle_y(_angle_y), angle_z(_angle_z), len(_len) { } }; template auto makecoor(const T1 &debut, const SECTION &step) { struct COOR{ COOROBJ::COOR sub; COOROBJ::COOR cur; }; struct { COOR sub; T1 cur; } ret; ret.cur = debut; ret.sub.cur.angle_x = step.angle_x; ret.sub.cur.angle_y = step.angle_y; ret.sub.cur.angle_z = step.angle_z; ret.sub.sub.z = step.len; return ret; } // Dessine un tube entre deux points en passant par un chemin template void tube(const T1 &debut, const T2 &fin, double ray, double res) { //translate(debut); auto p1 = followpath(debut); auto p2 = followpath(fin); #if 0 double dotprod = p1.x*p2.x + p1.y*p2.y + p1.z*p2.z; double p1len = sqrt(p1.x*p1.x + p1.y*p1.y + p1.z*p1.z); double p2len = sqrt(p2.x*p2.x + p2.y*p2.y + p2.z*p2.z); double cosa = dotprod/(p1len*p2len); double angle = acos(cosa)/M_PI*180; fprintf (stderr,"angle=%lf\n",angle); #endif double diffx = p2.x-p1.x; double diffy = p2.y-p1.y; double diffz = p2.z-p1.z; double len=sqrt(diffx*diffx+diffy*diffy+diffz*diffz); double angle_z = atan2(diffy,diffx); double scad_angle_z = angle_z/M_PI*180; double angle_y = atan2(diffz,sqrt(diffx*diffx+diffy*diffy)); double scad_angle_y = angle_y/M_PI*180; double angle_x = 0; #if 0 double angle_x = -atan2(diffy,diffz)/M_PI*180; double angle_y = -atan2(diffx,-diffz)/M_PI*180; double angle_z = -atan2(diffx,-diffy)/M_PI*180; double c_angle_z = angle_z; angle_z = 0; #endif //fprintf (stderr,"len=%lf diffx=%lf diffy=%lf diffz=%lf anglex=%lf angley=%lf -> %lf anglez=%lf -> %lf\n",len,diffx,diffy,diffz,angle_x,angle_y,scad_angle_y,angle_z,scad_angle_z); translate(p1.x,p1.y,p1.z); rotate (angle_x,90-scad_angle_y,scad_angle_z); openbrace(); //printf ("cube([100,100,1]);\n"); cylinder(ray,len,res); closebrace(); translate(p1.x,p1.y,p1.z); sphere(ray,40); //translate(p1.x,p1.y,p1.z); color("blue"); sphere(15,40); //translate(p2.x,p2.y,p2.z); color("red"); sphere(15,40); } template void tube(const T1 &debut, const SECTION §, double ray, double res) { translate(debut); //auto inter = makecoor(debut,section); rotate(sect.angle_x,sect.angle_y,sect.angle_z); openbrace(); cylinder(ray,sect.len,res); sphere(ray,res); closebrace(); } template void tube(const T1 &debut, const T2 &fin, double ray, double res, const SECTION §ion, Ts ... ts) { auto inter = makecoor(debut,section); tube (debut,section,ray,res); tube(inter,fin,ray,res,ts...); } template void tube(const T1 &debut, const T2 &fin, double ray, double res, const T3 pt, Ts ... ts) { tube (debut,pt,ray,res); tube (pt,fin,ray,res,ts...); } static void module_composante() { printf ("module COMPOSANTE(){\n"); } // Affiche une composante avec ses points d'intérêt template void show() { T p; module_composante(); p.print(); p.showconnect(); closebrace(); }