Recent Posts

Pages: [1] 2 3 ... 10
1
General Discussion / Re: Turtle graphics
« Last post by raymw 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.
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);
}
       
2
General Discussion / Re: drawing lines
« Last post by raymw on 2022-02-26, 14:35:01 »

Progress is slow, but so far it is getting to where I want it to be.
Code: [Select]

// AngelCAD code.

#include "aclib/fonts/LiberationSerif_Regular.as"

shape2d@ resistor(r v){   // on 100 grid
   
    string name = v.nam;
    as_font@ font = LiberationSerif_Regular();
    shape2d@ wire= rectangle (1,100,true);
    shape2d@ body= rectangle (15,50,true);
    shape2d@ t1 = translate(0,50)*circle(2);
    shape2d@ mk= translate(0,34)*square(4,true); //mark t1 end
    shape2d@ t2 = translate(0,-50)*circle(2);
    shape2d@ txt2d = translate(50,50)*font.text("  "+name,v.ltext);
return wire+body +t1 +t2 +mk + txt2d;
}


class r  // resistor class
{
double res, amp, t1v, t2v =0;
pos2d@ t1 = {0,0};
pos2d@ t2 = {0,0};
string nam = "xx";
int ltext=20;  // default text length
//amp=(t1v-t2v)/res;
//t1v=t2v + amp*res;
}


shape2d@ drawr(r v)
{
  shape2d@ resp;
   if (v.t1.y()>v.t2.y())
   {
   @resp = translate(v.t1.x(),v.t1.y()-50)*resistor(v); //t2.y < t1.y
   }
    if (v.t2.y() > v.t1.y()) // vertical, t1y<t2y
    {
    @resp = translate(v.t1.x(),v.t1.y() +50)*rotate_z(180)*resistor(v);
    }
     if (v.t1.x() < v.t2.x()) // horizontal t1 to left of t2
     {
     @resp = translate(v.t2.x()-50,v.t2.y())*rotate_z(90)*resistor(v);
     }
      if (v.t2.x() < v.t1.x()) // horizontal, t1 to right of t2
      {
      @resp = translate(v.t1.x()-50,v.t2.y())*rotate_z(270)*resistor(v);
      }
   
return resp;
}   

void main()
{
   // set up resistor network
   r r1;
   r r2 ;
   r r3 ;
   r r4;
   r r5;
   
  r1.nam="R1";
  r2.nam= "R2";
  r3.nam="R3";
  r4.nam="R4";
  r5.nam="R5";
 
  r1.res=20;
  r2.res=10;
  r3.res=20;
  r4.res=10;
  r5.res=10;
 
  @r1.t1= {0,200};
  @r1.t2= {0,100};
  @r2.t1= {0,100};
  @r2.t2= {0,0};
  @r3.t1= {0,100};
  @r3.t2= {100,100};
  @r4.t1= {100,200};
  @r4.t2= {100,100};
  @r5.t1= {100,100};
  @r5.t2= {100,0};
 
  //  draw network
    shape2d@ net= drawr(r1);
    @net = net +drawr(r2);
     @net = net +drawr(r3);
      @net = net +drawr(r4);
       @net = net +drawr(r5);
   
 shape2d@ obj = net;
   obj.write_xcsg(GetInputFullPath(),secant_tolerance:-1.0);
}
I've started by making the resistor components a standard size, and only allowing horizontal or vertical orientation. The small square marks the T1 end of the resistor. This will allow any network to be configured, using a resistor of zero ohms to act as a busbar, if necessary, allowing any number of connections to a 'star point' to be made. Once I've discovered how to rotate and move text  it could be tidied up a bit, but in the meantime, I can cout the results of calculations for each component. Probably it will need to do some verification, to ensure the connections are at the correct locations, but I may be even able to generate the locations given  just a list of connections.
3
General Discussion / text manipulation
« Last post by raymw on 2022-02-25, 16:17:30 »
Having looked at the 3d text sign example on git hub, I was thinking it would be straightforward to create 2d text
Code: [Select]
#include "aclib/fonts/LiberationSerif_Bold.as"

shape@ main_shape()
{
   
  array<string> name = { "text"};
       

   // Create font object used for text generation
   as_font@ font = LiberationSerif_Bold();
     shape2d@ txt2d = font.text(name,length:5);
     shape2d@ txtf= translate (20,20)*txt2d;
    return  txtf;
}

void main()
{
   shape@ obj = main_shape();
   obj.write_xcsg(GetInputFullPath(),secant_tolerance:-1.0);
}

However, I am unable to position the text other than bl at origin, and i would like to have a consistant height for the text (not length), which may involve finding the length of the string, which seems to be different than in c++.  (strlen() in c++). So, how do I set the height, and move the text around?
4
General Discussion / Re: drawing lines
« Last post by raymw on 2022-02-18, 20:54:11 »
Thanks. Having corrected my errors, line drawing is far to slow, using my method. I think that I will try to draw the components in my normal cad package, and import the dxf, if necessary. Each node and component will need labeling, and it is probably easier to do that outside of AngelCad, and then import the dxf, and use Angel ad to perform the calculations, and possibly write the results back to the dxf. I can't try it at the moment, the numerous electricity supply interruptions we've had today, has crashed my cad program, and it is asking for a registration code, but otherwise not responding.
5
General Discussion / Re: drawing lines
« Last post by Carsten Arnholm on 2022-02-18, 13:39:10 »
The code example below  will give you DXF

the abstract shape@ type cannot be used directly with transformations as per now.
for 2d work, use shape2d@
for 3d work, use solid@
https://arnholm.github.io/angelcad-docs/docs/classshape.html

so I changed your return types to shape2d@
I also used pos2d@ as parameters for the line

You can rotate 2d objects using rotate_z as you tried, but it must be used with shape2d@ or solid@ types


Code: [Select]
double rfd = PI/180;  //rads from degrees

shape2d@ horz(double leng)
{
   shape2d@ lin= translate (leng/2,0)*rectangle(leng,0.01,center:true);
   return lin;
}

shape2d@ aline(pos2d@ p1,pos2d@ p2)
{
   double len= p1.dist(p2);
   cout << "length " << len <<  endl;

   shape2d@ lin = horz(len);
   double ang = 45;
   cout <<  "angle " << ang  << endl;

   shape2d@ angled = rotate_z(deg:ang)*lin;  //  how to rotate 2d ?
   return angled;
}
 
void main()
{
   pos2d@ p1 = {1,1};
   pos2d@ p2 = {25,25};
   
   shape@ obj =  aline(p1,p2);  // should be 45 deg line from 1,1
   obj.write_xcsg(GetInputFullPath(),secant_tolerance:-1.0);
}


However, what you get from this is a DXF LWPOLYLINE describing a rectangular shape (as per your request), not a single DXF LINE. if you want a LWPOLYLINE describing some kind of path, you should instead build an array of points

Code: [Select]
array<pos2d@> points;
And when complete, construct a polygon from the points array and return it
https://arnholm.github.io/angelcad-docs/docs/classpolygon.html#a76801581a9e9430a55de55d3a0309522

a polygon2d is a shape2d and can be returned and used for generating a DXF.

Code: [Select]
shape2d@ somefunc(...)
{
    array<pos2d@> points;
    ... fill points
    return polygon(points);   
}

6
General Discussion / Re: drawing lines
« Last post by raymw on 2022-02-17, 23:41:00 »
I would prefer  dxf output, since I can annotate it in another program. I'm not getting much success, however.

This simple test works fine, wrt rotate.
Code: [Select]
shape@ main_shape()
{
  shape@ tt = rotate_z(45)*square(50);
return tt;
}

void main()
{
   shape@ obj = main_shape();
   obj.write_xcsg(GetInputFullPath(),secant_tolerance:-1.0);
}

However, having spent some time trying various options, then guesses, This fails at the rotate on line 19 - apart from the rotate it is OK, afaik.
Code: [Select]
double rfd = PI/180;  //rads from degrees

shape@ horz (double leng)
{
   shape@ lin= translate (leng/2,0)*rectangle(leng,0.01,center:true);
return lin;
}


shape@ aline(double p1x,double p1y,double p2x,double p2y)
{
 double len= sqrt(((p1x-p2x)*(p1x-p2x))+ ((p1y-p2y)*(p1y-p2y)));
          cout << "length " << len <<  "  ";
  shape@ lin = horz(len);
    double ang = sin(rfd*(p2y-p1y)/len);
          cout <<  " sin of angle " << ang/rfd ;
    shape@ angled = rotate_z(deg:ang)*lin;  //  how to rotate 2d ?
return angled;
}
 
void main()
{
      shape@ obj =  aline(1,1,25,25);  // should be 45 deg line from 1,1
      obj.write_xcsg(GetInputFullPath(),secant_tolerance:-1.0);
}


7
General Discussion / Re: drawing lines
« Last post by Carsten Arnholm on 2022-02-17, 17:11:03 »
A line2d is not a shape so that will not work
https://arnholm.github.io/angelcad-docs/docs/classline2d.html

A line2d is just a helper class. When you return something as a shape it must be one of the derivatives of shape
https://arnholm.github.io/angelcad-docs/docs/classshape.html

Note that both primitives and boolean operations return shape, either 2d or 3d

To "draw" something you need to use cylinder or cuboid.

8
General Discussion / drawing lines
« Last post by raymw on 2022-02-16, 22:19:21 »
stuck on producing lines in dxf
Code: [Select]
shape@ aline()
{
  shape@ ll= line2d(pos2d(1,2),pos2d(4,5));
return ll; 
 }
 
void main()
{
   shape@ obj = aline();
   obj.write_xcsg(GetInputFullPath(),secant_tolerance:-1.0);
}
Tried everything I can find, even tried a 'cast', but to no avail. The  AngelCAD sample: tutorial_primitives_2d.as does not include lines.
My intention is to be able to apply basic symbols/ text to dxf drawings of electrical circuits, for example.
9
General Discussion / Turtle graphics
« Last post by raymw on 2022-02-12, 19:33:31 »
I was around when Logo and turtle graphics were first popular, but more or less ignored them. Recently I saw a Utube video (numberphile) where it was explained hor turtle graphics could produce SierpiƄski Triangles, and I thought that maybe using AngelCAD could possibly do something similar but in 3d, for 3d printing. I've not used AngelCAD for sometime, and it is a struggle getting back into the flow, so to speak. I ran some simple tests, and decided that I would not be able to plot a meaningful triangle using my PC, in any reasonable amount of time.

However, with significant help from Carsten, I managed to produce something based loosely on turtle graphics, and I've put the code below. It sort of can print various patterned tubes, with or without a base. ( a vase, if you like), but if you water tight, you will need to adjust the various values. However, for the variables I've set, it fails after about 1250 iterations (i.e. in my code 'range' set to more than 1250) , however that may be a limitation in my particular PC. I started by generating a tube, then decided to add a base, and give a few other options, which can readily alter the appearance of the whole object. If the angle is not a factor of 360, then you will get a sort of spiral shape, as in the values I've shown. There are still a number of features that could be added - I've just added a print out of the approximate height, but with a bit of effort that could be more precisely calculated, and that value used to calculate 'range' .

Code: [Select]
double rfd = PI/180;  //rads from degrees

void settings (thing &out it)
{
    it.le = 20;  // length of rod
    it.w = 2;    // width of rod
    it.h = 2;    // height of rod
    it.rot = false; // rotate rods by 45 degree, to remove horizontal overhangs
    it.range = 1250;   // number of rods
    it.a = 50;    // angle between rods
    it.b = it.h/(360/it.a);  // vertical angle
    it.base = true; // false if base not needed
    it.round = false; // set to true if wanted rounded adges instead of square (diamete =w)
    it.blob = 0;  // diameter of blob at corners (0 to ignore)
   
    ////////////////////////////////////
    it.bang=0;
    it.cang=0;
return;

 
class thing
{
   double le, w, h, a, b, blob, bang, cang = 0;   
   int range = 0;
   bool base, round, rot = true;
}
   
solid@ part(thing it)
{       
           solid@ stroke = cuboid(it.le,it.w,it.h,false);
           
           if (it.rot == true)
           {
                 @stroke = rotate_x(rad:rfd*45)* stroke; // angle to make printable
           }
    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;
 
       @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 (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
                     }
           it.cang=it.cang+it.a;
              @now = last;
              @obj = obj+draw(it,now,last);
        count++;
      }       
           if (it.round==true)
           {
           @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);
              }
         // assume no overlap
              cout<< "aproximate height " << (it.range /(360/it.a))*it.h << endl;
      obj.write_xcsg(GetInputFullPath(),secant_tolerance:-1.0);
}

I've put the values you can change at the top of the program listing, in the settings function, but of course, you can do what you like with the rest of it. If you want to play with it, then set range to 590, to get a quick fstl, which will give you an idea of the patterns you can get.
10
General Discussion / Test post (please ignore)
« Last post by Carsten Arnholm on 2022-02-04, 17:12:16 »
Testing forum feature
Pages: [1] 2 3 ... 10