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.
// 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.
try this this
dim as string AngelCAD
AngelCAD &= !"// AngelCAD code. \n"
AngelCAD &= !"//inside dimensions of box \n"
AngelCAD &= !" double y= 45; \n"
' and so on
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.
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
' 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
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
you should be able to set a checkbox like this for example
frmMain.yourCheckBox.CheckState = unchecked
Thanks, Johan... again :)
Enum CheckBoxState
Checked = 1
Unchecked
Indeterminate
End Enum
Equates to:
CheckBoxState.Checked = 1
CheckBoxState..Unchecked = 2
CheckBoxState.Indeterminate = 3
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.
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.