Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.

Topics - raymw

Pages: [1]
General Discussion / Threads - ISO
« on: 2020-09-12, 15:34:18 »
I've been recently printing using pet-g. I find it has good mechanical properties for what I want, or at least better than abs or pla. It can be ground, filed and machined, without too many problems. I was thinking of using it for jigs and fixtures, clamps, etc, and was wondering about trying some rule of thumb tests. I designed a T nut, with a 12mm thread. Knowing that holes came out undersize, I changed the od to 12.2, it printed, but still a bit tight on the 12mm stud, so I ran a tap down through. I think the fit could be improved by using a 12mm od thread, as it should be, but I found it would not accept exactly 12mm. I based the code on Carsten's example. Here's my code. the '//this line' comment, was left from when I was originally going to tap a plain hole, but if it is removed, or changed to the root diameter, the code fails. I think, because of the countersinks interacting with the thread ends, it causes confusion in the rendering, changing the secant_tolerance dramatically effects the result.

Code: [Select]
// AngelCAD code.

double to_rad(double deg) { return PI*deg/180.0; } // from degrees to radians

   shape2d@ ISO_thread(double Dmaj, double pitch)
   double P = pitch;
   // basic thread profile
   double H = P*cos(to_rad(30));
   double delta = 0.01*P;

   // establish coordinates in profile
   double x1 = delta;;
   double x2 = P/8;
   double x3 = P/2 - P/16;
   double x4 = P/2 + P/16;
   double x5 = P - P/8;
   double x6 = P - delta;

   double y1 = 0;
   double y2 = H/4 - P/16;
   double y3 = H/4;
   double y4 = H - H/8;

   // build the thread profile, points CCW
   pos2d@[] points = { pos2d(x1,y1),  // p0
                       pos2d(x6,y1),  // p1
                       pos2d(x6,y2),  // p2
                       pos2d(x5,y3),  // p3
                       pos2d(x4,y4),  // p4
                       pos2d(x3,y4),  // p5
                       pos2d(x2,y3),  // p6
                       pos2d(x1,y2)   // p7
   shape2d@ profile = polygon(points);

   // put the profile in place, ready for rotation around Y
   @profile = translate(0.5*Dmaj-H+H/8,P/2)*rotate_z(deg:-90)*profile;

   return profile;
   solid@ ISO_screw(double Dmaj, double pitch)
   // EXPERIMENTAL: non-zero pitch and multiple revolutions
   // rotate profile around Y, 13 revolutions, then make it upright
   double revs = 15;
   shape2d@ thread_profile = ISO_thread(Dmaj:Dmaj,pitch:pitch);
   solid@ threads = translate(0,0,pitch*revs)*rotate_x(deg:90)*rotate_extrude(thread_profile,deg:360*revs,pitch:-pitch);

   //make a cylinder inside the threads, then cut the ends by intersecting with a large diameter cylinder

   double H = pitch*cos(to_rad(30));
   double Dmin = Dmaj + 2*(H/8 - H + 0.8*H/4);
   double Rmin = 0.5*Dmin;
   solid@ rod  = cylinder(r:Rmin,h:pitch*revs);
   solid@ screw = intersection3d(union3d(rod,threads),translate(0,0,0.5*pitch)*cylinder(h:pitch*revs*0.9,r:100));

   solid@ cutter = cone(h:pitch*revs*1.3,r1:Dmaj*1.35,r2:1);
   return translate(0,0,-5)*intersection3d(screw,cutter);

shape@ main_shape()
   // t nut with 10mm hole
   solid@ mynut = cuboid(28,22,8);
   @mynut = mynut + translate (0,4,0)*cuboid(28,14,15);
   // hole
   @mynut= mynut -translate(14,11,0)* cylinder(50,4); //this line
   solid@ bolt = ISO_screw(12.05,1.75) ;
  // add countersinks
   solid@ cs = translate(14,11,4)*cone (17.3,0,10);
   solid@ uc =  translate(14,11,-6.3)*cone(17.3,10,0);
   return mynut- translate( 14,11,0)* bolt -cs - uc;

 void main()
   shape@ obj = main_shape();

General Discussion / console mesages
« on: 2020-09-08, 15:59:24 »
Trying to tune up some code, making it more succint, to put in my library, and I find that it often does not complete execution. It seems often to struggle with tori. Below is the typical console message I get.
Code: [Select]
1796 > "C:\Program Files\AngelCAD\xcsg.exe" --csg --dxf --stl --svg --fullpath "C:\Users\Ray\Desktop\AngelCad\xcsg\handwheel2.xcsg"
xcsg processing: C:/Users/Ray/Desktop/AngelCad/xcsg/handwheel2.xcsg
processing solid: difference3d
...completed CSG tree: 21 boolean operations to process.
...starting boolean operations
...boolean progress: 9.5%
...boolean progress: 19%
...Info: rotate_extrude angle>=2*PI implies a torus
...boolean progress: 28.5%
...boolean progress: 38%
...boolean progress: 47.6%
...Info: rotate_extrude angle>=2*PI implies a torus
...boolean progress: 57.1%
...boolean progress: 66.6%
...Info: rotate_extrude angle>=2*PI implies a torus

playing with some values, or adjusting secant_tolerance may allow it to complete, but more often it stalls somewhere else. Is it possible to give more detail in the console messages, as to where in the script it may be failing? I comment out sections, etc., to try and find the error, but when perhaps I have a function that works most of the time, but sometimes when it is called, it stops, is it the function in error, or the calling that is the cause of failure? Alter the function, chances are it will not work where once it worked before.

edit, adjusted secant tolerance, and got this, as last two lines.
Code: [Select]
...Info: rotate_extrude angle>=2*PI implies a torus
xcsg finished with exception: (carve error): D:\cpde_dep\3rdparty\carve\lib\intersect_face_division.cpp:587  "implement me"

which most likely is a clue.

I'm wondering if the syntax for the user could be 'improved'. afaik, if I want to create an object with a number of alterations to it, say to represent a plate with a pattern of holes in it, I have to either make multiple objects, either adding them up as I proceed, or at the end, in a return statement, say. The alternative is to create an array, and add the holes there, which seems artificial, to me. Is there not a simpler construction that could be implemented, as in my commented code below, sort of incrementing an object in the similar way we handle other values?

Code: [Select]
// AngelCAD code.

shape@ main_shape()
   // create cube and 3 small cubes
   double d = 100;
   solid@ mycub = cube(d);
   solid@ hole = cube(2);
   solid@ holecube1 = mycub - translate(5,10,d-2)*hole;
   solid@ holecube2 = holecube1 -translate(90,5,d-2)*hole;
   solid@ holecube = holecube2 -translate(50,50,d-2)*hole;
   return holecube;

shape@ main_shape()
   // create cube & 3 small cubes - the way I'd like it
   double d = 100;
   solid@ mycub = cube(d);
   solid@ hole = cube(2);
   solid@ holecube = mycub - translate(5,10,d-2)*hole;
   holecube =- translate(90,5,d-2)*hole;
   holecube =- holecube2 -translate(50,50,d-2)*hole;
   return holecube;

void main()
   shape@ obj = main_shape();

General Discussion / rendering of imsges
« on: 2020-09-03, 15:53:38 »
One thing I like with AngelCad, is the speed of developing functional mechanical devices, in a sequential manner, where they do not need to look 'pretty', although it is fairly easy to round edges, etc. I needed a coupler, to extend a hand-wheel shaft, and in a few minutes, I got this -
Code: [Select]
// AngelCAD code.

shape@ main_shape()
   // create cube & sphere in default positions
   solid@ tube = cylinder(30,10);
   solid@ shank = cylinder(10,7.5);
   solid@ shaft = cylinder(30,4);
   solid@ fix = rotate_y(90)*cylinder(50,1);
//drill the two fixing holes straight through tube
   return tube-shank-shaft - translate(-20,0,4)*fix -translate(-20,0,22)*fix;

void main()
   shape@ obj = main_shape();

However, when viewing this, at most orientations, the fixing cross hole through the small bored end, looks wrong. At first view, I thought for some reason, I had not made it long enough, or it was offset too far. Just wondering if the lighting? could be improved.

edit to add, meshlab does not show that fix-hole at the surface, no matter how it is orientated, but Cura reports a fault - object not manifold, but it looks as it should, apart from highlighting at the hole surface, but it seems to slice OK, printing it now. So, I'm guessing it's within the mesh, not the lighting.

General Discussion / a simple clip
« on: 2020-08-29, 00:23:47 »
You can buy similar items for pennies, but if the shops are shut...

Having got a bit fed up with cutting/replacing cable ties, i thought of an alternative, similar to items I'd seen in garden centres for clipping plants to supports. As I have a 3d printer with nothing to do, i used AngelCad to make a similar clip, and thought that I could print it at different sizes, for holding different things, and if I used Pet-G filament, it would withstand the greenhouse temperatures, and unlike PLA, would be unlikely to bio-degrade.
So, here's some script with comments -

Code: [Select]
// AngelCAD code.

// Based on AngelCAD sample:
// demonstrate use of rotate_extrude with non-zero pitch to create screw threads.

double wirediam = 3;
double gripdiam = 8; // inside diameter of coil.

double ol = wirediam/10 ; // overlap
double gripr = (gripdiam +wirediam)/2;
double wirer = wirediam/2;
double len = gripr + wirer;

solid@ end()   // straight end with knob
  // generate ends
  solid@ end = cylinder (len,wirer/0.99);  // fudged the diameter of end
  solid@ ball= sphere(wirediam/1.2);
  return end+translate(0,0,len)*ball;

solid@ coil()
   // comments from example
   // create a polygon from the points,
   // and position the resulting profile on the positive x-axis
   // shape2d@ poly = translate(gripr,0)*rotate_z(deg:-90)*circle(wirer);
   shape2d@ poly = translate(gripr,0)*circle(wirer);

   // perform 1 full rotations, with s small pitch to offset the threads
return rotate_extrude(poly,deg:360*1,pitch:wirediam*1.1);  //single turn coil

shape@ all() // put the ends onto the coil
  solid@ end1= translate(gripr,0,ol)*rotate_y(180)*end();
  solid@ end2= translate(gripr,wirediam*1.1,-ol)*end();
return end1 + end2  + coil();

void main()
   shape@ obj = all();

I ran into a problem, because the ends of the coil are not cut on the x/y plane, which presents an angle to the two end pieces. I added an overlap to remove the gap, but found that It would not complete for wire diameters over 2.0, or so. I fudged it again, by making the end pieces slightly larger. This works, but it is not particularly elegant. It would be better to generate  a path from end to end, and extrude along that. However, these loops are now holding up my tomato plants, and smaller ones will be used as cable clips on the printer as originally intended. They print OK, lying flat, with a few supports.

edit to add a couple of quick pics

Being a fairly new user of AngelCad, I've been looking for suitable objects to model, and also 3d print, or machine. One such item is a standard steel oil-drum. The history of steel oil-drums is quite interesting, and the design soon became a world wide 'standard' The basic dimensions are 34 inches high and 23 inches in diameter, and capacity is 55 gallons (USA), 48 gallons (Imperial). They have a couple of ridges around the circumference, to add strength, and make them easy to roll.


The goal, is to make a model of a drum, in either 7mm to the foot scale, or 4mm to the foot.

Always, in cad, model in full size dimensions, and apply a scale factor at the end to get to the size of the object needed. Most cad programs, cnc (g-code) are unit-less, although obviously the machine will be set to convert the numbers into standard units of measurement.

So, this is how I've gone about the modelling of the oil drum. I'm putting in a fair bit of detail of my method, so that if you are a raw beginner, you can understand the process. Of course, there are dozens of ways of doing this, I'm not pretending this is 'the best', but it works for me.

We start with the main cylinder, 34 inches high by 23 inches diameter

so we can write

Code: [Select]
solid@ cyl1()
   return cylinder (34,11.5);

that is followed, as always by

Code: [Select]
void main()
   shape@ obj = cyl(1);

which will generate an stl file, and show the representation on screen, in the xcsg viewer.

So far, so good. What else is needed? Well there is a recess at the ends of the drum, where the top is folded into the sides in manufacturing. In reality, the steel is about 0.125 inches thick, but as we are trying to model this at a small scale, and 3d printing the results, then it will pay initially to allow that lip to be thicker. (Generally in modelling, details have to be exaggerated, for various reasons) (OK, I maybe breaking the rule about always model in full size dimensions ...   :-[)

So we can subtract a cylinder from each end of the main drum, giving us

Code: [Select]
solid@ cyl1()
    return cylinder(34,11.5)- translate(0,0,33)*cylinder(1,11) - cylinder(1,11);

the translate (0,0,33) puts the recess at top of cylinder.

Now, in the top of the drum, there are usually two caps, a filler and a vent, so that the drum does not collapse when the contents are sucked out, or an air lock does not form when being poured. A couple of small cylinders will suffice for that.

so, we can add the script for these caps as

Code: [Select]
solid@ caps()
   solid@ cap = cylinder (1,1.7);
   solid@ cap2 =cylinder(1,1.2);
   return translate(9,0,33)*cap + translate(-9,0,33)*cap2;
As the drum is centred on the origin, it is easy to get the caps evenly spaced on a diameter line, 9 inches either side of the centre.

Now, we want a couple of the reinforcement ridges, which are equally spaced on the circumference of the drum. Now, these are sort of smooth in profile, but at the small scale we are ultimately dealing with, we can represent them by a triangular profile. Thinking of a cone as being a circular triangle, and thinking of the top of one of these ridges, then the sort of shape we need is given by cone(1.1,12.2,11.3) which is saying that it is 1.1 high, and the bottom radius is 12.2, (0.7 bigger than the drum) and the inner radius is  11.3, 0.2 smaller than drum. This gives the sort of angle we are looking for, and since this shape will be added to the drum, the over lap in the diameters will not matter. We need a bottom edge of the ridge, so simply rotate the top edge around the x axis (or y) and add the top and bottom together

Code: [Select]
solid@ ridge()
   solid@ top= cone(1.1,12.2,11.3);
   solid@ bot= rotate_x(180)*top;
    return top + bot ;

You can now add together what we have so far, and view the result.

So, we now have to position the two ridges, but if If you look at an image of an oil drum, you can see there is also a lip at the top and bottom, so we may as well show that, too

so, we can make the lips 0.2inches wide, and position the ridges at 11 and 22 inches from the bottom of the drum

Code: [Select]
solid@ ridges()
   solid@ lip = cylinder(1,11.7)-cylinder (1,11.5);
   solid@ toplip = translate(0,0,33)*lip;
   return translate(0,0,11)*ridge()+ translate(0,0,22)*ridge() + lip + toplip;

That is the drum components completed, so add it all together

Code: [Select]
solid@ drum()
   return cyl1() + caps()+ridges();

remember, that if you have gone through this procedure outlined above, and viewed the results at each stage, you will need to modify the name of the object you are creating in main(). Also, secant_tolerance, adjusts the smoothness of the surface for curved objects, see

Now, part of the design features of standard oil drums, is that four of them sit quite nicely on a standard pallet, with one inch spacing between them (It is not clear if that is one inch between each drum body, or one inch between ridges).

So, we can position four of them, (The rotates make sure that the fillers are not lined up, I do not think they would be in reality, unless perhaps new empty drums from the manufacturer)

Code: [Select]
solid@ four()
   solid@ first = drum();
   solid@ second = translate(0,24.5,0)*rotate_z(25)* first;
   solid@ third = translate(24.5,0,0)*rotate_z(50)* first;
   solid@ fourth = translate(24.5,24.5,0)*rotate_z(150)*first;
   return first+second+third+fourth;

You may as well print four of these pallet-fulls. As an exercise, use translate and rotate so that none of the fillers line up. (In my example, I've not done the rotates.)

so, at 7mm to the foot, and most 3d printers expect mm dimensions, then the scale is 7/12 mm to the inch a scale of 58.3%, near enough.

Applying the AngelCad scaling transform we can have something like - scale(0.583)*four() in the  main function.

I've attached the complete script ( (attached as barrel.txt - you can rename it)

In practice, I may take care of the scaling in the slicing program, if wanting different scaled models.

I hope this has helped you, if you realise the power of Angel Cad, but can't make much sense of github, and the rest of the help system.

A few additional print related comments. The lips need to be far larger than the scaled full size, since the detail is too fine for a slicer, such as Cura to slice properly. The two fillers need to be bigger, too, they just look wrong. There are certain aspects in models, that need to be exaggerated, in order for them to 'look right'. In the same way that colours generally need to be more subdued, and matt finish paint, not gloss, etc, is preferred. Equally, there are some things that can not be readily modeled to scale, working tolerances, for example, sound too.

Edit (by Carsten Arnholm): I put your code snippets in code tags to make the post easier to read. Please use the # button for this purpose.

General Discussion / a first stab at something useful
« on: 2020-08-07, 20:49:26 »
I've only been playing around with angelcad for a few weeks, but I like the structure so far, and the ood aspects of it. Not having a background in c++, I find the syntax somewhat confusing, but I know that will change as I had a load of help from Carsten. I thought I'd show a component box, which can be 3d printed. It is designed such that sizes, ventilation, standoffs can be readily changed. Depending on the quality of the 3d print, you may need to adjust the 'shave' value, so that the lid fits nicely. I recently added rounded corners to the lid, (thinlid, in code) because often internal corners of 3d prints are not sharp. There are other alterations I may or may not make, and if anyone wants to modify or otherwise use it, feel free to do so.

Code: [Select]
// AngelCAD code.

//inside dimensions of box
   double y= 45;
   double x= 51;
   double z= 15;
//wall thickness   
   double wall=2.5;
// x1,y1,x3,y3 defines corners of ventilation hole area
   double x1= 15;
   double y1=15;
   double x3=36;
   double y3=30;
//hole is width of inividual ventilation hole   
   double hole =3;
//space is hole spacing   
   double space= 5;
//select if you want want ventialtion holes in box or lid  or both 
   bool lidhole = true;
   bool boxhole = false;
//soh is standoff height, sod is standoff diameter   
   double soh = 5 ;
   double sod = 6 ;
//shole is diameter of hole in centre of standoff   
   double shole = 2;
// son is number of standoffs
   int son =4;
// if you add more standoffs, adjust number 'son', above.
// if you don' twant standoffs, set son to 0, but leave values in stands
// (x,y) position of standoffs 'stands'
   array<pos2d@ > stands  = {
//shave is to give clearance for lid lip
//value of shave may depend on manufacturing method.   
  double shave=0.5;
 // fixed values below........
 // no need to edit values below here
 // w2 is half the wall thickness
   double w2= wall/2;
solid@ box()   //create box
   //smaller cuboid for inside
   solid@ boxis = cuboid(x,y,z+wall, false);
   // add walls to create outside of box
   solid@ boxos = cuboid(x+wall+wall,y+wall+wall,z+wall,false);
   //subtract inner from outer
   solid@ crate= translate(-wall,-wall,-wall)*boxos -boxis;
   //add lip to top size (0.5*wall) on outer edge
   solid@ lip= cuboid(x+wall+wall,y+wall+wall,wall) -translate(w2,w2,0)*cuboid(x+wall,y+wall,wall);
  solid@ all= translate (-wall,-wall,z-w2)*lip +crate;
return all;

solid@ thinlid(){
  //puts a 1mm radius on lip of inserted top
shape2d@ top= offset2d (rectangle (x+wall-shave-2,y+wall-shave-2),r:1);
return transform_extrude (top,translate(0,0,w2)*top);

solid@ lid()  //similar to box, but only half wall high rim
  solid@ topbig = cuboid(x+wall+wall,y+wall+wall,w2, false);
   //add insertedhalf wall (make it shave smaller to fit inside lip of box)
   solid@ topall =topbig + translate(w2+1+(shave/2),w2+1+(shave/2),w2)*thinlid();
   // add lid holes (diam 1.3 * shole) in corners for fixing screws
   double r = (1.3*shole)/2;
   double hr =shole/2;
   solid@ h1 = translate (hr+wall,hr+wall,-wall)*cylinder(20,r);
   solid@ h2 = translate (hr+wall,y+wall-hr,-wall)*cylinder(20,r);
   solid@ h3 = translate (x+wall-hr,hr+wall,-wall)*cylinder(20,r);
   solid@ h4 = translate (x-hr+wall,y-hr+wall,-wall)*cylinder(20,r);
return translate (-wall,-wall,-wall)*(topall - h1 - h2 - h3 - h4);
solid@ sup()    //support for pcb and screw holes for lid (standoff)
   solid@ block= cylinder(soh,sod/2,true)-cylinder(soh,shole/2,true);
   return translate(0,0,soh/2)*block;
solid@ standoffs()    // add standoffs
   array<solid@> p;
   for (int j=0;j<son;j++)
      p.push_back( translate(stands[j].x(),stands[j].y(),0)*sup());
return union3d(p);
solid@ holes()    // number of ventilation holes in each direction
   int nx= int((x3-x1)/space) ;
   int ny= int((y3-y1)/space) ;
   double dx=space;
   double dy=space;
   // create an array of cuboids a grid pattern in 1st quadrant
   array<solid@> h;
   for (int ix=0;ix<=nx;ix++)
      for (int iy=0;iy<=ny;iy++)
         double xh = x1 + ix*space;
         double yh = y1 + iy*space;
   // return the cylinders as a single solid
return union3d(h);   

solid@ fix()     // fix standoffs at top corners for screws for lid
   double hr =shole/2;
   solid@ h1 = translate (hr,hr,z-soh)*sup();
   solid@ h2 = translate (hr,y-hr,z-soh)*sup();
   solid@ h3 = translate (x-hr,hr,z-soh)*sup();
   solid@ h4 = translate (x-hr,y-hr,z-soh)* sup();
return h1 + h2 + h3 + h4;
solid@ boxholed()  //add ventilation holes to box if required
   if (boxhole == true)
      return box() - holes();
return box();
solid@ lidholed()  //add ventilation holes to lid if required
   if (lidhole == true)
      return lid() -holes();
return lid();     
void main()    //put all the parts together
   solid@ both=boxholed()+translate(0,y+3+wall+wall,0)*lidholed() +fix()+standoffs();

edited the above code to correctly offset resized rounded corner lid part - hopefully fits now!

Pages: [1]