1
General Discussion / Re: Turtle graphics
« on: 2022-03-07, 18:26:37 »
I've added a bit more complexity to the original code. It can produce interesting stl files 3d prints, or can, if the values are not correct, produce equally interesting errors.
With careful choice of parameters you can create a multi spiral sided pot, with a screw-on lid, for example. I have just added a facility to reverse the direction of the spiral at various heights. The values I have in the example code works, produces a water tight pot, other values may throw errors, at the moment it is almost trial and error. to choose workable values. I will add some images, if possible.
With careful choice of parameters you can create a multi spiral sided pot, with a screw-on lid, for example. I have just added a facility to reverse the direction of the spiral at various heights. The values I have in the example code works, produces a water tight pot, other values may throw errors, at the moment it is almost trial and error. to choose workable values. I will add some images, if possible.
Code: [Select]
// turtle tube
double rfd = PI/180; //rads from degrees
void settings (thing &out it)
{
it.le = 20; // length of rod
it.w = 1.5; // width of rod
it.h = 1.5; // height of rod
it.rot = false; // rotate rectangular rods by 45 degree, to remove horizontal overhangs
it.range = 200; // number of rods
it.a =61; // angle between rods
// it.b = 0.7*it.h/(360/it.a); // vertical angle
it.b = 0.5*it.h/(360/it.a); // smaller vertical angle to allow for reversal of direction.
it.base = true;// false if base not needed
it.flat = false ; // true for flat base
it.round = true; // set to true if wanted rounded adges instead of square (diamete =w)
it.blob = 2; // diameter of blob at corners (0 to ignore)
it.rev = false; // set true if you want spiral (if any) reversed
it.cut = 0 ; // if a positive value, it cuts off the top of 'cylinder', at cut.height
it.dir =24 ; // if a positive value, it reverses direction every dir number of rods
it.ar = 59 ; // 'reverse direction' angle
////////////////////////////////////
return;
}
class thing
{
double le, w, h, a, b, blob, bang, cang, cut, dir, dirc, ar = 0;
int range = 0;
bool base, round, rot, flat, rev = true;
}
solid@ part(thing it)
{
solid@ stroke = translate(it.le/2,0,0)*cuboid(it.le,it.w,it.h,true);
if (it.rot == true)
{
@stroke = rotate_x(rad:rfd*45)* stroke; // angle to make 3d printable - 45 deg overhangs
}
if (it.round==true)
{
@stroke = rotate_y (rad:PI/2)*cylinder(it.le,it.w/2);
}
return stroke;
}
solid@ ball(double blob)
{
return sphere(r:blob/2);
}
solid@ draw( thing it, pos3d@ now, pos3d@ &out last)
{
solid@ ans=
translate(now.x(),now.y(),now.z())*
rotate_z(rad:rfd*it.cang)*
part(it);
// calc 'last' for next 'now'
@last = now + pos3d(cos(rfd*it.cang)*it.le,sin(rfd*it.cang)*it.le,it.bang );
// put sphere at corner if needed
if (it.blob >0 )
{
@ans =ans + translate(last.x(),last.y(),last.z())*ball(it.blob);
}
return ans;
}
void main()
{
thing it;
settings(it); //get values
pos3d@ now = {0,0,0};
pos3d@ last= {it.le,0,0};
array <pos2d@> points;
solid@ obj;
double tempa = it.a;
if (it.base == true)
{
it.flat=true;
}
@obj = part(it); // this is to become the set of lines
int count=0;
while( count < it.range )
{
it.bang=0; // flatten bottom ( b, vertical angle =0) and make polygon
if (it.flat==true)
{
if (count <= 360/it.a)
{
points.push_back(pos2d(last.x(),last.y()));
}
if (count>((360/it.a)))
{
it.bang=it.bang+it.b; // now add vertical angle
}
if (count>=it.range-(360/it.a)-1) // to give flat top
{
it.bang=0; // vertical angle 0 for last few
}
}
if (it.flat == false)
{
it.bang=it.bang+it.b;
}
it.cang=it.cang+it.a;
@now = last;
@obj = obj+draw(it,now,last);
// change direction
if (it.dir >=1)
{
it.dirc=it.dirc+1;
if (it.dir== it.dirc)
{
tempa=it.a;
it.a=it.ar;
it.ar=tempa;
it.dirc=0;
}
}
count++;
}
if (it.rot==true)
{
// get rotaton position of base
@obj= translate(0,0,(sqrt((it.w *it.w) + (it.h*it.h))*0.5)-it.w/2)*obj;
}
@obj= translate(0,0,it.w/2)*obj;
if (it.base==true) // make solid base
{
polygon@ solid_base = polygon (points);
@obj=obj + linear_extrude(solid_base,height:it.h);
if (it.rev == true)
{
@obj= mirror(1,0,0)*obj;
}
if (it.cut>0) // cut off top using 500 cube centred
{
@obj = obj-translate(0,0,it.cut+250)*cube(500,true);
}
}
// assume no overlap
cout<< "aproximate height " << (it.range /(360/it.a))*it.h << endl;
obj.write_xcsg(GetInputFullPath(),secant_tolerance:0.0010);
}