PlanetSquires Forums

Support Forums => General Board => Topic started by: raymw on August 17, 2020, 08:45:16 AM

Title: generating scripts
Post by: raymw on August 17, 2020, 08:45:16 AM
Hi, not able to think straight at the moment, too many conflicting ideas, so maybe someone can kick me in the right direction. I recently discovered openscad, and then a scripting language with a far smaller following - AngelCad. The limitation for the sort of thing I'm looking for, is that there is no gui, the end user has to go into the script and set variable values, etc. So, I thought, I can write a fb gui interface to let the user enter the value, then it pushes out the script. So, I have a script, it is a sort of c++ format, and thought it is small enough to be used as a basic string, simply cut and paste the script into my free basic program inside the double quotes. It doesn't work. I'm hoping I haven't got to manually enter each line withing quotes, mess aroundd with line endings, etc. It never ceases to amaze me at how quickly I can forget things, these days ;(

Here's the text I want as a string. The idea being that I'll use the fb gui to enter the values I want to change, in  the first 40 lines or so, then save it as a text file to run as the new script.
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   
   bool lidhole = false;
   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 =0;
// (x,y) position of standoffs
// if you add more standoffs, adjust number 'son', above.
   array<pos2d@ > stands  = {
     {6,6},
     {45,6},
     {6,39},
     {45,39}
     };
//shave is to give clearance for lid lip
//value of shave may depend on manufacturing method.   
  double shave=0.5;
 
//add corner radius to outside of box and lid 
  double corner =1.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
{
      if (son ==0)
   {
      return null;
   } 
   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;
       h.push_back(translate(xh,yh,0)*cuboid(hole,hole,100,true));
      }
   }
   // 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@ roundedges()
 {
        // get shape to be subtracted from edges
   shape2d@  prof= square(corner) - circle(corner);
    // extrude it to be longer than any box
   solid@ round = translate(-corner,-corner,0)*transform_extrude (prof,translate(0,0,1000)*prof);
    // do vertical edges
    solid@ edge1 = translate(-wall,-wall,-wall)*( rotate_z(180)*round);
    solid@ edge2 = translate(-wall,y+wall,-wall)*(rotate_z(90)*round);
    solid@ edge3 = translate (x+wall,y+wall,-wall)*(round);
    solid@ edge4 = translate (x+wall,-wall,-wall)*(rotate_z(270)*round);
return  edge1+edge2+edge3+edge4;
 }   
   
  solid@ roundbase()

 shape2d@  prof= square(corner) - circle(corner);
    // extrude it to be longer than any box
   solid@ round = translate(-corner,-corner,0)*transform_extrude (prof,translate(0,0,1000)*prof);
    //do bottom 
    solid@ roundx = rotate_y(90)*round;
    solid@ base1 = translate (-wall,-wall,-wall)*(rotate_x(270)*roundx);
    solid@ base2 = translate(-wall,y+wall,-wall)*roundx;
    solid@ roundy = rotate_x(270)*round;
    solid@ base3 = translate(-wall,-wall,-wall)*(rotate_y(90)*roundy);
    solid@ base4 = translate(x+wall,-wall,-wall)*roundy;
    return  base1+base2+base3+base4;
 }
 
 solid@ roundcorners()
 {// this crashes....
     // lets round of corners with a sphere
    solid@ cs = translate(-corner,-corner,+corner)*(rotate_y(90)*(cube(corner) - sphere(corner)));
    solid@ c1 = translate (-wall,-wall,-wall)* rotate_z(180)*cs;
    solid@ c2 = translate (-wall,y+wall,-wall)*rotate_z(90)*cs;
    solid@ c3 = translate (x+wall,y+wall,-wall)*cs;
    solid@ c4 = translate (x+wall,-wall,-wall)*(rotate_z(270)*cs);
    return  c1 +c2 +c3 +c4;
}

 solid@ trimbox() // subtracts corner round from all edges
 {
    if (corner == 0 )
    {
       return boxholed();
    }
return boxholed() - roundedges() - roundbase();
 }
 
 solid@ trimlid() //subtracts corners from around edges
 {
     if (corner == 0 )
    {
       return lidholed();
    }
return lidholed() - roundedges()- roundbase();
}
 
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=trimbox()+translate(0,y+3+wall+wall,0)*trimlid() +fix()+standoffs();
   
 both.write_xcsg(GetInputFullPath(),secant_tolerance:-1.0);
 stands.resize(0);
}


I want the above code embedded as a string in my freebasic program, I do not want to read it in at run time. So, any suggestions as to the best way of doing that - I know there  is a simple solution, but as I indicated, I'm somewhat befuddled.
Title: Re: generating scripts
Post by: Johan Klassen on August 17, 2020, 09:06:22 AM
try this this
Code: [Select]
dim as string AngelCAD
AngelCAD &= !"// AngelCAD code. \n"
AngelCAD &= !"//inside dimensions of box \n"
AngelCAD &= !"   double y= 45; \n"
' and so on
Title: Re: generating scripts
Post by: raymw on August 17, 2020, 01:29:13 PM
Thanks, it looks like I'll have to write some code to read in the original script file, then save it as a text file that is fb acceptable. I was hoping for something simpler, a 'magic character' that I no longer remembered that said 'treat everything after me as a string, until you hit another magic character' - a bit like /* */ for comments in c++. Maybe I'll try search and replace in notepad++, notepad++ searches OK on line endings.

Title: Re: generating scripts
Post by: raymw on August 17, 2020, 10:31:09 PM
I decided to write a small program, to read in the script file to a single string. It will be useful, at least to me, since it will be able to read in any ascii file to a string. The string can then be edited and saved. You need a form, with a couple of text boxes for the file names, a button to load the file, one to save, and a label to say you've saved it, if you want to use it. I read the file in once, print it to the console widow, to confirm it is the file I want, then read it again, and write it a line at a time. I've not bothered to tidy it up, nor with file extensions, etc, just quick and dirty to do a job. Thanks Johan, again
Code: [Select]
' frmMain form code file

' ========================================================================================
' WinFBE - FreeBASIC Editor (Windows 32/64 bit)
' Visual Designer auto generated project
' ========================================================================================

' Main application entry point.
' Place any additional global variables or #include files here.

' For your convenience, below are some of the most commonly used WinFBX library
' include files. Uncomment the files that you wish to use in the project or add
' additional ones. Refer to the WinFBX Framework Help documentation for information
' on how to use the various functions.

' #Include Once "Afx\AfxFile.inc"
' #Include Once "Afx\AfxStr.inc"
' #Include Once "Afx\AfxTime.inc"
' #Include Once "Afx\CIniFile.inc"
' #Include Once "Afx\CMoney.inc"
' #Include Once "Afx\CPrint.inc"
#include "string.bi"
 
 #include once "windows.bi"
 #include "afx\afxwin.inc"
 #include "afx\afxpath.inc"

Application.Run(frmMain)

 dim shared as string afile

function fileopener()as string
   
DIM wszFile AS WSTRING * 260 = "*.*"
DIM wszInitialDir AS STRING * 260 = CURDIR
DIM wszFilter AS WSTRING * 260 = "BAS files (*.BAS)|*.BAS|" & "All Files (*.*)|*.*|"
DIM dwFlags AS DWORD = OFN_EXPLORER OR OFN_FILEMUSTEXIST OR OFN_HIDEREADONLY OR OFN_ALLOWMULTISELECT
DIM cws AS CWSTR = AfxOpenFileDialog(null, "", wszFile, wszInitialDir, wszFilter, "BAS", @dwFlags, NULL)
'AfxMsg cws
return cws
   
end function

function filesaver()  as string
   DIM wszFile AS WSTRING * 260 = "*.*"
DIM wszInitialDir AS STRING * 260 = CURDIR
DIM wszFilter AS WSTRING * 260 = "cnc files (*.dnc)|*.dnc|" & "All Files (*.*)|*.*|"
DIM dwFlags AS DWORD = OFN_EXPLORER OR OFN_FILEMUSTEXIST OR OFN_HIDEREADONLY OR OFN_OVERWRITEPROMPT
DIM cws AS CWSTR = AfxSaveFileDialog(null, "", wszFile, wszInitialDir, wszFilter, "BAS", @dwFlags)
'AfxMsg cws

return cws   
end function


Function frmMain_Initialize( ByRef sender As wfxForm, ByRef e As EventArgs ) As LRESULT
   frmmain.label3.visible=false
   Function = 0
End Function

''
''
Function frmMain_Button1_Click( ByRef sender As wfxButton, ByRef e As EventArgs ) As LRESULT
               '' load in file
            dim nl as string
                nl=chr(13)+chr(10)
            dim inf as integer
            dim  kount as integer
            dim aline as string
    Frmmain.text1.text=fileopener()
    inf=freefile
    open Frmmain.text1.text for input  as #inf
   
   while not eof(inf)
         line input #inf,aline
         afile &= aline +nl
   wend

   close #inf     
        ? afile
          frmmain.label3.visible=false
     
   Function = 0
End Function

''
''
Function frmMain_Button2_Click( ByRef sender As wfxButton, ByRef e As EventArgs ) As LRESULT
   '' convert and save
        'write it line at a time like    astring &= !"//inside dimensions of box \n"

   dim as integer inf1
   dim as integer wrf
   dim aline as string
   dim bline as string
        frmmain.text2.text=filesaver()
       inf1=freefile
    open Frmmain.text1.text for input  as #inf1
       wrf=freefile
   open Frmmain.text2.text for output as  #wrf
     
     while not eof(inf1)
        line input #inf1,aline       
        bline=aline
        bline= "astring &= !"+chr(34) + aline +"\n"+chr(34)
 
        print #wrf,bline
       
     wend
         close #inf1
         close #wrf

      frmmain.label3.visible=true
     
   Function = 0
End Function

Title: Re: generating scripts
Post by: raymw on August 18, 2020, 01:52:08 PM
In the script shown previously, branching is sort of controlled by booleans. In the gui interface that I'm working towards, using winfbe, I'll be using checkboxes. Is the checkbox documentation correct, or rather I don't understand it. (It's not helped as it seems the code autocomplete is not working - it seems to start off ok in a project, then sort of fizzles out, as if it is getting fed up with what I'm attempting)
Anyway I can read if a check box is checked or not by frmmain.thebox.checkstate . The winfbe help says that checkstate gets or sets the state of the control. I am unable to set the state programmatically.  The checkbox state enum states
 Enum CheckBoxState     
   Checked = 1
   Unchecked
   Indeterminate
End Enum

But what exactly does that mean, is it that it can either be a 1, or something else? Or the 1, is that just a value in a single bit or byte used as shorthand for boolean true, or something else? In any case, what is the code to set it?
Thanks,
Ray
Title: Re: generating scripts
Post by: Johan Klassen on August 18, 2020, 03:29:47 PM
you should be able to set a checkbox like this for example
Code: [Select]
frmMain.yourCheckBox.CheckState = unchecked
Title: Re: generating scripts
Post by: raymw on August 18, 2020, 04:01:01 PM
Thanks, Johan... again  :)     
Title: Re: generating scripts
Post by: Paul Squires on August 18, 2020, 06:21:49 PM
Code: [Select]
Enum CheckBoxState     
   Checked = 1
   Unchecked
   Indeterminate
End Enum

Equates to:

CheckBoxState.Checked = 1
CheckBoxState..Unchecked = 2
CheckBoxState.Indeterminate = 3
Title: Re: generating scripts
Post by: philbar on August 18, 2020, 08:25:43 PM
Ray, I have a suggestion for when your dropdowns don't. Save your work and reload the whole project from the Project/Recent Projects menu. For me, that refreshes the dropdowns until the next time I do a test compile. Then, when I come back to the editor, the dropdowns fizzle again until the next reload.
Title: Re: generating scripts
Post by: raymw on August 19, 2020, 05:13:41 PM
Well after too many cups of coffee, I've now got it working. If anyone is into 3d printing, or cnc milling component (or other smallish) boxes, then Let me know. I'll post the exe, or the basic code (but if I give you the code you'll need explanations, 'cos of the rat's nest) and you'll have to get hold of AngelCad, from GitHub. If one of you does that, that'll make about three of us.