From 73fa334d7fa54eaeecd60616a67f1019e4c32672 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9A=D0=BE=D0=B1=D0=B5=D0=BB=D0=B5=D0=B2=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B4=D1=80=D0=B5=D0=B9=20=D0=90=D0=BD=D0=B4=D1=80=D0=B5=D0=B5?= =?UTF-8?q?=D0=B2=D0=B8=D1=87?= Date: Mon, 9 Dec 2024 14:54:10 +0300 Subject: [PATCH] add handle and cup --- .gitignore | 2 + lib/ub.scad | 17363 ++++++++++++++++++++++++------------ models/candle/candle.scad | 153 +- models/cup/cup.scad | 46 +- models/cup/cup.stl | Bin 133084 -> 0 bytes models/cup/handle.scad | 35 + models/cup/tube.scad | 7 + 7 files changed, 11874 insertions(+), 5732 deletions(-) delete mode 100644 models/cup/cup.stl create mode 100644 models/cup/handle.scad create mode 100644 models/cup/tube.scad diff --git a/.gitignore b/.gitignore index 3f27ea8..42f8b22 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,5 @@ lib/bosl lib/dotSCAD-3.3 .DS_Store +*.stl +lib/ub.scad diff --git a/lib/ub.scad b/lib/ub.scad index db5113e..a1260fa 100644 --- a/lib/ub.scad +++ b/lib/ub.scad @@ -1,108 +1,178 @@ +// works from OpenSCAD version 2024 or higher maintained at https://github.com/UBaer21/UB.scad -//works from OpenSCAD version 2021 maintained at https://github.com/UBaer21/UB.scad - -/* save here +/* Infos + save here • Windows: ..\Documents\OpenSCAD\libraries • Linux: $HOME/.local/share/OpenSCAD/libraries/ • Mac OS X: $HOME/Documents/OpenSCAD/libraries/ +*/ +/** \mainpage + * ##Open SCAD library www.openscad.org + * **Author:** ulrich.baer+UBscad@gmail.com (mail me if you need help - i am happy to assist) -Open SCAD library www.openscad.org by ulrich.baer+openscad@gmail.com (mail me if you need help - i am happy to assist) Copy this file into your libaries directory (File » show Libraries) [https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Libraries] -Use it by starting your project with including the library. -All needed Information will be displayed in your console window, you may need to make that bigger. + +## Use it by starting your project with including the library. +## All needed Information will be displayed in your console window, you may need to make that bigger. + Write: include; [https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Include_Statement] -name="my project"; // the name will never be rendered -helpsw=1; // switch to show the information (1-5 or true) -$info=1; // switch to get feedback/info from objects -helpM=1; // switch to get help for used objects -nozzle=.4; // set your printers nozzle diameter -layer=.2; // set your layerhigh -show=2; // will show you Object n (any number) from this library -anima=1; // activate animation variables else "tset=.5" can be used -vp=1; // switch fixed Viewports -bed=true // Print bed active (centers vp printPos) -name="object"; // used in modules for showing name or number - if 0 no info is shown + \param name= "my project"; The name will never be rendered + \param helpsw=true Switch to show the information (1-5 or true) + \param $info=true; Switch to get feedback/info from objects + \param helpM=true; Switch to get help for used objects + \param nozzle=.4; Set your printers nozzle diameter + \param layer=.2; Set your layerhigh + \param show=2; Will show you Object n (any number) from this library + \param anima=1; Activate animation variables else "tset=.5" can be used + \param vp=1; Switch fixed Viewports + \param bed=true Print bed active (centers vp printPos) + \param name="object"; Used in modules for showing name or number - if 0 no info is shown Changelog (archive at the very bottom) -000|22 prepare release CHG VarioFill -001|22 CHG MKlon -002|22 CHG Line -004|22 FIX Gewinde CHG Vollwelle CHG Caliper CHG GewindeV3 -005|22 CHG Gewinde -006|22 CHG Anschluss FIX Zylinder -007|22 FIX Ellipse CHG Points ADD PolyH -008|22 FIX Ttorus CHG PolyH CHG RotLang -009|22 CHG Points add center CHG kreis add z CHG quad add z -011|22 FIX Box Prisma FIX Gewinde -012|22 CHG Rosette Add id od FIX spelling help CHG Anorden (fix for 2021.1) -0121|22 FIX Anordnen FIX SRing FIX Knochen -013|22 CHG Rosette autocalc -015|22 FIX Gewinde -016|22 CHG RingSeg FIX Kassette help CHG Superellipse -019|22 CHG Schnitt size -020|22 CHG KBS CHG Prisma CHG Box CHG Pille -021|22 CHG Pille FIX m chg v3 chg stern CHG Buchtung CHG Schnitt size -022|22 CHG Kassette ADD pathPoints CHG kreis ADD Coil ADD wStern CHG vektorWinkel CHG Halb CHG Superellipse CHG Glied ADD SGlied CHG Prisma ADD Tdrop CHG Bezier -Release - - +000|23 FIX Grid UPD vMult UPD Pin +002|23 UPD Prisma UPD WStern UPD Kreis UPD Bogen FIX Rand +004|23 UPD Cycloid Fix Roof UPD kreis Fix Quad +006|23 UPD Arc UPD Pin FIX Linse +008|23 UPD VorterantQ Vorterantrotor UPD Reuleaux UPD Roof FIX Gewinde +010|23 ADD Tesselation FIX CyclGear UPD Twins UPD Linse CHG Pin UPD Halbrund +020|23 CHG Linse CHG Pin UPD Tri CHG Bitaufnahme UPD PrevPos +024|23 UPD vollwelle, UPD Vollwelle, UPD Arc UPD menu UPD Kegelmantel UPD Kegel +040|23 UPD Pin UPD Kegel UPD Welle UPD Grid UPD HexGrid +050|23 CHG Kehle CHG RotEx FIX Prisma UPD HexGrid CHG Vollwelle CHG LinEx UPD Kegel +055|23 UPD kreis UPD polyRund upd SWelle upd PolyRund CHG Coil CHG pathPoints CHG Bezier +060|23 CHG quad CHG printPos upd Schnitt chg Gewinde +070|23 ADD Connector FIX Welle +080|23 UPD Glied FIX Kehle FIX Gewinde UPD arc UPD Connector FIX Welle +090|23 ADD QuadAnschluss upd Gewinde +100|23 CHG Vollwelle UPD QuadAnschluss CHG Connector +110|23 CHG Bogen CHG QuadAncshluss CHG Cut CHG Loch CHG Kehle +120|23 UPD QuadAnschluss FIX Torus UPD Coil CHG SRing CHG kreis ADD FlatMesh +130|23 CHG FlatMesh FIX GewindeV2 UPD Gewinde chg viewportsize UPD Points +140|23 CHG Ring CHG Riemen UPD riemen CHG Tri CHG Tri90 FIX Gewinde UPD SBogen +150|23 CHG SBogen CHG Kegel FIX Bezier chg fa UPD Anschluss UPD Welle UPD M +160|23 UPD Pille UPD Connector CHG DPfeil UPD Kreis kreis +180|23 UPD kreis FIX Text FIX kreis UPD SBogen UPD RotEx FIX Pille +190|23 CHG Points ADD sternDeg ADD SternDeg UPD Rund +200|23 UPD SternDeg UPD nut UPD Gewinde UPD octa FIX SGlied UPD KnurlTri +210|23 ADD bool UPD Knurl UPD Text ADD FlatKnurl UPD FlatMesh CHG Tesselation UPD Roof +220|23 UPD distS UPD Kehle ADD Penrose ADD RectTiling CHG Ellipse UPD Filter UPD Caliper +230|23 CHG Caliper UPD Rohr UPD Bogen UPD QuadAnschluss ADD vMin vMax vAdd UPD Torus +240|23 FIX QuadAnschluss CHG WaveEX UPD Polar CHG Isosphere UPD WKreis +250|23 FIX GewindeV4 FIX kreis FIX vollwelle CHG Filter FIX Loch +260|23 FIX Gewinde UPD Pfeil CHG CyclGear ADD Rod UPD Ring UPD Coil UPD SWelle +270|23 FIX Pille UPD Kegel UPD Pille UPD Anschluss UPD SBogen FIX GewindeV4 ADD radiusSH +275|23 UPD QuadAnschluss ADD transition CHG $fn UPD Ccube UPD Arc UPD Involute UPD involute +280|23 UPD Torus CHG transition CHG Gardena FIX Rod CHG Gewinde Fix Text FIX WStern UPD HexGrid +285|23 UPD HexGrid UPD Text Fix kreis UPD Kreis Fix Kegel UPD VorterantQ FIX Vorterantrotor +290|23 FIX Roof FIX Kegel UPD Balg UPD RotEx UPD Involute UPD Connector UPD Kehle FIX Loch +305|23 FIX HexGrid UPD Kegel FIX CycloidZahn FIX Roof FIX Kehle CHG Bogen FIX Rohr ADD CGear +310|23 UPD Caliper ADD CZahn UPD Rohr UPD Gewinde ADD vorterantQ() UPD Gewinde +320|23 UPD Kreis UPD GewindeV4 UPD QuadAnschluss FIX Cycloid FIX Rod +325|23 UPD Tdrop CHG CGear +330|23 UPD Cycloid CHG CGear UPD Kegel CHG gradS UPD Loch FIX kreis FIX LinEx UPD Roof +340|23 ADD triUmkreis ADD triInkreis UPD Switches ADD Voronoi +022|24 CHG Prisma CHG Rund CHG Halb FIX Gewinde UPD Voronoi +040|24 FIX Halb UPD Linear UPD BB UPD Welle UPD Kegel UPD Glied +055|24 UPD Glied UPD Loch UPD Rod UPD transition UPD Linse UPD Pille FIX Gewinde +100|24 UPD TDrop UPD Gewinde UPD QuadAnschluss UPD Superellipse UPD vollwelle FIX Spirale +110|24 UPD bend UPD sq UPD Kegel UPD Knurl FIX Quad UPD Text UPD FlatMesh FIX Cring +131|24 FIX Zylinder CHG Gewinde CHG Row FIX Loch +140|24 FIX Anschluss CHG CGear add deg2 FIX Loch FIX Rohr FIX Quadanschluss UPD CycloidZahn +150|24 UPD Coil UPD Tesselation +160|24 FIX Loch UPD Ccube ADD center() FIX Text(); UPD string2Num FIX CGear FIX Quad +170|24 UPD Torus FIX SpiralCut UPD Coil UPD Voronoi +180|24 UPD Vollwelle UPD Pille UPD Roof UPD Linse FIX fs2fn UPD Klon FIX clampToX0 +190|24 FIX Grid UPD Tesselation UPD Gewinde FIX Knurl +200|24 UPD KnurlTri FIX GewindeV4 FIX clampToX0 UPD Loch UPD Star UPD bed CHG ARC +210|24 UPD Strebe UPD WStrebe ADD Bayonet UPD Quad UPD Klammer UPD QuadAnschluss +220|24 UPD version() assert FIX Kegel UPD Bayonet UPD inkreis() UPD umkreis() UPD HexGrid +230|24 UPD Vollwelle UPD Rundrum UPD kathete UPD QuadAnschluss FIX Filter +240|24 UPD kreis UPD polyRund ADD Select CHG Bayonet +250|24 UPD Quad UPD Polar UPD Bayonet +260|24 UPD quad UPD Pille UPD LinEx UPD Strebe UPD Glied UPD DGlied CHG Torus UPD WKreis +270|24 FIX Rod UPD PolyH */ -//libraries direkt (program folder\oscad\libaries) ! +{//fold // Constants + + +// libraries direkt (program folder\oscad\libaries) ! /*[UB lib]*/ test=42; +designVersion=0; /*[Global]*/ -helpsw=false;//activates help in console window -//animation -anima=false; -// use print Bed as center and show boarder -bed=false; +/// activates help in console window +helpsw=false; + +/// activates menu +menu=true; + +/// animation switch +anima=false; + +/// use print Bed as center and show boarder +bed=false; + +/// switch for customizer +info=true; -info=true; // switch for customizer debug=$preview?anima?false:info:false; -$info=debug;//activates module information (name) -//viewpoint +/// activates module information (name) +$info=debug; +/// viewpoint //vp=false; vp=$preview?false:true; -//Project name +/// Project name name=undef; -//Düsen ∅ -nozzle=0.6; +/// Düsen ∅ +nozzle=0.4; +/// Area of nozzle +nozArea=(nozzle/2)^2*PI; +/// print line width +line=nozzle; -//Layer hight +/// Layer hight layer=0.08;// one step = 0.04 (8mm/200steps) -//Print Bed -printBed=[220,220]; -//Printposition; -pPos=[0,0]; -printPos=bed?concat(printBed,0)/2+pPos:[0,0,0]; -//global fragment size +/// Layer line Area +lineProfile=PI*(layer/2)^2+ (line-layer)*layer; + +/// Print Bed size +printBed=is_num(bed)?bed*[1,1]:is_list(bed)?bed:[220,220]; +/// Printposition; +pPos=[0,0,0]; +printPos=bed?concat(printBed,0)/2+v3(pPos):v3(pPos); + +/// render with Hires hires=false; fn=$fn?$fn:$preview?36: hires?144: 72; -fs=$preview?1.25:hires?.4:.75; -fa=$preview?5:hires?.5:1; -//demo objects +fs=$preview?.75:hires?.1:.2; +fa=$preview?10:hires?.5:1; + + +/// demo objects show=0; -//animation var +/// animation var tset=0;//[0:.01:1] -//clearance +/// clearance spiel=0.20; +pip=0.35; pivotSize=$vpd/15; -viewportSize=$preview?tan($vpf)*$vpd:50000; // größe Sichtfeld +/// size viewport +viewportSize=$preview?tan($vpf)*$vpd:1000; vpt=is_num(printPos.z)?printPos:concat(printPos,0); vpr=bed?[55.00,0.00,25.00]:$vpr; @@ -110,38 +180,141 @@ vpd=bed?300:$vpd;//[50:5:350] vpf=22.5; -//display project name -texton=name!=undef?$preview?true:false:false; +/// display project name +texton=name!=undef&&name!=""?$preview?true:false:false; -// Colors +/// Colors (version 2019) helpMColor="";//"#5500aa"; /*[Constant]*/ /*[Hidden]*/ -Version=22.022;// <<< --- VERSION VERSION VERSION •••••••••••••••• +Version=24.260;// <<< --- VERSION VERSION VERSION •••••••••••••••• useVersion=undef; UB=true; -PHI=1.6180339887498948;//1.618033988; -gw=360-360/PHI;// goldener Winkel; -tw=acos(-1/3);// tetraeder winkel; -twF=acos(1/3);// tetraeder winkel face edge face; -inch=25.4; // inch/Zoll +PHI=1.6180339887498948;/// golden ratio 1.618033988; +gw=360-360/PHI;/// goldener Winkel; +tw=acos(-1/3);/// tetraeder winkel; +twF=acos(1/3);/// tetraeder winkel face edge face; +inch=25.4; /// inch/Zoll minVal=0.0000001; // minimum für nicht 0 -needs2D=["Rand","WKreis","Welle","Rund","Rundrum", "LinEx", "RotEx","SBogen","Bogen","HypKehle"]; // modules needing 2D children +needs2D=["Rand","WKreis","Welle","Rund","Rundrum", "LinEx", "RotEx","SBogen","Bogen","HypKehle","Roof"]; /// modules needing 2D children //echo(tw,twF); //PHI=(1+sqrt(5))/2; -assert(useVersion?Version>=useVersion:true,str("lib version ",Version," detected, install ",useVersion," ub.scad library‼ ⇒http://v.gd/ubaer")); -assert(version()[0]>2019,"Install current http://openscad.org version"); -function l(x)=x*layer; -function n(x)=sign(x)*(abs(x)*nozzle+0.015);// 0.015 padding for slicer +}//fold // end constants ΔΔ + +assert(useVersion?Version>=useVersion:true,str("lib version ",Version," detected, install ",useVersion," ub.scad library‼ ⇒http://v.gd/ubaer")); +assert(version()[0]>2023,"Please install current http://openscad.org/downloads#snapshots version"); + +{//fold // \∇∇ functions ∇∇/ + + +/** \page functions \name center +\brief center() creates a v3 list to center objects (vMult size/2) where true is 0 +\param center input center +*/ +/// return v3 for center where true is [0,0,0] + + +function center(center=false)=is_list(center)?v3(center) + :center?[0,0,0] + :[1,1,1]; + + +function l(x=1,layer=layer)=x*layer; +function layer(x=1,layer=layer)=x*layer; + +function n(x=1,nozzle=nozzle)=sign(x)*(abs(x)*nozzle + 0.05*nozzle); /*(x==1?0.05*nozzle: + - layer*(1-PI/4) * (x-1)*0)); 0.05*nozzle padding for slicer */ + +function line(n=1,line=line,nozzle=nozzle)=sign(n)*(abs(n)*line + 0.05*nozzle); + +function testPoly(s=10)=[ +[0,0], +[s,0], +[s,s], +[s/2,s/2], +[0,s] +]; + +/** \page Functions \name triUmkreis +\brief triUmkreis() will give the center [x,y] of the circle containing 3 points +\param points points [[a],[b],[c]] +*/ +function triUmkreis(points=[[0,0],[0,10],[10,0]])= +let( + a=points[0],b=points[1],c=points[2], + d= 2* ( a.x * (b.y-c.y) + b.x * (c.y-a.y) + c.x * (a.y-b.y) ) +) + +[ ((a.x^2+a.y^2) * (b.y-c.y) + (b.x^2+b.y^2) * (c.y-a.y) + (c.x^2+c.y^2) * (a.y-b.y) )/d, + ((a.x^2+a.y^2) * (c.x-b.x) + (b.x^2+b.y^2) * (a.x-c.x) + (c.x^2+c.y^2) * (b.x-a.x) )/d, +]; + +/** \page Functions \name triInkreis +\brief triInkreis() will give the center [x,y] of the inscribed circle +\param points points [[a],[b],[c]] +*/ +function triInkreis(points=[[0,0],[0,10],[10,0]])= +let( +a=points[0],b=points[1],c=points[2], // points abc +sA=norm(c-b), sB=norm(c-a), sC=norm(b-a), //side length +u=sA+sB+sC// circumference +) +[ (sA*a.x+sB*b.x+sC*c.x)/u , (sA*a.y+sB*b.y+sC*c.y)/u ]; + +/* +T(triUmkreis())Rand(.1)circle(norm(triUmkreis())); +T(triInkreis())circle(triInkreis().y); +#polygon([[0,0],[0,10],[10,0]]); +//*/ + function Inkreis(eck,rU)=cos(180/eck)*rU; -function Umkreis(eck,rI)=rI/cos(180/eck); +function inkreis(eck,rU)=assert(is_num(eck)&&is_num(rU),str("inkreis() input need to be numbers rU=",rU," eck=",eck) )cos(180/eck)*rU; + +function Umkreis(eck,rI,name)=let(r=rI/cos(180/eck))is_undef(name)?r:echo(str(name," Umkreis=",r))r; +function umkreis(eck,rI,name)=let(r=assert(is_num(eck)&&is_num(rI),str("umkreis() input need to be numbers rI=",rI," eck=",eck))rI/cos(180/eck))is_undef(name)?r:echo(str(name," Umkreis=",r))r; + function Hypotenuse(a,b)=sqrt(pow(a,2)+pow(b,2)); +function hypotenuse(a,b)=sqrt(pow(a,2)+pow(b,2)); function Kathete(hyp,kat)=sqrt(pow(hyp,2)-pow(kat,2)); -function Sehne(n,r,a)=is_undef(a)?2*r*sin(180/n):2*r*sin(a/2);// n-eck oder a=α winkel zum r=radius +function kathete(hyp,kat)=assert(hyp>=kat,"hypotenuse first kathete(hyp,kat))")sqrt(hyp^2-kat^2); + +/** \page Functions \name vMax +vMax gives you the max of a number and a list +\param v vector or list +\param max max limiting value +*/ + +function vMax(v=[0],max=0)=[for(i=v)max(max, i) ]; +/** \page Functions \name vMin +vMin gives you the min of a number and a list +\param v vector or list +\param min min limiting value +*/ + +function vMin(v=[0],min=0)=[for(i=v)min(min, i) ]; + +/** \page Functions \name vAdd +vAdd gives you the addition of a number with a vector/list constituents +\param v vector or list +\param add added value +*/ + +function vAdd(v=[0],add=0)=[for(i=v) add + i ]; + + +/** \page Functions +Sehne() gives you the length of a chord +\param n n-gon +\param r radius +\param a,deg degree optional to n +*/ + +function Sehne(n,r,a,deg)=let(a=is_num(deg)?deg:a)is_undef(a)?2*r*sin(180/n):2*r*sin(a/2);// n-eck oder a=α winkel zum r=radius +function sehne(n,r,a)=is_undef(a)?2*r*sin(180/n):2*r*sin(a/2);// n-eck oder a=α winkel zum r=radius function t3(wert=1,grad=360,delta=0)=sin(($preview?anima?$t:tset:tset)*grad+delta)*wert; function RotLang(rot=0,l=10,l2,z,e,lz)=let( rot=is_undef(rot)?0:rot%360, @@ -149,20 +322,51 @@ l=is_undef(l)?0:l, l2=is_undef(l2)?l:l2, lz=is_undef(lz)?l:lz ) -is_undef(z)?is_undef(e)?[sin(rot)*l,cos(rot)*l2]:[sin(rot)*cos(e%360)*l,cos(rot)*cos(e%360)*l2,sin(e%360)*lz]:[sin(rot)*l,cos(rot)*l,z]; +is_undef(z)?is_undef(e)?[sin(rot)*l,cos(rot)*l2]: + [sin(rot)*cos(e%360)*l,cos(rot)*cos(e%360)*l2,sin(e%360)*lz]: + [sin(rot)*l,cos(rot)*l,z]; function Bezier(t,p0=[0,0],p1=[-20,20],p2=[20,20],p3=[0,0])=bezier(t,p0,p1,p2,p3); -function bezier(t,p0=[0,0],p1=[-20,20],p2=[20,20],p3=[0,0])= +function bezier(t,p0=[0,0],p1=[-20,20],p2=[20,20],p3=[0,0],p)= let( omt = 1 - t, omt2 = omt * omt, t2 = t * t ) -p0*(omt2*omt) + p1*(3*omt2*t) + p2*(3*omt*t2) + p3*(t2*t); +is_list(p)?p[0]*(omt2*omt) + p[1]*(3*omt2*t) + p[2]*(3*omt*t2) + p[3]*(t2*t): + p0*(omt2*omt) + p1*(3*omt2*t) + p2*(3*omt*t2) + p3*(t2*t); + +/** \page Functions \name kreis +kreis() generates points on a circle or arc +\param r radius +\param rand dist second radius +\param grad angle +\param grad2 angle second arc +\param fn fragments + +\param center center angle +\param sek chord or center point +\param r2 y component +\param rand2 y component +\param rot rotate points +\param t translate points +\param z z value for polyhedron +\param d ovewrite radius with diameter +\param endPoint end angle with point +\param fs fragment size +\param fs2 fragment size second arc +\param fn2 fragments second arc +\param minF minimum fragments +*/ function Kreis(r=10,rand=+5,grad=360,grad2,fn=fn,center=true,sek=true,r2=0,rand2,rcenter=0,rot=0,t=[0,0])=kreis(r,rand,grad,grad2,fn,center,sek,r2,rand2,rcenter,rot,t); -function kreis(r=10,rand=+5,grad=360,grad2,fn=fn,center=true,sek=true,r2=0,rand2,rcenter=0,rot=0,t=[0,0],z,d)= + + + +function kreis(r=10,rand=+5,grad=360,grad2,fn=fn,center=true,sek=true,r2=0,rand2,rcenter=0,rot=0,t=[0,0],z,d,endPoint=true,fs=fs,fs2,fn2,minF=1,fa=fa)= let ( +fa=is_undef(fa)?1:fa, +minF=bool(minF,bool=false), grad2=is_undef(grad2)?grad:grad2, r=is_num(d)?rcenter?(d+rand)/2:d/2: rcenter?r+rand/2:r, @@ -170,35 +374,51 @@ rand2=is_undef(rand2)?rand:rand2, r2=r2? rcenter?r2+rand2/2:r2 :r, -fn=max(1,floor(abs(fn))), -step=grad/fn, -step2=grad2/fn +ifn=is_num(fn)&&fn>0?max(1,ceil(abs(fn))) + :min(max(abs(grad)<180?1 + :abs(grad)==360?3 + :2,ceil(abs(PI*r*2/360*grad/max(fs,0.001))),minF),ceil(abs(grad)/fa) ), +fs2=is_undef(fs2)?fs:fs2, + +fn2=is_num(fn)&&fn>0?is_undef(fn2)?ifn:max(1,ceil(abs(fn2))) + :min(max(abs(grad2)<180?1:abs(grad2)==360?3:2,ceil(abs(PI*(r-rand)*2/360*grad2/max(fs2,0.001))),minF),ceil(grad/fa)), + +step=grad/ifn, +step2=grad2/fn2, +t=is_list(t)?t:[t,0], +endPoint=rand?true:endPoint ) is_num(z)?[ if(!sek&&!rand&&abs(grad)!=360&&grad)[0+t[0],0+t[1],z], // single points replacement -if(grad)for(i=[0:fn]) - let(iw=abs(grad)==360?i%fn:i) +if(grad==0&&minF)for([0:minF])[sin(rot+(center?-grad/2-90:0))*r +t[0], + cos(rot+(center?-grad/2-90:0))*r2 +t[1], + z], +if(grad)for(i=[0:endPoint?ifn:ifn-1]) + let(iw=abs(grad)==360?i%ifn:i) [sin(rot+(center?-grad/2-90:0)+iw*step)*r +t[0], cos(rot+(center?-grad/2-90:0)+iw*step)*r2 +t[1], z], -if(rand)for(i=[0:fn]) - let(iw=abs(grad2)==360?i%fn:i) +if(rand)for(i=[0:endPoint?fn2:fn2 -1]) + let(iw=abs(grad2)==360?i%fn2:i) [sin(rot+(center?grad2/2-90:grad2)+iw*-step2)*(r -rand )+t[0], cos(rot+(center?grad2/2-90:grad2)+iw*-step2)*(r2 -rand2)+t[1], z] ]: -[ +[ // if 2D if(!sek&&!rand&&abs(grad)!=360&&grad||r==0)[0+t[0],0+t[1]], // single points replacement -if(r&&grad)for(i=[0:fn]) - let(iw=abs(grad)==360?i%fn:i) +if(r&&grad)for(i=[0:endPoint?ifn:ifn-1]) + let(iw=abs(grad)==360?i%ifn:i) [sin(rot+(center?-grad/2-90:0)+iw*step)*r+t[0], cos(rot+(center?-grad/2-90:0)+iw*step)*r2+t[1]], -if(rand)for(i=[0:fn]) - let(iw=abs(grad2)==360?i%fn:i) +if(grad==0&&minF)for([0:minF])[sin(rot+(center?-grad/2-90:0))*r +t[0], + cos(rot+(center?-grad/2-90:0))*r2 +t[1]], +if(rand)for(i=[0:endPoint?fn2:fn2-1]) + let(iw=abs(grad2)==360?i%fn2:i) [sin(rot+(center?grad2/2-90:grad2)+iw*-step2)*(r-rand)+t[0], cos(rot+(center?grad2/2-90:grad2)+iw*-step2)*(r2-rand2)+t[1]] ]; + //PolyH([for(i=[0:100])each kreis(z=i/10,r=5+sin(i*3.6)*2)],loop=fn +fn+2); function kreisXY(r=5,grad=0)=[r*sin(grad),r*cos(grad)];//depreciated use RotLang @@ -209,10 +429,18 @@ function 5gon(b1=20,l1=15,b2=10,l2=30)=[[0,0],[b1,l1],[b2,l2],[-b2,l2],[-b1,l1]] function ZigZag(e=5,x=50,y=5,mod=2,delta=+0,base=2,shift=0)=zigZag(e,x,y,mod,delta,base,shift); function zigZag(e=5,x=50,y=5,mod=2,delta=+0,base=2,shift=0)=[for(i=[0:e*mod])[i%modabs(2*r)&&(is_undef($idx)||!$idx)?echo("\t⭕ ‼ gradS s > diameter (2×r) max ❗")180*sign(s)*sign(r) + :abs(s)>abs(2*r)?180*sign(s)*sign(r) + :asin(s/(2*r))*2;// winkel zur Sehne s des Kreisradiuses r + +/// radius of the circle that has chord s +/** +\param s length of the chord +\param n for a n-polygon +\param a if you have the angle +*/ +// Radius zur Sehne +function radiusS(s,n,a,r)=(s/2)/(sin((is_undef(n)? is_undef(a)?gradS(s,r) + :a + :360/n)/2)); + + +/// circumcircle radius for triange s=chord h=height +/** \name radiusSH \page functions +\param s chord +\param h height +*/ +function radiusSH(s,h)=((s/2)^2+h^2)/(2*h); + +/// distance chord s to center +function distS(s,r,n,a)=kathete(radiusS(s,n,a,r),s/2);//cos(gradS(s,r)/2)*r; + function runden(x,dec=2)=round(x*pow(10,dec))/pow(10,dec);//auf komastelle runden -//convert angle -function grad(grad=0,min=0,sec=0,h=0,prozent=0,gon=0,rad=0)=gradC(grad,min,sec,h,prozent,gon,rad); // compatibility as renamed gradC + +//convert angle ↦ gradC +function grad(grad=0,min=0,sec=0,h=0,prozent=0,gon=0,rad=0)=gradC(grad,min,sec,h,prozent,gon,rad);// compatibility as renamed gradC function gradC(grad=0,min=0,sec=0,h=0,prozent=0,gon=0,rad=0)=grad+h/24*360+min/60+sec/3600+atan(prozent/100)+gon/400*360+rad/(2*PI)*360; -function inch(inch)=inch*25.4; +function inch(inch=1)=inch*25.4; function kreisbogen(r,grad=360)=PI*r*2/360*grad; -function fs2fn(r,grad=360,fs=fs,minf=3)=max(minf,PI*r*2/360*grad/fs); -function clampToX0(points,interval=minVal)=is_list(points[0])?[for(e=points)[abs(e[0])>interval?e[0]:0,e[1]]]: - [abs(points[0])>interval?points[0]:0,points[1]]; +/// calculationg fragment number from fraqment size +function fs2fn(r,grad=360,fs=fs,minf=3,fa=fa)= + let( + fs=max(is_undef(fs)?$fs:fs,0.001), + fa=is_undef(fa)?$fa:fa, + minf=r&&grad?minf:0 + ) + ceil( + min( + max( + minf, + assert(is_num(r)&&is_num(grad)&&fs,str("fs2fn uses r=",r,", grad=",grad," ,fs=",fs))PI*abs(r)*2/360*abs(grad) / fs + ), + max(minf,1 / fa * abs(grad)) + ) + ); + +function clampToX0(points,interval=1e-12)=is_list(points[0])?[for(e=points)[abs(e[0])>interval?e[0]:0,e[1]]]: + [abs(points[0])>interval?points[0]:0,points[1]]; + + + // angle between two points used for e.g. Bezier - vektorWinkel= function(p1=[0,0,0],p2=[0,0,0])p1==p2?[0,0,0]:[ - - -acos((v3(p2).z-v3(p1).z)/norm(p2-p1))+90, + vektorWinkel= function(p1=[0,0,0],p2=[0,0,0]) + let(p1=v3(p1),p2=v3(p2)) + + p1==p2?[0,0,0]:[ + -acos((p2.z-p1.z)/norm(p2-p1))+90, 0, atan2(p2.y-p1.y,p2.x-p1.x)-90 ]; -function v3( v ) =is_num(v.y)?is_num(v.z)?len(v)==3?v: // make everything to a vector3 - [v.x,v.y,v.z]: + + + +function v3(v)= [ +is_num(v.x)?v.x:is_num(v)?v:0, +is_num(v.y)?v.y:0, +is_num(v.z)?v.z:0, + ]; + + +/* org +function v3org( v ) = + is_num(v.y)?is_num(v.z)?len(v)==3?v: // make everything to a vector3 + [v.x,v.y,v.z]: // shorten if len >3 concat(v,[0]): concat(v,[0,0]); + + + v=[1,undef,"a",2]; + echo(v3(v),v3org(v)); +// */ + + + + + + // list of parent modules [["name",id]] function parentList(n=-1,start=1)= is_undef($parent_modules)||$parent_modules==start?undef:[for(i=[start:$parent_modules +n])[parent_module(i),i]]; @@ -293,7 +593,7 @@ teiler = function (n,div=2) (n%div)?div>n?n: // generates G-Code (G1 x,y,(z),(e),(f)) -gcode=function(points,chunksize=600,i,f) +gcode=function(points,f,chunksize=600,i) let(i=is_undef(i)?len(points)-1:i, chunk=function(pos=0,end) (pos+1)>end?str(chunk(pos=pos-1,end=end), "\nG1 X", @@ -303,8 +603,11 @@ len(points[pos])>2?str(" Z",points[pos].z,""):"", len(points[pos])>3?str(" E",points[pos][3],""):"", is_num(f)||len(points[pos])>4?str(" F",len(points[pos])==5?points[pos][4]:f):"",""):"" ) -i>= 0?str(gcode(i=i-chunksize,chunksize=chunksize,points=points),chunk(i,max(0,i-chunksize))):""; +i>= 0?str(gcode(i=i-chunksize,chunksize=chunksize,points=points,f=f),chunk(i,max(0,i-chunksize))):""; + + +function bool(n,bool)= b(n,bool); function b(n,bool)= is_list(n)?[for(i=[0:len(n)-1])b(n[i],bool)]: is_num(n)?bool||is_undef(bool)?n?true: false: @@ -315,6 +618,17 @@ function b(n,bool)= is_list(n)?[for(i=[0:len(n)-1])b(n[i],bool)]: n?1: 0; +/* +echo(b(1),b(true)) +echo(boolTrue=b(1,true),b(true,true)); +echo(boolFalse=b(1,false),b(true,false)); +// */ + + + + + + function scaleGrad(grad=45,h=1,r=1)=assert(grad!=0)max(0,(r-(h/tan(grad)))/r); function is_parent(parent= needs2D, i= 0)= @@ -333,13 +647,12 @@ is_list(parent)?is_num(search(parent,parentList())[i])?true: */ - m = function (r=[0,0,0], t=[0,0,0], s=[1,1,1])//t2=[0,0,0], let( s=is_num(s)?[s,s,s]: len(s)==2?concat(s,[1]): s, -r=is_num(r)?[0,0,r]:len(r)==3?r:v3(r), +r=is_num(r)?[0,0,r]: is_list(r)?len(r)==3?r:v3(r) : [0,0,0], t=is_list(t)?len(t)==2?concat(t,[0]):len(t) == 3?t:v3(t):v3(t), //t2=len(t2)==2?concat(t2,[0]):t2, @@ -372,14 +685,14 @@ t=is_list(t)?len(t)==2?concat(t,[0]):len(t) == 3?t:v3(t):v3(t), [0, 0, 1, t2.z], [0, 0, 0, 0] ], - */ + */ ms = function (s=[ 1, 1, 1],t=t)[ [s.x, 0, 0, t.x], [0, s.y, 0, t.y], [0, 0, s.z, t.z], [0, 0, 0, 0] ], - out=rz(r.z)*ry(r.y)*rx(r.x)*ms(s)//*mt(t2)* + out=rz(r.z)*ry(r.y)*rx(r.x)*ms(s) // *mt(t2)* ) out; @@ -391,6 +704,20 @@ let( pointsI=is_list(points[0])?points:[points], dimension=len(pointsI[0]), out= +[for(i=pointsI)m(r=r,t=t,s=s)* + concat(i, + dimension==3?[1]:concat([for(dim=[1:3-dimension])0],[1]) // add to vector + ) + +[for(dim=[0:dimension-1])0]] // mask vector +)is_list(points[0])?out:out[0]; + + +//version prior β22|130 +function mPointsORG(points=[0,0], r=[0,0,0], t=[0,0,0], s=[1,1,1])= +let( +pointsI=is_list(points[0])?points:[points], +dimension=len(pointsI[0]), +out= [for(i=[0:len(pointsI)-1])m(r=r,t=t,s=s)* concat(pointsI[i], dimension==3?[1]:concat([for(dim=[1:3-dimension])0],[1]) // add to vector @@ -398,6 +725,13 @@ out= +[for(dim=[0:dimension-1])0]] // mask vector )is_list(points[0])?out:out[0]; + + + + +//echo(mPoints([[0,1]],r=50) ); + + /* rot=[+27,+28,+75]; sc=[1.3,0.4,1.3]; @@ -418,18 +752,33 @@ rotate(rot)translate(tr)scale(sc)hull()polyhedron(p,a); p2=mPoints(mPoints(p,t=tr,r=rot,s=sc),t=[0,0]); -//*/ +// */ -function pathPoints(points=[[0,0,0],[0,10,0],[10,0,0]],path=[[0,0,0],[0,+10,10]],twist=0,scale=1,open=true)= +function pathPoints(points=[[0,0,0],[0,10,0],[10,0,0]],path=[[0,0,0],[0,+10,10]],twist=0,scale=1,open=true,2D=false,rev=false)= + let( + pathLen=len(path)-1, + scale=is_list(scale)?scale:[scale,scale], + points=2D?[for(iPoint=points)[iPoint.x,iPoint.y]]: + len(points[0])==3?points:[for(iPoint=points)concat(iPoint,0)] + ) + [for (i=rev?[pathLen:-1:0] : [0:pathLen],jPoints=points) + mPoints ( mPoints(jPoints,r=i*twist/pathLen) , + r=vektorWinkel( path[ open? max(0,i-1): (i==0?pathLen -1:i-1)], path[open?min(i+1,pathLen):(i+1)%pathLen])+[90,0,0], + s=[1+i*(-1+scale.x)/pathLen,1+i*(-1+scale.y)/pathLen]) + + v3(path[i])]; + +//version prior β22|130 + +function pathPointsORG(points=[[0,0,0],[0,10,0],[10,0,0]],path=[[0,0,0],[0,+10,10]],twist=0,scale=1,open=true)= let(pathLen=len(path)-1, scale=is_list(scale)?scale:[scale,scale]) [for (i=[0:pathLen],j=[0:len(points)-1]) mPoints ( v3( mPoints(points[j],r=i*twist/pathLen) ) , r=vektorWinkel( path[ open? max(0,i-1): (i==0?pathLen -1:i-1)], path[open?min(i+1,pathLen):(i+1)%pathLen])+[-90,0,0], s=[1+i*(-1+scale.x)/pathLen,1+i*(-1+scale.y)/pathLen]) - + v3(path[i])]; - - + + v3(path[i])]; + + function octa (s=1) = @@ -438,47 +787,88 @@ s=is_list(s)?s: [s,-s,s,-s,s,-s] ) [ - [ s[1], 0, 0], - [ s[0], 0, 0], - [ 0, s[2], 0], - [ 0, s[3], 0], - [ 0, 0, s[4]], - [ 0, 0, s[5]] + [ s[1%len(s)], 0, 0], + [ s[0%len(s)], 0, 0], + [ 0, s[2%len(s)], 0], + [ 0, s[3%len(s)], 0], + [ 0, 0, s[4%len(s)]], + [ 0, 0, s[5%len(s)]] ]; //hull() polyhedron(octa(),[[for(i=[0:len(octa())-1])i]]); -function quad (x=10,y,r=1, z,fn=fn) = +/** \name quad \page Functions +quad() creates points for a square with rounded edges +\param x size x or [x,y] +\param y size y +\param r radius optional list +\param t translate points +\param z add z ↦ vector3 +\param center center quad points +\param fn fragment number optional list +*/ + +function quad (x=10,y,r,t=[0,0], z,center=true,fn=fn) = + let( + y=is_list(x)?assert(is_num(x.y))x.y:is_undef(y)?assert(is_num(x))x:assert(is_num(y))y, + x=is_list(x)?assert(is_num(x.x))x.x:assert(is_num(x))x, + rdg=runden(min(x,y)/PHI/2,2), + r=is_list(r)?r:is_undef(r)?[rdg,rdg,rdg,rdg]:[r,r,r,r], + tC=t+(center?[0,0]:[x,y]/2), + fn=is_list(fn)?fn:fn/4*[1,1,1,1] +) +concat( + arc(t=[-x/2 +r[0%len(r)], -y/2 +r[0%len(r)] ]+tC,r=r[0%len(r)],deg=90,rot=180,fn=fn[0%len(fn)],z=z), + arc(t=[ x/2 -r[1%len(r)], -y/2 +r[1%len(r)] ]+tC,r=r[1%len(r)],deg=90,rot=270 ,fn=fn[1%len(fn)],z=z), + arc(t=[ x/2 -r[2%len(r)], y/2 -r[2%len(r)] ]+tC,r=r[2%len(r)],deg=90,rot=0 ,fn=fn[2%len(fn)],z=z), + arc(t=[-x/2 +r[3%len(r)], y/2 -r[3%len(r)] ]+tC,r=r[3%len(r)],deg=90,rot=90,fn=fn[3%len(fn)],z=z) +); + +function quadR (x=10,y,r,t=[0,0], z,center=true,fn=fn) = let( y=is_list(x)?x.y:is_undef(y)?x:y, x=is_list(x)?x.x:x, - r=is_list(r)?r:[r,r,r,r], + rdg=runden(min(x,y)/PHI/2,2), + r=is_list(r)?r:is_undef(r)?[rdg,rdg,rdg,rdg]:[r,r,r,r], + tC=t+(center?[0,0]:[x,y]/2), fn=fn/4+0 ) concat( - kreis(t=[ x/2 -r[0], y/2 -r[0] ],r=r[0],rand=0,grad=90,rot=0 , center=false,fn=fn,z=z), - kreis(t=[ x/2 -r[1], -y/2 +r[1] ],r=r[1],rand=0,grad=90,rot=90 , center=false,fn=fn,z=z), - kreis(t=[-x/2 +r[2], -y/2 +r[2] ],r=r[2],rand=0,grad=90,rot=180, center=false,fn=fn,z=z), - kreis(t=[-x/2 +r[3], y/2 -r[3] ],r=r[3],rand=0,grad=90,rot=270, center=false,fn=fn,z=z) + kreis(t=[ x/2 -r[0], y/2 -r[0] ]+tC,r=r[0],rand=0,grad=90,rot=0 , center=false,fn=fn,z=z), + kreis(t=[ x/2 -r[1], -y/2 +r[1] ]+tC,r=r[1],rand=0,grad=90,rot=90 , center=false,fn=fn,z=z), + kreis(t=[-x/2 +r[2], -y/2 +r[2] ]+tC,r=r[2],rand=0,grad=90,rot=180, center=false,fn=fn,z=z), + kreis(t=[-x/2 +r[3], y/2 -r[3] ]+tC,r=r[3],rand=0,grad=90,rot=270, center=false,fn=fn,z=z) ); /* -polygon(quad(x=15,fn=16)); +polygon(quad(x=15,fn=16,t=[5,5],r=[1,2,3,4],center=false)); points=[for(i=[0:10])each quad(z=i,r=1.000+sin(i*36-90)*1,fn=36)]; -PolyH(points,loop=fn +4 ); +PolyH(points,loop=fn +4, flip=false ); Points(points,loop=(fn+4)*3,start=(fn+4)*5,hull=0); -//*/ +// */ +/** \page Functions +stern() creates points for a star shape +\name stern +\param e number of tips +\param r1 tip radius +\param r2 groove radius +\param mod add points +\param delta shifts junction of r1 to r2 to next point +*/ + +//polygon(stern(mod=9,delta=-1)); + function stern (e=5,r1=10,r2=5,mod=2,delta=+0,z)= let( schritt=360/(e*mod)) is_num(z)? - [for(i=[0:e*mod]) + [for(i=[0:e*mod-1]) i%mod0,"e must be positive")360/e/2, + a=(e-2)*180/e, + r2=is_undef(r2)?assert(deg=",a+180))Inkreis(e,r)-Sehne(e,r)/2*tan(180-deg/2+a/2):r2, + rot=90+rot +) +is_num(z)?[for(i=[0:e*2-1])[each([cos(i*step+rot),sin(i*step+rot)]*(i%2?r2:r)),z]] + :[for(i=[0:e*2-1])[cos(i*step+rot),sin(i*step+rot)]*(i%2?r2:r)] +; + +//Points(sternDeg(e=12,deg=120),hull=true); +//PolyH([for(z=[0:5])each sternDeg(e=12,z=z)],loop=24,flip=false); + + + + function wStern(f=5,r=1.65,a=.25,r2,fn=fn,rot=0,z)= let(step=360/fn, @@ -546,29 +964,566 @@ is_undef(z)?[for(f=[0:fn])let(i=f%fn*360/fn)each[ //polygon(superellipse(r=[5,2])); //Coil(points=superellipse(r=[3,2],n=3.5)); +// wall calculates perimeter number according to nozzle size for "soll"mm + +function wall(soll=.5,min=1.25,even=false,line=line,nozzle,name)= + let ( + line=is_num(nozzle)?nozzle:line, + isoll=abs(soll), + perimeterHi=ceil(isoll/line), + perimeterLow=floor(isoll/line), + min=isollstart?end:len(points)-(close?0:1)) + start0?fn:abs(ceil(PI*2*r/fs/360*grad)), + step=grad/(fn), + deltaStep=delta/(fn) +) +is_num(z)? + [for(i=rev?[fn:-1:0] : [0:fn]) [sin(i*step+rot), cos(i*step+rot),0]*r + [sin(i*step-90+rot), cos(i*step-90+rot), 0] * (2*PI*r/360*i*step+i*deltaStep)+[0,0,z]]: + [for(i=rev?[fn:-1:0] : [0:fn]) [sin(i*step+rot), cos(i*step+rot)]*r + [sin(i*step-90+rot), cos(i*step-90+rot)] * (2*PI*r/360*i*step+i*deltaStep)] +; + +function riemen(r1=5,r2=10,tx=20,fn=fn,fs=fs,z,center=false)= +let(a=asin((r2-r1)/tx)) +concat(kreis(r=r1,rand=0,grad=180 - 2*a,center=true,fn=fn,fs=fs,z=z,t=[center?-tx/2:0,0]),kreis(r=r2,rand=0,grad=180 + 2*a,t=[center?tx/2:tx,0],rot=180,center=true,fn=fn,fs=fs,z=z)); + + + +//polygon(kreisSek(grad=[60,81]*1,r=[+4,8],h=20,center=+0,rev=1,mitte=5)); + + +function kreisSek(r=10,grad=90,h=0,mitte=0,fn=fn,center=true,mirror=false,rev=0,t=[0,0],z)= +let( +t=v3(t), +tL=t+[center?-mitte/2:0,0,0], +tR=t+[center?mitte/2:mitte,0,0], +fn=is_list(fn)?fn:[ceil(fn/2),ceil(fn/2)], +r=is_list(r)?r:[r,r], +grad=is_list(grad)?[grad[0]%360,grad[1]%360]:[grad/2%360,grad/2%360], + +hSekL=r[0]-cos(grad[0])*r[0], +hSekR=r[1]-cos(grad[1])*r[1], +h=max(h,hSekL,hSekR), + +hyL=max(hSekL,hSekR,h)-hSekL, +hyR=max(hSekL,hSekR,h)-hSekR, + +yL=-cos(grad[0])*r[0] + hyL, +yR=-cos(grad[1])*r[1] + hyR, +xL=center?0:sin(grad[0])*r[0], +//xR=center?0:sin(grad[1])*r[1], +hxL=grad[0]==0||grad[0]==180?0:hyL/tan(grad[0]), +hxR=grad[1]==0||grad[1]==180?0:hyR/tan(grad[1]), +y0L=[concat((center?[-sin(grad[0])*r[0]-hxL,0]:[0,0])+tL,is_undef(z)?[]:[z])], +y0R=[concat([sin(grad[1])*r[1]+hxR+(center?0:sin(grad[0])*r[0]+hxL),0]+tR,is_undef(z)?[]:[z])], + + +sekL=[for(i=rev?[fn[0]:-1:0]:[0:fn[0]]) + let(stepL=(i*(grad[0]/fn[0]) - grad[0])%360) + is_undef(z)?[sin(stepL)*r[0]+(center?0:hxL+xL),(mirror?-1:1)*(cos(stepL)*r[0]+yL)]+tL: + [sin(stepL)*r[0]+(center?0:hxL+xL),(mirror?-1:1)*(cos(stepL)*r[0]+yL),z]+tL + ], +sekR=[for(i=rev?[fn[1]:-1:0]:[0:fn[1]]) + let(stepR=(i*(grad[1]/fn[1]) )%360) + is_undef(z)?[sin(stepR)*r[1]+(center?0:hxL+xL),(mirror?-1:1)*(cos(stepR)*r[1]+yR)]+tR: + [sin(stepR)*r[1]+(center?0:hxL+xL),(mirror?-1:1)*(cos(stepR)*r[1]+yR),z]+tR + ] +) +!rev?concat(y0L,sekL,sekR,y0R) +:concat(y0R,sekR,sekL,y0L); + + +/** \name sq \page functions +sq() creates points for a subdivided square +\param size size [x,y] +\param fn [x,y] subdivision +\param diff moves every 2nd point out of line +\param z creates vector 3 +\param center -1,0,1 or false true +*/ + +function sq (size=[10,10],fn=[10,10],diff=0,t=[0,0,0],z,center=true)= + let ( + center=is_list(center)?center:is_bool(center)?center?[0,0]:[1,1]:[center,center], + x=is_list(size)?size[0]:size, + y=is_list(size)?size[1]:size, + fnx=max(1,is_list(fn)?fn[0]:fn), + fny=max(1,is_list(fn)?fn[1]:fn), + diff=is_list(diff)?diff:[diff,diff,diff,diff], + t=[center.x?size.x/2*center.x:0,center.y?size.x/2*center.y:0]+v3(t), + points=is_undef(z)?[ + for(i=[0:fnx-1])[-x/2+x/fnx*i,-y/2+i%2*-diff[0]]+t, + for(i=[0:fny-1])[x/2+i%2*diff[1],-y/2+y/fny*i]+t, + for(i=[0:fnx-1])[x/2-x/fnx*i,y/2+i%2*diff[2]]+t, + for(i=[0:fny-1])[-x/2-i%2*diff[3],y/2-y/fny*i]+t + ]: + [ + for(i=[0:fnx-1])[-x/2+x/fnx*i, -y/2+i%2*-diff[0],z]+v3(t), + for(i=[0:fny-1])[x/2+i%2*diff[1], -y/2+y/fny*i, z]+v3(t), + for(i=[0:fnx-1])[x/2-x/fnx*i, y/2+i%2*diff[2], z]+v3(t), + for(i=[0:fny-1])[-x/2-i%2*diff[3], y/2-y/fny*i, z]+v3(t) + ] + ) + points; + + // polygon(sq(center=1,diff=5)); + + + +/** \name bend \page functions +bend() bends points (2D/3D) around z +\example polygon( bend(sq( center=[1,0], t=[ 5, 0 ] )) ); +\param points points to bend +\param r fix bend radius calculation 0 for dynamic +\param t translation vector for distance from bend center +\param rev reverse bend direction (convex concav) +*/ + +/* +polygon( bend(sq( center=[1,0]), t=[10,0]) ); +T(-10)circle(10-.1); +// */ + + +function bend (points,r=0,t=[0,0,0],rev=false)=let(t=v3(t)) [ + for (i= [0:len(points)-1]) + let( + x=points[i].x+t.x, + y=points[i].y+t.y, + z=is_undef(points[0].z)?undef:points[i].z + t.z,// + b=2*PI*(r?r:x), + deg=b?360/b*y:0 + ) + rev? is_undef(z)?[norm([x,y]),b/360*atan2(y,x)]:[norm(x,y),b/360*atan2(x,y),z] + + :is_undef(z)?[sin(deg+90),cos(deg+90)]*x-v3(t): + concat([sin(deg+90),cos(deg+90)]*x,z)-v3(t) + ] + ; + +/* +polygon( + bend( + bend( + sq( center=1, t=[ 10, 0 ] ), + r=10, rev=true // unbend + ), + r=10 // bend + ) +); + +// */ + + +/** \name scene +scene() creates an array of t for animation scenes +##Example +translate([ scene(2)[0]*10,0])cube(); +translate([ scene(2)[1]*10,1])cube(); + +\param scenes number of scenes or segments +\param t the counter 0-1 that is divided into scenes +*/ +function scene(scenes=10,t=$t)=[for(i=[0:scenes-1])min(max(t*scenes-i,0),1)]; + + +/** \name map +\brief maps value from range to range +\param val input value +\param from maps from range [from,to] +\param to maps to range [from,to] +\param constrain limit range +*/ + +function map(val=$t,from=[0,1],to=[0,1],constrain=true)= + let ( + from=is_num(from[2])?[from[0],from[2]]:from, + to= is_num(to[2]) ?[to[0] ,to[2]] :to, + + diff1=from[1]-from[0], + diff2=to[1]-to[0] + ) + constrain?min(max(diff2/diff1*( val - from[0] )+to[0],min(to) ),max(to) ): + diff2/diff1*(val-from[0])+to[0]; + +/** \page Functions +polyRund() replace points with arcs and offset +\name polyRund +\param points points input +\param r radius to round (can be list) +\param ir inner radius (if r is not list) +\param ofs offset of radii +\param delta change offset without radius +\param fn fs fragments for arcs (can be lists) +\param minF minimum fragments +\param rev if input has reversed point order +*/ + +/* // \example +p=[ +[0,0], +[10,0], +[10,10], +[5,2], +[0,10] +]; +T(y=15)color("pink")polygon(polyRund(revP(p),delta=+0,r=+0.5,ir=1,ofs=1.0,rev=true)); +polygon(polyRund(p,delta=+0,r=+0.5,ir=1,ofs=1)); +// */ + +function polyRund(points,r=0,ir,ofs=0,delta=0,fn=12,fs,fa,minF=1,rev=0)= +[for(p=[0:len(points)-1]) +let( + delta=rev?-delta:delta, + ofs= rev? -ofs:ofs, + fn=is_list(fn)?fn[p%len(fn)]:fn, + fs=is_list(fs)?fs[p%len(fs)]:fs, + ir=is_undef(ir)?r:ir, + lp=len(points), + pBef=points[(p+lp-1)%lp], + pNow=points[p], + pNex=points[(p+1)%lp], + grad1=atan2(pBef.x-pNow.x,pBef.y-pNow.y), + grad2=atan2(pNex.x-pNow.x,pNex.y-pNow.y), + gradDiff=grad1-grad2, + grad=gradDiff<0?abs(gradDiff):360-gradDiff, + gradSup=360-grad, + tPgrad=grad2+gradSup/2, + r=(is_num(r)?((rev?-grad:grad)<180? r : ir):r[p%len(r)]), + rk=grad<180?min(-r-ofs,0):max(r-ofs,0), + tPr=(rk==0?ofs:r), + tP=[sin(tPgrad),cos(tPgrad)]*tangentenP(grad=gradSup-180,r=tPr,rad=tPr)*(grad<180? -1:+1), + tPDelta=[sin(tPgrad),cos(tPgrad)]*tangentenP(grad=gradSup-180,r=delta,rad=delta) + + ) +each kreis(r=rk,rand=0,rot=grad1+90,grad=(grad-180),t=pNow+tP+tPDelta*sign(delta),center=false,z=pNow.z,fn=fn,fs=fs,fa=fa,minF=minF) +]; + +/** \page Functions +revP() reverse points order +*/ +function revP(points)=[for(p=[len(points)-1:-1:0])points[p]]; + +/** \page Functions +arc() creates points on an arc +\param r radius +\param deg angle optional [start,end] +\param r2 end radius at deg +\param rot rotate +\param t translate +\param z add z value ⇒vec3 +\param fn fragments +\param rev reverse point order +*/ + +//polygon(arc(deg=45)); + +function arc(r=10,deg=90,r2,rot=0,t=[0,0,0],z,fn=36,rev=false)= + let( + deg=is_num(deg)?[0,deg]:deg, + step=(deg[1]-deg[0])/fn + ) + [for (i=rev?[fn:-1:0]:[0:fn]) + let( + r=is_undef(r2)?r:r+(r2-r)/fn*i + ) + is_undef(z)?[cos(i*step +rot +deg[0])* r,sin(i*step +rot +deg[0]) * r] + [t[0],t[1]]: + [cos(i*step +rot +deg[0])* r,sin(i*step +rot +deg[0]) * r,z] + v3(t) + ]; + + +/** /page Functions +pt() give the typographic point size in mm +\param pt number of points 12pt ⇒ pt(12) = 1 pica = 4.2333mm +*/ + +function pt(pt=1)=25.4/72*pt; + + +/** /name parabel +/page Functions +parabel() gives points of a parabel +\param x width +\param a height ratio +\param fn fragments +\param exp exponent +\param bp focal point +\param lap overlap outside points +\param t translate points +\param rev reverse points +*/ + +function parabel(x=1,a=1,fn=fn,exp=2,bp=false,lap,t=[0,0],rev=false)= +let( +lap=is_num(lap)?[lap,lap]:lap, +t=is_num(t)?[t,0]:is_list(t)?len(t)>1?t.xy:[is_num(t.x)?t.x:0,0]:[0,0] +) +[ +if(is_list(lap)&&!bp)[0,-lap.y]+t, +(bp&&exp==2?[0,1/(a*4)]: + is_list(lap)?[x+lap.x,-lap.y]: + [0,a*x^exp]) ++t, +if(is_list(lap)&&!bp)[x+lap.x,a*x^exp]+t, + for(i=rev?[0:fn]:[fn:-1:0])let(step=x/fn)[i*step,a*(i*step)^exp]+t +]; + + + +// smooth Transition over i segements +function transition(i=0,fn=fn)= 0.5 + cos(min(abs(i),fn)*180/fn)/2; + +//for(i=[0:fn])T(i)cube([1,1,1+transition(i)*19]); +}//fold // ΔΔ END functions ΔΔ +{ // Help ––––––––––––––––––––––––––––––––––––––––––––––––––––––– - - - -/////////////////////////////////////////////////////// - -$fn=fn; +//$fn=fn; $fs=fs; $fa=fa; help=$preview?anima?false:helpsw:false; -helpHelper= helpsw==1||helpsw==true?true:false; //Helper -helpMod= helpsw==2||helpsw==true?true:false; // Objektmodifikatoren -help2D= helpsw==3||helpsw==true?true:false; // 2D Objekte -helpB= helpsw==4||helpsw==true?true:false; //Basis help -helpP= helpsw==5||helpsw==true?true:false; //Produkte help -helpFunc= helpsw==6||helpsw==true?true:false;//Funktionen +helpHelper= helpsw==1||helpsw==true?true:false; //Helper +helpMod= helpsw==2||helpsw==true?true:false; // Objektmodifikatoren +help2D= helpsw==3||helpsw==true?true:false; // 2D Objekte +helpB= helpsw==4||helpsw==true?true:false; //Basis help +helpP= helpsw==5||helpsw==true?true:false; //Produkte help +helpFunc= helpsw==6||helpsw==true?true:false; //Funktionen +helpGen= helpsw==7||helpsw==true?true:false;//Generator @@ -581,7 +1536,7 @@ t0=$t*360%360; t1=sin($t*360); t2=sin($t*180); -$vpr=vp?vpr:$vpr; +$vpr=vp?is_num(vpr)?[0,0,vpr]:vpr:$vpr; $vpt=vp?vpt:$vpt; $vpd=vp?vpd:$vpd; $vpf=vp?vpf:$vpf; @@ -591,26 +1546,24 @@ messpunkt=$preview?$info:false;//1 für aktiv $messpunkt=messpunkt; //n=0; -if (texton)%T(20,-30,25)R(90)color("slategrey")text(str(name),font="DejaVusans:style=bold",halign="left",size=3,$fn=100); +} // END Help + +if(menu)Menu(); // creates Menu + +module Menu(){ +if (texton&&$preview)%rotate($vpr)T(20,-30,25)color("slategrey")text(str(name),font="DejaVusans:style=bold",halign="left",size=is_num(texton)?texton:$vpd/75,$fn=100); if (bed&&!anima)color(alpha=.1)%Rand(-5,delta=1)square(printBed); -if(version()[0]<2021) -echo(str("

", -"

    •••••••••••••••••••••••••• UB (USER libary v2019) included! v.gd/ubaer •••••••••••••••••••••••••\n", -"••• Version: β",Version," v ",version()," —— Layer: ",layer," Nozzle ∅: ",nozzle," ••• fn=",fn,"••• Spiel: ",spiel," •••")); - -else if(!anima) { echo(str("•••••••••••••••••• UB (USER library v2021) included! v.gd/ubaer •••••••••••••••••")); -echo(str("• Version: β",Version," v ",version()," — Layer: ",layer," Nozzle ∅: ",nozzle," • fn=",fn," • Spiel: ",spiel," •")); +if(!anima) { echo(str("•••••• UB (USER library v2024) included! v.gd/ubaer ••••••" +,"\n• Version: β",Version," v ",version()," • Design: ",designVersion,"\nLayer: ",layer,"(",runden(lineProfile/nozArea*100,2),"%)",line==nozzle?str(" Nozzle ∅: ",nozzle):str(" Line/Nozzle ",line,"/",nozzle)," • fn:",fn," fs:",fs," fa:",fa," • Spiel: ",spiel," •")); } +Echo(str("nozzle area =",runden(nozArea,3),"mm²< print line profile",runden(lineProfile,3),"mm²"),color="redring",condition=nozArea<=lineProfile); - -if (!help&&!anima) if(version()[0]<2021)echo ("

    ••••• Help off use: helpsw=1; •••••"); - else echo ("❌••••• Help off use: helpsw=1; •••••"); +if (!help&&!anima) echo ("❌••••• Help off use: helpsw=1; •••••"); -if (help&&!anima||help2D||helpMod||helpFunc||helpB||helpP||helpHelper) -{ +if (help&&!anima||help2D||helpMod||helpFunc||helpB||helpP||helpHelper){ echo ("••••••• Konstanten: ••••••••"); echo(PHI=PHI,gw=gw,tw=tw,twF=twF,inch=inch); //echo(str("•••••••••• Help is on! (helpsw=1)•• debug=",debug," ••••••••••••••••••••••••")); @@ -623,6 +1576,7 @@ if(!helpHelper)echo("❌••••• Helper List off — use» helpHelper=tru if (helpHelper){ echo ("•••••••••• Helper: •••••••••••••••\n • Schnitt(help=1) cuts children\n +• Cut(help=1) cuts children\n • Col(help=1) colors children with palette\n • Color(help=1) colors children with hue\n • Pivot(help=1) marks p0\n @@ -635,6 +1589,8 @@ echo ("•••••••••• Helper: ••••••••• • HelpTxt(help=1) output helptxt \n • Echo(help=1) output txt \n • 3Projection(help=1) projects child along axis \n +• PrevPos(help=1) moves only for preview \n +• PolyDeg(help=1) show angle in points (2D)\n "); } @@ -645,18 +1601,19 @@ echo ("•••••••••• Funktionen: •••••••• echo (" ••• l(x) Layer\n ••• n(x) Nozzledurchmesser\n -••• Inkreis(eck, rU)\n -••• Umkreis(eck, rI)\n -••• Hypotenuse(a, b) length\n -••• Kathete(hyp, kat) length\n -••• Sehne(n, r, a) length n-eck/alpha winkel •••\n +••• line(n) perimeter \n +••• inkreis(eck, rU)\n +••• umkreis(eck, rI)\n +••• hypotenuse(a, b) length\n +••• kathete(hyp, kat) length\n +••• sehne(n, r, a) length n-eck/alpha winkel •••\n ••• RotLang(rot, l, z, e, lz) [vector] (e=elevation)•••\n ••• bezier(t, p0=[0,0], p1=[-20,20],p2=[20,20],p3=[0,0]) points •••\n ••• kreis(r=10, rand=+5, grad=360,grad2=+0,fn=fn,center=true,sek=true,r2=0,rand2=0,rcenter=0,rot=0,t=[0,0],z=undef) points •••\n -///••• kreisXY(r=5, grad=0) [vector]•••\n +// ••• kreisXY(r=5, grad=0) [vector]•••\n ••• 5gon(b1=20, l1=15, b2=10, l2=30) points •••\n ••• ZigZag(e=5, x=50, y=5, mod=2, delta=+0, base=2, shift=0) points •••\n -••• TangentenP(grad, rad, r) length •••\n +••• TangentenP(grad, rad, r, deg) length •••\n ••• Hexstring(c=[r, g, b]) #hexcolor •••\n ••• RotPoints(grad, points) •••\n ••• negRed(num) negative consolen Werte in rot•••\n @@ -664,7 +1621,9 @@ echo (" ••• gradS(s, r) grad zur Sehne s •••\n ••• vollwelle() ⇒ Vollwelle(help=1) •••\n ••• runden(x, dec=2) x runden auf Dezimalstelle ••• \n -••• radiusS(n, s, a) radius zur Sehne ••• \n +••• radiusS(s, n, a) radius zur Sehne ••• \n +••• radiusSH(sh) Radius zum Umkreis Sehne Höhe••• \n +••• distS(s,r) Distanz Sehne Mittelpunkt ••• \n ••• gradC(grad=0, min=0, sec=0, h=0, prozent=0, gon=0, rad=0) Winkelmaßumrechnung ••• \n ••• inch(inch) Inch⇒mm •••\n ••• kreisbogen(r, grad=360) ••• \n @@ -682,10 +1641,37 @@ echo (" ••• pathPoints(points,path,twist,scale) •••\n ••• tetra(r) tetrahedron points •••\n ••• octa(r,n,d) octaheadron points (subdiv n) ••• \n -••• quad(x,y,r,fn,z) Quad points ••• \n +••• quad(x,y,r,t,center,fn,z) Quad points ••• \n ••• stern(e=5,r1=10,r2=5,mod=2,delta=+0,z) Stern points ••• \n ••• wStern(f=5,r=1.65,a=.25,r2,fn=fn,rot=0,z) ••• \n ••• superellipse(n=2.5,r=10,z,fn=fn) ••• \n +••• star(e=5,r1=10,r2=5,grad=[0,0],grad2,radial=false,fn=0,z,angle=360,rot=0) ••• \n +••• wall(soll,min=1.75,even=false,nozzle=nozzle) adapt to line width (nozzle) ••• \n +••• vMult(v1,v2) vector multiplication ••• \n +••• vSum(v,start=0,end,val=0) ••• \n +••• naca(l,0012) NACA airfoil ••• \n +••• pathLength(points,start=0,end,close=0) ••• \n +••• stringChunk(txt,start=0,length) •••\n +••• string2num(string,start=0,length) •••\n +••• nut (e=2,es=10,a=6,b=6,base=1,h=1,s,center=true,shift=0,grad,z) •••\n +••• involute(r=10,grad=45,fn=fn,rot=0,rev=0,delta=0,z) ••• \n +••• riemen(r1=5,r2=10,tx=20,fn=fn,z,center=false) ••• \n +••• kreisSek(r=10,grad=90,h=0,mitte=0,fn=fn,center=true,mirror=false,rev=0,t=[0,0],z) ••• \n +••• sq (size=[10,10],fn=[10,10],diff=0,t=[0,0,0],z,center=true) ••• \n +••• bend (points,r=0,t=[0,0,0],rev=false) ••• \n +••• scene (scenes,t) ••• \n +••• map (val,from,to=[0,1],constrain=true) ••• \n +••• polyRund(points,r,ir,ofs,delta,fn,fs) round and offset input points••• \n +••• revP(points) reverse Point order ••• \n +••• arc(r,deg,r2,rot,t,z,fn,rev) ••• \n +••• pt(pt) typographic unit in mm••• \n +••• parabel(x,a,fn,exp,bp,lap,t,rev)••• \n +••• vMin(v=[1,2,3],min=0)••• \n +••• vMax(v=[1,2,3],max=0)••• \n +••• vAdd(v=[1,2,3],add=0)••• \n +••• transition(i,fn)••• \n +••• triUmkreis(points=[a,b,c]) circumcenter ••• \n +••• triInkreis(points=[a,b,c]) incenter••• \n "); @@ -697,7 +1683,7 @@ if (helpMod){ echo ("•••••••••• Objektmodifikatoren: ••••••"); echo ("•••• T(x=0,y=0,z=0)•Tz(z=0) ••• R(x=0,y=0,z=0) ••"); echo ("•••• M(skewzx=0,skewzy=0,skewxz=0,skewxy=0,skewyz=0,skewyx=+0,scale=1,scalexy=1,scalexz=1,scaleyz=1)••"); -echo ("•••• Rund(or=+0,ir=0,chamfer=false,fn=fn)polygon••"); +echo ("•••• Rund(or=+0,ir=0,chamfer=false,fn,fs=fs)polygon••"); echo ("•••• Linear(es=1,s=100,e=2,x=1,y=0,z=0,r=0,re=0,center=0,cx=0,cy=0,cz=0 ••"); echo ("•••• Polar(e=3,x=0,y=0,r=0,re=0,end=360,dr=0,mitte=false,name)dr=delta element rotation ••"); echo ("•••• Grid(es=[10,10,10],e=[2,2,1],center=true) ••"); @@ -705,31 +1691,39 @@ echo ("•••• HexGrid ()"); echo ("•••• Klon(tx=10,ty=0,tz=0,rx=0,ry=0,rz=0) Objekt "); echo ("•••• Halb(i=0,x=0,y=0,z=1,2D=0)Objekt ••"); echo ("•••• Drehpunkt(rx=0,ry=0,rz=0,x=0,y=0,z=0,messpunkt=1)Objekt ••"); -echo ("•••• Rundrum(x=+40,y=30,r=10,eck=4,twist=0,grad=0,spiel=0.005,fn=fn,name) polygon RStern(help=1)polygon ••"); echo ("•••• Kextrude(help=1); ••"); -echo ("•••• LinEx(help=1) polygon ••"); echo ("•••• LinEx2(bh=5,h=1,slices=10,s=1.00,ds=0.01,dh=0.7,fs=1,fh=1,twist=0,name,fn=fn) ••"); -echo ("•••• RotEx(grad=360,fn=fn,center=false) ••"); echo ("•••• Rand(rand=n(1),center=false,fn=fn,delta=false,chamfer=false) ••"); -echo ("•••• Elipse(x=2,y=2,z=0,fn=36)Object••"); -echo ("•••• Ttorus(r=20,twist=360,angle=360,fn=fn)3D-Objekt ••"); echo ("•••• Gewinde(help=1)••"); echo ("•••• GewindeV3(dn=5,h=10,kern=0,p=1,w=0,profil=0,gh=0.56,g=1,name,fn=36)••"); echo ("•••• Kontaktwinkel(help=1) Objekt ••"); -echo ("•••• Bezier(p0=[+0,+10,0],p1=[15,-5,0],p2=[15,+5,0],p3=[0,-10,0],w=1,max=1.0,min=+0.0,fn=50,ex=0,pabs=false,messpunkt=5,name) Objekt •••••"); echo ("•••• Laser3D(h=4,layer=10,var=0.002,name,on=-1)3D-Objekt ••"); echo ("\n •••• MKlon() //Objekt •• \n -•••• Bogen(help=1)// opt Polygon ••\n -•••• SBogen(help=1)// opt Polygon ••\n •••• Row(help=1)// opt. Objekt ••\n -•••• Bevel(help=1)// Objekt ••\n •••• Scale(help=1)// Objekt ••\n +•••• Select()// Children ••\n "); } +if(!helpGen)echo("❌••••• ObjektGenerator List off — use» helpGen=true; •••••"); +if (helpGen){ + echo("\n + •••• Rundrum(x=+40,y=30,r=10,eck=4,twist=0,grad=0,spiel=0.005,fn=fn,name) polygon RStern(help=1)polygon •• + •••• Bogen(help=1)// opt Polygon ••\n + •••• SBogen(help=1)// opt Polygon ••\n + •••• Bevel(help=1)// Objekt ••\n + •••• Bezier(help=1) Objekt ••\n + •••• Schlaufe(help=1) polygon •• \n + •••• Elipse(x=2,y=2,z=0,fn=36)Object•• \n + •••• RotEx(grad=360,fn=fn,center=false) ••\n + •••• LinEx(help=1) polygon •• + •••• Ttorus(r=20,twist=360,angle=360,fn=fn)3D-Objekt •• + + "); +} // 2D @@ -756,16 +1750,29 @@ echo ("•••••• Polygons ••••••\n •• Cycloid(help=1);\n •• SQ(help=1);\n •• Vollwelle(help=1);\n +•• SWelle(help=1);\n •• CycloidZahn(help=1);\n •• Nut(help=1);\n •• DBogen(help=1);/*(opt polygon)\n*/ •• Pfeil(help=1);\n +•• DPfeil(help=1);\n •• Rosette(help=1);\n •• GT(help=1);\n •• Egg(help=1);\n •• VarioFill(help=1);\n •• Welle(help=1);\n •• Tdrop(help=1);\n +•• Star(help=1);\n +•• NACA(help=1);\n +•• Involute(help=1);\n +•• Riemen(help=1);\n +•• PolyRund(help=1);\n +•• Arc(help=1);\n +•• Tesselation(help=1);\n +•• Connector(help=1);\n +•• Penrose(help=1);\n +•• RectTiling(help=1);\n +•• Voronoi(help=1);\n "); } @@ -773,6 +1780,7 @@ echo ("•••••• Polygons ••••••\n if(!helpB)echo("❌••••• Basis objects List off — use» helpB=true; •••••"); if(helpB){// BASIS OBJEKTE + echo(); echo ("•••••••••• BasisObjekte: •••••••••••••\n @@ -796,7 +1804,7 @@ echo ("•••••••••• BasisObjekte: ••••••• •• HypKehle(help=1);\n •• HypKehleD();\n -•• [46] Text(text=“»«”,size=5,h=0,cx=0,cy=0,cz=0,center=0,font=“Bahnschrift:style=bold”);\n +•• [46] Text(text=\"»«\",size=5,h=0,cx=0,cy=0,cz=0,center=0,font=\"Bahnschrift:style=bold\");\n •• [47] W5(kurv=15,arms=3,detail=.3,h=50,tz=+0,start=0.7,end=13.7,topdiameter=1,topenddiameter=1,bottomenddiameter=+2);\n •• [50] Rohr(grad=90,rad=5,d=8,l1=10,l2=12,fn=fn,fn2=fn,rand=n(2),name=0);\n @@ -806,6 +1814,7 @@ echo ("•••••••••• BasisObjekte: ••••••• •• [55] Kassette(r1=2,r2=2,size=20,h=0,gon=3,fn=fn,fn2=36,r=0,grad=90,grad2=90,spiel=0.001,mitte=true,sizey=0,help=$helpM);\n •• Surface(help=$helpM);\n +•• FlatMesh(help=true);\n •• [58] Box(x=8,y=8,z=5,d2=0,c=3.5,s=1.5,eck=4,outer=true,fnC=36,fnS=24);\n •• [62] Spirale(grad=400,diff=2,radius=10,rand=n(2),detail=5,exp=1,hull=true);/*opt Object*/\n •• [63] Area(a=10,aInnen=0,rInnen=0,h=0,name);\n @@ -816,13 +1825,17 @@ echo ("•••••••••• BasisObjekte: ••••••• •• Zylinder(help=1);\n •• Welle(help=1); /*opt polygon*/\n •• Anschluss(help=1);\n +•• QuadAnschluss(help=1);\n •• RingSeg(help=1); \n •• Buchtung(help=1);\n •• SpiralCut(help=1);\n •• Isosphere(help=1);\n •• OctaH(help=1); /*Octahedron*/\n •• PolyH(); /*Polyhedron auto faces */\n -•• Coil(); +•• Coil();\n +•• Knurl();\n +•• KnurlTri();\n +•• Loch(); "); @@ -850,16 +1863,16 @@ echo ("•• [59] ReuleauxIntersect(h=2,rU=5,2D=false) ••••••"); echo ("•• [60] Glied3(x) ••• [61] Gelenk(l,w) ••••••"); echo ("•• [64] Balg(sizex=16,sizey=16,z=10.0,kerb=6.9,rand=-0.5)••••"); echo ("•• [67] Tring(spiel=+0,angle=153,r=5.0,xd=+0.0,h=1.75,top=n(2.5),base=n(4),name=0)••••"); -echo ("•• [201] Servokopf(rot,spiel)Objekt ••••"); +echo ("•• [201] Servokopf(help=1)Objekt ••••"); echo ("•• [202] Halbrund(h=15,d=3+2*spiel,x=1.0,n=1)Objekt mikroGetriebemotor Wellenaufnahme ••••"); echo ("•• [203] Riemenscheibe(e=40,radius=25,nockendurchmesser1=2,nockendurchmesser2=2,hoehe=8,name)Objekt ••••"); -echo ("•• Cring(id=20,grad=230,h=15,rand=3,rad=1,end=1,txt=undef,tWeite=15,tSize=5,center=true,fn=fn,fn2=36)••••"); +echo ("•• Cring(help=1)••••"); echo ("\n •• PCBcase(help=1);••••\n •• Klammer(help=1);••••\n •• Pin(help=1);••••\n -•• CyclGetriebe(help=1);••••\n +•• CyclGetriebe(help=1);/CyclGear();••••\n •• SRing(help=1);••••\n •• DRing(help=1);opt polygon••••\n •• GewindeV4(help=1); ••••\n @@ -867,6 +1880,8 @@ echo ("\n •• Abzweig(help=1) ••••\n •• GT2Pulley(help=1) ••••\n •• KBS(help=1) KlemmBauStein••••\n +•• Filter(help=1) Filter Sieve••••\n +•• Bayonet(help=1) ••••\n "); } @@ -876,41 +1891,34 @@ echo ("\n // SCHALTER - if(version()[0]<2021)echo (str("

    Schalter• -messpunkt=",messpunkt?"On":"Off", -" • vp=",vp?"On":"Off", -" • anima=",anima?"On":"Off", -" • texton=",texton?"On":"Off", -" • help=",help?"On":"Off", -" • $info=",$info?"On":"Off", -" •")); - else echo (str("Schalter•\n -messpunkt=",messpunkt?"🟢✔":"❌", -" • vp=",vp?"🟢✔":"❌", -" • anima=",anima?"🟢✔":"❌", -//" • texton=",texton?"🟢✔":"❌", -" • help=",help?"🟢✔":"❌", -" • $info=",$info?"🟢✔":"❌", -" • bed=",bed?"🟢✔":"❌", -" • hires=",hires?"🟢✔":"❌", -" •")); + +echo (str("Schalter•\n +messpunkt=",messpunkt?"✅":"❌", +" • vp=",vp?"✅":"❌", +" • anima=",anima?"✅":"❌", +//" • texton=",texton?"✅":"❌", +" • help=",help?"✅":"❌", +" • $info=",$info?"✅":"❌", +" • bed=",bed?"✅":"❌", +" • hires=",hires?"✅":"❌", +" •\n")); if(anima||tset)echo(str("\n Zeit t0:",t0, "\nZeit t1:",t1,"\nZeit t2:",t2,"\n Zeit t3:",t3(),"\n •••• anima on! tset=",tset," t=0⇒1 || t0=0⇒360 || t1=-1⇔1 || t2=0⇔1 || t3(wert=1,grad=360,delta=0) •••••")); -if (vp)echo (str(version()[0]<2021?"\n

    ": - "", +if (vp)echo (str( "\n\tViewportcontrol vpr: ",$vpr,"\n\t Viewportcontrol vpt: ",$vpt,"\n\t Viewportcontrol vpd: ",$vpd,"\n\t Viewportcontrol vpf: ",$vpf,"\n\t •••• vp=on •••••")); -if(!$preview) echo("\n\t\t⏳ Rendering…wait! ⌛"); +if(!$preview) echo("\n\t\t⏳ Rendering…wait! ⌛"); -//////////////////////////// Modules ///////////////////////////// +} // end Menu +// –––––––––––––––––––––––– Modules ––––––––––––––––––––––––––––––––––– module Example(variable=1,name,help){ @@ -924,7 +1932,7 @@ if(name=="Test"||name=="test"||is_bool(name)||name==undef||is_num(name)) { HelpTxt("Example",["variable",variable,"name",name],help); } -/////////////////////////////////////// END Example ///////////////////////// +// – ///////////////////////////////////// END Example ///////////////////////// module Laby(rec=8,l=10,b=1,p){ @@ -953,22 +1961,31 @@ if(is_string(name)&&name!="test"&&name!="Test"){rand=rands(0,1,1)[0];n=floor(ran } // end example +{//fold // \∇∇ Tools / Modifier ∇∇/ // + +/** \page Modifier + * \brief Select() let you select children + * \name Select + * \param n children optional list +*/ + +/* +Select([3,1]){ + cube(5); + sphere(4); + cylinder(5,5,0); +}//*/ + +module Select(n=0){ +if(n==0||n==true)children(); +else if(n!=false&&(is_list(n)||n>0)) for(i=n)children(max(i-1,0)%$children); +} +/// short for translate[]; - - -///∇∇ Tools / Modificator ∇∇/// - - - - - - - -// short for translate[]; module T(x=0,y=0,z=0,help=false) { //translate([x,y,z])children(); @@ -976,7 +1993,7 @@ if(is_list(x)) multmatrix(m=[ [1,0,0,x[0]], [0,1,0,x[1]], - [0,0,1,x[2]], + [0,0,1,is_undef(x.z)?z:x[2]+z], [0,0,0,1] ])children(); else @@ -992,7 +2009,25 @@ else HelpTxt("T",["x",x,"y",y,"z",z],help); } -// short for T(z=0); + + + + + + + + + +/** \page Modifier + * Tz() translates children in Z + * \name Tz +## Examples +Tz() cube(); + * \brief short for T(z=0); + * \param z translates[0,0,z] + +*/ + module Tz(z=0,help=false){ multmatrix([ [1,0,0,0], @@ -1012,44 +2047,90 @@ module R(x=0,y=0,z=0,help=false) HelpTxt("R",["x",x,"y",y,"z",z],help); } +/** \name M +\page Modifier +M() multmatrix objects +\param skewXY skew the x axis along y +\param scaleXY scales x and y +*/ // short for multmatrix and skewing objects -module M(skewzx=0,skewzy=0,skewxz=0,skewxy=0,skewyz=0,skewyx=+0,scale=1,scalexy=1,scalexz=1,scaleyz=1,help=false){ - scalex=scale*scalexy*scalexz; - scaley=scale*scalexy*scaleyz; - scalez=scale*scalexz*scaleyz; +module M(skewZX=0,skewZY=0,skewXZ=0,skewXY=0,skewYZ=0,skewYX=+0,scale=1,scaleXY=1,scaleXZ=1,scaleYZ=1,help=false,skewxy,skewxz,skewyx,skewyz,skewzx,skewzy,scalexy,scalexz,scaleyz){ + scale=is_list(scale)?scale:scale*[1,1,1]; + skewXY=is_undef(skewxy)?skewXY:skewxy; + skewXZ=is_undef(skewxz)?skewXZ:skewxz; + skewYX=is_undef(skewyx)?skewYX:skewyx; + skewYZ=is_undef(skewyz)?skewYZ:skewyz; + skewZX=is_undef(skewzx)?skewZX:skewzx; + skewZY=is_undef(skewzy)?skewZY:skewzy; + + scaleXY=is_undef(scalexy)?scaleXY:scalexy; + scaleXZ=is_undef(scalexz)?scaleXZ:scalexz; + scaleYZ=is_undef(scaleyz)?scaleYZ:scaleyz; + + scaleX=scale.x*scaleXY*scaleXZ; + scaleY=scale.y*scaleXY*scaleYZ; + scaleZ=scale.z*scaleXZ*scaleYZ; + multmatrix([ - [scalex,skewyx,skewzx,0], - [skewxy,scaley,skewzy,0], - [skewxz,skewyz,scalez,0], + [scaleX,skewYX,skewZX,0], + [skewXY,scaleY,skewZY,0], + [skewXZ,skewYZ,scaleZ,0], [0,0,0,1.0], - ])children(); + ])children(); + MO(!$children); - HelpTxt("M",["skewzx",skewzx,"skewzy",skewzy,"skewxz",skewxz,"skewxy",skewxy,"skewyz",skewyz,"skewyx",skewyx,"scale",scale,"scalexy",scalexy,"scalexz",scalexz,"scaleyz",scaleyz],help); + HelpTxt("M",["skewZX",skewZX,"skewZY",skewZY,"skewXZ",skewXZ,"skewXY",skewXY,"skewYZ",skewYZ,"skewYX",skewYX,"scale",scale,"scaleXY",scaleXY,"scaleXZ",scaleXZ,"scaleYZ",scaleYZ],help); } +/** +\name Polar +\page Modifier +Polar() object multiply children polar (e=number, x/y=radial distance) +\param e number objects (cloned children) +\param x,y,z radius (distance) of objects +\param rot rotate polar +\param rotE rotate objects +\param end for degree +\param dr delta rotate objects according to position +\param mitte add center object +\param v rotation axis +\param es element distance +\param name, help name help +*/ -// multiply children polar (e=number, x/y=radial distance) -module Polar(e=3,x=0,y=0,r=0,re=0,end=360,dr=0,mitte=false,name,n,help=false){ +//Polar(5,[3,3],v=[0,1,1])cube(); +//Polar(3,10)square([$r*2,.1],true); + +module Polar(e=3,x=0,y=0,z=0,rot=0,rotE=0,end=360,dr=0,mitte=false,v=[0,0,1],es,name,n,help=false,r,re){ + e=floor(abs(e)); + y=is_list(x)?is_num(x.y)?x.y+y:y:y; + z=is_list(x)?is_num(x.z)?x.z+z:z:z; + x=is_list(x)?x.x:es?radiusS(s=es,n=e):x; + rot=is_undef(r)?rot:r; // compability + rotE=is_undef(re)?rotE:re; // compability name=is_undef(n)?is_undef(name)?is_undef($info)?false: $info: name: n; - radius=Hypotenuse(x,y); + radius=norm([x,y,z]); + $r=radius; end=end==0?360:end; winkel=abs(end)==360?360/e:end/max(1,e-1); + + if(norm(v)>1)%color("chartreuse",.5)rotate(vektorWinkel(p2=v)-[90,0,0])cylinder(norm([x,y,z]),d=.5); InfoTxt("Polar",["elements",str(e, - " radius ",radius,"mm ",re?str("rotElements=",re,"°"):"",end!=360?str(" End=",end,"°"):""," Element=",winkel,"° Abstand=",2*radius*PI/360*winkel,"mm (Sekante=",2*radius*sin(winkel/2),")")],name); + " radius ",radius,"mm ",rotE?str("rotElements=",rotE,"°"):"",end!=360?str(" End=",end,"°"):""," Element=",winkel,"° Abstand=",2*radius*PI/360*winkel,"mm (Sekante=",2*radius*sin(winkel/2),")")],name); - if(e>+0) rotate(r)for(i=[0:e-1]){ + if(e>+0) rotate(rot)for(i=[0:e-1]){ $idx=i; $tab=is_undef($tab)?1:b($tab,false)+1; $info=$idx?false:name; - rotate(e==1&&end<360?winkel/2:i*winkel)translate([x,y,0])rotate([0,0, re+(i*winkel)/end*dr])children(); + rotate(a=e==1&&end<360?winkel/2:i*winkel,v=v)translate([x,y,z])rotate(a=rotE+(i*winkel)/end*dr,v=v)children(); } if(mitte){ $idx=e; @@ -1057,7 +2138,7 @@ module Polar(e=3,x=0,y=0,r=0,re=0,end=360,dr=0,mitte=false,name,n,help=false){ } - HelpTxt("Polar",["e",e,"x",x,"y",y,"r",r,"re",re,"end",end,"dr",dr,"mitte",mitte,"name",name],help); + HelpTxt("Polar",["e",e,"x",x,"y",y,"z",z,"rot",rot,"rotE",rotE,"end",end,"dr",dr,"mitte",mitte,"v",v,"es",es,"name",name],help); MO(!$children); @@ -1065,7 +2146,7 @@ MO(!$children); -// multiply children linear (e=number, es=distance) +/// multiply children linear (e=number, es=distance) module Linear(e=2,es=1,s=0,x=0,y=0,z=0,r=0,re=0,center=0,cx=0,cy=0,cz=0,name,n,help)// ordnet das Element 20× im Abstand x Linear an.. es skaliert die vektoren . cx = center x { name=is_undef(n)?is_undef(name)?is_undef($info)?false: @@ -1073,10 +2154,15 @@ module Linear(e=2,es=1,s=0,x=0,y=0,z=0,r=0,re=0,center=0,cx=0,cy=0,cz=0,name,n,h name: n; -$helpM=0; -s=es==1?s:0; - x=!y&&!z?1:x; + $helpM=0; + e=floor(e); + s=es==1?s:0; + + x=!y&&!z?1:b(x,false); + y=b(y,false); + z=b(z,false); + $es=s?s/e:es; cx=center?1:cx; cy=center?1:cy; cz=center?1:cz; @@ -1153,7 +2239,7 @@ module Mklon(tx=0,ty=0,tz=0,rx=0,ry=0,rz=0,mx=0,my=0,mz=1) } // Clone Object -module Klon(tx=0,ty=0,tz=0,rx=0,ry=0,rz=0,help=false){ +module Klon(tx=0,ty=0,tz=0,rx=0,ry=0,rz=0,center=true,help=false){ union(){ $idx=0; translate([tx,ty,tz])rotate([rx,ry,rz])children(); @@ -1163,53 +2249,73 @@ module Klon(tx=0,ty=0,tz=0,rx=0,ry=0,rz=0,help=false){ $helpM=0; $info=0; $idxON=false; - translate([-tx,-ty,-tz])rotate([-rx,-ry,-rz])children(); + if(center)translate([-tx,-ty,-tz])rotate([-rx,-ry,-rz])children(); + else rotate([-rx,-ry,-rz])children(); } MO(!$children); - HelpTxt("Klon",["tx",tx,"ty",ty,"tz",tz,"rx",rx,"ry",ry,"rz",rz],help); + HelpTxt("Klon",["tx",tx,"ty",ty,"tz",tz,"rx",rx,"ry",ry,"rz",rz,"center",center],help); } -// Cuts away half of Object at [0,0,0] -module Halb(i=0,x=0,y=0,z=0,2D=0,size=max(400,viewportSize*5),help=false) + +/** +\page Modifier +\name Halb +Halb() Object Cuts away half of Object at [0,0,0] +\param i inverse side +\param x,y,z cutting axis +\param 2D for 2D objects +\param size cuttingblock size +*/ + +//Halb(x=1)sphere(5); + + +module Halb(i=0,x=0,y=0,z=0,2D=0,size=max(400,viewportSize*4),t=[0,0,0],help=false) { +t=v3(t); +xChange=-x; +x=(is_num(useVersion)&&useVersion<22.250&&!2D)?y:x; +y=(is_num(useVersion)&&useVersion<22.250&&!2D)?xChange:y; if(!2D){ - if(i)difference() + if(i||z<0)difference() { - children(); - R(x?90:0,y?90:0) cylinder(size,d=size,$fn=6); + union()children(); + translate(t)R(-90*sign(y),90*sign(x)) cylinder(size,d=size,$fn=6); } - if(!i) intersection() + else intersection() { - children(); - R(x?90:0,y?90:0) cylinder(size,d=size,$fn=6); + union()children(); + translate(t)R(-90*sign(y),90*sign(x)) cylinder(size,d=size,$fn=6); } } if(2D){ if(i)difference() { - children(); - T(y?-size/2:0,x?-size/2:0) square(size); + union()children(); + if(x)translate([x?size/2*sign(x):0,0]+t) square(size,true); + if(y)translate([0,y?size/2*sign(y):0]+t) square(size,true); } if(!i) intersection() { - children(); - T(y?-size/2:0,x?-size/2:0) square(size); + union()children(); + translate([x?size/2*sign(x):0,y?size/2*sign(y):0]+t) square(size,true); } } MO(!$children); - HelpTxt("Halb",["i",i,"x",x,"y",y,"z",z,"2D",2D,"size",size],help); + HelpTxt("Halb",["i",i,"x",x,"y",y,"z",z,"2D",2D,"size",size,"t",t],help); } //short for rotate_extrude(angle,convexity=5) with options -module RotEx(grad=360,fn=fn,center=false,cut=false,convexity=5,help=false){ + +module RotEx(grad=360,fn,fs=fs,fa=fa,center=false,cut=false,convexity=5,help=false){ fnrotex=$fn; rotate(center?sign(grad)*-min(abs(grad)/2,180):grad>=360?180:0) - rotate_extrude(angle=grad,convexity=convexity, $fa =fn?abs(grad/fn):$fa,$fs=.2,$fn=0)intersection(){ + rotate_extrude(angle=grad,convexity=convexity, $fa =fn?abs(grad/fn):fa,$fs=fs,$fn=is_num(fn)&&fn<5&&grad==360?fn:0)intersection(){ $fn=fnrotex; $fa=fa; $fs=fs; @@ -1221,19 +2327,28 @@ module RotEx(grad=360,fn=fn,center=false,cut=false,convexity=5,help=false){ HelpTxt("RotEx",["grad",grad,"fn",fn,"center",center,"cut",cut,"convexity",convexity],help); } - +/** \name Grid \page Modifier +Grid() children(); creates a grid of children +\param e elements [x,y] +\param es element spacing [x,y] +\param s total space ↦ es +\param center true/false +*/ // multiply children in a given matrix (e= number es =distance) + +//Grid(e=[3,2],es=20)Text($idx2); + module Grid(e=[2,2,1],es=10,s,center=true,name,help){ name=is_undef(name)?is_undef($info)?false: $info: name; - function n0(e)=is_undef(e)?1:max(e,1); + function n0(e)=is_undef(e)?1:max(round(e),0); function n0s(e)=max(e-1,1);// e-1 must not be 0 center=is_list(center)?v3(center):[center,center,center]; - e=is_list(e)?is_num(e[2])?[max(e[0],1),max(e[1],1),n0(e[2])]: - concat(e,[1]): + e=is_list(e)?is_num(e[2])?[max(round(e[0]),0),max(round(e[1]),0),n0(e[2])]: + [round(e.x),round(e.y),1]: // z = 1 es[2]?[n0(e),n0(e),n0(e)]: [n0(e),n0(e),1]; @@ -1246,7 +2361,7 @@ module Grid(e=[2,2,1],es=10,s,center=true,name,help){ [s/n0s(e[0]),s/n0s(e[1]),s/n0s(e[2])]; MO(!$children); - InfoTxt("Grid",[str("Gridsize(",e,")"),str(e[0]*e[1]*e[2]," elements ",(e[0]-1)*es[0],"×",(e[1]-1)*es[1],"×",(e[2]-1)*es[2],"mm ", + InfoTxt("Grid",[str("Gridsize(",e,")"),str(e[0]*e[1]*e[2]," elements= ",(e[0]-1)*es[0],"×",(e[1]-1)*es[1],"×",(e[2]-1)*es[2],"mm \n element spacing= ",es," mm", center.x?str("\n\tX ",-(e[0]-1)*es[0]/2," ⇔ ",(e[0]-1)*es[0]/2," mm"):"", center.y?str("\n\tY ",-(e[1]-1)*es[1]/2," ⇔ ",(e[1]-1)*es[1]/2," mm"):"", @@ -1262,1516 +2377,116 @@ module Grid(e=[2,2,1],es=10,s,center=true,name,help){ ,"center",center ,"name",name] ,help); - - translate([ + + centerPos=[ center.x?((1-e[0])*es[0])/2:0, center.y?((1-e[1])*es[1])/2:0, - center.z?((1-e[2])*es[2])/2:0]) for(x=[0:e[0]-1],y=[0:e[1]-1],z=[0:e[2]-1]){ + center.z?((1-e[2])*es[2])/2:0]; + + if(e.x&&e.y&&e.z) for(x=[0:e[0]-1],y=[0:e[1]-1],z=[0:e[2]-1]){ $idx=[x,y,z]; + $idx2=[e.y*e.x*z + e.x*y + x, e.y*e.x*z + e.y*x + y]; + $pos=[x*es.x,y*es.y,z*es.z]+centerPos; $info=norm($idx)?false:name; $tab=is_undef($tab)?1:b($tab,false)+1; + $es=es; // $helpM=norm($idx)?false:$helpM; - T(x*es[0],y*es[1],z*es[2])children(); + translate([x*es[0],y*es[1],z*es[2]]+centerPos)children(); } } +//Grid(4)Text($pos.xy,size=3); // Grid but with alternating row offset - hex or circle packing -module HexGrid(e=[11,4],es=5,center=true,name){ - es=is_list(es)?es:[es*sin(60),es]; - Grid(e=e,es=es,center=center,name=name) - translate([0, - $idx[0]%2?is_list(es)?es[1]/2:es/2: - 0 - ])children(); - MO(!$children); - - InfoTxt("HexGrid",["es",es],name); +//HexGrid()circle(d=$es.y); +//HexGrid()circle(d=Umkreis(6,$d-.1),$fn=6); + +/** \name HexGrid \page Modifier +HexGrid() children(); creates an interlaced grid of children +\param e elements [x,y] e+.1 or -.1 will change the pattern +\param es element spacing [x,y] +\param center true/false or ±num for x/y shift, can be a list +\param $d $r $es $idx $idx2 $pos output for children +\param name help name help +*/ + +//HexGrid(center=[-3,+0]); +/* //sphere packing +difference(){ +lift=(sqrt(6)/3); +rotate(30)cylinder(5*lift*2-2,r=5,$fn=6); + +echo( sin(atan(sqrt(2)) ), lift ); +color("yellow",.5)HexGrid(7.1,center=true,es=5)sphere($r); +color("magenta",.5) Tz(5 * lift-1) HexGrid(7.1,es=5,center=[+3,3])sphere($r); +color("cyan",.5)Tz(2* (5 * lift-1))HexGrid(7.1,es=5,center=[-3,3])sphere($r); } - - - - - - - -///ΔΔ Modificatoren ΔΔ/// - -///∇∇ Helper ∇∇/// (not for creating geometry or objects) - -//Points(octa(5),loop=4,size=0.4); - -module Points(points,color,size,hull=.5,loop=25,start=0,mark,markS,center=true,help){ - lp=assert(points[0],"no point(s) input")len(points); - cMark=["Chartreuse","Aqua","Magenta","LightSkyBlue"]; - size=is_undef(size)?$vpd/100:size; - markS=is_undef(markS)?$vpd/40:markS;// scale marks - %if($preview){ - - - for (i=[0:is_list(points[0])?lp-1:0])translate(is_list(points[0])?points[i]:points){ - if(is_num(mark)&&i==mark)color("Chartreuse", alpha=.6)OctaH(.6*markS); - if(is_list(mark)) for(j=[0:len(mark)-1])if(i==mark[j])color(cMark[j%len(cMark)], alpha=0.4)OctaH(0.4*markS,$fn=12); - - if(i>=start&&i2) if(len(points[0])==3)color(alpha=is_bool(hull)?1: hull) - hull() polyhedron(points, [[for(i=[0:len(points)-1]) i ]]); - else if(len(points[0])==2)color(alpha=is_undef(color[3])?.2:color[3])polygon(points); - - } - - HelpTxt("Points",["points",[[1,2,3]],"color",color,"size",size,"hull",hull,"loop",loop,"start",start,"mark",mark,"markS",markS,"center",center],help); - } - - //Points(Kreis(grad=120,fn=6),start=0,loop=6,mark=[2,3,4,12]); - - - - -// Cutaway children for preview -module Schnitt(on=$preview,r=0,x=0,y=0,z=-0.01,rx=0,ry=0,sizex,sizey,sizez,center=0) -{ - sizex=is_undef(sizex)?bed?printBed.x:max(viewportSize*5,150):sizex; - sizey=is_undef(sizey)?bed?printBed.y:max(viewportSize*5,150):sizey; - sizez=is_undef(sizez)?bed?100:max(viewportSize*5,150):sizez; - - center=is_bool(center)?center?1:0:center; - if($children)difference() - { - union()children(); - if((on&&$preview)||on==2) translate([x,y,z])rotate([rx,ry,r])color([1,0,0,1])translate([center>0?-sizex/2:0,abs(center)==1?-sizey/2:-sizey,center>1||center<0?-sizez/2:0])cube([sizex,sizey,sizez],center=false); - } - -Echo("»»»»––SCHNITT in render! ––«««« \n",color="warning",condition=on==2); - -MO(!$children); -} - -// 3 axis Projection - -module 3Projection(s=10,cut=true,active=[1,1,1],help){ - s=is_list(s)?s:[s,s]; - cut=is_list(cut)?cut:[cut,cut,cut]; - $info=false; - $helpM=false; - if(active.z) projection(cut=cut.z)children(); - if(active.x) translate([s.x,0,0])projection(cut=cut.x)rotate([0,90,0])children(); - if(active.y) translate([0,s.y,0])projection(cut=cut.y)rotate([-90,0,0])children(); - %children(); - MO(!$children); - HelpTxt("3Projection",["s",s,"cut",cut,"active",active],help); - -} - - -//Arranges (and color) list of children for display -module Anordnen(es=10,e,option=1,axis=1,c=0,r,cl=.5,rot=0,loop=true,center=true,inverse=false,name,help){ - -option=option==3&&version()==[2021, 1, 0]?4:option; -optiE= function(e=[0,0,1]) - let (sqC=sqrt($children)) - e.x*e.y==$children? - e: - e.x>4?optiE([e.x-1,e.y,1])://min 4 rows else alternate to circumvent primes - e.y>$children?[round(sqC),ceil($children/round(sqC)),1]: - optiE([ceil(sqC),e.y+1,1]); - -//echo(optiE()); - e=option==3||option==4?is_undef(e)?optiE(): - is_list(e)? - e.z?e: - concat(e,1): - [ceil($children/e),e,1]: - is_undef(e)?$children:e; - -InfoTxt("Anordnen",["e",e,"children",$children],name); - - - - if(option==1){ - r=is_undef(r)?(es/2)/sin(180/e):r; - Polar(e,x=r,re=rot,name=false){ - ///idx=$idx; - //$idx=0; - $idxON=true; - $info=name; - if(is_undef(c)&&(loop?true:$idx<$children)) - children((inverse?$children-$idx-1:$idx)%$children);// - else Color(c+1/$children*$idx,l=cl) - if(loop?true:$idx<$children)children((inverse?$children-$idx-1:$idx)%$children); - } - } - - if(option==2) - Linear(e=e,es=es,re=rot,center=center,x=axis==1?1:0,y=axis==2?1:0,z=axis==3?1:0,name=false){ - $info=name; - //idx=$idx; - //$idx=0; - $idxON=true; - if(is_undef(c))children($idx%$children); - else Color(c+1/$children*$idx,l=cl)children($idx%$children); - } - - if(option==3) Grid(e=e,es=es,center=center,name=false){ - $info=name; - childINDX=inverse?(loop?e.x*e.y*e.z:$children -1)-($idx[0]+e.x*$idx[1]):($idx[0]+e.x*$idx[1]); - //idx=$idx; - //$idx=0; - $idxON=true; - rotate(rot) - if(is_undef(c)&&(loop?true:$idx.x+e.x*$idx.y+e.x*e.y*$idx.z<$children))children(childINDX%$children); - else Color(([$idx.x/(e.x -1),$idx.y/(e.y -1),$idx.z/e.z]+[ 0,0,cl])){ - if(loop?true:$idx.x+e.x*$idx.y+e.x*e.y*$idx.z<$children)children(childINDX%$children); - //text(str([$idx.x/(e.x-1), $idx.y/(e.y-1), $idx.z/e.z]+[ 0,0,cl]),size=2); - } - } - - if(option==4) Grid(e=e,es=es,center=center,name=false)IDX($idx,$children)children($idx%$children); - - module IDX(idx,childrn){ - $info=name; - $idxON=true; - $idx=inverse?(loop?e.x*e.y*e.z:childrn -1)-(idx[0]+e.x*idx[1]):(idx[0]+e.x*idx[1]); - rotate(rot) - if(is_undef(c)&&(loop?true:idx.x+e.x*idx.y+e.x*e.y*idx.zlen(co[pal])-1)?" — Out of Range":"")],name); - } - } - MO(!$children); -} - - -// object color with hue (and rgb) also color change for multiple children -module Color(hue=0,alpha=1,v=1,l=0.5,spread=1,$idxON=true,name=0,help=false){ - - function val(delta=0,hue=-hue*360,v=v,l=l*-2+1)= - v*max( - min( - (0.5+sin((hue+delta)))*(l>0?1-l:1) - +(max( - .5+sin((180+hue+delta)) - ,0)*(l<=0?-l:0)) - ,1) - ,0); - - start=90;// to start with red - - if($children) for(i=[0:$children-1]){// - $idx=is_undef($idx)?i:$idx; - c=is_string(hue)?hue:is_list(hue)?[(hue[0]+i*(1-hue[0]%1.001)/(spread*$children))%1.001,(hue[1]+i*(1-hue[1]%1.001)/(spread*$children))%1.001,(hue[2]+i*(1-hue[2]%1.001)/(spread*$children))%1.001]:[val(start,hue=(-hue-i/(spread*$children))*360),val(+start+120,hue=(-hue-i/(spread*$children))*360),val(start+240,hue=(-hue-i/(spread*$children))*360)]; - - if(name) echo(str("Color ",name," child ($idx) ",i," hex=",Hexstring(c)," ",Hex(alpha*255),//" ████ - "RGB=",c)); - // $idxON=true; - color(c,alpha)children(i); - - - } - else MO(!$children); - - HelpTxt("Color",[ - "hue",hue,"alpha",alpha,"v",v,"l",l,"spread",spread,"name",name, - ],help); -} - -/// Echo Helper /// console texts - -// missing object text -module MO(condition=true,warn=false){ -Echo(str(parent_module(2)," has no children!"),color=warn?"warning":"red",condition=condition&&$parent_modules>1,help=false); -} - - -// echo color differtiations -module Echo(title,color="#FF0000",size=2,condition=true,help=false){ - - if(condition) - if(version()[0]<2021)echo(str("",title)); - else if (color=="#FF0000"||color=="red")echo(str("\n⭕\t»»» ",title)); - else if (color=="#FFA500"||color=="orange")echo(str("\n🟠\t»»» ",title)); - else if (color=="#00FF00"||color=="green"||color=="info")echo(str("🟢\t ",title)); - else if (color=="#0000FF"||color=="blue") echo(str("🔵\t ",title)); - else if (color=="#FF00FF"||color=="purple") echo(str("🟣\t ",title)); - else if (color=="#000000"||color=="black") echo(str("⬤\t ",title)); - else if (color=="#FFFFFF"||color=="white") echo(str("◯\t ",title)); - else if (color=="#FFFF00"||color=="yellow"||color=="warning") echo(str("⚠\t ",title)); - else echo(str("• ",title)); - HelpTxt("Echo",["title",title,"color",color,"size",size,"condition",condition],help); -} - -/// display variable values -module InfoTxt(name,string,info,help=false){ - $tab=is_undef($tab)?0:$tab; - info=is_undef(info)?is_undef($info)?false: - $info: - info; - - // https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/User-Defined_Functions_and_Modules#Function_Literals - idx=is_undef($idx)?false:is_list($idx)?norm($idx):$idx; - idxON=is_undef($idxON)?false:$idxON?true:false; - joinArray= function(in,out="",pos=0) pos>=len(in)?out: // scad version > 2021 - joinArray(in=in,out=str(out,in[pos]),pos=pos +1); - - if(version()[0]<2021){ - infoText=[for(i=[0:2:len(string)-1])str(string[i],"=",is_num(string[i+1])?negRed(string[i+1]):string[i+1],i",info," ",name," ", -infoText[0] -,infoText[1]?infoText[1]:"" -,infoText[2]?infoText[2]:"" -,infoText[3]?infoText[3]:"" -,infoText[4]?infoText[4]:"" -,infoText[5]?infoText[5]:"" -,infoText[6]?infoText[6]:"" -,infoText[7]?infoText[7]:"" -,infoText[8]?infoText[8]:"" -,infoText[9]?infoText[9]:"" -)); -else HelpTxt(titel="InfoTxt",string=["name",name,"string","[text,variable]","info",info],help=1); -} -else { // current version info - infoText=[for(i=[0:2:len(string)-1])str(string[i],"=",string[i+1],i1?" ┗▶ ": - " ",info," ",name," ", -joinArray(infoText))); - -else HelpTxt(titel="InfoTxt",string=["name",name,"string","[text,variable]","info",info],help=1); -} -HelpTxt(titel="InfoTxt",string=["name",name,"string","[text,variable]","info",info],help=help); -} - - -// display the module variables in a copyable format -module HelpTxt(titel,string,help){ - help=is_undef(help)?is_undef($helpM)?false: - $helpM: - help; - idxON=is_undef($idxON)?false:$idxON?true:false; - idx=is_undef($idx)||idxON?false:is_list($idx)?norm($idx):$idx; - - joinArray= function(in,out="",pos=0) pos>=len(in)?out: - joinArray(in=in,out=str(out,in[pos]),pos=pos +1); - -helpText=[for(i=[0:2:len(string)-1])str(string[i],"=",string[i+1],",\n ")]; - if(version()[0]<2021){ -if(help)if(is_list(string))echo( - -str("

    Help ",titel, "(", - helpText[0] -,helpText[1]?helpText[1]:"" -,helpText[2]?helpText[2]:"" -,helpText[3]?helpText[3]:"" -,helpText[4]?helpText[4]:"" -,helpText[5]?helpText[5]:"" -,helpText[6]?helpText[6]:"" -,helpText[7]?helpText[7]:"" -,helpText[8]?helpText[8]:"" -,helpText[9]?helpText[9]:"" -,helpText[10]?helpText[10]:"" -,helpText[11]?helpText[11]:"" -,helpText[12]?helpText[12]:"" -,helpText[13]?helpText[13]:"" -,helpText[14]?helpText[14]:"" -,helpText[15]?helpText[15]:"" -,helpText[16]?helpText[16]:"" -,helpText[17]?helpText[17]:"" -,helpText[18]?helpText[18]:"" -,helpText[19]?helpText[19]:"" -,helpText[20]?helpText[20]:"" -,helpText[21]?helpText[21]:"" -,helpText[22]?helpText[22]:"" -,helpText[23]?helpText[23]:"" -,helpText[24]?helpText[24]:"" -,helpText[25]?helpText[25]:"" -,helpText[26]?helpText[26]:"" -,helpText[27]?helpText[27]:"" -,helpText[28]?helpText[28]:"" -,helpText[29]?helpText[29]:"" - - -//," name=",name, -," help);")); -else HelpTxt("Help",["titel",titel,"string",["string","data","help",help],"help",help],help=1); -} -else{ // current versions help -if(help&&!idx)if(is_list(string))echo( - -str("🟪\nHelp ",titel, "(\n ", -joinArray(helpText) -,"help=",help,"\n);\n")); -else HelpTxt("Help",["titel",titel,"string",string,"help",help],help=1); -} -} - - - - -module Caliper(l=20,in=1,s,center=true,messpunkt=true,translate=[0,0,0],end=1,h=1.1,render=false,l2,txt,size=$vpd/15,help){ - - s=s?s:size; - txt=is_undef(txt)?str(l,"mm "):txt; - center=is_bool(center)?center?1:0:center; - textl=in>1?s/3:s/4*(len(str(txt)));// end=0 use own def - line=s/20; - //l2=is_undef(l2)?s:l2; - - - if($preview||render)translate(translate)translate(in>1?center?[0,0]:[0,l/2]:center?[0,0]:[l/2,0]){ - if(end==1&&h)Col(5){ - rotate(in?in==2?90:in==3?-90:180:0)linear_extrude(h,center=true)Mklon(tx=l/2,mz=0)polygon([[max(-5,-l/3),0],[0,s],[0,0]]); - rotate(in?in==2?90:in==3?-90:180:0)linear_extrude(h,center=true)Mklon(tx=-l/2,mz=0)polygon([[max(-5,-l/3),0],[0,-s],[0,0]]); - - Text(h=h+.1,text=txt,center=true,size=s/4); - } - else if(end==2&&h)Col(3)union(){ - rotate(in?in==2?90:in==3?-90:180:0)MKlon(tx=l/2)T(-(l-textl)/4,0)cube([(l-textl)/2,line,h],center=true); - rotate(in?in==2?90:in==3?-90:180:0)MKlon(tx=l/2)T(-line/2)cube([line,s,h],center=true); - translate([(l1?l/2+textl/2+1:0,0])Text(h=h+.1,text=txt,center=true,size=s/4); - if(l1?s/3:s/4*len(txt); - // text line - rotate(in?in==2?90:in==3?-90:180:0)MKlon(tx=l/2)T(-(l-textl)/4,0)square([(l-textl)/2,line],center=true); - //End lines - rotate(in?in==2?90:in==3?-90:180:0){MKlon(tx=l/2){ - T(+line/2) square([line,l2],center=true); - Pfeil([0,min(l/3,s/2)],b=[line,s],center=[-1,1],name=false); - } - translate([l1?-90:180) Text(h=0,text=txt,center=true,size=s/4); - // verbindung text ausserhalb - if(l0?1:0,0])square([line,abs(translate.y)],false); - if(translate.x)MKlon(ty=l/2) mirror([translate.x>0?1:0,0,0])square([abs(translate.x),line],false); - //if(translate.x) mirror([translate.x>0?1:0,0,0])T(l/2,-line/2)square([abs(translate.x),line],false); - - } - } - Echo("Caliper will render",color="warning",condition=render); -if(h&&end) -Pivot(messpunkt=messpunkt,p0=translate,active=[1,1,1,1,norm(translate)]); - - HelpTxt("Caliper",[ - "l",l, - "in",in, - "size",size, - "center",center, - "messpunkt",messpunkt, - "translate",translate, - "end",end, - "h",h, - "render",render, - "l2",l2, - "txt",txt] - ,help); -} - - - - -module SCT(a=90){ - echo(str("

    Winkel=",a," sin=",sin(a)," cos=",cos(a)," tan=",tan(a))); - echo(str("

    Winkel=",a," asin=",asin(a)," acos=",acos(a)," atan=",atan(a))); -} - - - - - - - -///ΔΔ Helper ΔΔ\\\ -///∇∇ Polygons ∇∇/// - - - -module Tdrop(r=1,d,grad,cut=true,name,help){ - -kgrad=is_undef(grad)?atan(layer/(nozzle/1.75)):90-grad; -delta=is_bool(cut)?nozzle-layer:cut; // added cut - -r=is_num(d)?d/2:r; -h=cos(kgrad)*r; -x=sin(kgrad)*r; -h2=cut==false?h+tan(kgrad)*x:min(r+delta,h+tan(kgrad)*x); -x2=cut==false? 0:x - (h2-h)/tan(kgrad); - - -points=[ -//[-x,h], -//[ x,h], -each kreis(rand=0,r=r,grad=360-kgrad*2,center=true,rot=-90), -if(x2>minVal)[- x2,h2], -clampToX0([ x2,h2]) -]; - -if(messpunkt)%Tz(.1)color("green",.25)circle(r=r,$fn=fn); -polygon(points); -InfoTxt("Tdrop",["grad",90-kgrad,"cut",cut],name); -HelpTxt("Tdrop",["r",r,"d",d,"grad",grad,"cut",cut,"name",name],help); -} - -module VarioFill( -l=15, -exp=+2, -dia, -h, -chamfer=1, -deg=45, -extrude=0, -grad=90,//[0,90] -spiel=spiel, -fn=fn, -name, -help -){ - -grad=is_list(grad)?grad:[+0,grad]; - -padding=is_undef(spiel)?[0,0]: - is_list(spiel)?[spiel.x,spiel.y]: - [spiel,spiel]; - -spiel=is_undef(spiel)?[0,0]:is_list(spiel)? - [spiel.x*max(1,(1/(sin(grad.y)*cos(grad.x)))),spiel.y*max(1,(1/(cos(grad.x)*sin(grad.y))))]: - [spiel*max(1,(1/(sin(grad.y)*cos(grad.x)))),spiel*max(1,(1/(cos(grad.x)*sin(grad.y))))]; - //[spiel*(1/sin(grad.y)),spiel*(1/cos(grad.x))]; - -l=is_list(l)?l:deg?[l,tan(deg)*l]:[l,l]; - -fn=is_undef(fn)?$fn==0?fs2fn(r=norm(l),grad=90,fs=$fs):$fn:fn; - -diaw=dia; // if undef ⇒ 2D - -dia=is_num(dia)?dia:0; - -extrude=extrude*sign(l.x); -rot=-180; -p1=[ -[-spiel.y*sign(l.x) +dia/2, -spiel.x*sign(l.y)], -[-spiel.y*sign(l.x) +dia/2, l.y+sin(grad.x)*spiel.y*sign(l.y)], -[+extrude+dia/2,l.y], -for(i=[fn-1:-1:0])let(seg=90/fn*i) - !chamfer?([sin(seg+rot)*l.x+extrude+l.x+dia/2, cos(seg+rot)*l.y+l.y]): - [pow(((fn-1)-i)/(fn-1),abs(exp))*l.x+extrude+dia/2,pow(i/(fn-1),abs(exp))*l.y], - -[extrude+l.x+dia/2,0], -[extrude+l.x-cos(grad.y)*spiel.x*sign(l.x) +dia/2,-spiel.x*sign(l.y)], -]; - - -m=[ -[cos(grad.x),sin(grad.y-90),0,0],// scale x, skew x, trans x -[sin(grad.x),cos(grad.y-90),0,0], // skew y, scale y, trans y -[0,0,1,0], -]; - -points=grad==[0,90]?p1: - [for(i=[0:len(p1)-1])let(p=m*concat(p1[i],[1,0]))[p.x,p.y]]; - -gK=sin(grad.y)*l.y-sin(grad.x)*l.x; -aK=cos(grad.x)*l.x+cos(grad.y)*l.y; - -///color("red")square([aK,gK]); -//polygon(points,convexity=5); -//p2=[for(i=[0:len(points)-1])let(p=m*concat(points[i],[1,0]))[p.x,p.y]]; - -InfoTxt("VarioFill",["sekantenWinkel",atan(gK/aK)],name); - - -cut=spiel.x>abs(dia/2) || - sign(dia)*sign(l.x)==1?false : // both pos or neg - sign(dia)*l.x0?grad.y>90:grad.y<90 || (l.y>0?grad.x<0:grad.x>0) ) - intersection(){ - polygon(points); - mirror([sign(l.x)==1?0:1,sign(l.y)==1?0:1])translate([-padding.y+dia/2-(extrude*sign(l.x)<0?-extrude*sign(l.x):0),grad.x<0?-l.y:-padding.x]) - square([abs(extrude)+abs(l.x)+padding.y,grad.x<0?2*l.y:abs(l.y)+padding.x]); - } - else polygon(points); - -//%multmatrix(m)translate([-spiel.y,-spiel.x])square([l.x+spiel.y,l.y+spiel.x]); -HelpTxt("VarioFill",[ - "l",l, - "exp",exp, - "dia",dia, - "h",h, - "chamfer",chamfer, - "deg",deg, - "extrude",extrude, - "grad",grad,//[0,90] - "spiel",spiel, - "fn",fn, - "name",name - ],help); - -} - - - -module Kreis(r=10,rand=0,grad=360,grad2,fn=fn,center=true,sek=false,r2=0,rand2,rcenter=0,rot=0,t=[0,0],name,help,d,b){ - r=is_undef(d)?r:d/2; - d=2*r; - grad=is_undef(b)?grad:r==0?0:b/(2*PI*r)*360; - b=2*r*PI*grad/360; - - polygon( kreis(r=r,rand=rand,grad=grad,grad2=grad2,fn=fn,center=center,sek=sek,r2=r2,rand2=rand2,rcenter=rcenter,rot=grad==360?center?rot:rot+90:center?rot+180:rot+90,t=t),convexity=5); - - - HelpTxt("Kreis",["r",r,"rand",rand,"grad",grad,"grad2",grad2,"fn",fn,"center",center,"sek",sek,"r2",r2,"rand2",rand2,"rcenter",rcenter,"rot",rot,"t",t,"name",name,"d",d,", b",b],help); - - if(name){ - if(!rcenter){ - if(rand>0)echo(str(name," Kreis id=",2*(r-abs(rand))," od=",2*r)); - if(rand<0)echo(str(name," Kreis id=",2*r," od=",2*(r+abs(rand)))); - } - else if(rand)echo(str(name," Kreis id=",2*r-abs(rand)," od=",2*r+abs(rand))); - } -} - - -module ZigZag(e=5,es=0,x=50,y=7,mod=2,delta=+0,base=2,shift=0,center=true,name,help){ - x=es?e*es:x; - es=es?es:x/e; - T(center?-x/2:0) polygon(ZigZag(e=e,x=x,y=y,mod=mod,delta=delta,base=base,shift=shift),convexity=5); - abst=x/e; - h=y-base; - if(name)echo(str(n," ZigZag Winkel=",atan((abst/2+shift)/h),"°+",atan((abst/2-shift)/h),"°=",atan((abst/2+shift)/h)+atan((abst/2-shift)/h),"° Spitzenabstand=",abst,"mm Zackenhöhe=",h,"mm ‼ use Nut(a=0,b=0);")); - if(help){ - echo(str("

    Help ZigZag(e=",e,",es=",es,",x=",x,",y=",y,",mod=",mod,",delta=",delta,",base=",base,",shift=",shift,",center=",center,",name=",name,",help)")); - } -} - - - - -///ΔΔ Polygons ΔΔ\\\ -///∇∇ Generator ∇∇/// - - - - -module Rundrum(x=+40,y,r=10,eck=4,twist=0,grad=90,grad2=90,spiel=0.005,fn=fn,name,help){ - -$info=name; -$idxON=false; - -$fa=fa; -$fs=fs; -$fn=fn; - // WIP - Echo("Angle with different radii not implemeted yet",condition=(r1!=r2||r2!=r3||r3!=r4)&&(grad2!=90||grad!=90)); - r1=is_list(r)?r[0]:r; - r2=is_list(r)?r[1]:r; - r3=is_list(r)?r[2]:r; - r4=is_list(r)?r[3]:r; - r=is_list(r)?r[0]:r; - y=is_list(x)?x[1]:is_undef(y)?x:y; - x=is_list(x)?x[0]:x; - - //grad2=grad-20;// WIP - shift=tan(grad-90)*y; - grad=grad?grad:shift>0?atan(shift/y):-atan(-shift/y); - shiftx=shift-r*2*tan(grad-90); - shiftx2=tan(grad2-90)*y-r*2*tan(grad2-90); - shiftYLang=Hypotenuse(shiftx,y-2*r); - shiftYLang2=Hypotenuse(shiftx2,y-2*r); - if(eck==4&&grad!=90&&name)echo(str(name," Rundrum grad=",grad,"° ShiftX=",shiftx,"mm (+-",shiftx/2,"mm) Lot(x)=",x*sin(grad),"mm")); - //rx=r?r*(r/(sin(grad)*r)):0; - function rx(r=r,grad=grad)=r*1/sin(grad); - - -if(eck==4&&twist==0) - if(grad==90&&grad2==90){ - $info=is_undef(name)?$info:name; - $tab=is_undef($tab)?1:b($tab,false)+1; - //Ecken - T(-x/2+r1,y/2-r1)rotate(90)RotEx(90,fn=fn/4,cut=true)T(r1)children();// R1 - union(){ - $info=false; - $helpM=false; - $idx=true; // disable help - T(x/2-r2,y/2-r2)RotEx(90,fn=fn/4,cut=true)T(r2)children();// R2 - T(-x/2+r3,-y/2+r3)rotate(180)RotEx(90,fn=fn/4,cut=true)T(r3)children();// R3 - T(x/2-r4,-y/2+r4)rotate(-90)RotEx(90,fn=fn/4,cut=true)T(r4)children();// R4 - //Graden - //X - T((r1-r2)/2,y/2)R(90,0,90)linear_extrude(x-r1-r2+spiel,center=true,convexity=5)children(); - T((r3-r4)/2,-y/2)R(90,0,-90)linear_extrude(x-r3-r4+spiel,center=true,convexity=5)children(); - //Y - T(-x/2,(r3-r1)/2)R(90,0,180)linear_extrude(y-r1-r3+spiel,center=true,convexity=5)children(); - T(x/2,(r4-r2)/2)R(90,0,+0)linear_extrude(y-r2-r4+spiel,center=true,convexity=5)children(); - } - - } -else T(-shiftx/2*0){ - $info=is_undef(name)?$info:name; - $tab=is_undef($tab)?1:b($tab,false)+1; - //plus x - T(x/2-rx(r2,grad2)+shiftx2/2,y/2-r2)rotate(90-grad2)rotate_extrude(angle=grad2,convexity=5,$fn=0,$fa = grad2/(fn/4), $fs = 0.1)Ecke(r2)children(); - union(){ - $idx=true; // disable help - $helpM=0; - $info=0; - T(x/2-rx(r4,grad2)-shiftx2/2,-y/2+r4)rotate(-90)rotate_extrude(angle=180-grad2,convexity=5,$fn=0,$fa = (180-grad2)/(fn/4), $fs = 0.1)Ecke(r4)children(); - //minus x - T(-x/2+rx(r1)+shiftx/2,y/2-r1)rotate(90)rotate_extrude(angle=180-grad,convexity=5,$fn=0,$fa = (180-grad)/(fn/4), $fs = 0.1)Ecke(r1)children(); - T(-x/2+rx(r3)-shiftx/2,-y/2+r3)rotate(-90)rotate_extrude(angle=-grad,convexity=5,$fn=0,$fa = grad/(fn/4), $fs = 0.1)Ecke(r3)children(); - - - //linear x -+ - T(+x/2-rx((r2+r4)/2,grad2)+shiftx2/2,y/2-r)rotate(90-grad2)T(+r)R(90,0,0)Tz(-spiel/2)linear_extrude(shiftYLang2+spiel,convexity=5,center=false,$fn=fn)children(); - T(-x/2+rx(r1/2+r3/2)-shiftx/2,-y/2+r)rotate(90-grad)T(-r)R(90,0,180)Tz(-spiel/2)linear_extrude(shiftYLang+spiel,convexity=5,center=false,$fn=fn)children(); - - //linear y -+ - T(-x/2+rx()+shiftx/2-spiel/2,y/2+0)R(90,0,90)linear_extrude(x-rx(r1)-rx(r2,grad=grad2)+spiel+shiftx2/2-shiftx/2,convexity=5,center=false,$fn=fn)children(); - T(+x/2-rx(grad=grad2)+spiel/2-shiftx2/2,-y/2)R(90,0,-90)linear_extrude(x-rx()-rx(grad=grad2)+spiel-shiftx2/2+shiftx/2,convexity=5,center=false,$fn=fn)children(); - } - if(2*r>x||2*r>y){ - echo(); - Echo(str("››»!!!«‹‹ ",name," Rundrum WARNUNG !!! Radius zu groß !!!"),color="red"); - echo(); - - } - - if(name) if((2*r==x||2*r==y)&&x!=y)echo(str(name," Rundrum Halbkreis")); - if(name) if(2*r==x&&2*r==y)echo(str(name," Rundrum Vollkreis")); - - } - else{ - for(i=[0:eck-1]){ - - $tab=is_undef($tab)?1:b($tab,false)+1; - $info=is_undef(name)?$info:name; - $idx=i*2; - stepDeg=360/eck; - rotate(i*stepDeg)T(Umkreis(eck,x-r))rotate(-180/eck)rotate_extrude(angle=stepDeg,$fn=fn,convexity=5)intersection(){ - T(r)rotate(i*(twist/eck))children(); - translate([0,-150])square(300); - } - union(){ - $helpM=0; - $info=0; - $idx=i*2+1; - rotate(i*stepDeg+180/eck)T(x) R(90)linear_extrude(2*Kathete(Umkreis(eck,x-r),x-r)+spiel,center=true,twist=twist/eck,$fn=fn,convexity=5)rotate(+twist/eck+i*(twist/eck))children(); - } - } - - } -MO(!$children); - - module Ecke(r=r){ - render()intersection(){ - T(r)children(); - translate([0,-150])square(300); - } - } - -HelpTxt("Rundrum",["x",x,"y",y,"r",r,"eck",eck,"twist",twist,"grad",grad,"spiel",spiel,"fn",fn,"name",name],help); -} - - - -module Torus(trx=+6,d=4,a=360,fn=fn,fn2=38,r=0,grad=0,dia=0,center=true,end=0,gradEnd=90,trxEnd=0,endRot=0,endspiel=+0,name,help) - rotate(grad?0:-a/2){ - - end=is_undef(spheres)?is_bool(end)?end?-1:0:end:spheres;//compatibility - $d=d; - $r=d/2; - endRot=is_list(endRot)?endRot:[endRot,endRot]; - trx=dia?dia/2-d/2:trx; - grad=grad?grad:a; - a=end==-1&&!trxEnd? grad-(asin($r/trx)*2)*sign(grad): - grad; - // end==-1&&!$children? a-(asin($r/trx)*2)*sign(a): - // a; - - - $idxON=false; - - InfoTxt("Torus",["Innen∅",2*trx-d,"Mitten∅",2*trx,"Aussen∅",2*trx+d],info=name); - HelpTxt("Torus",["trx",trx,"d",d,"a",a,"fn",fn,"fn2",fn2,",r=",r,", grad=",grad,"dia",dia,"center",center,"end",end,"gradEnd",gradEnd,"trxEnd",trxEnd,"endRot",endRot,"endspiel",endspiel,"name",name,"$d",$d],help); - - -rotate(end==-1? (asin($r/trx))*sign(grad): - 0){ - $idx=true; - $info=is_undef(name)?is_undef($info)?false:$info:name; - translate([0,0,center?0:d/2]) RotEx(grad=a,fn=fn,cut=1,help=false){ - $idx=0; - $tab=is_undef($tab)?1:b($tab,false)+1; - if($children)T(x=trx)R(0,0,r)children(); - else T(x=trx)R(0,0,r)circle(d=d,$fn=fn2); - } - - if(end&&a!=360&&!trxEnd){ - if($children){ - rotate(a+endspiel*sign(grad))translate([trx,0,center?0:d/2])scale([1,abs(end),1])R(0,endRot[1])RotEx(cut=sign(end*grad),grad=180*sign(end),fn=fn/2,help=false)rotate(endRot[1])children(); - rotate(+0)translate([trx,0,center?0:d/2])rotate(180)scale([1,abs(end),1])R(0,-endRot[0])RotEx(cut=sign(end*grad),grad=180*sign(end),fn=fn/2,help=false)rotate(endRot[0])children(); - } - else{ - rotate(a-sign(grad)*minVal)translate([trx,0,center?0:d/2])scale([1,abs(end),1])R(90)Halb(sign(grad)>0?1:0)sphere(d=d,$fn=fn2); - rotate(sign(grad)*minVal)translate([trx,0,center?0:d/2])scale([1,abs(end),1])R(90)Halb(sign(grad)>0?0:1)sphere(d=d,$fn=fn2); - } - } - - if(trxEnd)translate([0,0,center?0:d/2]){ // End Ringstück - if($children){ - T(trx-trxEnd)rotate(gradEnd*sign(-trxEnd)){ - RotEx(grad=gradEnd*sign(trxEnd),cut=+0,fn=fn/360*gradEnd)T(trxEnd)children(); - if(end)translate([trxEnd,0,0])rotate(180)scale([1,abs(end),1])R(0,-endRot[0])RotEx(cut=sign(end*gradEnd),grad=180*sign(gradEnd*end),fn=fn/4,help=false)rotate(endRot[0])children(); - } - rotate(180+grad)T(-trx+trxEnd)rotate(180){ - RotEx(grad=gradEnd*sign(trxEnd),cut=+0,fn=fn/360*gradEnd)T(trxEnd)children(); - if(end)rotate(gradEnd*sign(trxEnd))translate([trxEnd,0,0])scale([1,abs(end),1])R(0,endRot[1])RotEx(cut=sign(end*gradEnd),grad=180*sign(gradEnd*end),fn=fn/4,help=false)rotate(endRot[1])children(); - } - } - else{ - T(trx-trxEnd)rotate(gradEnd*sign(-trxEnd)){ - RotEx(grad=gradEnd*sign(trxEnd),fn=fn/360*gradEnd,cut=+0)T(trxEnd)circle(d=d,$fn=fn2); - if(end)translate([trxEnd,0,0])rotate(180)scale([1,abs(end),1])RotEx(cut=sign(end*gradEnd),grad=180*sign(gradEnd*end),fn=fn/8,help=false)circle(d=d,$fn=fn2); - } - rotate(180+grad)T(-trx+trxEnd)rotate(180){ - RotEx(grad=gradEnd*sign(trxEnd),cut=+0,fn=fn/360*gradEnd)T(trxEnd)circle(d=d,$fn=fn2); - if(end)rotate(gradEnd*sign(trxEnd))translate([trxEnd,0,0])scale([1,abs(end),1])RotEx(cut=sign(end*gradEnd),grad=180*sign(gradEnd*end),fn=fn/8,help=false)circle(d=d,$fn=fn2); - } - } - } -} - - -} - - - - -module LinEx(h=5,h2=0,h22,scale=0.85,scale2,twist,twistcap=1,slices,$d,$r=5,grad,grad2,mantelwinkel=0,center=false,rotCenter=false,end=0,fn=12,name,help,n){ - - -$info=is_undef(name)?is_undef($info)?false:$info:name; -$helpM=0; -$idxON=false; - -end=is_bool(end)?end?[1,1]:[0,0]:is_list(end)?end:[end,end]; -name=is_undef(n)?name:n; -twistcap=is_list(twistcap)?twistcap:[twistcap,twistcap]; -$r=is_undef($d)?$r:$d/2; -$d=2*$r; -h22=abs(is_undef(h22)?is_list(h2)?h2[1]:h2:h22); -h2=abs(is_list(h2)?h2[0]:h2); -hc=h-h2-h22; - -scale2=is_undef(grad2)? - is_undef(grad)? - is_undef(scale2)?h22?scale:1:scale2 - :is_list(grad)?is_list($r)?[($r[0]-(h22/tan(grad[0])))/($r[0]),($r[1]-(h22/tan(grad[1])))/($r[1])]:[($r-(h22/tan(grad[0])))/($r),($r-(h22/tan(grad[1])))/($r)]:($r-(h22/tan(grad)))/($r) - :is_list(grad2)? - is_list($r)?[($r[0]-(h22/tan(grad2[0])))/($r[0]),($r[1]-(h22/tan(grad2[1])))/($r[1])]:[($r-(h22/tan(grad2[0])))/($r),($r-(h22/tan(grad2[1])))/($r)]:($r-(h22/tan(grad2)))/($r); -scale=h2?is_undef(grad)?scale: - is_list(grad)? - is_list($r)?[($r[0]-(h2/tan(grad[0])))/($r[0]),($r[1]-(h2/tan(grad[1])))/($r[1])]:[($r-(h2/tan(grad[0])))/($r),($r-(h2/tan(grad[1])))/($r)]:($r-(h2/tan(grad)))/($r):1; - - - -grad=h2?is_list(scale)? - is_list($r)?[atan(h2/($r[0]-$r[0]*scale[0])),atan(h2/($r[1]-$r[1]*scale[1]))]:[atan(h2/($r-$r*scale[0])),atan(h2/($r-$r*scale[1]))] - :atan(h2/($r-$r*scale)):0; - -grad2=h22?is_list(scale2)?is_list($r)?[atan(h22/($r[0]-$r[0]*scale2[0])),atan(h22/($r[1]-$r[1]*scale2[1]))]:[atan(h22/($r-$r*scale2[0])),atan(h22/($r-$r*scale2[1]))]:atan(h22/($r-$r*scale2)):0; - -mantelwinkel=is_undef(twist)?mantelwinkel:atan(twist*PI*$d/360/hc); -twist=is_undef(twist)?mantelwinkel?360*tan(mantelwinkel)*hc/(2*PI*$r):0:twist; -slices=is_undef(slices)?$preview?twist?fn:1:round(min(abs(twist)/hc*10,hc/l(2))):slices; - - - - InfoTxt("LinEx",["core h",str(hc,"mm - twist per mm=",twist/(hc),"°, Fase für $d= ",$d,"mm ist ",grad,"°/",grad2,"° d=",$d*scale,"/",$d*scale2,"mm - r=",$r*scale,"/",$r*scale2,"mm Mantelwinkel für $d/$r=",$d,"/",$r,"mm⇒ ",mantelwinkel,"° twist=",twist,"° slices=",slices)],name); - - - - Echo(str(name," LinEx Höhe center=",hc,"mm"),color="red",condition=hc<0); - - if(is_list(grad2)?$r*tan(min(grad2[0],grad2[1]))<(is_list($r)?[h22,h22]:h22)&&min(grad2[0],grad2[1])<90&&min(grad2[0],grad2[1])>0:$r*tan(grad2)<(is_list($r)?[h22,h22]:h22)&&grad2<90&&grad2>0)Echo(str(name," LinEx Höhe h22=",h22," mm zu groß oder winkel/$r zu klein min=",atan(h22/$r),"° max=",is_list(grad2)?$r*tan(min(grad2[0],grad2[1])):$r*tan(grad2),"mm"),color="red"); - - if(is_list(grad)?$r*tan(min(grad[0],grad[1]))<(is_list($r)?[h2,h2]:h2)&&min(grad[0],grad[1])<90&&min(grad[0],grad[1])>0:$r*tan(grad)0)Echo(str(name," LinEx Höhe h2=",h2," mm zu groß oder winkel/$r zu klein min=",atan(h2/$r),"° max=",$r*tan(grad),"mm"),color="red"); - - HelpTxt("LinEx",["h",h,"h2",h2,"h22",h22,"scale",scale,"scale2",scale2,"twist",twist,"twistcap",twistcap,"slices",slices,"$d",$d,"grad",grad,"grad2",grad2,", mantelwinkel",mantelwinkel,"center",center,"rotCenter",rotCenter,"end",end,"fn",fn,"name",name],help); - - - -rotate(center?0:rotCenter?-twist/2:-twist/2+(twistcap[0]&&hc?-twist/hc*h2:0)) - T(z=center?-h/2:0){ - - $idx=true; - union(){ - - //capoben - if(h22)T(z=h-h22)rotate(-twist/2)linear_extrude(h22,scale=scale2,twist=twistcap[1]?twist/(hc)*h22:0,convexity=5,slices=slices/hc*h22)children(); - - //capunten - if(h2)Tz(h2)rotate(twist/2)mirror([0,0,1])linear_extrude(h2,scale=scale,twist=twistcap[0]?-twist/(hc)*h2:0,convexity=5,slices=slices/hc*h2)children(); - } - - //center - Tz(h2){ - $idx=0; - $tab=is_undef($tab)?1:b($tab,false)+1; - rotate(twist/2)linear_extrude(hc,scale=1,convexity=5,twist=twist,slices=slices,center=false)children(); - } - - - - if(end[0]){ - - rotate(twist/2+(twistcap[0]?twist/(hc)*h2:0))rotate(sign(end[0])>+0?[-90,0,-90]:[-90,0,0]) RotEx(cut=true,grad=180,fn=fn)scale(scale)rotate(sign(end[0])>0?90:0)children(); - } - if(end[1]){ - - Tz(h)rotate(-twist/2-(twistcap[1]?twist/(hc)*h22:0))rotate(sign(end[1])>+0?[-90,0,-90]:[-90,0,0])RotEx(cut=true,grad=-180,fn=fn) - scale(scale2)rotate(sign(end[1])>0?90:0)children(); - } - - } - MO(!$children); - -} - - - - - - - - -///ΔΔ Generator ΔΔ/// - -///∇∇ Basic Objects ∇∇/// - - -/* -points=[[0,0,-2],for(i=[0:35])[sin(i*10),cos(i*10),0],for(i=[0:35])[sin(i*10),cos(i*10),5],[0,0,7]]; -points1=[for(i=[0:36])[sin(i*10),cos(i*10),0]*1.5,for(i=[0:36])[sin(i*10),cos(i*10),5],for(i=[0:36])[sin(i*10)*0.75,cos(i*10)*1.5,10]]; -pointsE1=[[0,0,-2],for(i=[0:35])[sin(i*10),cos(i*10),0],for(i=[0:35])[sin(i*10),cos(i*10),5]]; -pointsE2=[for(i=[0:35])[sin(i*10),cos(i*10),0],for(i=[0:35])[sin(i*10),cos(i*10),5],[0,0,7]]; - - -//Points(points1,loop=36,start=36*2); -//echo(points1[36]); - -PolyH(points,loop=36,pointEnd=true,end=true,name="pointy"); -T(10)PolyH(pointsE1,loop=36,pointEnd=1,end=true,name="point∇"); -T(-10)PolyH(pointsE2,loop=36,pointEnd=2,end=true,name="pointΔ");//WIP -T(0,-10)PolyH(points1,loop=37,pointEnd=0,end=true); -T(0,10)PolyH(octa(5)); //*/ -module PolyH(points,loop,end=true,pointEnd=false,convexity=5,name,help){ -loop=is_undef(loop)||loop<3?1:loop; -points=assert(!is_undef(points))points; -lp=len(points); -loops=pointEnd?pointEnd==1||pointEnd==2?(lp-1)/loop: - (lp-2)/loop: - lp/loop; +module HexGrid(e=[11,4],es=5,center=true,name,help){ -fBottom=[[for(i=[loop -1:-1:0])i]]; -fTop=[[for(i=[0:loop -1])i+lp-(loop)]]; -fBody=loops>1?[for(lev=[0:loops -2],i=[0:loop -1])[ - i +loop*lev, - (i +1)%loop+loop*lev, - (i +1)%loop+loop*(lev+1), - i +loop*(lev+1) -]]:[]; + es=is_list(es)?es:assert(is_num(es),str("HexGrid es need to be list or number es=",es))[es*sin(60),es]; + e=is_list(e)?e:assert(is_num(e),str("HexGrid e need to be list or number e=",e))[e,e,1]; + $d=es.y; + $r=$d/2; + center=is_list(center)?bool(center,false):bool(center,false) * [1,1,1]; + iCenterX=center.x>1?(center.x-1)*es.x/6 + :center.x<-1?(center.x+1)*es.x/6 + : 0; + iCenterY=center.y>1?(center.y-1)*es.y/4 + :center.y<-1?(center.y+1)*es.y/4 + : 0; - -faces=loop>1?end?concat( - fBottom, - pointEnd==2?[for(i=[0:loop -1])[lp-i -2,lp-1,lp-(i+1)%loop -2]]:fTop, - fBody - ): - fBody: - [[for(i=[0:lp-1])i]] -; - -pointyFaces=(pointEnd==true||pointEnd==1)&&loops>1?[ -if(pointEnd==true||pointEnd==1) for(i=[0:loop -1])[(i + 1)%loop + 1,i +1,0],//bottom -if(pointEnd==true||pointEnd==2) for(i=[0:loop -1])[lp-i -2,lp-1,lp-(i+1)%loop -2],//top -for(lev=[0:loops -2],i=[0:loop -1])let(pE=1)[ - pE + i +loop*lev, - pE + (i +1)%loop+loop*lev, - pE + (i +1)%loop+loop*(lev+1), - pE + i +loop*(lev+1) -] -]:[]; - - -if(loop>1)polyhedron(points,(pointEnd==true||pointEnd==1)&&loop>1?pointEnd==1?concat(pointyFaces,fTop): - pointyFaces: - faces,convexity=convexity); - else hull()polyhedron(points,faces,convexity=convexity); - -InfoTxt("PolyH",["loops",loops,"points",lp],loop>1?name:false); -InfoTxt("PolyH using hull—",["points",lp],loop==1?name:false); +//shifting for center and pattern change + shift=(is_undef(useVersion)||useVersion>23.300)? + [iCenterX,iCenterY+(e.y>round(e.y)?-es.y/2 + :e.yround(e.y)?-es.y/2:e.y0||($idx.x)%2)children(); } + else children(); } - } -InfoTxt("KBS",["size",str( - str(d+rand*2+ks*(e.x-1),"×",d+rand*2+ks*(e.y-1),e.z?str("×",e.z*bh):"") - ,grad?str(" diff ",grad,"° bei h=2mm ",tan(grad)*2): - "" - )],name); - -HelpTxt("KBS",["e",e,"grad",grad,"center",center,"male",male,"female",female,"rot",rot,"n",n,"top",top,"knob",knob,"knobH",knobH,"fKnob",fKnob,"fKnobH",fKnobH,"dist",dist,"bh",bh,"name",name],help); -} - - - - - - - - - - - - -module GT2Pulley( -h=6,// Belt h -z=16,// teeth -achse=6.6,//hole -center=true, -name, -help){ -d=2*z/PI+(0.63-0.254)*2+0.2; - -center=is_bool(center)?center?1:0:center; -T(center?center<0?[0,0,h/2+1.1]: - [0,0,0]: - [z/PI,z/PI,h/2]){ -if($info)%Ring(h,d=2*z/PI,rand=-.63,center=true); -$info=false; -LinEx(h+1,center=true)GT(z=z,achse=achse); -difference(){ + if(!$children)color("magenta",.5)HexGrid(e=e,es=es,center=center,name=false)circle($r); -MKlon(tz=-h/2-1.1){ -Pille(.5,d=d,rad2=0,center=false);//cylinder(.5,d=12); -Tz(.5)Kegel(d1=d,d2=d-2.5,grad=25); -} -cylinder(50,d=achse,center=true); -MKlon(tz=-h/2-1.3)Kegel(achse+0.75); -} -//%Ring(h,d=d,rand=1.38,center=true); - -} - -InfoTxt("GT2Pulley",["aussenH",h+2.2,"d",d,"radius Riemenmitte",z/PI],name); -HelpTxt("GT2Pulley",["h",h,"z",z,"achse",achse,"center",center,"name",name],help); -} - - - -// Was KreisSeg( Was TorusSeg( -module RingSeg( -grad=90, -size=4, -h, -rad=1.0, -r=10, -spiel=.5, -fn=fn, -fn2, -name, -help -){ - HelpTxt("RingSeg",["grad",grad,"size",size,"h",h,"rad",rad,"r",r,"spiel",spiel,"fn",fn,"fn2",fn2,"name",name],help); - $info=name; - rad2=rad+spiel;//spiel - -h=assert(is_num(size))is_undef(h)?size:h; - winkel2=asin(rad2/(r+size/2-rad)); - winkel1=asin(rad2/(r-size/2+rad)); - -fn2=is_undef(fn2)?fn:fn2; -fnS=fn2; + MO(!$children); +// info of Grid will be used additional for changed pattern this: + if(e.y%1)InfoTxt("HexGrid",["elements",round(e.x)*round(e.y)*(e.z?e.z:1) + - (e.yr1"); - fn2=fn/2; - //$fn=fn; - -function h(i)=Kathete(r2+rad,cos(i*360/fn)*(r1+rad))-rad; -function hIn(i)=Kathete(r2+rad,cos(i*360/fn)*(r1+rad*1.50))+rad; -sc=(r1+rad-rad*sin(asin((r1+rad)/(r2+rad))))/(r1+rad); - -rotate(inside?180:0,v=[0,1])intersection(){ - difference(){ - if(!inside)cylinder(r2+rad,r=r1+rad); - if(inside)scale([1+(1-sc),1])Tz(-r2*2+rad)cylinder(r2+rad,r=r1+rad); - cylinder((r2+rad)*3,r=r1-spiel,center=true); - if(!inside)R(90)cylinder((r1+rad)*3,r=r2-spiel,center=true,$fa=+1,$fn=undef); - Tz(inside?rad*3:rad)for(i=[0:fn]){ - step=360/fn; - hull(){ - Tz(inside?-hIn(i):h(i))rotate(i*step)T(r1+rad,z=-rad)Pille(l=.1+r2+(inside?rad*3:rad)-h(i),r=rad,rad=rad,rad2=0,center=false,name=false,fn=fn,fn2=fn2); - Tz(inside?-hIn(i+1):h(i+1))rotate((i+1)*step)T(r1+rad,z=-rad)Pille(l=.1+r2+(inside?rad*3:rad)-h(i+1),r=rad,rad=rad,rad2=0,center=false,name=false,fn=fn,fn2=fn2); - } - /*hull(){ hull(){ - Tz(inside?-hIn(i):h(i))rotate(i*step)T(r1+rad)R(90)sphere(r=rad); - Tz((inside?-1:1)*r2)rotate(i*step)T(r1+rad)R(90)cylinder(.5,r1=rad,r2=0); - } - hull(){ - Tz(inside?-hIn(i+1):h(i+1))rotate((i+1)*step)T(r1+rad)R(90)sphere(rad);//cylinder(.5,r1=rad,r2=0); - Tz((inside?-1:1)*r2)rotate((i+1)*step)T(r1+rad)R(90)cylinder(.5,r1=rad,r2=0); - } - } // end hull */ - } - } -if(!inside)scale([sc,1.00])cylinder(500,r=r1+rad,center=true); -if(inside)R(90) cylinder(500,r=r2+spiel,center=true); -} - -HelpTxt("Abzweig",["r1",r1,"r2",r2,"rad",rad,"inside",inside,"d1",d1,"d2",d2,"spiel",spiel,"fn",fn],help); -} - -module HypKehleD(grad=40,steps=15,l=10,l2,l3,d=2.5,d2,fill=false,exp=1,fn=24,name,help){ - exp=is_num(exp)?[exp,exp]:is_bool(exp)?[1,1]:exp; - d3=is_undef(d3)?d:d3; - l= is_list(l)?len(l)==3?l: - concat(l,l[0]): - [l,l,l]; - - l3=is_undef(l3)?l[2]:l3; - l2=is_undef(l2)?l[1]:l2; - HypKehle(grad=90-grad,l=l2,l2=l3,steps=steps,d1=d,d2=d2,exp=exp[1],fill=fill,fn=fn); - R(0,180)HypKehle(grad=90+grad,l=l[0],l2=l3,d1=d,d2=d2,steps=steps,exp=exp[0],fill=fill,fn=fn); - - HelpTxt("HypKehleD",["grad",grad,"steps",steps,"l",l,"l2",l2,"l3",l3,"d",d,"d2",d2,"fn",fn,"fill",fill,"exp",exp,"name",name],help); -} - - - -module HypKehle(l=15,grad=90,d1=3,d2,l2,steps=20,fn=24,fill=false,exp=1,center=false,name,help){ - - rot=1; - d2=is_undef(d2)?d1:d2; - $d=d1; - $r=d1/2; - l2=is_undef(l2)?l:l2; - $info=false; - $idxON=false; - $tab=is_undef($tab)?1:b($tab,false)+1; - -R(center?-grad/2:0) -for(i=[0:steps-1]){ - Color(1/(steps*1.5)*i,$idxON=false)hull() - union(){ - $idx=i; - Tz(pow(i,exp)*l/pow(steps-1,exp))R((grad +(180-grad)/(steps-1)*i)*rot +(rot?0:180)) - if($children)linear_extrude(.1,scale=0)children(0); - else rotate(180/fn)cylinder(.1,d1=d1,d2=0,$fn=fn); - - if(fill){ - $info=false; - if($children)R(0,90)RotEx(cut=true,fn=fn)rotate(90)children(); - else Isosphere(d=is_num(fill)?fill:max(d1,d2),$fn=fn); - } - - Color($idxON=false) R(grad)Tz(pow((steps-1)-i,exp)*l2/pow(steps-1,exp)) R( (180-grad)/(steps-1)*i*rot +180) - if($children){ - $info=$children>1?1:0; - linear_extrude(.1,scale=0)mirror([0,1])children($children>1?1:0); - } - else rotate(180/fn)cylinder(.1,d1=d2,d2=0,$fn=fn); - } -} -if(!fill&&!$children)R(0,0,90)Isosphere(d=is_num(fill)?fill:max(d1,d2),$fn=fn); -HelpTxt("HypKehle",["l",l,"grad",grad,"d1",d1,"d2",d2,"l2",l2,"steps",steps,"fn",fn,"fill",fill,"exp",exp,"center",center,"name",name],help); -} - - - -module BB( -r=10, -ball=5, -rand=1, -e, -spiel=0.125, -support=0.15, -h, -top, -cage=false, -cyl=true, -achse, -od, -rad=[.75,.75], -center=true, -name, -help -){ -$info=false; -$helpM=false; -rand=is_list(rand)?rand:[rand,rand]; -top=is_undef(top)?rand[0]/2:top; -h=is_undef(h)?ball+top*2:h; - -if(achse&&achse>r*2-ball-2*rand[1]-2*spiel)Echo("BB Achse zu groß - limited",color="red"); -if(od&&odball+top*2) Echo("BB Kugel = Walze!",color="green"); -achseDia=is_undef(achse)?r*2-ball-2*rand[1]-2*spiel:min(r*2-ball-2*rand[1]-2*spiel,achse); -oDia=is_undef(od)? r*2+ball+2*rand[0]+2*spiel:max(od,r*2+ball+2*rand[0]+2*spiel); -e=is_undef(e)?floor(360/gradS(r=r,s=ball+spiel)):min(e,floor(360/gradS(r=r,s=ball+spiel))); - - - InfoTxt("BB",["Achse",achseDia,"Hoch",h,"OD",oDia,"Kugel∅",h>ball+top*2?str(ball,"×",h-top*2):ball,"Anzahl",e],name); - Tz(center?0:h/2){ - Polar(e,r)if(h>ball+top*2)Pille(h-top*2,d=ball);else sphere(d=ball); - difference(){ - union(){ - Pille(h,d=oDia,rad=rad[0]);//Body - Tz(center?0:-h/2)children(); - } - if(achseDia) Strebe(h,d=achseDia,rad=rad[1],center=true);// Achse - - if(h>ball+top*2)Torus(trx=r,d=ball+spiel*2)MKlon(mx=1)Pille(h-top*2+spiel*2,d=$d,2D=+1); - else Torus(trx=r,d=ball+spiel*2);//Rille - Mklon(tz=h/2+1.25)Torus(trx=r,d=ball,fn2=6);//innenfase - Ring(h+1,d=r*2,rand=ball/2,rcenter=true,center=true);//Trennspalt - } - - if (cage) difference(){ - union(){ - if(h>ball+top*2)Torus(trx=r,d=ball-spiel*2)MKlon(mx=1)Pille(h-top*2-spiel*2,d=$d,2D=+1); - else Torus(trx=r,d=ball-spiel*2); - Ring(h=h,d=r*2,rand=ball/2,rcenter=true,center=true); - } - Polar(e,r)if(h>ball+top*2)Pille(h-top*2+.6,d=ball+.6); else sphere(d=ball+.6); - Tz(-h/2) Ring(h=top,d=r*2,rand=ball,rcenter=true,center=false); - } - -//supportbrim - if(support&&!cyl)difference(){ - Tz(-h/2) Ring(h=top+.2,d=r*2,rand=ball/2-.5,rcenter=true,center=false); - - if (h>ball+top*2) Tz(-h/2+top+ball/2)Polar(e,r)sphere(r=ball/2+support); - else Polar(e,r)sphere(r=ball/2+support); - } - if(cyl)Tz(-h/2){ - Polar(e,r)cylinder(h=h/2,d=ball/2-.5); - if(support)Ring(l(2),r=r,rand=n(2),rcenter=true); - } - } -HelpTxt("BB",["r",r,"ball",ball,"rand",rand,"e",e,"spiel",spiel,"support",support,"h",h,"top",top,"cage",cage,"cyl",cyl,"achse",achse,"od",od,"rad",rad,"center",center,"name",name],help); -} - - -module Egg(r1=10,r2=3,breit,grad,r3=true,fs=fs,name,help){ - - breit=is_undef(breit)?r1:breit; - x=r1-breit/2; - r2=is_undef(grad)?r2:r1-(Hypotenuse(x,tan(grad)*x)); - assert(breit>=r2*2,str("max r2=",breit/2,"/ breit min=",r2*2," r2=",r2,"breit=",breit)); - a=r1-r2; - grad=is_undef(grad)?acos(x/a):grad; - hM=tan(grad)*x; - -// %Color(){ -// Kreis(r1,grad=grad,center=false,t=[0,-r1/2]); -// Kreis(r2,grad=180-grad*2,center=true,t=[hM,0]); -// Kreis(r1,grad=grad,center=false,rot=180-grad,t=[0,r1/2]); -// if(r3)Kreis(grad=180,r1/2,rot=180); } - - - - points=concat( - kreis(r1,grad=grad,rot=-90,center=false,t=[x,0],rand=0,sek=true,fn=fs2fn(r1,grad,fs,5)) - , kreis(r2,grad=180-grad*2,rot=90,center=true,t=[0,hM],rand=0,sek=true,fn=fs2fn(r2,180-grad*2,fs,5))//spitze - , kreis(r1,grad=grad,center=false,rot=90-grad,t=[-x,0],rand=0,sek=true,fn=fs2fn(r1,grad,fs,5)) - ); - - pointsR3=Kreis(grad=180,r=breit/2,rot=-90,rand=0,sek=true,fn=fs2fn(breit/2,180,fs,10)); - - polygon(r3?concat(points,pointsR3):points); - - //if(help)echo("Help Egg(r1=10,r2=3,grad,r3=1,name,help);"); - HelpTxt("Egg",["r1",r1,"r2",r2,"breit",breit,"grad",grad,"r3",r3,"fs",fs,"name",name],help); - InfoTxt("Egg",["hM",hM,"h",str(hM+r2,r3?str("/",hM+r2+breit/2):""),"breit(r3×2)",breit,"grad",grad,"r1",r1,"r2",r2],name); -} - - - -module GT(z=20,achse=3.5,spiel=.05,evolute=true,pulley=true,linear=true,fn=fn,name,help){ - fn=max(6,fn); - p=2; // zahnabstand - PLD=0.254; // ?Mittellinie? Pitch Line distance - r1=.15;//kehle basis zahn - r2=1; // zahn flanken radius im abstand [b,i] - r3=.555;// zahn spitzen radius - b=0.4;// abstand mitte Mittelpunkt r2 - h=1.38; //gesamt h (i+ht) - ht=0.75; // zahnhöhe - i=.63; // band dicke - breiteZahn=(r2-b)*2; - umfang=z*p; - - - -module GT2(){ //GT2 - - - pointsGT2= concat( - [[-p,ht],[-p,ht+i],[p,ht+i],[p,ht]] - , kreis(r=r2,fn=fn/16,grad=22.5,center=false,t=[-b,ht],rot=90,rand=0,sek=true) - , kreis(r=r3,grad=180-45,rot=-90,fn=fn/4,t=[0,r3],rand=0,sek=true) - , kreis(r=r2,fn=fn/16,grad=22.5,center=false,t=[b,ht],rot=-90-22.5,rand=0,sek=true) - ); - - T(0,-ht)Rund(0,r1,fn=fn) - polygon(pointsGT2); - -//union(){ -//%T(-p,ht)square([2*p,i]); -// } -// Color("lime")T(0,r3,-0.1)circle(r3,$fn=fn); -// Color("green")T(0,ht,-.11)intersection(){ -// T(b)circle(r=r2,$fn=fn); -// T(-b)circle(r=r2,$fn=fn); -// square([2,0.85],true); -// } - //%Color("red")T(0,ht-r1)MKlon(0.736)circle(r1); - -} - - -if(pulley){ - if(evolute){ - offset(-spiel)Rund(0.1,0,fn=fn){ - r=umfang/2/PI; - difference(){ - circle(r,$fn=z*2); - for(i=[0:z-1])rotate(i*360/z) - for(i=[-20:20])rotate(-i)T(-umfang/360*i,r-PLD)GT2(); - if(achse)circle(d=achse-spiel*2,$fn=fn); - } - InfoTxt("GT2 Pulley evolute profile",["Dia",r*2-spiel*2-PLD*2,"z",z],name); - //if(name)echo(str(is_bool(name)?"":"",name," GT2 Pulley evolute profil Dia=",r*2-spiel*2-PLD*2," z=",z)); - } - } - else{ - offset(-spiel)Rund(r1,0,fn=fn){ - r=umfang/2/PI-PLD; - difference(){ - circle(r,$fn=z*2); - for(i=[0:z-1])rotate(i*360/z)T(0,r)GT2(); - if(achse) circle(d=achse-spiel*2,$fn=fn); - } - InfoTxt("GT2 Pulley",["Dia",r*2-spiel*2,"z",z],name); - //echo(str(is_bool(name)?"":"",name," GT2 Pulley Dia=",r*2-spiel*2,"z=",z)); - } - } - - } - else { - $info=false; - if (linear)Linear(e=z,es=2)GT2(); - else { - r=umfang/2/PI; - intersection(){ - Polar(e=z,y=r-PLD)GT2(); - circle(r+i-PLD,$fn=z*2); - } - } - InfoTxt("GT2 Belt",concat(["Länge",z*p],linear?[]:["(aussen",str((umfang/2/PI+i-PLD)*2*PI,")")]),name); - // echo(str(is_bool(name)?"":"",name," GT2 Belt Länge=",z*p,linear?"":str("(aussen ",(umfang/2/PI+i-PLD)*2*PI,")"))); - - } - -HelpTxt("GT",["z",z, -"achse",achse, -"spiel",spiel, -"evolute",evolute, -"pulley",pulley, -"linear",linear, -"fn",fn, -"name",name -],help); - + HelpTxt("HexGrid",[ + "e",e + ,"es",es + ,"center",center + ,"name",name] + ,help); } @@ -2847,6 +2562,2578 @@ MO(!$children); } +module Drehpunkt(x=0,rz=0,rx=0,ry=0,y=0,z=0,messpunkt=messpunkt,help) +{ + y=is_list(x)?x[1]:y; + z=is_undef(x[2])?z:x[2]; + x=is_list(x)?x[0]:x; + lMP=is_bool(messpunkt)?$vpd/4:messpunkt; + + translate([x,y,z])rotate([rx,ry,rz])translate([-x,-y,-z])children(); + if(messpunkt) + { + if(rz)%color("blue")translate([x,y,z])cylinder(lMP,d=.5,center=true,$fn=12); + if(ry)%color("green")translate([x,y,z])rotate([0,0,rz])rotate([90,0,0])cylinder(lMP,d=.5,center=true,$fn=12); + if(rx)%color("red")translate([x,y,z])rotate([rx,ry,rz])rotate([0,90,0])cylinder(lMP,d=.5,center=true,$fn=12); + %color("yellow")translate([x,y,z])sphere(d=1,$fn=12); + } + MO(!$children); + + HelpTxt("Drehpunkt",[ + "x",x, + "rz",rz, + "rx",rx, + "ry",ry, + "y",y, + "z",z, + "messpunkt",messpunkt], + help); + +} + +/** \page Modifier +Rand() creates an outline on a polygon +\param rand thickness of outline + or - +\param center if outline centered +\param fn,fs fragments for outline +\param delta, chamfer use delta (no radial extension) +\param help help +*/ + +/* +Rand(1,center=1.0,delta=0)Star(8); +Tz(-1)Color(alpha=0.3)Star(8); +//*/ + +module Rand(rand=n(1),center=false,fn=0,fs=$preview?min(fs,.3):fs,delta=false,chamfer=false,help){ + $fs=fs; + ifn=$fn; + +if(!center){ + if(rand>0)difference(){ + offset(r=delta?undef:rand,delta=rand,$fn=fn,chamfer=chamfer?true:false)children($fn=ifn); + union(){ + $helpM=0; + $info=0; + children(); + } + } + if(rand<0)difference(){ + children(); + union(){ + $helpM=0; + $info=0; + offset(r=delta?undef:rand,delta=rand,$fn=fn,chamfer=chamfer?true:false)children($fn=ifn); + } + } + } + +if(center&&rand) + difference(){ + chg=sign(b(center,false))*(rand/2)*(1-abs(b(center,false)) ); + offset(r=delta?undef:abs(rand)+chg,$fn=fn,delta=abs(rand),chamfer=chamfer?true:false)offset(r=true?undef:-abs(rand/2)-chg,$fn=fn,delta=-abs(rand/2)-chg,chamfer=chamfer?true:false)children($fn=ifn); + union(){ + $helpM=0; + $info=0; + offset(r=delta?undef:-abs(rand)-chg,$fn=fn,delta=-abs(rand),chamfer=chamfer?true:false) offset(r=true?undef:(abs(rand/2)+chg),$fn=fn,delta=abs(rand/2)+chg,chamfer=chamfer?true:false)children($fn=ifn); + } + } + +if(rand==0)children(); + MO(!$children); + + HelpTxt("Rand",["rand",rand,"center",center,"fn",fn,"fs",fs,"delta",delta,"chamfer",chamfer],help); +} + +/** \page Polygons +Rund() polygon rounds a polygon via offset +\param or outer radius +\param ir inner radius outer radius is used if undef +\param chamfer use chamfer +\param fn fragments (optional [or,ir]) +\param fs fragmentsize (optional [or,ir]) +*/ +//Rund(1,2)Star(); + + +module Rund(or=+0,ir,chamfer=false,fn,fs=$preview?min(fs,.3):fs,fa=$fa,help) { + fs=is_list(fs)?fs:[fs,fs]; + fn=is_list(fn)?fn:[fn,fn]; + ir=is_undef(ir)?is_list(or)?or[1]:or:ir; + or=is_list(or)?or[0]:or; + chamfer=chamfer?true:false; + if(!chamfer) + offset(r = -ir,$fn=fn[1],$fs=fs[1],$fa=fa)offset(delta = ir,$fn=fn[1],$fs=fs[1],$fa=fa) + offset(r = or,$fn=fn[0],$fs=fs[0],$fa=fa)offset(delta = -or,$fn=fn[0],$fs=fs[0],$fa=fa) + children(); + + + if(chamfer)offset(delta = or,chamfer=chamfer)offset(delta = -or,chamfer=false) + offset(delta = -ir,chamfer=chamfer)offset(delta = ir,chamfer=false) + children(); +MO(!$children); +HelpTxt("Rund",["or",or,"ir",ir,"chamfer",chamfer,"fn",fn,"fs",fs],help); +} + + +}//fold// /ΔΔ Modificatoren ΔΔ/ // +{//fold // \∇∇ Helper ∇∇/ // (not for creating geometry or objects) + + +/** \page Helper +PolyDeg(points) shows the angle with colors in a polygon +\name PolyDeg +\param points points +\param rad radius of marker +\param poly draw polygon from points +\param txt anotation angle +*/ +module PolyDeg(points,rad=1,poly=true,txt=true,help){ + +c=[ +"darkOrange", +"Chartreuse", +"LightSkyBlue", +"SteelBlue", +]; + +HelpTxt("PolyDeg",["points",points,"rad",rad,"poly",poly,"txt",txt],help); + +Echo("No Points",color="redring",condition=!is_list(points[2])); +if(is_list(points[2])&&poly)polygon(points,convexity=5); + +if(is_list(points[2])) + for(p=[0:len(points)-1])translate(points[p]) { + let( + offset=0, + pBef=points[(p+len(points)-1)%len(points)], + pNow=points[p], + pNex=points[(p+1)%len(points)], + grad1=atan2(pBef.x-pNow.x,pBef.y-pNow.y), + grad2=atan2(pNex.x-pNow.x,pNex.y-pNow.y), + gradDiff=grad1-grad2, + grad=gradDiff<0?abs(gradDiff):360-gradDiff, + gradSup=360-grad + ) + %Tz(.1)union(){ + color(abs(grad)%90?abs(grad)>90?abs(grad)>180?c[3]:c[2]:c[0]:c[1])polygon(kreis(r=rad,grad=grad,rot=grad1,center=false,rand=rad/5)); + color(abs(gradSup)%90?abs(gradSup)>90?abs(gradSup)>180?c[3]:c[2]:c[0]:c[1])polygon(kreis(r=rad,grad=gradSup,rot=grad2,center=false,rand=-rad/5)); + + if(txt)color(abs(gradSup)%90?abs(gradSup)>90?abs(gradSup)>180?c[3]:c[2]:c[0]:c[1])text(str(gradSup,"° "),size=b(txt,false),halign="right"); + if(txt)color(abs(grad)%90?abs(grad)>90?abs(grad)>180?c[3]:c[2]:c[0]:c[1])text(str(grad,"°"),size=b(txt,false)); + } + } +} + +/** \page Helper +PrevPos() object position Object for preview only +\name PrevPos +\param t translate preview position +\param z translate z in preview +\param rot rotates in preview +\param tP translates the print position +*/ + +module PrevPos(on=true,t=[0,0,0],z=0,rot=[180,0,0],tP=[0,0,0],help){ +rot=is_num(rot)?[0,0,rot]:rot; +if($preview&&on||on==2)translate(v3(t)+[0,0,z])rotate(v3(rot))children(); +else translate(v3(tP))children(); + +Echo("Render with PrevPos!",color="warning",condition=on==2); + +MO(!$children); + +HelpTxt("PrevPos",["on",on,"t",t,"z",z,"rot",rot,"tP",tP],help); +}; + + +/** \page Helper +Points() show point position with numbers in preview only +\name Points +\param points points list to show +\param color optional color else rainbow is used +\param size optional else distance is used to scale +\param hull optional creates a convex hull around points - number will be used for transparency/alpha +\param loop size of a loop of points +\param start start point of that loop +\param mark list for points to mark +\param markS markCol marking size and color +\param face highlight marked points as face with normal and order number +\param center orientation of number label radial (true) or viewpoint +\param help help +*/ + +//Points(octa(5),loop=4,size=0.4); +//Points(kreis(),mark=[0,1,2,3,4,5,6,7,8],loop=13,start=10); +//Points(octa(5),mark=[3,4,2,1],hull=.5*0); +//Points(octa(5),mark=[3,0,2,1],hull=true); + + + +module Points(points=[[0,0]],color,size,hull,loop,start=0,mark,markS,markCol,face=true,center,help){ + center=is_undef(center)?is_num(points[0].z)?true:false:center; + lp=assert(is_list(points),"no point(s) input")len(points); + loop=is_undef(loop)?lp>25?lp: + lp: + loop; + cMark=is_undef(markCol)?["Magenta","Chartreuse","Aqua","LightSkyBlue"]:markCol; + size=is_undef(size)?$vpd/100:size; + markS=is_undef(markS)?$vpd/40:markS;// scale marks + lenM=is_list(mark)?len(mark):0; + + if($preview){ + + if(face&&lenM>2){ + color("Chartreuse",alpha=.5) + polyhedron([for(i=[0:lenM-1])points[mark[i]]],[[for(i=[0:lenM-1])i]]); + if(len(points[0])==3)for(i=[0:lenM-1]){ + p0=points[mark[i]]; + p1=points[mark[(i+1)%lenM]]-points[mark[i]]; + p2=points[mark[(i+2)%lenM]]-points[mark[i]]; + pNormal=cross( p2, p1 ); +//echo(i,norm(pNormal)); + translate((p0+points[mark[(i+1)%lenM]]+points[mark[(i+2)%lenM]])/3){ + color("Lime",0.8)hull(){ + translate(pNormal/norm(pNormal)*markS)sphere(minVal,$fn=3); + sphere(d=markS/3,$fn=9); + } + color("HotPink",0.8)sphere(d=markS/2.9,$fn=9); + } + } + } + + for (i=[0:is_list(points[0])?lp-1:0])translate(is_list(points[0])?points[i]:points){ + if(is_num(mark)&&i==mark){ + color("Chartreuse", alpha=.6)OctaH(.6*markS); + color("Chartreuse", alpha=1)T(0,markS)linear_extrude(.01,convexity=3)text(str(points[i]),size=markS/3,halign="center"); + } + if(is_list(mark)) for(j=[0:len(mark)-1])if(i==mark[j]){ + color(cMark[j%len(cMark)], alpha=0.4)OctaH(0.4*markS,$fn=12); + if(face){ + // color("DarkGrey", alpha=1)rotate($vpr)T(0,markS*0.5)linear_extrude(.01,convexity=3)text(str(j),size=markS/4,halign="center"); + color("white", alpha=1)rotate($vpr)T(0,0,markS*0.5)linear_extrude(.01,convexity=3)text(str(j),size=markS/4,halign="center",valign="center"); + } + } + + if(i>=start&&i2) if(len(points[0])==3) + color(alpha=is_bool(hull)?.5: hull) hull() polyhedron(points, [[for(i=[0:len(points)-1]) i ]]); + else if(len(points[0])==2)color(alpha=is_undef(color[3])?is_bool(hull)?.2:hull:color[3])polygon(points); + + } + + HelpTxt("Points",["points",[[1,2,3]],"color",color,"size",size,"hull",hull,"loop",loop,"start",start,"mark",mark,"markS",markS,"markCol",markCol,"face",face,"center",center],help); + } + + //Points(Kreis(grad=120,fn=6),start=0,loop=6,mark=[2,3,4,12]); + + +/// Cutaway children for preview +module Schnitt(on=$preview,r=0,x=0,y=0,z=-0.01,rx=0,ry=0,sizex,sizey,sizez,center=0,help){ + sizex=is_undef(sizex)?bed?printBed.x:max(viewportSize*5,150):sizex; + sizey=is_undef(sizey)?bed?printBed.y:max(viewportSize*5,150):sizey; + sizez=is_undef(sizez)?bed?100:max(viewportSize*5,150):sizez; + + center=is_bool(center)?center?1:0:center; + if($children)difference() + { + union()children(); + if((on&&$preview)||on==2) translate([x,y,z])rotate([rx,ry,r])color([1,0,0,1])translate([center>0?-sizex/2:0,abs(center)==1?-sizey/2:-sizey,center>1||center<0?-sizez/2:0])cube([sizex,sizey,sizez],center=false); + } + +Echo("»»»»––SCHNITT in render! ––«««« \n",color="warning",condition=on==2); + +HelpTxt("Schnitt",["on",on,"r",r,"x",x,"y",y,"z",z,"rx",rx,"ry",ry,"sizex",sizex,"sizey",sizey,"sizez",sizez,"center",center],help); + +MO(!$children); +} + + +module Cut(on=1,cut=[+1,+1,+1],t=[+0,0,+0.01],rot=+0,z=0,size=500,color,ghost=false,help){ + +cut=v3(cut); +t=v3(t); +ghost=is_bool(ghost)?ghost?0.15:ghost:ghost; +size=is_list(size)?size:[1,1,1]*size; +ghostscale=.9999; +$idx=0; + +intersection(){ + union()children(); + if($preview&&on||on==2)color(color)rotate(rot){ + if(cut.x)color("red")translate([(cut.x>0?-size.x:0) + t.x,- size.y/2 , - size.z/2])cube(size); + if(cut.y)color("green")translate([-size.x/2 ,(cut.y>0?0:-size.y) + t.y, - size.z/2])cube(size); + if(cut.z)color("blue")translate([-size.x/2 ,- size.y/2 ,(cut.z>0? -size.z:0) + t.z+z])cube(size); + } +} + +if(ghost&&on&&$preview){ + $info=false; + $idx=1; + + color("lightSkyBlue",alpha=ghost)%scale(ghostscale)children(); + } +Echo("»»»»––Cut is rendered! ––«««« \n",color="warning",condition=on==2); +HelpTxt("Cut",["on",on,"cut",cut,"t",t,"rot",rot,"z",z,"size",size,"color",color,"ghost",ghost],help); +MO(!$children); +} + + + +/// 3 axis Projection + +module 3Projection(s=10,cut=true,active=[1,1,1],help){ + s=is_list(s)?s:[s,s]; + cut=is_list(cut)?cut:[cut,cut,cut]; + $info=false; + $helpM=false; + if(active.z) projection(cut=cut.z)children(); + if(active.x) translate([s.x,0,0])projection(cut=cut.x)rotate([0,90,0])children(); + if(active.y) translate([0,s.y,0])projection(cut=cut.y)rotate([-90,0,0])children(); + %children(); + MO(!$children); + HelpTxt("3Projection",["s",s,"cut",cut,"active",active],help); + +} + + +/// Arranges (and color) list of children for display +module Anordnen(es=10,e,option=1,axis=1,c=0,r,cl=.5,rot=0,loop=true,center=true,inverse=false,name,help){ + +//option=option==3&&version()==[2021, 1, 0]?4:option; +optiE= function(e=[0,0,1]) + let (sqC=sqrt($children)) + e.x*e.y==$children? + e: + e.x>4?optiE([e.x-1,e.y,1])://min 4 rows else alternate to circumvent primes + e.y>$children?[round(sqC),ceil($children/round(sqC)),1]: + optiE([ceil(sqC),e.y+1,1]); + +//echo(optiE()); + e=option==3||option==4?is_undef(e)?optiE(): + is_list(e)? + e.z?e: + concat(e,1): + [ceil($children/e),e,1]: + is_undef(e)?$children:e; + +InfoTxt("Anordnen",["e",e,"children",$children],name); + + + + if(option==1){ + r=is_undef(r)?e==1?0:(es/2)/sin(180/e):r; + Polar(e,x=r,re=rot,name=false){ + // idx=$idx; + // $idx=0; + $idxON=true; + $info=name; + if(is_undef(c)&&(loop?true:$idx<$children)) + children((inverse?$children-$idx-1:$idx)%$children);// + else Color(c+1/$children*$idx,l=cl) + if(loop?true:$idx<$children)children((inverse?$children-$idx-1:$idx)%$children); + } + } + + if(option==2) + Linear(e=e,es=es,re=rot,center=center,x=axis==1?1:0,y=axis==2?1:0,z=axis==3?1:0,name=false){ + $info=name; + //idx=$idx; + //$idx=0; + $idxON=true; + if(is_undef(c))children($idx%$children); + else Color(c+1/$children*$idx,l=cl)children($idx%$children); + } + + if(option==3) Grid(e=e,es=es,center=center,name=false){ + $info=name; + childINDX=inverse?(loop?e.x*e.y*e.z:$children -1)-($idx[0]+e.x*$idx[1]):($idx[0]+e.x*$idx[1]); + //idx=$idx; + //$idx=0; + $idxON=true; + rotate(rot) + if(is_undef(c)&&(loop?true:$idx.x+e.x*$idx.y+e.x*e.y*$idx.z<$children))children(childINDX%$children); + else Color(([$idx.x/(e.x -1),$idx.y/(e.y -1),$idx.z/e.z]+[ 0,0,cl])){ + if(loop?true:$idx.x+e.x*$idx.y+e.x*e.y*$idx.z<$children)children(childINDX%$children); + //text(str([$idx.x/(e.x-1), $idx.y/(e.y-1), $idx.z/e.z]+[ 0,0,cl]),size=2); + } + } + +// if(option==4) Grid(e=e,es=es,center=center,name=false)IDX($idx,$children)children($idx%$children); +// +// module IDX(idx,childrn){ +// $info=name; +// $idxON=true; +// $idx=inverse?(loop?e.x*e.y*e.z:childrn -1)-(idx[0]+e.x*idx[1]):(idx[0]+e.x*idx[1]); +// rotate(rot) +// if(is_undef(c)&&(loop?true:idx.x+e.x*idx.y+e.x*e.y*idx.zlen(co[pal])-1)?" — Out of Range":"")],name); + } + } + MO(!$children); +} + + +// object color with hue (and rgb) also color change for multiple children +module Color(hue=0,alpha=1,v=1,l=0.5,spread=1,$idxON=true,name=0,help=false){ + + function val(delta=0,hue=-hue*360,v=v,l=l*-2+1)= + v*max( + min( + (0.5+sin((hue+delta)))*(l>0?1-l:1) + +(max( + .5+sin((180+hue+delta)) + ,0)*(l<=0?-l:0)) + ,1) + ,0); + + start=90;// to start with red + + if($children) for(i=[0:$children-1]){// + $idx=is_undef($idx)?i:$idx; + c=is_string(hue)?hue:is_list(hue)?[(hue[0]+i*(1-hue[0]%1.001)/(spread*$children))%1.001,(hue[1]+i*(1-hue[1]%1.001)/(spread*$children))%1.001,(hue[2]+i*(1-hue[2]%1.001)/(spread*$children))%1.001]:[val(start,hue=(-hue-i/(spread*$children))*360),val(+start+120,hue=(-hue-i/(spread*$children))*360),val(start+240,hue=(-hue-i/(spread*$children))*360)]; + + if(name) echo(str("Color ",name," child ($idx) ",i," hex=",Hexstring(c)," ",Hex(alpha*255),//" ████ + "RGB=",c)); + // $idxON=true; + color(c,alpha)children(i); + + + } + else MO(!$children); + + HelpTxt("Color",[ + "hue",hue,"alpha",alpha,"v",v,"l",l,"spread",spread,"name",name, + ],help); +} + +// / Echo Helper // / console texts + +/// missing object text +module MO(condition=true,warn=false){ +$idx=is_undef($idx)?false:$idx; +Echo(str(parent_module(2)," has no children!"),color=warn?"warning":"red",condition=condition&&$parent_modules>1&&!$idx,help=false); +} + + +/// echo color differtiations +module Echo(title,color="#FF0000",size=2,condition=true,help=false){ + idx=is_undef($idx)?false:is_list($idx)?norm($idx):$idx; + idxON=is_undef($idxON)?false:$idxON?true:false; + if(condition&&(!idx||idxON)) + if (color=="#FF0000"||color=="red")echo(str("\n🔴\t»»» ",title)); + else if (color=="redring")echo(str("\n⭕\t»»» ",title)); + else if (color=="#FFA500"||color=="orange")echo(str("\n🟠\t»»» ",title)); + else if (color=="#00FF00"||color=="green"||color=="info")echo(str("🟢\t ",title)); + else if (color=="#0000FF"||color=="blue") echo(str("🔵\t ",title)); + else if (color=="#FF00FF"||color=="purple") echo(str("🟣\t ",title)); + else if (color=="#000000"||color=="black") echo(str("⬤\t ",title)); + else if (color=="#FFFFFF"||color=="white") echo(str("◯\t ",title)); + else if (color=="#FFFF00"||color=="yellow"||color=="warning") echo(str("⚠\t ",title)); + else echo(str("• ",title)); + + HelpTxt("Echo",["title",title,"color",color,"size",size,"condition",condition],help); +} + +/// display variable values +module InfoTxt(name,string,info,help=false){ + $tab=is_undef($tab)?0:$tab; + info=is_undef(info)?is_undef($info)?false: + $info: + info; + + // https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/User-Defined_Functions_and_Modules#Function_Literals + noInfo=is_undef($noInfo)?false:$noInfo; + idx=is_undef($idx)?false:is_list($idx)?norm($idx):$idx; + idxON=is_undef($idxON)?false:$idxON?true:false; + joinArray= function(in,out="",pos=0) pos>=len(in)?out: // scad version > 2021 + joinArray(in=in,out=str(out,in[pos]),pos=pos +1); + + + // current version info + infoText=[for(i=[0:2:len(string)-1])str(string[i],"=",string[i+1],i1?" ┗▶ ": + " ",info," ",name," ", +joinArray(infoText))); + +else HelpTxt(titel="InfoTxt",string=["name",name,"string","[text,variable]","info",info],help=1); + +HelpTxt(titel="InfoTxt",string=["name",name,"string","[text,variable]","info",info],help=help); +} + + +// display the module variables in a copyable format +module HelpTxt(titel,string,help){ + help=is_undef(help)?is_undef($helpM)?false: + $helpM: + help; + idxON=is_undef($idxON)?false:$idxON?true:false; + idx=is_undef($idx)||idxON?false:is_list($idx)?norm($idx):$idx; + + joinArray= function(in,out="",pos=0) pos>=len(in)?out: + joinArray(in=in,out=str(out,in[pos]),pos=pos +1); + +helpText=[for(i=[0:2:len(string)-1])str(string[i],"=",string[i+1],",\n ")]; + + + // current versions help +if(help&&!idx)if(is_list(string))echo( + +str("🟪\nHelp ",titel, "(\n ", +joinArray(helpText) +,"help=",help,"\n);\n")); +else HelpTxt("Help",["titel",titel,"string",string,"help",help],help=1); + +} + +/** \page Helper + Caliper() shows a distance and can be used as annotation + \brief Caliper shows a distance and can be used as annotation + \param l length to show + \param in direction + \param center centered length + \param messpunkt show / size of gizmo + \param translate translates the text and arrow + \param end differnt end options [0:none,1:triangle, 2:square, 3:arrow in, 4:arrow out] + \param h height while end=0,3,4 can be 2D if h=0 + \param on switch on=2 if Caliper should be rendered + \param l2 arrow width + \param txt l+mm is used optional text + \param txt2 optional second text + \param size size +*/ +//Caliper(end=0,messpunkt=0,in=1,translate=[20,-5],center=+1); + +//Caliper(end=3); +//Caliper(end=3,txt2="X—Length",in=+1,txtCenter=0); + + +module Caliper(l=40,in=1,center=true,messpunkt=true,translate=[0,0,0],end=1,h,on=$preview,l2,txt,txt2,size=$vpd/15,render,s,t,txtCenter=true,help){ + + on=render?render:on; + s=s?s:size; + txt=is_undef(txt)?str(l,end==2?"":"mm"):str(txt); + center=is_bool(center)?center?1:0:center; + textl=in>1?s/2.5:s/4*(len(str(txt)));// end=0,3,4 use own def + line=s/20; + translate=t?v3(t):v3(translate); + //l2=is_undef(l2)?s:l2; + + + if(on&&$preview||on==2)translate(translate)translate(in>1?center?[0,0]:[0,l/2]:center?[0,0]:[l/2,0]){ + if(end==1)Col(5){ + h=is_undef(h)?1.1:max(minVal,h); + rotate(in?in==2?90:in==3?-90:180:0)linear_extrude(h,center=true)Mklon(tx=l/2,mz=0)polygon([[max(-5,-l/3),0],[0,s],[0,0]]); + rotate(in?in==2?90:in==3?-90:180:0)linear_extrude(h,center=true)Mklon(tx=-l/2,mz=0)polygon([[max(-5,-l/3),0],[0,-s],[0,0]]); + + Text(h=h+.1,text=txt,center=true,size=s/4,trueSize="size"); + } + else if(end==2)Col(3)union(){ + h=is_undef(h)?1.1:max(minVal,h); + rotate(in?in==2?90:in==3?-90:180:0)MKlon(tx=l/2)T(-(l-textl*2)/4,0)cube([max(l-textl*2,.01)/2,line,h],center=true); + rotate(in?in==2?90:in==3?-90:180:0)MKlon(tx=l/2)cube([line,s,h],center=true); + translate([(l1?l/2+s/4+1:0,0]) + Text(h=h+.1,text=txt,center=true,size=s/2,trueSize="size"); + if(l=2) translate([0,.25])square([line,l+.5],true); + + } + else Col(1) { + h=is_undef(h)?.1:h; + if(h) linear_extrude(h,convexity=5) Dimensioning(); + else Dimensioning(); + } + } + +Echo("Caliper will render",color="warning",condition=on==2); +if(h&&end&&on&&end<3) +Pivot(messpunkt=messpunkt,p0=translate,active=[1,1,1,1,norm(translate)]); + + HelpTxt("Caliper",[ + "l",l, + "in",in, + "size",size, + "center",center, + "messpunkt",messpunkt, + "translate",translate, + "end",end, + "h",h, + "on",on, + "l2",l2, + "txt",txt, + "txt2",txt2, + "txtCentre",txtCenter] + ,help); + + + module Dimensioning (t=translate){ + s=s==$vpd/15?5:s; + txt2=txt2?str(txt2):""; + line=s/20; + textS=len(txt2)?s/2*.72:s*.72;//text size + l2=l2?l2:s/1.5; + textl=in>1?(len(txt2)?3:1.5)*textS:1+textS*max(len(txt),len(txt2))*0.95; + arrowL=min(l/6,s); + textOut=bool(txtCenter,false)!=1||ll/2&& (in==2||in==3) )||(abs(translate.x)>l/2&&in!=2&&in!=3); // is text outside l ⇒ no gap + textOffset=l0)rotate(in?in==2?90:in==3?-90:180:0){ + if(!textOut&&l-textl - diffT*2>0) T(-l/2)T((l-textl)/4 +diffT/2,0)square([(l-textl)/2-diffT,line],center=true); + if(!textOut&&l-textl + diffT*2>0) T( l/2)T(-(l-textl)/4 +diffT/2,0)square([(l-textl)/2+diffT,line],center=true); + } +//End lines vertical + translate(in!=2&&in!=3?[-translate.x,0]:[0,-translate.y])rotate(in?in==2?90:in==3?-90:180:0){ + MKlon(tx=l/2){ + T(end?end==4?-line/2:+line/2:0) square([line,s],center=true); + if(end)rotate(end==4?180:0)Pfeil([0,arrowL],b=[line,l2],center=[-1,1],name=false); + } + if(textOut) square([l,line],true); // Verbindung Pfeile +// text pos + translate(in!=2&&in!=3?[(in?1:-1) * -translate.x,0]:[(in==2?1:-1)*translate.y,0]){ + translate([textOffset,0])rotate(in>1?-90:180){ + if(len(txt2))translate(txtT+[0,-textS/1.5])Text(h=0,text=txt2,center=true, cx=cx,cy=cy==1?1:cy==0?-1:2, size=textS,trueSize="size",name=false); + translate(txtT+[0,len(txt2)?textS/1.5:0])Text(h=0,text=txt,center=true, cx=cx, cy=cy==1?1:cy==0?-1:2, size=textS,trueSize="size",name=false); + } + } +// verbindung text ausserhalb + tOutDist=(in!=2&&in!=3)? t.x *(in ?-1:1) + textOffset : + t.y *(in==3?-1:1) + textOffset ; + + if(textOut&&tOutDist)rotate(tOutDist<0?180:0)translate([0,-line/2])square([abs(tOutDist)-textl/2 ,line]); + } + +// verlängerungen translate auf 0.5 + mkL=end?end==4?l/2-line:l/2:l/2-line/2; + if(abs(translate.y)>(l2/2+.5)&&in!=2&&in!=3)translate([-translate.x,0])MKlon(tx=mkL) mirror([0,translate.y>0?1:0,0])square([line,abs(translate.y)-.5],false); + if(abs(translate.x)>(l2/2+.5)&&(in==2||in==3))translate([0,-translate.y])MKlon(ty=mkL) mirror([translate.x>0?1:0,0,0])square([abs(translate.x)-.5,line],false); + //if(translate.x) mirror([translate.x>0?1:0,0,0])T(l/2,-line/2)square([abs(translate.x),line],false); + + }// end Dimensioning + + +}// end Caliper + +/** \page Helper + Rod() is a Level staff + /brief Rod() is a Level staff + /param on 0=off,1= on,2= on in render + /param pos positon [x,y,z] + /param size length + /param s segment length + /param axis [x,y,z] 0=off ,1 on, -1 add negative + /param d diameter + /param help help +*/ +//Rod(size=10.2,s=0.5); + +module Rod(on=1,pos=[0,0,0],size=$vpd,s=1,axis=[1,1,-1],d=1,help){ +$fn=8; +size=is_list(size)?size:[size,size,size]; +if($preview&&on||on==2)translate(pos){ + if(axis.x&&size.x)rotate([0,90]){Axis(size=size.x,col=colX1); + if(axis.x<0&&size.x)rotate([180])Axis(size=size.x,col=colX0);} + if(axis.y&&size.y)rotate([-90]){Axis(size=size.y,col=colY1); + if(axis.y<0&&size.y)rotate([180])Axis(size=size.y,col=colY0);} + if(axis.z&&size.z)Axis(size=size.z,col=colZ1); + if(axis.z<01&&size.z)rotate([180])Axis(size=size.z,col=colZ0); +} +HelpTxt("Rod",["on",on,"pos",pos,"size",size,"s",s,"axis",axis,"d",d],help); +colX0=[ [0.5,0,0],[0,0,0],[1,0.5,0],[.5,0.5,0.5],"magenta" ]; +colX1=[ [0.5,0,0],[1,1,1],[1,0.5,0],[.5,0.5,0.5],"magenta" ]; +colY0=[ [0,0.5,0],[0,0,0],[.5,1,.5],[.5,0.5,0.5],"lime" ]; +colY1=[ [0,0.5,0],[1,1,1],[.5,1,.5],[.5,0.5,0.5],"lime" ]; +colZ0=[ [0,0,0.5],[0,0,0],[0,0.5,1],[.5,0.5,0.5],"aqua" ]; +colZ1=[ [0,0,0.5],[1,1,1],[0,0.5,1],[.5,0.5,0.5],"aqua" ]; + + module Axis(s=s,size=max(size),col=[[0,0,0]]){for (i=[0:size/s-1])translate([0,0,s*i]) + if(i%10||!i)color(col[i%2+(i%10<5?0:2)],.75)cylinder(d1=d,d2=d/1.5,h=s); + else color(col[4],.5)cylinder(d1=d*2,d2=d/1.5,h=s); + if(size/s%1)color("red")cylinder(h=size,d=d/1.5); + } +} + + +module SCT(a=90){ + echo(str("

    Winkel=",a," sin=",sin(a)," cos=",cos(a)," tan=",tan(a))); + echo(str("

    Winkel=",a," asin=",asin(a)," acos=",acos(a)," atan=",atan(a))); +} + + +module Line(p0=[0,0,0],p1=[10,10,0],d=.5,center=false,2D=false,text=false,fn=8,h,help=false){ + p0=p0[2]==undef?concat(p0,[0]):p0; + p1=p1[2]==undef?concat(p1,[0]):p1; +p1t=p1-p0; + + h=is_undef(h)?0:h; +x= p1t[0]; y = p1t[1]; z = p1t[2]; // point coordinates of end of cylinder + +length = norm([x,y,z]); // radial distance +b = length?acos(z/length):0; // inclination angle +c = atan2(y,x); // azimuthal angle + +points=center?[-p1t+p0,p0,p1]:[p0,p1t/2+p0,p1]; // for d=0 1d polyhedron + +if(d) + if(2D&&length&&!h)translate(p0)rotate([0,b-90,c])translate([0,center?0:-d/2,0]) square([center?length*2:length,d],center=center?true:false); + else if(h&&length)translate(p0)rotate([0,b-90,c])translate([0,center?0:-d/2,0]) linear_extrude(h,center=center)square([center?length*2:length,d],center=center?true:false); + + else if(!2D&&!h&&length)translate(p0)rotate([0, b, c]) + cylinder(h=center?length*2:length,d=d,$fn=fn,center=center?true:false); + +if(!d) polyhedron(points,[[0,1,2]]); +//Points(points); + + if (text&&$preview) + %color("slategrey")translate(center?p0:p0+p1t/2)rotate($vpr) + text(str(runden(center?length*2:length,3),"mm"),size=b(text,false)); + +HelpTxt("Line",[ + "p0",p0, + "p1",p1, + "d",d, + "center",center, + "2D",2D, + "text",text, + "fn",fn, + "h",h + ],help); + +} + +module LineORG(p0=[0,0,0], p1=[10,10,0], d=.5,center=true) { //from https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Tips_and_Tricks + + p0=p0[2]==undef?concat(p0,[0]):p0; + p1=p1[2]==undef?concat(p1,[0]):p1; + + // Find the unitary vector with direction v. Fails if v=[0,0,0]. +function unit(v) = norm(v)>0 ? v/norm(v) : undef; +// Find the transpose of a rectangular matrix +function transpose(m) = // m is any rectangular matrix of objects + [ for(j=[0:len(m[0])-1]) [ for(i=[0:len(m)-1]) m[i][j] ] ]; +// The identity matrix with dimension n +function identity(n) = [for(i=[0:n-1]) [for(j=[0:n-1]) i==j ? 1 : 0] ]; + +// computes the rotation with minimum angle that brings a to b +// the code fails if a and b are opposed to each other +function rotate_from_to(a,b) = + let( axis = unit(cross(a,b)) ) + axis*axis >= 0.99 ? + transpose([unit(b), axis, cross(axis, unit(b))]) * + [unit(a), axis, cross(axis, unit(a))] : + identity(3); + + v = p1-p0; + translate(p0) + // rotate the cylinder so its z axis is brought to direction v + multmatrix(rotate_from_to([0,0,1],v)) + cylinder(d=d, h=center?norm(v)*2:norm(v), $fn=12,center=center); +} + +/** \page Helper +Pivot() creates a pivot gizmo +* \name Pivot +* \brief creates a pivot gizmo +* \param p0 position of the Gizmo +* \param size size of the Gizmo +* \param active activate parts (center axis rotation text +* \param messpunkt activates +* \param txt adds text +* \param rot rotates +* \param vpr orient text +* \param help activate help +*/ + +module Pivot(p0=[0,0,0],size,active=[1,1,1,1,1,1],messpunkt,txt,rot=0,vpr=$vpr,help=false){ + messpunkt=is_undef(messpunkt)?is_undef($messpunkt)?true:$messpunkt:messpunkt; + p0=is_num(p0)?[p0,0]:p0; + size=is_undef(size)?is_bool(messpunkt)?pivotSize:messpunkt:size; + + size2=size/+5; + if(messpunkt&&$preview)translate(p0)%union(){ + + if(active[3])rotate(rot) color("blue")cylinder(size,d1=.5*size2,d2=0,center=false,$fn=4); + if(active[2])rotate(rot) color("green")rotate([-90,0,0])cylinder(size,d1=.5*size2,d2=0,center=false,$fn=4); + if(active[1])rotate(rot) color("red")rotate([0,90,0])cylinder(size,d1=.5*size2,d2=0,center=false,$fn=4); + if(active[0]) color("yellow")sphere(d=size2*.6,$fn=12); + //Text + if(active[4]) %color("grey")rotate(vpr) + //linear_extrude(.1,$fn=1) + text(text=str(norm(p0)?p0:""," ",rot?str(rot,"°"):""," "),size=size2,halign="right",valign="top",font="Bahnschrift:style=light",$fn=1); + + if(txt&&active[5])%color("lightgrey")rotate(vpr)translate([0,size/15])//linear_extrude(.1,$fn=1) + Tz(0.1) text(text=str(txt," "),size=size2,font="Bahnschrift:style=light",halign="right",valign="bottom",$fn=1); + } + HelpTxt("Pivot",[ + "p0",p0, + "size",size, + "active",active, + "messpunkt",messpunkt, + "txt",txt, + "rot",rot, + "vpr",vpr] + ,help); + +} + + + + + + +}//fold // \ΔΔ Helper ΔΔ\ \\ +{//fold // \∇∇ Polygons ∇∇/ // + + +/** \page Polygons +Connector creates a connector pin +\param l length +\param l2 center length +\param d diameter +\param d2 center diameter +\param dicke wall thickness +\param flat length flat sections +\param latch latch height +\param collar collar height +\param deg,degC,degEnd angle of chamfers +\param end end diameter change from d +\param cut cut end length +\param half for half x side +\param center center +\param 2D polygon or 3D connector +\param printCut overhang angle horizontal print +\param print rotate and move 3D pin up + +*/ + +//Roof(2,[.25,.25])Connector(d=3,d2=3.5,dicke=1.2,latch=.25,end=-.5,flat=0.7); +//Connector(l=[20,15],d=5,end=-.5,d2=6,2D=false,collar=0,l2=+0,print=true,center=false); + +module Connector(l=10,d=5,l2=0,d2,dicke=1.5,flat=[0.5,0.5],flatC,latch=.5,collar=0,deg=45,degC=45,degEnd=45,end=-.5,cut=undef,half=false,center=true,2D=true,printCut=50,print=false,spiel=0,help){ + +half=is_parent("RotEx")?spiel?half:true:half; +2D=is_parent(needs2D)?true:2D; + +d=is_num(d)?[d,d]:d; +l=is_num(l)?[l,l]:l; +flat=is_num(flat)?[flat,flat]:flat; +flatC=is_undef(flatC)?flat:is_num(flatC)?[flatC,flatC]:flatC; +dicke=is_num(dicke)?[min(d[0]/2,dicke),min(d[1]/2,dicke)]:dicke; +l2=is_num(l2)?[l2,l2]:l2; +collar=is_num(collar)?[collar,collar]:collar; +cut=is_list(cut)?cut:[cut,cut]; +latch=is_num(latch)?[latch,latch]:latch; +deg=is_num(deg)?[deg,deg]:deg; +degC=is_num(degC)?[degC,degC]:degC; +degEnd=is_num(degEnd)?[degEnd,degEnd]:degEnd; + +d2=is_num(d2)?[d2,d2]:is_undef(d2)?d+collar*2:d2; +end=is_num(end)?[end,end]:end; +//center length 0 +cnt=max(l2[0],(d2[0]==d[0]+collar[0]*2?0:tan(degC[0]*sign(d[0]-d2[0]+collar[0]*2))*((d[0]-d2[0])/2+collar[0]))+(collar[0]?l2?flatC[0]:flatC[0]/2:-flatC[0]))+(l[0]+flat[0]+tan(degEnd[0])*(-end[0]+latch[0])); + +HelpTxt("Connector",["l",l,"d",d,"l2",l2,"d2",d2,"dicke",dicke,"flat",flat,"flatC",flatC,"latch",latch,"collar",collar,"deg",deg,"degC",degC,"degEnd",degEnd,"end",end,"cut",cut,"half",half,"center",center,"2D",2D,"printCut",printCut,"print",print,"spiel",spiel],help); + +function latch(mirror=[1,1],latch=0.5,dicke=dicke[0],collar=2,l2=l2[0],l0=l[0],flat=flat,d=d[0],d2=d2[0],deg=+45,degC=25,degEnd=degEnd[0],end=end[0],cut=cut[0],center=center,cnt=cnt)= +let( + fn=fs2fn(r=d/2-dicke,grad=90,fs=fs), + icollar=collar, + collarL=tan(degC*sign(d-d2+icollar*2))*((d-d2)/2+icollar), + step=90/fn, + flat0=flat[0], + flat1=collar?flat[1]:0, // for collar + flat2=collar?0:flat[1]/2,// no collar + l0=l2||collar?l0:l0-collarL-flat2, + l2=max(l2,(d2==d+collar*2?0:collarL)+flat2+flat1), + end=max(-dicke+.25,end),//end diameter change to d/2 + lEnd=(l0+flat0+abs( tan(degEnd)*(-end+latch) ) ), // length of head section + cut=is_undef(cut)?lEnd-l0+min(3.5,l2+l0-.5):min(cut,max(0,lEnd+l2-.5) ), + rad=min(cut/2.5,(d/2-dicke)/PHI), + cnt=center||min(l)==0?[0,0]:[0,cnt]//l2+lEnd] + ) + +[ +if(half&&min(l)==0)cnt+[0,0], +if(half)cnt+[0,mirror.y * -(l2+lEnd-cut)], +if(cut&&d/2-dicke>=pip/2)for(i=[0:fn])cnt+[mirror.x * (d/2-dicke-rad+rad*sin(i*step)),mirror.y * (rad*cos(i*step)-(rad+l2+lEnd-cut))],// freiraum +cnt+[mirror.x * (d/2-dicke),mirror.y * -(lEnd+l2)],// end freiraum +cnt+[mirror.x * (d/2+end),mirror.y *-(lEnd+l2)],// start chamfer +cnt+[mirror.x * (d/2+latch),mirror.y *-(l2+l0+flat0)],// end chamfer +cnt+[mirror.x * (d/2+latch),mirror.y *-(l2+l0)],// end chamfer +cnt+[mirror.x * (d/2),mirror.y *-(l2+l0+tan(-deg)*abs(latch))],// end chamfer + +cnt+[mirror.x * d/2,mirror.y * -l2], // d +if(collar)cnt+[mirror.x * (d/2+icollar),mirror.y * -l2],// collar +if(collar)cnt+[mirror.x * (d/2+icollar),mirror.y * -(l2-flat1 )],// collar +if(d2!=d||!min(l))cnt+[mirror.x * d2/2,mirror.y * -(l2-flat1- collarL )],// l2 body +if(!min(l))cnt+[mirror.x * d2/2,0]// body +]; + + + +points= +half?concat( + l[0]?latch([1, 1],l0=l[0],flat=[flat[0],flatC[0]],dicke=dicke[0],l2=l2[0],cut=cut[0],collar=collar[0],latch=latch[0],deg=deg[0],degC=degC[0],degEnd=degEnd[0],end=end[0],d2=d2[0],d=d[0]):[], + l[1]?revP(latch([1,-1],l0=l[1],flat=[flat[1],flatC[1]],dicke=dicke[1],l2=l2[1],cut=cut[1],collar=collar[1],latch=latch[1],deg=deg[1],degC=degC[1],degEnd=degEnd[1],end=end[1],d2=d2[1],d=d[1]) ):[] +): +concat( + l[0]?latch([ 1, 1],l0=l[0],flat=[flat[0],flatC[0]],dicke=dicke[0],l2=l2[0],cut=cut[0],collar=collar[0],latch=latch[0],deg=deg[0],degC=degC[0],degEnd=degEnd[0],end=end[0],d2=d2[0],d=d[0]):[], + l[1]?revP(latch([ 1,-1],l0=l[1],flat=[flat[1],flatC[1]],dicke=dicke[1],end=end[1],l2=l2[1],cut=cut[1],collar=collar[1],latch=latch[1],deg=deg[1],degC=degC[1],degEnd=degEnd[1],d2=d2[1],d=d[1]) ):[], + l[1]? latch([-1,-1],l0=l[1],flat=[flat[1],flatC[1]],dicke=dicke[1],l2=l2[1],cut=cut[1],collar=collar[1],latch=latch[1],deg=deg[1],degC=degC[1],degEnd=degEnd[1],end=end[1],d2=d2[1],d=d[1]):[], + l[0]?revP(latch([-1, 1],l0=l[0],flat=[flat[0],flatC[0]],dicke=dicke[0],l2=l2[0],cut=cut[0],collar=collar[0],latch=latch[0],deg=deg[0],degC=degC[0],degEnd=degEnd[0],end=end[0],d2=d2[0],d=d[0]) ):[] +); + +if(2D)offset(delta=spiel)polygon(points); + else { + + h=printCut==false?max(d)*3:min(d)*sin(printCut)+spiel*2; + Tz(print?h/2:0)R(print?-90:0) + intersection(){ + RotEx(cut=spiel?true:false)Connector(l=l,d=d,l2=l2,d2=d2,dicke=dicke,flat=flat,flatC=flatC,latch=latch,collar=collar,deg=deg,degC=degC,degEnd=degEnd,end=end,cut=cut,center=center,spiel=spiel); + R(90)LinEx(h,center=true)Connector(l=l,d=d,l2=l2,d2=d2,dicke=printCut==false?d/2-latch-[.5,.5]:min(d)/2*(1-cos(printCut))+.5,flat=flat,flatC=flatC,latch=latch,collar=collar,deg=deg,degC=degC,degEnd=degEnd,end=end,cut=cut,center=center,spiel=spiel); + } + } + +} + + +/** \page Polygons +Tesselation creates tilings +\param size size [x,y] +\param d object diameter [x,y] for squares +\param dist spacing between objects +\param dicke line thickness +\param pat pattern 1:grid 2:hex 3:penrose +\param tile 0 none 1 circle 2 square ... 100 children +\param rad rounding tile +\param rot rotation +\param ofs position offset +\param alt alterating rotation angle +\param fn fraqment number +\param center center +*/ + +//Tesselation(size=20,d=5,pat=1,fn=6,alt=30); +//Tesselation(size=20,d=4,pat=2,dist=0.6,fn=6); + +//Tesselation(size=20,d=5,tile=3,pat=1,dist=.5,fn=6,alt=90);//alternating rectangles +//Tesselation(size=80,pat=4,d=5,tile=12);//pentaTile + +/* //TriHex +difference(){ + Tesselation(size=30,pat=2,d=3,rot=60,dist=+0.5,tile=5,fn=6,center=1);//TriHex + color("lime")Tesselation(size=30,pat=2,d=3,rot=60,dist=+0.5,dicke=.5,tile=5,fn=6,center=1);//TriHex +}//*/ + +//Tesselation(pat=2,rot=0,tile=5,dist=+0.1,dicke=2,fn=6);// TriHex + +/* +HexGrid(es=10/(3/4)+.5) +Tesselation(tile=13,dist=0.5,pat=0);//floral +//*/ + + /*//hex tri penta +difference(){ +square(50,true); +Tesselation(tile=11,pat=2,fn=6,dist=.4,dicke=.7,alt=[60,60]); +}//*/ + +//Tesselation(tile=9,dist=0.75,alt=60,dicke=.5,fn=6,pat=2); + +//Tesselation(size=80,tile=0,pat=3,fn=5,d=2,dicke=1); + +//Tesselation(pat=5,tile=0); + +//Tesselation(pat=2,center=0); + +module Tesselation(size=[40,40],d=5,dist=1,dicke=0,pat=0,tile=1,rad=0,rot=0,ofs=[0,0],alt=[0,0],fn=6,center=true,name, help,obj){ + +dist=is_list(dist)?dist:[dist,dist]; +d=is_list(d)?d:d*[1,1]; +radius=is_num(size)?size/2:0; +size=is_list(size)?size:size*[1,1]; +alt=is_list(alt)?b(alt,false):b(alt,false)*[1,1]; +e=[max(1,size.x/(d.x+dist.x)),max(1,size.y/(d.y+dist.y))]; +tile=$children?100:is_undef(obj)?tile:obj; +center=is_list(center)?center:[center,center]; +$d=d; +$r=d/2; +$info=false; + +HelpTxt("Tesselation",["size",size,"d",d,"dist",dist,"dicke",dicke,"pat",pat,"tile",tile,"rad",rad,"rot",rot,"ofs",ofs,"alt",alt,"fn",fn,"center",center,"name",name],help); + +if(pat==0)rotate(alt.y+alt.x+rot)Tile()children(); + +if(pat==1)Grid(e=e,es=d+dist,center=center)rotate(($idx.y%2?0:alt.y)+($idx.x%2?0:alt.x)+rot) + if(radius?norm($pos)<=radius-max(d)/2 + :abs($pos.x)<=(size.x-max(d))/2&&abs($pos.y)<=(size.y-max(d))/2 + ) +Tile()children(); + +if(pat==2)HexGrid(e=[e.x,e.y*sqrt(3)/2]*2,es=[(d.x+dist.x)*sqrt(3)/2,(d.y+dist.y)],center=center)rotate(($idx.y%2?0:alt.y)+($idx.x%2?0:alt.x)+rot) + if(radius?norm($pos)<=radius-max(d)/2 + :abs($pos.x)<=((center.x?size.x:size.x*2)-max(d))/2&&abs($pos.y)<=((center.y?size.y:size.y*2)-max(d))/2 + ) + + Tile(d=fn==6?umkreis(6,d):d)children(); +//Penrose + if(pat==3)Polar(fn)Penrose(radius=max(size)/2,dicke=dicke,fn=fn,chld=tile,case=1,d=max(d) )rotate(rot)Tile()children(); + +//Cairo tile diagonal + if(pat==4){ + dist=max(dist); + es=[max(d),max(d)*2]*1.5; + e=[ceil(size.x/es.x),ceil(size.y/es.y)]; + + HexGrid(e=[e.x,e.y],es=es,center=center) + if(abs($pos.x)<=size.x/2-es.x&&abs($pos.y)<=size.y/2-es.y/2) + Tile()children(); + } +// Rectangle Tiling + if(pat==5)RectTiling(size=size,dicke=dicke,chld=tile,d=max(d))rotate(rot)Tile()children(); + + +module Tile(opt=tile,ofs=ofs,dicke=dicke,fn=fn,d=d,dist=dist,rad=rad)T(ofs)render()Rund(rad){ +assert(min(d)>0); + if(opt==100)children(); + if(opt==1)circle(d=max(d),$fn=fn); // ngon + if(opt==2)square(d,center=true); // squares +// blocks + if(opt==3){ + MKlon(ty=d.y/4+dist.y/4)square(vMult(d,[1,.5])-[0,dist.y/2],true); + } +//tri blocks + if(opt==4)Polar(fn/2,d.x/4)square([d.x/2,dicke?dicke:1],center=true);//Tri +//tri Hex + + + if(opt==5){ + f=sqrt(3)/2; + d=max(d)/f; + dicke=(is_list(dicke)?1:[1,1])*(dicke?dicke:d/2); + + Polar(3,rot=30)hull(){circle(d=dicke.y,$fn=6);T(d/2-dicke.x/2)circle(d=dicke.x,$fn=fn);} + //color("red")Polar(3,dicke/2,rot=30)circle(d=dicke,$fn=6); + } + +//triangles Hex +if(opt==6)difference(){ + circle(d=d.x,$fn=fn); + Polar(fn,d.x/2,rot=0)square([d.x,dicke?dicke:dist.y],true); + } + +/*//triangles Hex + if(opt==6){ + d=umkreis(3,max(d))/sqrt(3); + Polar(6,max(d)/2,rot=30)offset(-max(dist)/2)rotate(60)circle(d=d,$fn=3); + } + //*/ + +//triangles + if(opt==7)MKlon((max(d)+dist.x)/sqrt(3)/2)circle(d=max(d)/sqrt(3)*2,$fn=3); +//Star + if(opt==8)rotate(180/fn)Star(e=round(fn),d/2,d/3);// star + // diamonds Hex + if(opt==9)difference(){ + circle(d=d.x,$fn=fn); + Polar(3,d.x/2,rot=0)square([d.x,dicke?dicke:dist.y],true); + } + +//PentaTile + if(opt==10)difference(){ + circle(d=d.x,$fn=fn); + square([d.x+2,dicke?dicke:dist.y],true); + } + if(opt==11)difference(){ + circle(d=d.x,$fn=fn); + Polar(fn/2,d.x/2,rot=180/fn)square([d.x,dicke?dicke:dist.y],true); + } + +//Cairo + if(opt==12)union(){ + dist=max(dist); + d=max(d); + MKlon(ty=-d)offset(-dist/2)polygon(5gon(d*0.75,d*0.25,d*0.5,d)); + rotate(90)MKlon(ty=d*0.5)offset(-dist/2)polygon(5gon(d*0.75,d*0.25,d*0.5,d)); + } +//Penta floral + if(opt==13){ + d=max(d); + p=[for(i=[0:3])[cos(i*60),sin(i*60)]*d/2/(sqrt(3)/2)+[0,d],[0,0]]; + Polar(6,rot=rot?rot:90+atan(sqrt(3)/9))offset(-max(dist)/2)polygon(p); + } + + union(){ + dicke=dicke?dicke:1; + //3halfcircle + if(opt==14){d=max(d)/sqrt(3); + Polar(3,d/2+dist.x*0,rotE=rot*0)Kreis(d=d,grad=180,rcenter=true,rand=dicke,rot=90);} + //6halfcircle + if(opt==15)Polar(6,max(d)/4+dist.x/4,rot=30,rotE=rot*+1)Kreis(d=max(d)/2,grad=180,rcenter=true,rand=dicke,rot=90); + //6Wave + if(opt==16)Polar(6,max(d)/4,rot=30,rotE=rot*0){d=d/4; + MKlon(max(d)/2)Kreis(d=max(d),grad=180,rcenter=true,rand=dicke,rot=$idx*180+90);} + } + + +} + +} // end Tesselation + + + +/** \name Penrose Tiling +\page Polygons +Penrose() creates a penrose tiling or children arrangement +\param rec recursion limit (optional) +\param tri start triangle [p0,p1,p2] (optional) +\param radius penrose size via fn and radius ↦ tri +\param case tiling start case +\param dicke space between triangles +\param ratio tiling ratio +\param fn symetry ↦ tri +\param d triangle size limit (recursion stop condition) +\param mirror mirror triangles for symetry ↦ tri +\param $d $pos $tri output variables - inner diameter center triangle points + +*/ +//Polar(10)Penrose(mirror=0,fn=10,d=5); + + +module Penrose(rec=20,tri,radius=50,case=1,dicke=1,ratio=1.618,color=5,seed = 42,fn=6,chld,d=5,mirror=true,help){//<- change start case 1 or 2 + +HelpTxt("Penrose",["rec",rec,"tri",tri,"radius",radius,"case",case,"dicke",dicke,"ratio",ratio,"fn",fn,"d",d,"mirror",mirror],help); + +function GR(a,b,ratio=ratio)=a+(b-a)/ratio; + +chld=is_undef(chld)?$children:chld; + +// we using two mirrored parts so each triangle is half and the angle from center hence only a quarter +fn=max(fn,2); +angle= mirror?360 / (fn*4):360/fn/2; +dicke=is_undef(dicke)?0:dicke; + + +tri=is_undef(tri)?let(a=[0,0])[ + a, // a first point at center + a + [sin( angle), cos( angle)]* radius, // b the adjactant sides end point at angle and length + a + [sin(-angle), cos(-angle)]* radius, // c + ] + :tri; + + a=tri[0]; + b=tri[1]; + c=tri[2]; + + //iratio=rands(1.5,2.0,5,seed); + iratio=[1,1,1,1,1]*ratio; + +// side length + sA=norm(c-b); + sB=norm(c-a); + sC=norm(b-a); +// circumfence + u=(sA+sB+sC); + s=u/2; + +// inner diameter + $d=sqrt( ((s-sA)*(s-sB)*(s-sC))/s )*2-dicke; + + if ($d>(d*2)&&rec>0){ + if(case==1){ + // the smaller resulting tri will be cut in two the next time (case 1) + Penrose(rec=rec-1, tri= [c , GR(a, b), b], case=1,fn=fn,chld=chld,d=d, dicke=dicke, mirror=mirror, color= 0,ratio=iratio[0], seed = seed * rec + 0)children(); + + // the bigger gets cut in 3 the next time + Penrose(rec=rec-1, tri= [GR(a, b), c , a], case=2,fn=fn,chld=chld,d=d, dicke=dicke, mirror=mirror, color= 1,ratio=iratio[1], seed = seed * rec + 1000)children(); + } + if(case==2){ + Penrose(rec=rec-1, tri= [GR(b, a), GR(b, c), b], case= 2,fn=fn,chld=chld,d=d, dicke=dicke, mirror=mirror, color= 2,ratio=iratio[2], seed = seed * rec + 2000)children(); + Penrose(rec=rec-1, tri= [GR(b, c), GR(b, a), a], case= 1,fn=fn,chld=chld,d=d, dicke=dicke, mirror=mirror, color= 3,ratio=iratio[3], seed = seed * rec + 3000)children(); + Penrose(rec=rec-1, tri= [GR(b, c), c, a], case= 2,fn=fn,chld=chld,d=d, dicke=dicke, mirror=mirror, color= 4,ratio=iratio[4], seed = seed * rec + 4000)children(); + } + } + + + else { // only draw the pattern at the last recursion + + iM=[ (sA*a.x+sB*b.x+sC*c.x)/u , (sA*a.y+sB*b.y+sC*c.y)/u ]; + $pos=iM; + $tri=tri; + color(color/5*[1,1,1]){ + rotate(90/fn) + if(chld)T(iM)children(); + //T((a+(b+c)/2)/2)children(); + else { + offset(-dicke/2)polygon(tri); + } + + if(mirror)mirror([1,0])rotate(90/fn) + if(chld)T(iM)children();//T((a+(b+c)/2)/2)children(); + + else offset(-dicke/2)polygon(tri); + } + } +} // end Penrose + + + +/** \page Polygons \name RectTiling +RectTiling() tiles a rectangle in random smaller rectangles +\param size size +\param ratio [min:max] dividing ratio or list or num +\param d minimal size (recursive stop condition) +\param dicke space thickness between +\param seed seed for randomness +\param $size $seed output data +\param chld use children +\param info help info help +*/ +//RectTiling(dicke=0); + +//RectTiling(ratio=[2.7,2],d=5); + + + + +module RectTiling(size=[30,40],ratio=[1.25:5],d=5,dicke=1,chld,seed=13,rec=0,info,help){ +chld=is_undef(chld)?$children:chld; +assert (is_undef(ratio[2])?min(ratio)>=1:min([ratio[1],ratio[2]])>=1,"ratio <= 1"); +assert (d>0,"d need to be > 0"); +assert (is_num(dicke),"dicke need to be a number"); + +ratio=is_num(ratio)?[1/(1-1/ratio),ratio]:ratio; +if(rec==0&&info)echo(ratio=ratio); +useRatio=is_list(ratio)?ratio[floor(rands(0,len(ratio),1,seed)[0])] + :rands(ratio[0],ratio[2],1,seed)[0]; +if(info)echo(useRatio=useRatio,rec=rec); +HelpTxt("RectTiling",["size",size,"ratio",ratio,"d",d,"dicke",dicke,"seed",seed,"info",info],help); + + if(max(size)/useRatio>d+dicke*1.0&&max(size)-max(size)/useRatio>d+dicke&&rec<30){ + if(size.x>size.y){ + RectTiling(size=[size.x/useRatio,size.y],ratio=ratio,d=d,dicke=dicke,chld=chld,seed=seed+1,rec=rec+1, info=info)children(); + translate([size.x/useRatio,0])RectTiling(size=[size.x-size.x/useRatio,size.y],ratio=ratio,d=d,dicke=dicke,chld=chld,seed=seed*2,rec=rec+1, info=info)children(); + } + else { + RectTiling(size=[size.x,size.y/useRatio],ratio=ratio,d=d,dicke=dicke,chld=chld, seed=seed+1,rec=rec+1, info=info)children(); + translate([0,size.y/useRatio])RectTiling(size=[size.x,size.y-size.y/useRatio],ratio=ratio,d=d,dicke=dicke,chld=chld, seed=seed*2,rec=rec+1, info=info)children(); + } + + } + else { + if(chld) { + $size=size; + $seed=seed; + translate(size/2)children(); + } + else //color(rands(0,1,3)) + Color(rands(0,1,1)[0],l=dicke?1:0.5) + offset(-dicke/2)square(size); + + if(info)%color("grey")scale([1,1,2])translate(size/2)text(str(rec,"/",seed),size=d/4,halign="center",valign="center"); + } + +} + +/** \page Polygons \name Voronoi +\brief Voronoi() creates a Voronoi tiling +\param size [x,y] size +\param dicke gap width +\param grid [x,y] base grid for cells +\param of offset factor +\param seed seed for random offset +\param center center [x,y] +\param repeat [x,y] generate equal seed for start end to place tile for tesselation +\param help help +*/ + +//Voronoi(dicke=.25,grid=5,center=[0,0],size=[12,10]); +/*union(){ // endless tesselation +seed=44;of=0.6; +Voronoi(repeat=[1,1],seed=seed,of=of); +T(50.1)Voronoi(repeat=[0,1],seed=seed,of=of); +T(50.1,50.1)Voronoi(repeat=[0,1],seed=seed,of=of); +} +//*/ + +module Voronoi(size=[50,50],dicke=0.3,grid=[2,3],of=.7,seed=5566,center=false,repeat=true,help){ + + +repeat=is_list(repeat)?repeat:[repeat,repeat]; +size=assert(size, "Voronoi needs a size")is_list(size)?size:[size,size]; +grid=is_list(grid)?[ceil(grid.x),ceil(grid.y)]:[ceil(grid),ceil(grid)]; +center=is_list(center)?bool(center,false):center?[0,0]:[1,1]; + +HelpTxt("Voronoi",["size",size,"dicke",dicke,"grid",grid,"of",of,"seed",seed,"center",center,"repeat",repeat],help); + +offset=assert(is_num(size.x)&&is_num(size.y),"Voronoi size contain nan")[size.x/grid.x/2,size.y/grid.y/2]*of; + +points=[ +for(y=[0:grid.y])[for (x=[0:grid.x]) + let(rand=rands(-1,1,2,seed+(repeat.x&&x==grid.x?0:x)+(repeat.y&&y==grid.y?0:y)*grid.x))[ +size.x/grid.x*x + offset.x*rand[0], +size.y/grid.y*y + offset.y*rand[1] +]] +]; + +//clamping cell values +function pVal(x,y,points=points,offset=15)= + let( + valX= x<0?-offset + :x>grid.x?size.x+offset + :points[min(max(y,0),grid.y)][x].x, +valY= y<0?-offset + :y>grid.y?size.y+offset + :points[y][min(max(x,0),grid.x)].y + ) +[valX,valY]; + + + +translate([center.x*size.x,center.y*size.y]/2 - size/2) + for(y=[0:grid.y],x=[0:grid.x]) + let(p=[for (ix=[-1,0,1],iy=[-1,0,1])if(ix||iy)pVal(x+ix,y+iy)]){ + intersection(){ + square(size); + offset(-dicke/2)Cell(cp=points[y][x],p=p); + } + } + + +module Cell(cp=[0,0],p=[[1,1],[5,5],[1,5],[5,1]]){ + +distances=[for(i=[0:len(p)-1])norm(p[i]-cp)]; +minDist=min(distances); + + + + difference(){ + translate(cp)circle(max(distances),$fn=6); + + for(i=[0:len(p)-1]){ + pH=(p[i]-cp)/2; + deg=atan2(pH[0],pH[1]); + translate(cp+pH)rotate(-deg)translate([-max(size),0])square(max(size)*2); + } + } +} + +} + + + + +/** \page Polygons +Arc() creates an arc +\param r radius +\param deg angle +\param r2 end radius at deg +\param fn fragments +\param rand fringe thickness +\param center center arc rotation +\param cP center Point +\param rot rotate arc [r,rand] + +*/ +//Arc(r=10,deg=90,r2=8,rand=2); +//Arc(r=10,deg=90,rand=[5,1]); + +//Arc(r=10,deg=[110,0],center=0); + +module Arc(r=10,deg=90,r2,fn=36,rand,center=false,cP=true,rot=0,help){ +deg=is_list(deg)?deg:rand?[deg,deg]:[deg,0]; +rand=is_num(rand)?[rand,rand]:rand; +rot=is_num(rot)?[rot,0]:rot; + +points=rand?concat(arc(r=r,deg=deg[0],r2=r2,rot=(center?-deg[0]/2:0)+rot[0],fn=fn), + arc(r=r+rand[0],deg=deg[1],r2=is_undef(r2)?r+rand[1]:r2+rand[1],rot=(center?-deg[1]/2:0)+rot[1],fn=fn,rev=true) + ) + + : concat(cP?[[0,0]]:[],arc(r=r,deg=deg,r2=r2,rot=(center?-deg[0]/2:0)+rot[0],fn=fn)); + + +polygon(points,convexity=5); + +HelpTxt("Arc",["r",r,"deg",deg,"r2",r2,"fn",fn,"rand",rand,"center",center,"cP",cP,"rot",rot],help); +} + + +/** \page Polygons \name VorterantQ +\brief Vorterant Q creates a rotor for the Quad Vorterant pump +\param size rotor diameter +\param ofs rounding edge +\param adjusted if size is adjusted to the edge offset +\param fs fn fraqments +\param name help name help +\param h for 180°twist and volume calculation message +*/ + +/// Vorterant Q creates a rotor for the Quad Vorterant pump +//Grid(e=3,es=10*sqrt(2))rotate(($idx.x+$idx.y)%2?0:90)rotate(t0)VorterantQ(); +//Polar(4,10.0,rotE=90)VorterantQ(h=10); + + +/* +VorterantQ(ofs=2,adjusted=true); +x=10-sqrt(2)*2; +Tz(.1)Color()offset(2)Linse(dia=x*2,r=x*sqrt(2)); +//*/ + +/* +VorterantQ(); +Kreis(10,dicke=.1); +T(10){ +Kreis(10*sqrt(2),dicke=.1); +Pivot(); +} +//*/ + + +module VorterantQ(size=20,ofs=.5,adjusted,fs=fs,fa=fa,fn=0,name,help,h){ +adjusted=is_undef(adjusted)?useVersion&&useVersion>23||Version>23?true:false + :adjusted; +s=adjusted?Umkreis(4,size/2)-ofs*2 : Umkreis(4,size/2-ofs); + +k1=kreis(s,rand=0,grad=90,rot=180,endPoint=0,fs=fs,fa=fa,fn=fn); +versch=[for(i=[0:len(k1)-1])[-inkreis(4,s),0]]; +offset= [for(i=[0:len(k1)-1])[ofs*sin(45+i*90/len(k1)),ofs*cos(45+i*90/len(k1))]]; +function offsetvert(fn=12)= [for(i=[0:fn])[ofs*sin(-45+i*90/fn),ofs*cos(-45+i*90/fn)+inkreis(4,s)]]; + +linse=concat(k1+versch+offset,-offsetvert(),-k1-versch-offset,offsetvert()); +polygon(linse); + +if(name)echo(str(name," VQ Size=",adjusted?size-tangentenP(grad=90,rad=ofs)*2:size," ,Radius=",s,"mm - Verschoben um",inkreis(4,s)-ofs,"mm")); +HelpTxt("VorterantQ",["size",size,"ofs",ofs,"adjusted",adjusted,"fn",fn,"fs",fs,"name",name],help); + +function area(angle=0,r=size/2) =( r * sqrt(2) * abs( cos(angle) ) )^2; +if(h){ + + +areaS=[for(i=[0:180])area(angle=i)*h/180]; + +volume=vSum(areaS); + +if(is_undef($idx)?true:is_list($idx)?!max($idx):!$idx) InfoTxt("VorterantQ",["~volume",volume,"cubeside",volume^(1/3)],name); + +} +} + +function vorterantQ(size=20,r=.15,z,fn=50,fn2=10) = +let(rad=size/2,r=max(min(size/sqrt(2),r),0)) + [ + each arc(r=size/sqrt(2)-r,deg=90-90/fn,rot=-45,t=[-rad+r*sqrt(2),0],fn=fn-1,z=z), + each arc(r=r,deg=90-90/fn2,rot=+45,t=[0, rad-tangentenP(grad=90,rad=r,r=r) ],fn=fn2-1,z=z), + each -arc(r=size/sqrt(2)-r,deg=90-90/fn,rot=-45,t=[-rad+r*sqrt(2),0],fn=fn-1,z=is_num(z)?-z:undef), + each -arc(r=r,deg=90-90/fn2,rot=+45,t=[0, rad-tangentenP(grad=90,rad=r,r=r) ],fn=fn2-1,z=is_num(z)?-z:undef), + ]; + + +/* +size=10; +vP=concat( +[for(z=[0:.2:25]) each mPoints(vorterantQ(size=size,r=.15+size/2/sqrt(2)*transition(z,5),z=z,fn2=50),r=z/3*30) ], +[for(z=[25.2:.2:30]) each mPoints(vorterantQ(size=size,r=.15+size/2/sqrt(2)*transition(30-z,5),z=z,fn2=50),r=z/3*30) ] +); +difference(){ + PolyH(vP,loop=50*4,flip=false); + Loch(30,.25,d=3.2,rad=.5); +} +//*/ + + + +/** \name Reuleaux +\page Polygons +Reuleaux creates a Reuleaux triangle +\param rU Edge radius +\param fs fn fraqments size / number +*/ + +//Reuleaux(); + +module Reuleaux(rU=5,fn=0,fs=fs,name,help){ + r=rU/(sqrt(3)/3); + intersection_for (i=[0,120,240]) + { + rotate(i)T(rU) circle(r=r,$fn=fn,$fs=fs); + + } + if(name)echo(str(name," Reuleaux rU=",rU," r=",r)); + HelpTxt("Reuleaux",["rU",rU,"fn",fn,"name",name],help); +} + +/** \page Polygons +PolyRund([[0,1],[10,20],[-50,50]],r=5); creates a rounded polygon +\param points the points of polygon +\param r the rounding radius (list optional) +\param ir radius of inner corners (if r is not a list) +\param ofs offset for the polygon +\param delta delta offset (no radius change) +\param fn,fs fragments, fragment size +\param messpunkt show points and radii +\param help help +*/ + +//PolyRund([[0,1],[10,20],[-50,50]],r=2,messpunkt=true,delta=+0); + + +module PolyRund(points,r=0,ir,ofs=0,delta=0,fn,fs=fs,minF=8,messpunkt=false,help){ + +Echo("No Points",color="redring",condition=!is_list(points[2])); +if(is_list(points[2]))polygon(polyRund(points,r=r,ir=ir,ofs=ofs,delta=delta,fn=fn,fs=is_undef(fn)?fs:undef,minF=minF),convexity=5); + lenR=is_num(r)?2:len(r); + %Tz(.1)if(messpunkt!=false){ + Tz(-0.05)color("silver",0.3)polygon(points); + translate(points[0])Color("HotPink")text(str("№ ",0),size=1,halign="center",valign="center"); + for(p=is_num(messpunkt)?abs(messpunkt)%len(points):[0:len(points)-1]){ + //let(p=p%lenR) + translate(points[p]){ + //Color("darkOrange")Kreis(r=r[p],rand=min(.25,r[p]/10),name=0); + //Color("Orange")DPfeil(r[p]*2,b=min(.25,r[p]/10),name=0,txt=true); + if(p)Color("lightGrey")text(str("№ ",p),size=1,halign="center",valign="center"); + } + + + let( + //p=is_num(r)?p:p%lenR, + fn=is_list(fn)?fn[p%len(fn)]:fn, + fs=is_list(fs)?fs[p%len(fs)]:fs, + ir=is_undef(ir)?r:ir, + lp=len(points), + pBef=points[(p+lp-1)%lp], + pNow=points[p], + pNex=points[(p+1)%lp], + grad1=atan2(pBef.x-pNow.x,pBef.y-pNow.y), + grad2=atan2(pNex.x-pNow.x,pNex.y-pNow.y), + gradDiff=grad1-grad2, + grad=gradDiff<0?abs(gradDiff):360-gradDiff, + gradSup=360-grad, + tPgrad=grad2+gradSup/2, + r=(is_num(r)?(grad<180?-r : ir):r[p%len(r)]*(grad<180?-1:1)), + + tP=[sin(tPgrad),cos(tPgrad)]*tangentenP(grad=gradSup-180,r=r,rad=r)*(grad<180? -1:+1), + tPDelta=[sin(tPgrad),cos(tPgrad)]*tangentenP(grad=gradSup-180,r=delta,rad=delta) + )union(){ + dia=2*(grad<180?max(abs(r)+ofs,0):max(abs(r)-ofs,0)); + Color(grad<180?"Orange":"lightSkyBlue")translate(pNow+tP+tPDelta*sign(delta))DPfeil(dia,b=min(.25,r/10),name=0,txt=true); + if(dia)Color(grad<180?"darkOrange":"SkyBlue")polygon(kreis(d=dia*sign(r),rand=min(.25,r/10),rot=grad1+90,grad=(grad-180)*0+360*1,t=pNow+tP+tPDelta*sign(delta),center=false,fn=is_undef(fn)?undef:fn/abs(grad-180)*360,fs=fs,minF=minF)); + if(dia)Tz(.1)Color("chartreuse")polygon(kreis(d=dia*sign(r),rand=min(.25,r/10),rot=grad1+90,grad=(grad-180),t=pNow+tP+tPDelta*sign(delta),center=false,fn=fn,fs=fs,minF=minF)); + } + } + } + +HelpTxt("PolyRund",["points",points,"r",r,"ir",ir,"ofs",ofs,"delta",delta,"fn",fn,"fs",fs,"minF",minF,"messpunkt",messpunkt],help); +} + +/** \page Polygons +WStern() a sin wave star +\name WStern() +\brief creates a sin wave star +## Example +WStern(); + * \param f frequency + * \param r radius + * \param a amplitude + * \param r2 optional radius to calc amplitude + * \param fv phase shift + * \param fn fragments should be multiple of f + +*/ +//WStern(f=5,r=5,a=10); + +module WStern(f=5,r=1.65,a=.25,r2,fn=0,fs=fs,fv=0,name,help){ + + a=is_undef(r2)?a:(r2-r)/2; + + fn=fn?fn:ceil(fs2fn(fs=fs,r=abs(r)+abs(a),minf=f*2,fa=.5)/f)*f; + r=is_undef(r2)?r:r+a; + step=360/fn; + + + points=[for(i=[0:fn])let(i=i%fn)[(r+a*cos(f*i*step+fv))*sin(i*step),(r+a*cos(f*i*step+fv))*cos(i*step)]]; + + + polygon(points); + InfoTxt("WStern",["OD",(r+a)*2,"ID",(r-a)*2,"r",r,"a",a],name); + HelpTxt("WStern",["f",f,"r",r,"a",a,"r2",r2,"fn",fn,"fs",fs,"fv",fv,"name",name],help); + +} + + + +/** \name Tri90 \page Polygons +Tri() creates a right angled triangle +\param grad angle optional +\param a seide lenght +\param b second side +\param c third side +\param r radius rounding +\param messpunkt show center +\param tang but round at origin +\param fn fs fragments +*/ + + +module Tri90(grad,a=25,b=25,c,r=0,messpunkt=0,tang=true,fn,fs=fs,name,help){ + + if (is_list(r)&&!tang)Echo("Tri90 Winkelfehler r is list & tang=false!",color="red"); + + b=is_undef(grad)?is_undef(c)?b:sqrt(pow(c,2)-pow(a,2)):tan(grad)*a; + grad=atan(b/a); + r1=is_list(r)?is_undef(r[0])?0:r[0]:r; + r2=is_list(r)?is_undef(r[1])?0:r[1]:r; + r3=is_list(r)?is_undef(r[2])?0:r[2]:r; + + gradB=90-grad; + + wA=90+grad; + wB=90+gradB; + wC=90; + a=tang?a:a+RotLang(90+grad/2,TangentenP(wB,r2))[0]; + btang=b+RotLang(+0-gradB/2,TangentenP(wA,r1))[1]; + + tA=[0,tang?b:btang]-RotLang(+0-gradB/2,TangentenP(wA,r1,r1)); + tB=[a,0]-RotLang(90+grad/2,TangentenP(wB,r2,r2)); + tC=RotLang(45,TangentenP(wC,r3,r3)); + +if(messpunkt){ + Col(6)union(){ // mittelpunkte + Pivot(tA,active=[1,0,0,1,1],size=messpunkt); + Pivot(tB,active=[1,0,0,1,1],size=messpunkt); + Pivot(tC,active=[1,0,0,1,1],size=messpunkt); + } + union(){ // tangentenpunkte + Pivot([0,0],active=[1,0,0,1,1,1],txt="C",size=messpunkt); + Pivot([0,b],active=[1,0,0,1,1],size=messpunkt); + Pivot([a,0],active=[1,0,0,1,1],size=messpunkt); + } + +} + + points=concat( + + r3==0?[[0,0]]:kreis(rot=180,grad=wC,fn=fn,fs=fs,rand=0,r=r3,t=tC,center=false), + r1==0?[[0,b]]:kreis(rot=270,grad=wA,fn=fn,fs=fs,rand=0,r=r1,t=tA,center=false), + r2==0?[[a,0]]:kreis(rot=+180-wB,grad=wB,fn=fn,fs=fs,rand=0,r=r2,t=tB,center=false) + +); + + polygon(points,convexity=5); + +InfoTxt("Tri90",["a",str(a," b=",b," c=",Hypotenuse(a,b),"mm",r?str(" true a=",tB[0]+r2," b=",tA[1]+r1," c=",norm(tA-tB)+r1+r2):""," grad α=",grad,"° grad β=",gradB,"° γ=90° Höhe c=",a*sin(gradB))],name); +HelpTxt("Tri90",["grad",grad,"a",a,"b",b,"c",c,"r",r,"messpunkt",messpunkt,"tang",tang,"fn",fn,"fs",fs,"name",name],help); + +} + +/** \name Tri \page Polygons +Tri() creates a isosceles triangle +\param grad angle +\param l seide lenght +\param l2 optional second side +\param h height +\param r radius rounding +\param messpunkt show center +\param center center +\param top put tip at origin +\param tang but round at origin +\param c side c +\param fn fs fragments +*/ + +module Tri(grad=60,l=20,l2,h=0,r=0,messpunkt=0,center=+0,top=0,tang=1,c,fn,fs=fs,name,help){ + assert(grad!=180&&grad,"Tri bad grad"); + Echo("WIP‼ c and tang=0",color="red",condition=is_num(c)&&!tang); + h=is_num(c)?c/tan(grad/2)/2:h; + l22=is_undef(l2)?l:l2; //wip + + fn=is_undef(fn)?0:fn; + + w1=180-grad; //Supplementwinkel + w2=(360-w1)/2; + w3=(360-w1)/2; + + rot=w2/2; + + r1=is_list(r)?is_undef(r[0])?0: + r[0]: + r; + r2=is_list(r)?is_undef(r[1])?0: + r[1]: + r; + r3=is_list(r)?is_undef(r[2])?0: + r[2]: + r; + + + l2=h?1/cos(grad/2)*(!tang?h+TangentenP(w1,r1):h):l22; + l3=h?1/cos(grad/2)*(!tang?h+TangentenP(w1,r1):h):l; + + hc=h?h:l*cos(grad/2); + + t1=[TangentenP(w1,r1,r1),0]; + t2=RotLang(90-grad/2,l2)-RotLang(90-w2/2,TangentenP(w2,r2,r2)); + t3=RotLang(90+grad/2,l3)-RotLang(90+w3/2,TangentenP(w3,r3,r3)); + +points=concat( + kreis(rand=0,r=r1,grad=w1,t=t1,fn=fn/3,fs=fs), + kreis(rand=0,r=r2,rot=-rot+180,grad=w2,t=t2,fn=fn/3,fs=fs), + kreis(rand=0,r=r3,rot=rot+180,grad=w3,t=t3,fn=fn/3,fs=fs) +); + + rotate(top?0:180)translate([center? + //-2*Kathete(l2,hc)/(2*sin(grad)):top? // center Umkreis + -(tang?hc+TangentenP(w1,r1):hc+2*TangentenP(w1,r1))/2:top? // center h + tang? + 0:-TangentenP(w1,r1) + :tang?-hc:h?-hc-TangentenP(w1,r1):-hc,0,0]){//Basis + polygon(points,convexity=5); + if(messpunkt){ + union(){//TangentenP + Pivot(active=[1,1,0,1],size=messpunkt); + translate(RotLang(90-grad/2,l2))rotate(90+w2/2)Pivot(active=[1,0,1,1],size=messpunkt); + translate(RotLang(90+grad/2,l3))rotate(90-w3/2)Pivot(active=[1,0,1,1],size=messpunkt); + } + + Col(6)union(){ // mittelpunkte + Pivot(t1,active=[1,0,0,1],size=messpunkt); + Pivot(t2,active=[1,0,0,1],size=messpunkt); + Pivot(t3,active=[1,0,0,1],size=messpunkt); + } + + } + } + + InfoTxt("Tri",["reale Höhe=",tang?hc-TangentenP(w1,r1):hc,"h",tang?hc:hc+TangentenP(w1,r1),"Basis",2*Kathete(l2,tang?hc:hc+TangentenP(w1,r1)),"Umkreis r",2*Kathete(l2,hc)/(2*sin(grad)),"c",l==l22?sin(grad/2)*l*2:"WIP"],name); + HelpTxt("Tri",["grad",grad,"l",l,"l2",l2,"h",h,"r",r,",messpunkt",messpunkt,",center=",center,"top",top,"tang",tang,"c",c,"fn",fn,"fs",fs,"name",name],help); + +} + + +/** +\name Welle +\page Polygons +Welle() creates multiple arcs or extrusions with children +\param e number of arc pairs +\param r radius arc 1 +\param r2 radius arc 2 +\param rand wall thickness +\param grad angle of arcs +\param ext extruded base when rand=0 +\param h height of wave +\param fn fragments +\param lap angle overlap +\param center 0-3 center at 0,1= center between arcs ,2= center arc 1,3= center arc 2 +*/ + +/* +c1=3; +Welle(e=3,r=12,r2=7,rand=0.0,grad=200,ext=20,h=0,fn=36,center=c1); +Tz(.5)Welle(e=3,r=12,r2=7,rand=0.5,grad=200,ext=20,h=0,fn=36,center=c1); +//*/ + +// Welle(rand=1,h=[6,10],e=3,ext=24); +// Welle(rand=1,h=[6,10],r=4,r2=6,e=3,grad=120); + +//Welle(grad=[60,40],h=5,r=[4,7],e=2);//WIP +//Welle(grad=40,h=6.8,r=[3,6],center=3,e=4); + + +module Welle(e=3,grad=200,r=5,r2,center=3,rand=2,h=0,ext=0,end=false,fn,fs=fs,lap=0,name,help,overlap){ + gradSUM=assert(grad)vSum(grad); + end=is_list(end)?end:[end,end]; + e=round(e); + lap=is_undef(overlap)?lap:overlap; // compatibility + r2=is_undef(r2)?is_list(r)?r[1]:r + :r2; + r=is_list(r)?r[0]:r; + + $x=rand; + grad1=(is_list(grad)?grad[0]:grad/2); //between S segments + grad2=(is_list(grad)?grad[1]:grad/2); //in S segment + + w=(gradSUM-180)/2; + y=sin(grad2)*r ; // shift r + y2=sin(grad2)*r2;// shift r2 + yg1=sin(grad1)*r ; // shift r + y2g1=sin(grad1)*r2;// shift r2 + + hORG=h; + Echo("h increased to min height",color="warning",condition=is_num(hORG)&&hORG>0&&(hORG/2<(1-cos(grad2))*r||hORG/2<(1-cos(grad2))*r2 ) ); + + hList=is_list(h)?h:[max(h/2,(1-cos(grad2))*r),max(h/2,(1-cos(grad2))*r2)]; + h=[hList[0]-(1-cos(grad2))*r , hList[1]-(1-cos(grad2))*r2 ]; + Echo("h for 3D not implemeted",color="redring",condition=max(h)&&$children); + hi=[-cos(grad2)*r , -cos(grad2)*r2]+h; + + + Echo(str("h diff sum",h,"Σ=",vSum(h)," < 0"),color="redring",condition=vSum(h)<0); + + + + //delta=(h[0]*tan(90-grad1)+h[1]*tan(90-grad2))*2; + + delta2= vSum(h) *tan(90-grad2) ; // in S Segment + delta=y+y2+yg1+y2g1 + (vSum(h))*tan(90-grad1) + delta2 ;// between S segments + + fn=is_undef(fn)||fn==0?[fs2fn(r=r,grad=gradSUM,fs=fs),fs2fn(r=r2,grad=gradSUM,fs=fs)]:is_list(fn)?fn:[fn,fn]; + points=[ + each for(i=[0:round(e-1)])each[ + arc(r2+rand/2,deg=grad1+grad2+(i==0&&end[0]?90-grad1:0),t=[-hi[1],-y2+delta*i],rot=180-grad2,fn=fn[1],rev=1), + arc(r-rand/2,deg=grad1+grad2+(i==(e-1)&&end[1]?90-grad1:0),t=[hi[0],y+delta2+delta*i],rot=-grad2,fn=fn[0],rev=0) + ] , + + if (rand) each[ + if(end[1]&&hi[0]>0)[0,y+r+delta2+ delta*(e -1)-rand/2], + if(end[1]&&hi[0]>0)[0,y+r+delta2+ delta*(e -1)+rand/2], + + each for(i=[round(e-1):-1:0])each[ + arc(r+rand/2,deg=grad1+grad2+(i==(e-1)&&end[1]?90-grad1:0),t=[hi[0],y+delta2+delta*i],rot=-grad2,fn=fn[0],rev=1), + arc(r2-rand/2,deg=grad2+grad1+(i==0&&end[0]?90-grad1:0),t=[-hi[1],-y2+delta*i],rot=180-grad2,fn=fn[1],rev=0) + ] , + + //[0,-y2+rand/2],[0,-y2-rand/2] , + if(end[0]&&hi[1]>0 )[0,-y2-r2+rand/2], + if(end[0]&&hi[1]>0 )[0,-y2-r2-rand/2], + ], + // extension + if (rand==0) each[ [ext,y*2+delta2+ delta *(e -1)],[ext,-y2*2] ], + ]; + + //echo(points); + + if(!$children)T(0,center?center>1?center>2?y2- delta *(e-1)/2// c3 + :-delta2-y- delta*(e-1)/2// c2 + :0-delta2/2- delta*(e -1)/2 // c1 WIP!! + :end[0]?r2+y2:y2*2) + polygon(points); + + + T(0,center?center>1?center>2?y2:-y:0:y2*2)Linear(es=(y+y2)*2,e=e,x=0,y=1,center=center) + union(){ + + if(false){ + T(hi[0],y/2) Kreis(grad=grad+lap,r=r,fn=fn[0],rand=rand,rcenter=true,sek=true); + T(-hi[1],-y2/2) Kreis(grad=grad+lap,fn=fn[1],r=-r2,rand=rand,rcenter=true,sek=true); + } + +//3D + if($children) { + T(sin(w)*r,y) RotEx(grad=grad+lap,fn=fn[0],center=true)T(r)children(); + union(){ + $info=0; + $helpM=0; + T(-sin(w)*r2,-y2)RotEx(grad=grad+lap,fn=fn[1],center=true)T(-r2)children(); + } + + } + } + + InfoTxt("Welle",["Wellenenhöhe h+r/r2=",str(h[0]+r+sin(w)*r,"/",-h[1]-r2-sin(w)*r2),"Abstand r/r2=",str(y,"/",y2),"Länge=",e*(y+y2)],name); + HelpTxt("Welle",[ + "e",e, + "grad",grad, + "r",r, + "r2",r2, + "center",center, + "rand",rand, + "h",h, + "ext",ext, + "end",end, + "fn",fn, + "fs",fs, + "lap",lap, + "name",name] + ,help); +} + + +/** \name Riemen \page Polygons +Riemen() creates a belt form can use polygons as children for 3D +\param r1 radius pulley 1 +\param r2 raduis pulley 2 +\param tx pulley distance +\param fn fs fragments +\param center center +\param lap overlap (for 3D) +\param name help name help +*/ + +//Rand(1)Riemen(tx=25,r1=5,r2=10,center=-1,$messpunkt=true); +//Cut()Riemen(center=+0,fn=25)rotate(90)Rund(0.2,fn=12)Nut(a=undef,b=undef,es=2,e=5,grad=70,center=false); + + + + +module Riemen(r1=5,r2=10,tx=25,fn,fs=fs,center=false,lap=0.005,spiel=0,name,help){ +lapL=0; +r1=r1+spiel; +r2=r2+spiel; +a=asin((r2-r1)/tx); +lTrum=cos(a)*tx; +tx0=r2/sin(a)-tx; +U=lTrum*2+r1*PI/180*(180-a*2)+r2*PI/180*(180+a*2); + +if(r1!=r2)Pivot(p0=b(center,false)<0?[0,0]:[(center?-tx/2:0)-tx0,0],rot=a); + +InfoTxt("Riemen",["alpha",a,"Trum",lTrum,"Umfang",U,"tx",tx,"ratio",str("1:",r1/r2,"/",r2/r1,":1")],name); + +Echo(str(name," Wellen Abstand ",tx,"mm nicht Norm gemäß! min tx=",1.4*(r1+r2)," max=",4*(r1+r2)," Winkel=",a,"°"),color="warning",condition=(1.4*(r1+r2)>tx||4*(r1+r2)20)&&(is_undef($idx)||!$idx)); + +if(!$children){ + if(b(center,false)<0&&r1!=r2) translate([tx0,0])polygon(riemen(r1=r1,r2=r2,tx=tx,fn=fn,fs=fs,center=0)); + else polygon(riemen(r1=r1,r2=r2,tx=tx,fn=fn,fs=fs,center=center)); + } else translate([(center?b(center,false)<0&&r1!=r2?tx0:-tx/2:0),0,0]){ + $idx=1; + + union(){ + $idx=0; + rotate(180)RotEx(grad=180 - a*2 +gradS(s=lap,r=r1)*2,center=true,fn=fn)T(r1)children(); + } + + T(tx)RotEx(grad=180 + a*2 +gradS(s=lap,r=r2)*2,center=true,fn=fn)T(r2)children(); + rotate([0, 90,-a +180])T(0,r1)rotate(-270)Tz(-lTrum+lapL)linear_extrude(lTrum-lapL*2,convexity=5)children(); + rotate([0,-90, a +180])T(0,-r1)rotate(-90)Tz(+lapL)linear_extrude(lTrum-lapL*2,convexity=5)children(); + } + +//echo(pathLength(riemen(r1=r1,r2=r2,tx=tx,fn=fn,center=center),close=true)); +HelpTxt("Riemen",["r1",r1,"r2",r2,"tx",tx,"fn",fn,"fs",fs,"center",center,"spiel",spiel,"name",name],help); + +} + +/** \name Involute \page Polygons +\brief Involute() creates an involute polygon +\param r radius +\param s width +\param h height +\param r2 ↦ h+r +\param grad degree circle segment (optional) +\param end -1,0,1,2 end connection termination +\param delta outside change can be list for delta2 +\param delta2 inside change optional +\param center s center or outside +\param oppose opposing involutes +\param centerP creates a point at [0,0] +\param fn fs fargment number or size +\param name name for info +\parma help help +*/ +//Involute(oppose=0,h=3,grad=0,end=+2,center=+0,delta=0,s=1,centerP=true);// Involute profile +//Involute(r=10,r2=25); + +module Involute(r=10,s=1,h=5,r2,grad,end=+1,delta=0,delta2,center=true,oppose=false,centerP=false,fn,fs=fs,name,help){ + +//fn=ceil(grad/360)*fn; +h=max(0,is_undef(r2)?h:r2-r); +grad=grad?grad:360/(PI*2*r) * sqrt( 2*r*h+h^2); +deltaList=delta; +delta=is_list(delta)?delta[0]:delta; +deltai =is_undef(delta2)&&is_num(deltaList)? delta/2:delta ; +delta2=is_undef(delta2)&&is_num(deltaList)?-delta:is_list(deltaList)?deltaList[1]:delta2; +grads=gradS(s=s,r=r); + + +p1=involute(r=r,grad=grad,rot=0,rev=true,delta=delta,fn=1); +pOpp=involute(r=r,grad=grad+(end>0?grads:0),rot=0,rev=true,delta=deltai,fn=1); +ih=oppose?norm(p1[0]):norm(pOpp[0]); + +winkel=(atan2(p1[0].x,p1[0].y)); +rot=winkel+gradS(r=ih,s=s)/2; + + +points=oppose?concat( + centerP?[[0,0]]:[], + involute(r=r,grad=grad,rot=center?-rot:0,delta=delta,fn=fn,fs=fs), + involute(r=r,grad=-grad,rot=center?rot:rot*2,rev=true,delta=-delta,fn=fn,fs=fs) +): + concat( + centerP?[[0,0]]:[], + involute(r=r,grad=grad+(end>0? end>1?grads/2 : grads:0),rot=center?-grads/2:0,delta=deltai,fn=fn,fs=fs), + involute(r=r,grad=grad+(end<0?-grads:end>1?-grads/2 : 0),rot=center?grads/2:grads,rev=true,delta=delta2,fn=fn,fs=fs) + ) +; + + +polygon(points); + +InfoTxt("Involute",["h",ih],name); + +HelpTxt("Involute",["r",r,"s",s,"h",h,"grad",grad,"end",end,"delta",delta,"delta2",delta2,"center",center,"oppose",oppose,"centerP",centerP,"fn",fn,"fs",fs,"name",name],help); +} + + + + +//NACA(); // 2D NACA airfoil profil + +module NACA(l=10,naca=0012,fn=fn,center=false,name,help){ + +points=naca(l=l,naca=naca,fn=fn); +InfoTxt("NACA",["Surface length",pathLength(points),"center",center?center==2?str("30%-max Thickness=",l*0.3):str("¼-25% neutral (N)=",l*0.25):0],name); +translate([center?center==2?-l*0.3:-l*.25:0,0])polygon(points); +HelpTxt("NACA",["l",l,"naca",str(naca<1000?"00":"",naca%100),"fn",fn,"center",center,name],help); +} + +//Star(od=10,id=5); + +module Star(e=5,r1=10,r2=5,grad=[0,0],grad2,radial=false,fn=0,fn2,d,od,id,r,help){ + kfn=is_num(fn2)?round(fn2):d?max(12,fs2fn(r=abs(d/2),fs=fs)):12; + r1=is_num(od)||is_list(od)?od/2 + :is_list(r)?r[0]:r1; + r2=is_num(id)||is_list(id)?id/2 + :is_list(r)?r[1]:r2; + + od=assert(is_num(r1)||is_list(r1),str("Star r1=",r1))r1*2; + id=assert(is_num(r2)||is_list(r2),str("Star r2=",r2))r2*2; + + points=concat( + star(e=e,r1=r1,r2=r2,grad=grad,grad2=grad2,radial=radial,fn=fn,z=undef), + d? kreis(d=d,rand=0,fn=kfn,endPoint=false):[] + ); + + paths=[ + [for(i=[0:len(star(e=e,fn=fn))-1])i], + if(d) [for(i=[0:len(kreis(rand=0,fn=kfn,endPoint=false))-1])i+len(star(e=e,fn=fn))] + ]; +polygon(points,paths,convexity=5); + +HelpTxt("Star",["e",e,"r1",r1,"r2",r2,"grad",grad,"grad2",grad2,"radial",radial,"fn",fn,"fn2",fn2,"d",d,"od",od,"id",id],help); + +} + +/** \name Tdrop +\page Polygons +Tdrop() creates a Teardrop polygon +\param r radius +\param d diameter ↦ r +\param deg angle +\param cut flat top cut +\param fn,fs fragments +\param name name +\param help help +*/ + +module Tdrop(r=1,d,deg,cut=true,fn,fs=fs,nozzle=nozzle,layer=layer,name,help,grad){ + +grad=is_undef(grad)?deg:grad; +kgrad=is_undef(grad)?atan(layer/(nozzle/1.75)):90-grad; +delta=is_bool(cut)?nozzle-layer:cut; // added cut + +r=is_num(d)?d/2:r; +h=cos(kgrad)*r; +x=sin(kgrad)*r; +h2=cut==false?h+tan(kgrad)*x:min(r+delta,h+tan(kgrad)*x); +x2=cut==false? 0:x - (h2-h)/tan(kgrad); + + +points=[ +//[-x,h], +//[ x,h], +each kreis(rand=0,r=r,grad=360-kgrad*2,center=true,rot=-90,fn=fn,fs=fs), +if(x2>minVal)[- x2,h2], +clampToX0([ x2,h2]) +]; + +if(messpunkt)%Tz(.1)color("green",.25)circle(r=r,$fn=fn); +polygon(points); +InfoTxt("Tdrop",["grad",90-kgrad,"cut",cut],name); +HelpTxt("Tdrop",["r",r,"d",d,"deg",deg,"cut",cut,"fn",fn,"fs",fs,"nozzle",nozzle,"layer",layer,"name",name],help); +} + +/** \name VarioFill +\page Polygons +VarioFill() creates an fillet, chamfer round or hyperbolic +\param l length [x,y] +\param exp hyperbolic exponent +\param dia,h 3D rotate or linear extrude +\param chamfer if true exp=1, false = ellipsoid +\param deg angle if l is number +\param extrude move in x ↦ radius for RotEx() +\param grad angles of sides to create fillet +\param lap overlap - [x,y] +*/ + +//VarioFill([5,2],exp=2.0,fn=3,chamfer=0); + + + + +module VarioFill( +l=15, +exp=+2, +dia, +h, +chamfer=true, +deg=45, +extrude=0, +grad=90,//[0,90] +spiel, +lap=.2, +fn=fn, +fs=fs, +name, +help +){ + +lap=is_list(lap)?lap:[lap,lap]; +grad=is_list(grad)?grad:[+0,grad]; + +padding=is_undef(spiel)?lap.yx: + is_list(spiel)?[spiel.x,spiel.y]: + [spiel,spiel]; + +spiel=is_undef(spiel)?lap.yx:is_list(spiel)? // spiel xy is mixed up + [spiel.x*max(1,(1/(sin(grad.y)*cos(grad.x)))),spiel.y*max(1,(1/(cos(grad.x)*sin(grad.y))))]: + [spiel*max(1,(1/(sin(grad.y)*cos(grad.x)))),spiel*max(1,(1/(cos(grad.x)*sin(grad.y))))]; + //[spiel*(1/sin(grad.y)),spiel*(1/cos(grad.x))]; + +l=is_list(l)?l:deg?[l,tan(deg)*l]:[l,l]; + +fn=is_undef(fn)||fn==0?fs2fn(r=max(l),grad=90,fs=fs):fn; + +diaw=dia; // if undef ⇒ 2D + +dia=is_num(dia)?grad.x?2*Hypotenuse(dia/2,tan(grad.x)*dia/2) + :dia + :0; + +extrude=extrude*sign(l.x); +rot=-180; +p1=[ +[-spiel.y*sign(l.x) +dia/2, -spiel.x*sign(l.y)], +[-spiel.y*sign(l.x) +dia/2, l.y+sin(grad.x)*spiel.y*sign(l.y)], +[+extrude+dia/2,l.y], +for(i=[fn -1:-1:+0])let(seg=90/fn*i) + chamfer?[pow((fn-i)/fn,abs(exp))*l.x+extrude+dia/2,pow(i/fn,abs(exp))*l.y]: + [sin(seg+rot)*l.x+extrude+l.x+dia/2, cos(seg+rot)*l.y+l.y], + +[extrude+l.x+dia/2,0], +[extrude+l.x-cos(grad.y)*spiel.x*sign(l.x) +dia/2,-spiel.x*sign(l.y)], +]; + + +m=[ +[cos(grad.x),sin(grad.y-90),+0,0],// scale x, skew x, trans x +[sin(grad.x),cos(grad.y-90),0,0], // skew y, scale y, trans y +[0,0,1,0], +]; + +points=grad==[0,90]?p1: + [for(i=[0:len(p1)-1])let(p=m*concat(p1[i],[1,0]))[p.x,p.y]]; + +gK=sin(grad.y)*l.y-sin(grad.x)*l.x; +aK=cos(grad.x)*l.x+cos(grad.y)*l.y; + +// color("red")square([aK,gK]); +//polygon(points,convexity=5); +//p2=[for(i=[0:len(points)-1])let(p=m*concat(points[i],[1,0]))[p.x,p.y]]; + +InfoTxt("VarioFill",["sekantenWinkel",atan(gK/aK)],name); + + +cut=spiel.y>abs(dia/2)?true: + sign(dia*l.x)==1?false : // both pos or neg + sign(dia)*l.x<=sign(l.x)*dia/2; + + + +if(is_num(diaw) && !is_parent(needs2D)) RotEx(cut=grad.x==0&&grad.y==90?cut:true) polygon(points); + else if(h && !is_parent(needs2D)) linear_extrude(h,convexity=2,$fn=fn)polygon(points); + else if( l.x>0?grad.y>90:grad.y<90 || (l.y>0?grad.x<0:grad.x>0) ) + intersection(){ + polygon(points); + mirror([sign(l.x)==1?0:1,sign(l.y)==1?0:1])translate([-padding.y+dia/2-(extrude*sign(l.x)<0?-extrude*sign(l.x):0),grad.x<0?-l.y:-padding.x]) + square([abs(extrude)+abs(l.x)+padding.y,grad.x<0?2*l.y:abs(l.y)+padding.x]); + } + else polygon(points); + +//%multmatrix(m)translate([-spiel.y,-spiel.x])square([l.x+spiel.y,l.y+spiel.x]); +HelpTxt("VarioFill",[ + "l",l, + "exp",exp, + "dia",dia, + "h",h, + "chamfer",chamfer, + "deg",deg, + "extrude",extrude, + "grad",grad,//[0,90] + "lap",lap, + "fn",fn, + "name",name + ],help); + +} + + + +/** \page Polygons +Kreis() creates a circle polygon +\name Kreis +\param r radius +\param dicke rim +\param grad angle +\param grad2 optional rim angle +\param fn fragments +\param center center (angle <360) +\param sek secant or center point (angle <360) +\param r2 y radius for oval +\param rcenter rim center +\param rot rotate circle +\param t translate circle +\param name name for circle +\param help help +\param d diameter optional to r = d↦r +\param id optional to dicke +\param b optional to grad, L of the circular arc +\param fs,fa fragment size optional to fn fs↦fn,min fraqment angle + +*/ + +//Kreis(d=10,id=8,grad=270); + + +module Kreis(r=10,dicke=0,grad=360,grad2,fn,center=true,sek=false,r2=0,rand2,rcenter=0,rot=0,t=[0,0],name,help,d,b,fs=fs,fa=fa,rand,id){ + r=is_undef(d)?r:d/2; + d=2*r; + dicke=is_undef(rand)?is_undef(id)?dicke:(d-id)/2 + :rand; + + grad=is_undef(b)?grad:r==0?0:b/(2*PI*r)*360; + b=2*r*PI*grad/360; + + points=kreis(r=r,rand=dicke,grad=grad,grad2=grad2,fn=fn,center=center,sek=sek,r2=r2,rand2=rand2,rcenter=rcenter,rot=grad==360?center?rot:rot+90:center?rot+180:rot+90,t=t,fs=fn?undef:fs,endPoint=grad==360?false:true,fa=fa); + + path=dicke&&grad==360&&is_num(fn)?[[for(i=[0:fn]) i],[for(i=[fn:len(points)-1]) i]] + :[[for(i=[0:len(points)-1]) i]]; + + polygon(points=points ,paths=path,convexity=5); + + HelpTxt("Kreis",["r",r,"dicke",dicke,"grad",grad,"grad2",grad2,"fn",fn,"center",center,"sek",sek,"r2",r2,"rand2",rand2,"rcenter",rcenter,"rot",rot,"t",t,"name",name,"d",d,", b",b,"id",id,"fs",fs],help); + + + if(!rcenter){ + if(dicke>0)InfoTxt("Kreis",["id",2*(r-abs(dicke)),"od",2*r],name); + if(dicke<0)InfoTxt("Kreis",["id",2*r,"od",2*(r+abs(dicke))],name); + } + else if(dicke)InfoTxt("Kreis",["id",2*r-abs(dicke)," od=",2*r+abs(dicke)],name); + +} + + +module ZigZag(e=5,es=0,x=50,y=7,mod=2,delta=+0,base=2,shift=0,center=true,name,help){ + x=es?e*es:x; + es=es?es:x/e; + T(center?-x/2:0) polygon(ZigZag(e=e,x=x,y=y,mod=mod,delta=delta,base=base,shift=shift),convexity=5); + abst=x/e; + h=y-base; + InfoTxt("ZigZag",["Winkel",str(atan((abst/2+shift)/h),"°+",atan((abst/2-shift)/h),"°=",atan((abst/2+shift)/h)+atan((abst/2-shift)/h),"°"),"Spitzenabstand",abst,"Zackenhöhe",h],name); +Echo("‼ use Nut(a=0,b=0)",color="redring"); +HelpTxt("ZigZag",["e",e,"es",es,"x",x,"y",y,"mod",mod,"delta",delta,"base",base,"shift",shift,"center",center,"name",name],help); + +} + + +/** \name Nut +\page Polygons +Nut() creates grooves or notches or dovetails +\param e elements or number of notches +\param es element spacing, distance between, will be calculated if grad is used +\param a length top of the notch - can be undef +\param b bottom length of notch - can be undef +\param base base thickness below +\param h height of notches +\param s total length ↦ es +\param center center +\param shift shift top sections / skew +\param grad winkel the angle of the notches +\param name help name and help +*/ + +//union()Color(){ +//Nut(a=5,b=5); +//Tz(.1)Nut(a=undef,b=1,grad=40); +//} + +//Nut(es=10,a=undef,b=undef,grad=60); + +module Nut(e=2,es=10,a=6,b=6,base=1,h=1,s,center=true,shift=0,winkel,grad,name,help){ + grad=is_undef(winkel)?assert(grad!=0)grad:assert(winkel!=0)winkel; + + esA=is_undef(s)?es:s/e; + a= is_undef(a)?is_undef(b)?(esA/2+1*h*tan(90+grad)):esA+2*h*tan(90+grad)-b:a; + + s=is_undef(s)?is_num(grad)&&is_num(b)?e*(a+b-2*h*tan(90+grad)): + is_undef(es)?assert( is_num(b) && is_num(a),"define a + b")a+b: + e * es: + s; + + + es=is_num(grad)&&is_num(b)?a+b-2*h*tan(90+grad): + s/e; + + b=is_undef(grad)?is_undef(b)?es-a: + b: + 2*(h*tan(90+grad))+es-a; + + + points=assert(e>0,"Nut has no elements")[[s,base],[s,0],[0,0],[0,base], +for(i=[0:e-1])each[ + [b/2+i*es,base], + [es/2-a/2+shift+i*es,h+base], + [es/2+a/2+shift+i*es,h+base], + [(es-b/2)+i*es,base]] + ]; + path=[[for(i=[0:len(points)-1])i]]; + // echo (points,path); + + + translate(center?[-s/2,-base]:[0,0]) polygon(points,path,convexity=10); + winkel1=atan(h/(es/2-a/2-b/2+shift)); + winkel2=atan(h/(es/2-a/2-b/2-shift)); + + InfoTxt("Nut",concat(["winkel",str(winkel1,shift?str(" /",winkel2):"","°"), + "Länge",s, + "Abstand",es], + "Abstand a",negRed(es-a), + "Abstand b",negRed(es-b), + grad?["b",negRed(b)]:[]) + ,name); + + HelpTxt("Nut",[ + "e",e, + "es",es, + "a",a, + "b",b, + "base",base, + "h",h, + "s",s, + "center",center, + "shift",shift, + "grad",grad, + "name",name], + help); +} + + + +module Egg(r1=10,r2=3,breit,grad,r3=true,fs=fs,name,help){ + + breit=is_undef(breit)?r1:breit; + x=r1-breit/2; + r2=is_undef(grad)?r2:r1-(Hypotenuse(x,tan(grad)*x)); + assert(breit>=r2*2,str("max r2=",breit/2,"/ breit min=",r2*2," r2=",r2,"breit=",breit)); + assert(breit<=r1*2,str("breit>r1*2 r1=",r1," breit=",breit)); + a=r1-r2; + grad=is_undef(grad)?acos(x/a):grad; + hM=tan(grad)*x; + r3=r3?true:false; + +// %Color(){ +// Kreis(r1,grad=grad,center=false,t=[0,-r1/2]); +// Kreis(r2,grad=180-grad*2,center=true,t=[hM,0]); +// Kreis(r1,grad=grad,center=false,rot=180-grad,t=[0,r1/2]); +// if(r3)Kreis(grad=180,r1/2,rot=180); } + + + + points=concat( + kreis(r1,grad=grad,rot=-90,center=false,t=[x,0],rand=0,sek=true,fn=fs2fn(r1,grad,fs,5)) + , kreis(r2,grad=180-grad*2,rot=90,center=true,t=[0,hM],rand=0,sek=true,fn=fs2fn(r2,180-grad*2,fs,5))//spitze + , kreis(r1,grad=grad,center=false,rot=90-grad,t=[-x,0],rand=0,sek=true,fn=fs2fn(r1,grad,fs,5)) + ); + + pointsR3=Kreis(grad=180,r=breit/2,rot=-90,rand=0,sek=true,fn=fs2fn(breit/2,180,fs,10)); + + polygon(r3?concat(points,pointsR3):points); + + //if(help)echo("Help Egg(r1=10,r2=3,grad,r3=1,name,help);"); + HelpTxt("Egg",["r1",r1,"r2",r2,"breit",breit,"grad",grad,"r3",r3,"fs",fs,"name",name],help); + InfoTxt("Egg",["hM",hM,"h",str(hM+r2,r3?str("/",hM+r2+breit/2):""),"breit(r3×2)",breit,"grad",grad,"r1",r1,"r2",r2],name); +} + +/* +Tz(.25)color("green")GT(spiel=0,spielO=0); +Tz(.75)color("red")GT(spielO=0.05,spiel=0);// pre β22|064 +Tz(.5)GT(); +// */ + + +/// GT2 tooth +module GT2(spiel=0,fn=fn){ + fn=max(6,fn); + p=2; // zahnabstand + PLD=0.254; // ?Mittellinie? Pitch Line distance + r1=.15;//kehle basis zahn + r2=1+spiel; // zahn flanken radius im abstand [b,i] + r3=.555+spiel;// zahn spitzen radius + b=0.4;// abstand mitte Mittelpunkt r2 + h=1.38; //gesamt h (i+ht) + ht=0.75+spiel; // zahnhöhe + i=.63; // band dicke + + l=p +0.1; + + pointsGT2= concat( + [[-l/2,ht],[-l/2,ht+i],[l/2,ht+i],[l/2,ht]] + , kreis(r=r2,fn=fn/16,grad=22.5,center=false,t=[-b,ht],rot=90,rand=0,sek=true) + , kreis(r=r3,grad=180-45,rot=-90,fn=fn/4,t=[0,r3],rand=0,sek=true) + , kreis(r=r2,fn=fn/16,grad=22.5,center=false,t=[b,ht],rot=-90-22.5,rand=0,sek=true) + ); + + T(0,-ht )Rund(0,r1,fn=fn) + polygon(pointsGT2); + +//union(){ +//%T(-p,ht)square([2*p,i]); +// } +// Color("lime")T(0,r3,-0.1)circle(r3,$fn=fn); +// Color("green")T(0,ht,-.11)intersection(){ +// T(b)circle(r=r2,$fn=fn); +// T(-b)circle(r=r2,$fn=fn); +// square([2,0.85],true); +// } + //%Color("red")T(0,ht-r1)MKlon(0.736)circle(r1); + +} + + // GT(); +/// GT2 profile rack, belt or pulley +module GT(z=20,achse=3.5,spiel=.05,evolute=true,pulley=true,linear=true,fn=fn,name,help,spielO=0){ + p=2; // zahnabstand + PLD=0.254; // ?Mittellinie? Pitch Line distance + b=0.4;// abstand mitte Mittelpunkt r2 + r1=.15;//kehle basis zahn + r2=1; // zahn flanken radius im abstand [b,i] + i=.63; // band dicke + breiteZahn=(r2-b)*2; + umfang=z*p; + zahnWinkel=360/z; + + +if(pulley){ + if(evolute){ + offset(-spielO) + Rund(r1,0,fn=fn/4) + union(){ + r=umfang/2/PI; + difference(){ + circle(r,$fn=z*2); + for(i=[0:z-1])rotate(i*360/z) + for(i=[-ceil(zahnWinkel/2):ceil(zahnWinkel/2)])rotate(-i)T(-umfang/360*i,r-PLD)GT2(spiel); + if(achse)circle(d=achse-spielO*2,$fn=fn); + } + InfoTxt("GT2 Pulley evolute profile",["Dia",r*2-spiel*2-PLD*2,"z",z],name); + //if(name)echo(str(is_bool(name)?"":"",name," GT2 Pulley evolute profil Dia=",r*2-spiel*2-PLD*2," z=",z)); + } + } + else{ + offset(-spielO) + Rund(r1,0,fn=fn/4) + union(){ + r=umfang/2/PI-PLD; + difference(){ + circle(r,$fn=z*2); + for(i=[0:z-1])rotate(i*360/z)T(0,r)GT2(spiel); + if(achse) circle(d=achse-spielO*2,$fn=fn); + } + InfoTxt("GT2 Pulley",["Dia",r*2-spielO*2,"z",z],name); + //echo(str(is_bool(name)?"":"",name," GT2 Pulley Dia=",r*2-spiel*2,"z=",z)); + } + } + + } + else offset(-spielO){ + $info=false; + if (linear)Linear(e=z,es=2)GT2(-spiel); + else { + r=umfang/2/PI; + intersection(){ + Polar(e=z,y=r-PLD)GT2(-spiel); + circle(r+i-PLD,$fn=z*2); + } + } + InfoTxt("GT2 Belt",concat(["Länge",z*p],linear?[]:["(aussen",str((umfang/2/PI+i-PLD)*2*PI,")")]),name); + // echo(str(is_bool(name)?"":"",name," GT2 Belt Länge=",z*p,linear?"":str("(aussen ",(umfang/2/PI+i-PLD)*2*PI,")"))); + + } + +HelpTxt("GT",["z",z, +"achse",achse, +"spiel",spiel, +"evolute",evolute, +"pulley",pulley, +"linear",linear, +"fn",fn, +"spielO",spielO, +"name",name +],help); + +} + module Rosette( r1=10, r2=15, @@ -2901,12 +5188,42 @@ HelpTxt("Rosette",[ ], help); } +/** \page Polygons +Pfeil() creates an arrow +\brief creates an arrow +\name Pfeil +\param l length [tail,head] or total length +\param b width [tail,head] or teil and head is calculated by angle(grad) +\param shift shifting center and end points +\param grad arrow head angle +\param d form circular arrow +\param angle angle of circular arrow (optional) +\param center centers arrow +\param name names arrow +\param help activate help +*/ -module Pfeil(l=[+2,+3.5],b=+2,shift=0,grad=60,d,center=true,name,help){ +//Pfeil(d=20,angle=-70,shift=-1); + + +module Pfeil(l=[+2,+3.5],b=+2,shift=0,grad=60,d=0,angle=0,center=true,name,help){ shift=is_list(shift)?shift:[shift,-shift]; - l=is_list(l)?l:[l/2,l/2]; - b=is_list(b)?b:[b,2*(l[1]-shift[0])*tan(grad/2)]; - center=is_bool(center)?center?[1,1]:[0,0]:is_list(center)?center:[center,center]; + l=is_list(l)?l:[l/2,l/2]; + b=is_list(b)?b:[b,2*(l[1]-(d?0:shift[0]))*tan(grad/2)]; + center=is_bool(center)?center?[1,1]:[0,0]:is_list(center)?center:[center,center]; + dir=sign(d)*(angle?sign(angle):1); + d=d?max(abs(d),abs(b[1])):0; + + lD=[angle?min(abs(d)*PI/360*abs(angle),PI*abs(d)-l[1]-shift[0]-.01 ) :l[0],l[1]];// lenght circular arrow + angle=angle?angle:gradB(r=d/2,b=l[0])*dir; + + gradB=d?gradB(b=lD[1]+ shift[1],r=d/2) :0; // länge Pfeilspitze auf Kreis + + fnD=max(8,ceil(norm([b[1]/2,lD[1]])/$fs)); // fraqments gebogene Spitze + fnDend=max(10,ceil(abs(lD[0])/$fs)); + + spitze=false; // gebogene Spitze = false + points=[ [l[1],0],//spitze [shift[0],b[1]/2], @@ -2919,23 +5236,32 @@ module Pfeil(l=[+2,+3.5],b=+2,shift=0,grad=60,d,center=true,name,help){ ]; -if(d)translate(center.y?center.y<0?[0,d/2]: - [0,0]: - [0,-d/2]){ - Kreis(d=d,rand=b[0],b=-l[0],center=false,rcenter=true,rot=-90); + pointsD=[ + [0,d/2-b[0]/2], + each kreis(rand=0,grad=dir*gradB(r=d/2+b[0]/2*0,b=-lD[0]),d=d+b[0],center=0,fn=fnDend), + [sin(dir*-gradB(r=d/2,b=lD[0] +shift[0]))*d/2,cos(dir*-gradB(r=d/2,b=lD[0] +shift[0]))*d/2],//shift End - translate([0,d/2])polygon(points); -// intersection(){ // bend arrow head option -// square(50); -// difference(){ -// sca=0.4; -// T(+0)scale([1-sca,1])circle(r=d/2+b[1]/2); -// T(+0)scale([1.1+sca,1])circle(r=d/2-b[1]/2);//+b[1]/2); -// } -// %circle(r=d/2); -// } -} - else translate([center.x?center.x>0?0:-l[1]:l[0],center.y?center.y>0?0:-b[1]/2:b[1]/2]) polygon(points); + each kreis(rand=0,grad=dir*-gradB(r=d/2-b[0]/2*0,b=-lD[0]),d=d-b[0],center=0,rot=dir*gradB(r=d/2-b[0]/2*0,b=-lD[0]),fn=fnDend), + + [0,d/2+b[0]/2], + for(i=[0:fnD ]) let(deg= dir * (i*gradB/fnD - gradB(shift[1],r=d/2) ), r=d/2 +(b[1]/2/fnD)*(fnD-i)) + [sin(deg)*r,cos(deg)*r], + for(i=[fnD :-1:0]) let(deg= dir * (i*gradB/fnD - gradB(shift[1],r=d/2) ), r=d/2 -(b[1]/2/fnD)*(fnD-i)) + [sin(deg)*r,cos(deg)*r], + + ]; + + if(d)translate(center.y?center.y<0?[0,d/2]: + [0,0]: + [0,-d/2]){ + if(spitze)union(){ + Kreis(d=d,rand=b[0],b=-l[0],center=false,rcenter=true,rot=-90); + T(y=d/2)polygon(points); + } + else polygon(pointsD); + + } + else translate([center.x?center.x>0?0:-l[1]:l[0],center.y?center.y>0?0:-b[1]/2:b[1]/2]) polygon(points); InfoTxt("Pfeil",["Winkel",2*atan((b[1]/2)/(l[1]-shift[0]))],name); HelpTxt("Pfeil",[ @@ -2944,10 +5270,4339 @@ HelpTxt("Pfeil",[ "shift",shift, "grad",grad, "d",d, + "angle",angle, "center",center, "name",name],help); } +/** \page Polygons +DPfeil() creates a double head arrow +\brief creates a double head arrow +\name DPfeil +\param l total length +\param b width [tail,head] or teil and head is calculated by angle(grad) +\param shift shifting center and end points +\param grad arrow head angle +\param d form circular arrow +\param txt add text +\param rot rotate text +\param center centers arrow +\param name names arrow +\param help activate help + +##Example +DPfeil(l=[60,10],grad=30,txt="ABC"); +T(0,10)DPfeil(); +T(0,-10)DPfeil(shift=-1,txt=true); +*/ + +//for(l=[3:5:30])T(y=l/1)DPfeil([l,4],txt=true,rot=0); + +module DPfeil(l=40,b=undef,shift=0,grad=35,d=0,txt,rot,center=true,name,help){ + + l=is_list(l)?l:[l,l/8]; + shift=is_list(shift)?shift:[shift,txt?-shift:0]; + lP=[l[0]/2-l[1],l[1]]; + b=is_list(b)?b:[is_undef(b)?l[0]/20:b,2*(lP[1]-(d?0:shift[0]))*tan(grad/2)]; + //center=is_bool(center)?center?[1,1]:[0,0]:is_list(center)?center:[center,center]; + d=d?max(abs(d),abs(b[1]))*sign(d) : 0; + txt=txt==true?str(l[0],"mm") : txt; + txtL=txt?len(str(txt)) * b[1] *0.675 +.25 : 0; + rot=is_num(rot)?rot:rot?90:0; + +if(!d)T(center?0:l[0]/2)MKlon(max(0.1,(l[0]-lP[1]*2)/2 ))Pfeil(l=[lP[0]-(rot&&abs(rot)!=180?b[1]/2:lP[0]>txtL/2?txtL/2:0) ,lP[1]],b=b,shift=shift,grad=grad,d=d,center=true,name=name,help=false); + +if(d)T(y=center?0:d/2)MKlon(mx=1)rotate(-gradB(b=min(lP[0],PI*d/2-lP[1]),r=d/2))Pfeil(l=[min(lP[0]-txtL/2,PI*d/2-lP[1]-txtL/2),lP[1]],b=b,shift=shift,grad=grad,d=d,center=true,name=name,help=false); + +if(txt)T(center?0:d?[0,d/2]:l[0]/2,!rot&&lP[0] include ub.scad> ")); + + z1=z%1?floor(z)+0.4999999:z; + //z=z%1?floor(z)+.5:z; + z=floor(z*f)/f; + + l=modul*PI*z-spiel*2; + r=modul*z/2;//Wälzkreis + spielwinkel=spiel/(r*2*PI)*360; + rund=[modul/5/f,modul/2/f]; + //rund=[0,0]; + //rot=90/z; + rot=180/z-180/z/f; // for radial + //tra=modul*PI/4; // for linear + tra=modul/2*PI - modul/2*PI/f; // for linear + + kreis=umkreis(z*f,z*modul/2+(modul/kreisDivisor)+(d>r*2?spiel:-spiel)+modul/5*(scale-1)); + $info=false; + +//current + if(!linear) + Rund(rund[0],rund[1],fs=fs) + intersection(){ + Polar(z*f,rot=d0){ + T(center?-l/2:0)Rund(rund[0],rund[1],fs=fs)intersection(){ + T(-tra/2+ lambda/f/4) Linear(e=f,es=lambda/f) intersection(){ + T(+tra/2+spiel-lambda) Cycloid(modul=modul,z=z+2,d=d,linear=linear,fn=fn); + T(-tra/2-spiel-lambda) Cycloid(modul=modul,z=z+2,d=d,linear=linear,fn=fn); + } + T(0,-(linear==true?modul:linear)) square([l,(linear==true?modul:linear)+modul/kreisDivisor]); + } + + +//old ∇ + if(b(linear,bool=false)<0)Polar(z%1?2:1,end=z%1?180+rot:360,r=z%1?0:180/(z*4)) + Rund(modul/10,fs=fs){ + intersection (){ + rotate(-spielwinkel) Cycloid(modul=modul,z=z1,d=d,fn=fn); + rotate(rot+spielwinkel) Cycloid(modul=modul,z=z1,d=d,fn=fn); + if(d0,str("r=",r)); + +points=[ +[-0.01,0], +for(i=[-fn:0])[cos(i*hypStep2),sin(i*hypStep2)]*(r-r2[1])+[cos(-i*(hypStep-hypStep2)),sin(-i*(hypStep-hypStep2))]*r2[1], +for(i=[0:fn])[cos(i*epiStep2),sin(i*epiStep2)]*(r+r2[0])-[cos(i*(epiStep+epiStep2)),sin(i*(epiStep+epiStep2))]*r2[0] + +]; + +lastP=points[len(points)-1]; + +rotate(-atan(lastP.x/lastP.y))mirror([1,0])polygon(points); +rotate(atan(lastP.x/lastP.y))polygon(points); +HelpTxt("CZahn",["modul",modul,"r",r,"deg",deg,"fn",fn],help); +} + + + +//union(){ +//r=1; +// r2=1; +// grad=70; +// h=undef; +// mitte=2; +// extrude=+9.34; +// xCenter=-1; +//polygon([for(i=[0:27])vollwelle(fn=5,l=18,grad=grad,h=h,r=r,r2=r2,mitte=mitte,xCenter=xCenter,grad2=50,extrude=extrude)[i]]); +//T(0,0,-0.1)color("green")Vollwelle(fn=5,l=18,grad=grad,h=h,r=r,mitte=mitte,r2=r2,xCenter=xCenter,grad2=+50,extrude=extrude); +//T(0,2.4)color("red")square([8.68,1],center=0); +// *T(extrude-h,1)color("red")square([h,1],center=0); +// *T(5,4)square([r2-sin(90-grad)*r2,1]); +// *T(5+6.5,1)square([r-sin(90-grad)*r,1]); +// +//} + +/// creates points for vollwelle +/* +p=vollwelle(grad2=-100,minF=12); +polygon(p); +echo(len(p)); +//*/ + +function vollwelle(r=1,r2,grad=+60,grad2=+0,h=0,l,extrude=+5,center=true,xCenter=1,fn=12,x0=0,mitte=0,tMitte,g2End=[1,1],minF,z)= +let( + fn=is_list(fn)?fn:[fn,fn], + grad=is_list(grad)?grad:[grad,grad], + grad2=is_list(grad2)?[max(grad2[0],-grad[0]),max(grad2[1],-grad[1])]:[max(grad2,-grad[0]),max(grad2,-grad[0])], + sc=1,// scaling r center + r2=is_num(r2)?r2:is_list(r)?r[1]:r, + r=is_list(r)?r[0]:r, + + //r mittelpunkt verschiebung für tangenten Kontakt +/* tangY=[r*sin(grad[0])-tan(90-grad[0])*(r-cos(grad[0])*r), + r*sin(grad[1])-tan(90-grad[1])*(r-cos(grad[1])*r)],// */ + + mitte=max(0,is_undef(tMitte)?mitte:tMitte - tan(grad[0]/2)*r - tan(grad[1]/2)*r), + w=grad[0]-90,//del=echo(w,grad[0]-90), + wOben=(grad[1]-90), + hR=r-sin(90-grad[0])*r, + hRO=r-sin(90-grad[1])*r, + hR2=r2-sin(90-grad[0])*r2, + hR2O=r2-sin(90-grad[1])*r2, + h=max(hR+hR2,hRO+hR2O,h), + hDiv=h-(hR+hR2), + hDivOben=h-(hRO+hR2O), + //hDiv=is_undef(h)?0:w>0?h-(sin(w)*r+sin(w)*r2):h-((sin(w)*r+sin(w)*r2))*0, + y=2*cos(w)*r*sc+(hDiv*-tan(w)*2), + yOben=2*cos(wOben)*r*sc+(hDivOben*-tan(wOben)*2),// kreis r2 oben incl. l1 + y2Oben=2*cos(wOben)*r2,// kreis r2 oben ohne l1 + y2=2*cos(w)*r2, + + x= sin(w)*r+hDiv*1, + x2= sin(w)*r2 , +// l0 länge unterhalb (-y) l1 länge oberhalb (+y) + l0=is_undef(l)?y/2+y2/2+sin(grad2[0])*r2+mitte/2:is_list(l)?is_undef(l[0])?y/2+y2/2+sin(grad2[0])*r2+mitte/2:l[0]:l/2, + l1=is_undef(l)?yOben/2+y2Oben/2+sin(grad2[1])*r2+mitte/2:is_list(l)?is_undef(l[1])?yOben/2+y2Oben/2+sin(grad2[1])*r2+mitte/2:l[1]:l/2, + extrude=xCenter==0?extrude-hDiv/2 + :xCenter>0?extrude-x-r + :xCenter<-1?xCenter<-2?extrude+x2+cos(grad2[1])*r2 + :extrude+x2+cos(grad2[0])*r2 + :extrude+x2+r2, + + trans=is_num(z)?[+0,center?0:l0,z]:[+0,center?0:l0],// all points translation + g2End=is_list(g2End)?g2End:[g2End,g2End], + yKL1=l1-(yOben/2+y2Oben/2+mitte/2+sin(grad2[1])*r2), // Abstand Kreisende bis l1 + yKL0=l0+(-y/2-y2/2-mitte/2-sin(grad2[0])*r2), // Abstand Kreisende bis l0 + g2EndX0=grad2[0]!=90? g2End[0]? yKL0*tan(grad2[0]): // End Punkt unten winkel verlängerung + 0: + 0, + g2EndX1=grad2[1]!=90? g2End[1]? yKL1*tan(grad2[1]): // End Punkt oben winkel verlängerung + 0: + 0 + ) +concat( + + [concat([extrude-x2-cos(grad2[1])*r2+g2EndX1,l1],is_num(z)?0:[])]+[trans]//oben Kreis verl. + , kreis(r=r2,rand=0,rot=-90+grad2[1],center=false,grad=-grad[1]-grad2[1],t=[extrude-x2,yOben/2+y2Oben/2+mitte/2]+trans,fn=fn[0],minF=minF,z=z)//oben + , kreis(r=r,r2=r*sc,rand=0,rot=90-grad[1],grad=grad[1],t=[extrude+x,mitte/2]+trans,fn=fn[1],center=false,minF=minF,z=z)//mitte oben + , kreis(r=r,r2=r*sc,rand=0,rot=90,grad=grad[0],t=[extrude+x,-mitte/2]+trans,fn=fn[1],center=false,minF=minF,z=z)//mitte unten + , kreis(r=r2,rand=0,rot=grad[0]-90,center=false,grad=-grad[0]-grad2[0],t=[extrude-x2,-y/2-y2/2-mitte/2]+trans,fn=fn[0],minF=minF,z=z) //unten + + ,[concat([extrude-x2-cos(grad2[0])*r2+g2EndX0,-l0],is_num(z)?0:[])]+[trans]//unten Kreis verl. + ,[concat([x0,-l0],is_num(z)?0:[])]+[trans]//unten + ,[concat([x0,l1],is_num(z)?0:[])]+[trans]//oben + + ); + + + + +/** \name SWelle +\page Polygons +SWelle() creates 2 attached arcsegments to form a wave (or S shape) +/param r,r2 radii +/param h y height +/param deg contact angle +/param ext x extension +/param lap [-x,-y] overlap +/param center center y -1,0,1 +/param fs fragment Size +/param name help name help +*/ + +//SWelle(center=+1,h=7,deg=45); + +module SWelle(r=2,r2,h=0,deg=90,ext=0,lap=[0,0.25],center=0,fs=fs,name,help){ + +r2=is_undef(r2)?is_list(r)?r.y:r:r2; +r=is_list(r)?r.x:r; +lap=is_list(lap)?lap:[lap,lap]; +rH=(1-cos(deg))*r2 - cos(deg)*r ; +ty=max(h-r, rH ); + +deltaY=ty-rH; + +tx=deg%180?sin(deg)*r2+sin(deg)*r +tan(90-deg)*deltaY+ext:ext; + +points=[ +[-lap.x,-lap.y], +[tx,-lap.y], +each arc(rot=270-deg,deg=deg,r=r2,t=[tx,r2],rev=true,fn=fs2fn(r=r2,fs=fs,grad=deg)), // base r +each arc(r=r,t=[ext,ty],deg=-deg,rot=(90-deg)*0+90,fn=fs2fn(r=r,fs=fs,grad=deg),rev=true), // top r +[-lap.x,ty+r] +]; + +translate([0,center==0?0:center==-1?-(ty+r):-(ty+r)/2 +]) +polygon(points); + +HelpTxt("SWelle",["r",r,"r2",r2,"h",h,"deg",deg,"ext",ext,"lap",lap,"center",center,"fs",fs,"name",name],help); + +} + + + +/** \name Vollwelle +\page Polygons +Vollwelle() creates 4 attached arcsegments to form a wave + +\param r,r2 radii +\param grad angle between +\param grad2 angle outside end +\param h height of the wave (x amplitude) +\param l length (y) of the polygon +\param extrude move wave part on x (base stays at x0) +\param center center end or center +\parame xCenter center x on base(-1) mid(0) or top (1) of the wave +\parame x0 move the base of the polygon on x +\param mitte elongate y center +\param tMitte tangential center part length ↦ mitte +\param g2End extensions of grad2 on or of [bottom, top] +\param fn fragments for arcs [fn r2, fn r] +\param fs fragmentsize for arcs [fs r2, fs r] ,↦ fn +\param help name help name +*/ + +//Vollwelle(); + +module Vollwelle(r=1,r2,grad=+60,grad2=+0,h,l,extrude=+5,center=true,xCenter=0,fn,x0=0,mitte=0,tMitte,g2End=[1,1],fs=fs,help,name){ + + // calc for geometry is done by function -- values here are only for console + + //ifn=is_list(fn)?fn:[fn,fn]; + //grad=is_list(grad)?is_undef(h)?echo(str("

    Vollwelle define h"))[grad[0],grad[0]]:grad:[grad,grad]; + + grad=is_list(grad)?grad:[grad,grad]; + grad2=is_list(grad2)?grad2:[grad2,grad2]; + sc=1;// scaling r center + r2=is_undef(r2)?is_list(r)?r[1]:r:r2; + r=assert(!is_undef(r),"Vollwelle r can't be undef")is_list(r)?r[0]:r; + w=(2*grad[0]-180)/2; + wOben=(2*grad[1]-180)/2; + fs=is_list(fs)?fs:[fs,fs]; + fn=is_undef(fn)||!fn?[fs2fn(r=r2,fs=fs[0],grad=max(grad)+max(grad2),minf=5 ),fs2fn(r=r,fs=fs[1],grad=max(grad),minf=5 )]:fn; + + //r mittelpunkt verschiebung für tangenten Kontakt + tangY=[tan(grad[0]/2)*r,tan(grad[1]/2)*r]; + /*[r*sin(grad[0])-tan(90-grad[0])*(r-cos(grad[0])*r), + r*sin(grad[1])-tan(90-grad[1])*(r-cos(grad[1])*r)];// */ + + + mitte=is_undef(tMitte)?mitte:tMitte- tangY[0] -tangY[1]; + +// echo(w); + // hDiv=is_undef(h)?0:w>0?h-(sin(w)*r+sin(w)*r2):h+(sin(w)*r-sin(w)*r2); + hR=r-sin(90-grad[0])*r; + hR2=r2-sin(90-grad[0])*r2; + hRO=r-sin(90-grad[1])*r; + hR2O=r2-sin(90-grad[1])*r2; + h=is_undef(h)?max(hR+hR2,hRO+hR2O):h; + hDiv=h-(hR+hR2); + + y=2*cos(w)*r*sc+(hDiv*-tan(w)*2); + yOben=2*cos(wOben)*r*sc+(hDiv*-tan(wOben)*2); + y2=2*cos(w)*r2; + + x= sin(w)*r+hDiv ; + x2= sin(w)*r2 +0; + l1=is_undef(l)?y/2+y2/2+sin(grad2[0])*r2+mitte/2:is_list(l)?is_undef(l[0])?y/2+y2/2+sin(grad2[0])*r2+mitte/2:l[0]:l/2; + l2=is_undef(l)?yOben/2+y2/2+sin(grad2[1])*r2+mitte/2:is_list(l)?is_undef(l[1])?yOben/2+y2/2+sin(grad2[1])*r2+mitte/2:l[1]:l/2; + + Echo(str(name," Vollwelle h ist minimal= ",h),color="green",condition=name&&h==(hR+hR2)); + + Echo(str(name," Vollwelle h zu klein! min=",(hR+hR2)),color="red",condition=h<(hR+hR2)); + Echo(str(name," Vollwelle tMitte zu klein! min=",(tangY[0]+tangY[1])),color="red",condition=mitte<0); + + + Echo("Vollwelle use Number for xCenter",color="red",condition=is_bool(xCenter)); + //xCenter=is_bool(xCenter)?0:xCenter; + extrudeUnchanged=assert(is_num(extrude))extrude; + extrude=xCenter==0?extrude-hDiv/2:xCenter>0?extrude-x-r:xCenter<-1?xCenter<-2?extrude+x2+cos(grad2[1])*r2:extrude+x2+cos(grad2[0])*r2:extrude+x2+r2; + +/* replaced with function vollwelle + points=concat( + + //[[x0,-y/2-y2/2-sin(grad2[0])*r2-mitte/2+0]],//unten + [[extrude-x2-cos(grad2[0])*r2,-l1]],//unten Kreis verl. + [[x0,-l1]],//unten + //[[x0,y/2+y2/2+sin(grad2[1])*r2+mitte/2]],//oben + [[x0,l2]],//oben + [[extrude-x2-cos(grad2[1])*r2,l2]],//oben Kreis verl. + + Kreis(r=r2,rand=0,rot=-90+grad2[1],center=false,grad=-grad[1]-grad2[1],t=[extrude-x2,yOben/2+y2/2+mitte/2],fn=fn[0]),//oben + Kreis(r=r,r2=r*sc,rand=0,rot=90-grad[1],grad=grad[1],t=[extrude+x,mitte/2],fn=fn[1],center=false),//mitte oben + Kreis(r=r,r2=r*sc,rand=0,rot=90,grad=grad[0]*1,t=[extrude+x,-mitte/2],fn=fn[1],center=false),//mitte unten + Kreis(r=r2,rand=0,rot=grad[0]-90,center=false,grad=-grad[0]-grad2[0],t=[extrude-x2,-y/2-y2/2-mitte/2],fn=fn[0]) //unten + ); + + translate([0,center?0:l1])//(y2+y)/2+sin(grad2[0])*r2+mitte/2]) + polygon(points,convexity=5); +*/ + polygon(vollwelle(r=r,r2=r2,grad=grad,grad2=grad2,h=h,l=l,extrude=extrudeUnchanged,center=center,xCenter=xCenter,fn=fn,x0=x0,mitte=mitte,tMitte=tMitte,g2End=g2End)); + + minimum=[extrude-x2-r2*(grad2[0]<0?cos(grad2[0]):1),extrude-x2-r2*(grad2[1]<0?cos(grad2[1]):1)]; + maximum=[extrude+x+r,extrude+x+r]; + + InfoTxt("Vollwelle",[str("min=",grad2[0]==grad2[1]? + grad2[0]<0?extrude-x2-r2*cos(grad2[0]):extrude-x2-r2 + :str(extrude-x2-r2*(grad2[0]<0?cos(grad2[0]):1),"/",extrude-x2-r2*(grad2[1]<0?cos(grad2[1]):1)), + "(×2∅=",grad2[0]==grad2[1]? + grad2[0]<0?2*(extrude-x2-r2*cos(grad2[0])):2*(extrude-x2-r2) + :str(2*(extrude-x2-r2*(grad2[0]<0?cos(grad2[0]):1)),"/",2*(extrude-x2-r2*(grad2[1]<0?cos(grad2[1]):1))), + "mm) — max=",extrude+x+r," (×2∅=",(extrude+x+r)*2,"mm)- Y länge=",l1+l2,"(",l1,"/",l2,")",//,y+y2+sin(grad2[0])*r2+sin(grad2[1])*r2+mitte, + "mm Wellenhöhe="),grad2[0]==grad2[1]?maximum[0]-minimum[0]:maximum-minimum],info=name); + + HelpTxt("Vollwelle",[ + "r",r, + "r2",r2, + "grad",grad, + "grad2",grad2, + "h",h, + "l",l, + "extrude",extrudeUnchanged, + "center",center, + "xCenter",xCenter, + "fn",fn, + "x0",x0, + "mitte",is_undef(tMitte)?mitte:str(mitte,"/*(calc)*/"), + "tMitte",tMitte, + "g2End",g2End, + "fs",fs, + "name",name] + ,help); + +} + + + +module SQ(size=[10,10],fn=[10,2],diff=[0.0001,0.0001,0.0001,0.0001],center=true,help){ + + x=is_list(size)?size[0]:size; + y=is_list(size)?size[1]:size; + fnx=is_list(fn)?fn[0]:fn; + fny=is_list(fn)?fn[1]:fn; + diff=is_list(diff)?diff:[diff,diff,diff,diff]; + center=b(is_list(center)?center:[center,center],false); + + points=[ + for(i=[0:fnx])[-x/2+x/fnx*i,-y/2+i%2*-diff[0]], + for(i=[0:fny])[x/2+i%2*diff[1],-y/2+y/fny*i], + for(i=[0:fnx])[x/2-x/fnx*i,y/2+i%2*diff[2]], + for(i=[0:fny])[-x/2-i%2*diff[3],y/2-y/fny*i], + + ] ; + + // echo(points); + path=[[for(i=[0:len(points)-1])i]]; + //echo (path); + translate([-x/2*center.x,-y/2*center.y]+[x/2,y/2]) polygon(points,path); + + + if($info) echo("instead SQ for twisted extrusions use linear_extrude(segments=20)"); +HelpTxt("SQ",["size",[x,y],"fn",[fnx,fny],"diff",diff,"center",center] ,help); +} + +/* +union(){ // Gear TEST + z=6; +rot=+0.5; + +Cycloid(linear=+2,option=+0); +T(rot*PI*z-PI/4,z/2)rotate(-rot*360-90)Cycloid(option=+0,z=z,l=+0.00,d=1); +} +// */ +/** +\name Cycloid +\page Polygon +Cycloid() creates a cycloid + +\param modul cycloid circle size +\param z number of teeth (×2 revolutions) +\param fn fragments per teeth +\param option -1,0,1 hyp hybrid epi +\param l reduce height without changing base radius +\param delta contracted or extended cycloid +\param d circle for cener hole or generate inside teeth +\param fnd fraqments for d +\param linear rack +\param name help name help +*/ + +//Cycloid(delta=0,linear=false); +//Cycloid(delta=-0.15,option=-1,linear=true); + + + +module Cycloid(modul=1,z=5,fn=36,option=+0,l=0,delta=0,d=0,fnd,linear=false,name,help,zahn){ + z=is_undef(zahn)?z:zahn; + r=modul*z/2; + rCav=r; + rVex=r; + e=z*2; + + linear=is_bool(linear)?linear==true?modul:false:linear; + //r=modul*e; + fn2=fn*abs(e); + r2=modul/4-l;//r/(e)-l; + r2Vex=r2+delta; + r2Cav=r2+delta; + step1=360/fn2; + step2=step1*e; + step2Cav=-step1*(e-1); + // delta=+180; + fnd=is_undef(fnd)&&d? fs2fn(r=d/2,fs=fs,fa=fa):fnd; + +if(linear){ + if(name) echo(str(is_string(name)?"

    ":"",name," Zahnstangenlänge=",r*PI*2," Zahnabschnitt=",r*PI*2/z)); + box=[[PI*2*r,-linear],[0,-linear]]; + pointsEpi=[for(i=[0:fn2])[PI*2*r*i/fn2+r2Vex*-sin(i*step2),r2-r2Vex*cos(i*step2)]]; + pointsHyp=[for(i=[0:fn2])[PI*2*r*i/fn2+r2Cav*-sin(i*step2),-r2-r2Cav*-cos(i*step2)]]; + if(option==1)color("pink")polygon(concat(box,pointsEpi)); + if(option==-1)color("cyan")polygon(concat(box,pointsHyp)); + points=[for(z=[0:2:e-2])each[for(i=[fn*z:fn*(z+1)])pointsEpi[i] +,for(i=[fn*(z+1):fn*(z+2)])pointsHyp[i]]]; + if(!option)color("orange")polygon(concat(box,points)); +} + + +if(!linear){ + + if(d) InfoTxt("Cycloid",["ZahnkreisRadius",str(r,"mm"),"fn Kreis rot",str(180/e,"°"),"d",d,"fnd",fnd],name); + else InfoTxt("Cycloid",["ZahnkreisRadius",str(r,"mm")],name); + + + pointsEX=[for(i=[0:fn2]) + let(iw=i%fn2) + [ + (rVex+r2)*cos(iw*step1)-r2Vex*cos(iw*(step2+step1)), + (rVex+r2)*sin(iw*step1)-r2Vex*sin(iw*(step2+step1)) + ] + ]; + pointsCAV=[for(i=[0:fn2]) + let(iw=i%fn2) + [ + (rCav-r2)*cos(iw*step1)+r2Cav*cos(iw*step2Cav), + (rCav-r2)*sin(iw*step1)+r2Cav*sin(iw*step2Cav) + ] + ]; + + +pointsRand=kreis(r=d/2,rand=0,fn=fnd); + +if(option==1)color("pink")polygon( + d?concat(pointsRand,pointsEX):pointsEX + ,paths= + d?[[for(i=[0:len(pointsRand)-1])i], + [for(i=[len(pointsRand):len(pointsEX)-1+len(pointsRand)])i]]: + [[for(i=[0:len(pointsEX)-1])i]] + ,convexity=5 + +); +if(option==-1)color("cyan")polygon( + d?concat(pointsRand,pointsCAV):pointsCAV + ,paths= + d?[[for(i=[0:len(pointsRand)-1])i], + [for(i=[len(pointsRand):len(pointsCAV)-1+len(pointsRand)])i]]: + [[for(i=[0:len(pointsCAV)-1])i]] + ,convexity=5); + +points=[for(z=[0:2:e -2])each[ + for(i=[fn*z:fn*(z+1)])pointsEX[i], + for(i=[fn*(z+1):fn*(z+2)])pointsCAV[i] + ] ]; + +pointsSingle=dd1?pow(abs(d1/d2-1),+7):0):r; //WIP + diff1=-d1/2*cos(grad1/2)+diff; + diff2=d2/2*cos(grad2/2)-diff; + + rEck=Umkreis(e*2,r); + rK1=Kathete(r,sin(grad1/2)*d1/2)+diff1; + rK2=Kathete(r,sin(grad2/2)*d2/2)+diff2; + umfang=PI*r*2; + umfang1=PI*(rK1)*2; + umfang2=PI*(rK2)*2; + umfangEck=e*(d1+d2); + + + wk=[for(i=[0:e-1])each concat( + kreis(r=-d2/2,rot=90-winkel/2+i*winkel*2,rand=0,grad=-grad2,sek=true,t=RotLang(-winkel/2+i*winkel*2,rK2),fn=fn,fs=fs) + , kreis(r=d1/2,rot=90+winkel/2+i*winkel*2,rand=0,grad=grad1,sek=true,t=RotLang(winkel/2+i*winkel*2,rK1),fn=fn,fs=fs) + )]; + + rotate(winkel/2-90) polygon(wk,convexity=5); + + InfoTxt("Wkreis",["länge",str(umfangEck,"mm - Umfang(r=",r,")=",umfang,"mm Grad=",grad1,"°/",grad2,"°"),"\n\tAußen r",str(rK1+d1/2," OD=",2*rK1+d1," — Umfang=",umfang1,"mm Kreismitte=",rK1),"\n\tInnen r",str(rK2-d2/2," ID =",2*rK2-d2," — Umfang=",umfang2,"mm Kreismitte=",rK2)],name); + +HelpTxt("Wkreis",[ + "e",e, + "d1",d1, + "d2",d2, + "grad",grad, + "r",r, + "diff",diff, + "fn",fn, + "fs",fs, + "r1",r1, + "r2",r2, + "name",name], +help); + +} + +//Seg7(n="2-899",ratio=0.7,center=0,deg=45,spiel=+0.0); +//Seg7(n=[[1,1,1,1,0,1,0],[1,1,1,1,1],[1,1,1,1,0,1,0]],ratio=0.7,center=0,deg=35,spiel=+0.5); +//Seg7(88,spacing=-1,ratio=.5); + + + +module Seg7(n=8,h=10,b=1,spiel=n(1),l,center=false,rund,ratio=1,deg=45,spacing=1,fs=fs,name,help){ + spielADJ=spiel/sqrt(2); + l=is_undef(h)?l:h/2-b/2-spielADJ*2; + deg=deg%180; + y=l/2; + x=b/2; + y2=deg?y-x *(tan(90-deg)):y; + assert(l!=0,"change b"); + /* + num=[for(n)each + if(n==0)[1,1,1,1,1,0,1] + else if(n==1) [0,1,0,1,0,0,0] + else if(n==2) [1,0,0,1,1,1,1] + else if(n==3) [0,1,0,1,1,1,1] + else if(n==4) [0,1,1,1,0,1,0] + else if(n==5) [0,1,1,0,1,1,1] + else if(n==6) [1,1,1,0,1,1,1] + else if(n==7) [0,1,0,1,0,0,1] + else if(n==8) [1,1,1,1,1,1,1] + else if(n==9) [0,1,1,1,1,1,1] + else if(is_list(n))n + ]; + */ + codetable=[ + [1,1,1,1,1,0,1] + ,[0,1,0,1,0,0,0] + ,[1,0,0,1,1,1,1] + ,[0,1,0,1,1,1,1] + ,[0,1,1,1,0,1,0] + ,[0,1,1,0,1,1,1] + ,[1,1,1,0,1,1,1] + ,[0,1,0,1,0,0,1] + ,[1,1,1,1,1,1,1] + ,[0,1,1,1,1,1,1] + ]; + num=is_list(n)?n:codetable[n]; + + function points(x=x,y=y,y2=y2)=[[0,y],[x,y2],[x,-y2],[0,-y],[-x,-y2],[-x,y2]]; + + if ( (is_list(n)&&is_num(n[0]) ) || (is_num(n)&&n<10) ) + T(center?0:l/2*ratio+b/2+spielADJ,b(center,false)==1?0:(b(center,false)>2?-1:1)*(l+b/2+spielADJ*2)) + Rund(is_undef(rund)?0: + is_list(rund)?[min(rund[0],b/2-0.00001),min(rund[1],(l*min(ratio,1)+spielADJ*2-b)/2-.00001)]: + [min(is_bool(rund)?b(rund,false)*b/2-0.00001:rund,b/2-0.00001),0],fs=fs){ + //Verticals + Grid(es=[l*ratio+spielADJ*2,l+spielADJ*2],name=0)if(num[$idx[0]+$idx[1]*2])polygon(points(x=x,y=y,y2=y2)); + // Horizontals + Grid(es=[l*ratio+spielADJ*2,l+spielADJ*2],e=[1,3,1],name=0)rotate(90)if(num[4+$idx[1]])polygon(points(x,y*ratio,y*ratio-(deg?x*tan(90-deg):0))); + } + else { // multi character + + if(is_list(n[0]))for (i=[0:len(n)-1])T((l*ratio+b+spielADJ*2+b*spacing)*i-(center?(l*ratio+b+spielADJ*2+b)*(len(string)-1)/2:0)) Seg7(n=n[i],h=h,b=b,spiel=spiel,l=l,center=center,rund=rund,ratio=ratio,deg=deg,name=false); // binary lists + + else { + Echo("number too big format n as string",color="red",condition=is_num(n)&&n>10^10); + string=is_string(n)?n:log(n)<6?str(n):str(str(floor(n/10000)),str(n-floor(n/10000)*10000) ); + //echo(string); + for (i=[0:len(string)-1])T((l*ratio+b+spielADJ*2+b*spacing)*i-(center?(l*ratio+b+spielADJ*2+b)*(len(string)-1)/2:0)){ + if(ord(string[i])>47&&ord(string[i])<58)Seg7(n=ord(string[i])-48,h=h,b=b,spiel=spiel,l=l,center=center,rund=rund,ratio=ratio,deg=deg,name=false); // numbers + else if(string[i]=="-"||string[i]=="−"||string[i]=="—")Seg7(n=[0,0,0,0,0,1,0],h=h,b=b,spiel=spiel,l=l,center=center,rund=rund,ratio=ratio,deg=deg,name=false);// mitte + else if(string[i]=="_")Seg7(n=[0,0,0,0,1,0,0],h=h,b=b,spiel=spiel,l=l,center=center,rund=rund,ratio=ratio,deg=deg,name=false);// under + else if(string[i]==".")T(center?0:l/2*ratio+b/2+spielADJ,b(center,false)==1?-(l+b/2+spielADJ*2):(b(center,false)>2?-2:0)*(l+b/2+spielADJ*2))Seg7(n=[0,0,0,0,1,0,0],h=undef,b=b,spiel=spiel,l=l,center=2,rund=rund,ratio=b/l,deg=deg,name=false);// dot + else if(string[i]==":")T(center?0:l/2*ratio+b/2+spielADJ,b(center,false)==1?-(l+ b + spielADJ*2)/2:(b(center,false)>2?-3:1)*(l+spielADJ*2)/2)Seg7(n=[0,0,0,0,1,1,0],h=h,b=b,spiel=spiel,l=b,center=2,rund=rund,ratio=b/l,deg=deg,name=false);// colon + else if(string[i]!=" ")Seg7(n=[1,1,0,0,1,1,0],h=h,b=b,spiel=spiel,l=l,center=center,rund=rund,ratio=ratio,deg=deg,name=false);// other + } + } + } + + + InfoTxt("Seg7",["Höhe",str(l*2+b+spielADJ*4,"mm"),"Breite",str(l*ratio+b+spielADJ*2,"mm")],name); + + HelpTxt("Seg7",["n",n,"h",h,"b",b,"spiel",spiel,"l",l,"center",center,"rund",rund,"ratio",ratio,"deg",deg,"spacing",spacing,"fs",fs,"name",name],help); +} + +module Flower(e=8,n=15,r=10,r2=0,min=5,fn=720,name,help){ +points=[for(f=[+0:fn])let(i=f*360/fn)RotLang(i,r2+max(min-r2,(r-r2)*pow(abs(sin(e*.5*i)),2/n)))]; + +polygon(points,convexity=5); + +HelpTxt("Flower",["e",e,"n",n,"r",r,"r2",r2,"min",min,"fn",fn,"name",name],help); +} + + +/** \name Superellipse \page polygons +Superellipse() creates a Superellipsoid 2D or 3D +\param n exponent for rounding - can be list[4] +\param r radius [x,y] or [x,y,z] or [[x,x],[y,y],[z,z]] (z for 3D) +\param r1 radius x optional [-x,x] +\param r2 radius Y optional [-y,y] +\param r3 radius z optional [-z,+z] makes 3D +\param n2, +/parma n3,n31,n32 exponents for rounding z [-z,z],n31=x [-z,+z] ,n32=y +\param fn fnz facetts +\param name, help name help +*/ + +//Superellipse(r=10,r3=10,n=3); + + +module Superellipse(n=4,r=10,n2,r2,n3,n31,n32,r3,r1,fn=fn,fnz,name,help){ + + + r2=is_undef(r2)?is_list(r.y)?r.y + :is_num(r.y)?r.y*[1,1] + :is_num(r)?r*[1,1]:r.x + :is_list(r2)?r2:r2*[1,1]; + + r3=is_num(r.z)?r.z*[1,1]:is_list(r.z)?r.z:is_list(r3)?r3:is_num(r3)?abs(r3)*[1,1]:r3; + r=is_list(r)?is_list(r.x)?r.x:r.x*[1,1]:r*[1,1]; + r1=is_undef(r1)?r:is_list(r1)?r1:[1,1]*r1; + + n11=is_list(n)?n[0]:n; + n12=is_list(n)?n[1]:n; + n13=is_list(n)?n[2]:n; + n14=is_list(n)?n[3]:n; + n2=is_undef(n2)?n:n2; + n21=is_list(n2)?n2[0]:n2; + n22=is_list(n2)?n2[1]:n2; + n23=is_list(n2)?n2[2]:n2; + n24=is_list(n2)?n2[3]:n2; + + //n3i=is_undef(n3)?is_list(n)?n[0]:n:n3; + n3=is_undef(n3)?is_list(n)?[n[0],n[0]]:[n,n]:is_list(n3)?n3:[n3,n3]; + n31=is_undef(n31)?n3:is_list(n31)?n31:[n31,n31]; + n32=is_undef(n32)?n3:is_list(n32)?n32:[n32,n32]; + + + fnz=is_undef(fnz)?fn:fnz; + InfoTxt("Superellipse",["n",str(n,is_undef(r3)?" is 2D":" is elipsoid 3D")],name); + + if(is_undef(r3)) + polygon([for(f=[0:fn])let(i=f%fn*360/fn)each[ + if(i<=90)[r1[1]*pow(sin(i),2/n11),r2[1]*pow(cos(i),2/n21)], + if(i>90&&i<=180)[r1[1]*pow(abs(sin(i)),2/n12),-r2[0]*pow(abs(cos(i)),2/n22)], + if(i>180&&i<=270)[-r1[0]*pow(abs(sin(i)),2/n13),-r2[0]*pow(abs(cos(i)),2/n23)], + if(i>270&&i)[-r1[0]*pow(abs(sin(i)),2/n14),r2[1]*pow(abs(cos(i)),2/n24)], + ] + ]); + else{ + points=[for(fz=[0:fnz],f=[0:fn]) + let(i=f%fn*360/fn,j=fz*180/fnz) + each[ + + if(i<=90&&j<=90) [r1[1]*pow(sin(i),2/n11)*pow(sin(j),2/n31[1]),r2[1]*pow(cos(i),2/n21)*pow(sin(j),2/n32[1]),r3[1]*pow(cos(j),2/n3[1])], + if(i>90&&i<=180&&j<=90) [r1[1]*pow(abs(sin(i)),2/n12)*pow(sin(j),2/n31[1]),-r2[0]*pow(abs(cos(i)),2/n22)*pow(sin(j),2/n32[1]),r3[1]*pow(cos(j),2/n3[1])], + if(i>180&&i<=270&&j<=90)[-r1[0]*pow(abs(sin(i)),2/n13)*pow(sin(j),2/n31[1]),-r2[0]*pow(abs(cos(i)),2/n23)*pow(sin(j),2/n32[1]),r3[1]*pow(cos(j),2/n3[1])], + if(i>270&&i&&j<=90) [-r1[0]*pow(abs(sin(i)),2/n14)*pow(sin(j),2/n31[1]),r2[1]*pow(abs(cos(i)),2/n24)*pow(sin(j),2/n32[1]),r3[1]*pow(cos(j),2/n3[1])], + + if(i<=90&&j>90) [r1[1]*pow(sin(i),2/n11)*pow(sin(j),2/n31[0]),r2[1]*pow(cos(i),2/n21)*pow(sin(j),2/n32[0]),-r3[0]*pow(abs(cos(j)),2/n3[0])], + if(i>90&&i<=180&&j>90) [r1[1]*pow(abs(sin(i)),2/n12)*pow(sin(j),2/n31[0]),-r2[0]*pow(abs(cos(i)),2/n22)*pow(sin(j),2/n32[0]),-r3[0]*pow(abs(cos(j)),2/n3[0])], + if(i>180&&i<=270&&j>90) [-r1[0]*pow(abs(sin(i)),2/n13)*pow(sin(j),2/n31[0]),-r2[0]*pow(abs(cos(i)),2/n23)*pow(sin(j),2/n32[0]),-r3[0]*pow(abs(cos(j)),2/n3[0])], + if(i>270&&i&&j>90) [-r1[0]*pow(abs(sin(i)),2/n14)*pow(sin(j),2/n31[0]),r2[1]*pow(abs(cos(i)),2/n24)*pow(sin(j),2/n32[0]),-r3[0]*pow(abs(cos(j)),2/n3[0])], + + + ] + ]; + + + faces=[for(i=[0:len(points)-fn -3])[i+1,i,i+fn+1,i+2+fn]]; + //faces2=[[for(i=[0:fn-1])i],[for(i=[len(points)-fn:len(points)-1])i]]; + + polyhedron(points,faces,convexity=5); + + } + + + HelpTxt("Superellipse",["n",n,"r",r,"n2",n2,"r2",r2,"n3",n3,"n31",n31,"n32",n32,"r3",r3,"fn",fn,"fnz",fnz,"name",name],help); +} + + + +//Quad(50,20,rad=10,center=[0,1]); + +module Quad(x=20,y,r,r1,r2,r3,r4,grad=90,grad2=90,fn,center=true,messpunkt=false,basisX=0,trueX=false,centerX,tangent=true,rad,fs=fs,name,help){ + assert(grad!=0&&grad2!=0); + basisX=is_bool(basisX)?basisX?1:0:is_undef(centerX)?basisX:is_bool(centerX)?centerX?1:0:centerX; + + grad2=is_list(grad)?assert(is_num(grad[1]))grad[1]:assert(is_num(grad2))grad2; + grad=is_list(grad)?assert(is_num(grad[0]))grad[0]:assert(is_num(grad))grad; + r=is_undef(rad)?r:rad; + + + + y=is_num(y)?y: + is_list(x)?assert(is_num(x[1]))x[1]: + x; + + + xNum=assert(x)is_list(x)?x[0]:x; + +//oblong case + oblong=is_num(r)&&(xNum==2*r||y==2*r)&&grad==90&&grad2==90; + obR=min(xNum,y)/2; + oblongFN=is_undef(fn)?fs2fn(r=obR,fs=max(fs),grad=180):fn; + + obCenter=is_list(center)?[ + !center.x?1:bool(center.x,false)==1?0:-1, + !center.y?1:bool(center.y,false)==1?0:-1] + :center(center); + oblongP=oblong?let(r=obR)xNum==y?kreis(r=r,rand=0,t=obCenter*r,fs=max(fs),fn=is_list(fn)?max(fn):fn):xNum>y? + [ + each arc (deg=180,r=r,t=[-(xNum/2-r),0]+vMult(obCenter,[xNum,y]/2),rot=90,fn=oblongFN), + each arc (deg=180,r=r,t=[xNum/2-r,0]+vMult(obCenter,[xNum,y]/2),rot=-90,fn=oblongFN), + ]: + [ + each arc (deg=180,r=r,t=[0,-(y/2-r)]+vMult(obCenter,[xNum,y]/2),rot=180,fn=oblongFN), + each arc (deg=180,r=r,t=[0,y/2-r]+vMult(obCenter,[xNum,y]/2),rot=0,fn=oblongFN), + ]:[[0,0]] + ; + + + rundung=runden(min(xNum,y)/PHI/2,2); + //r=is_undef(r)?[rundung,rundung,rundung,rundung]:is_list(r)?r:[r,r,r,r]; + + r1=is_num(r1)?r1:is_undef(r[0])?is_num(r)?r:rundung:r[0]; + r2=is_num(r2)?r2:is_undef(r[1])?is_num(r)?r:rundung:r[1]; + r3=is_num(r3)?r3:is_undef(r[2])?is_num(r)?r:rundung:r[2]; + r4=is_num(r4)?r4:is_undef(r[3])?is_num(r)?r:rundung:r[3]; + + radList=[r1,r2,r3,r4]; + fs=is_list(fs)?fs:[fs]; + //fn=is_undef(fn)?[for(i=[0:3])fs2fn(fs=$fs,r=radList[i],minf=12)]:is_list(fn)?fn:[fn]; + fn=is_list(fn)?fn:[fn]; + + rf1=1/sin(grad); + rf2=1/sin(grad2); + shiftX1=tan(grad-90)*y-r1*2*tan(grad-90); + shiftX2=tan(grad2-90)*y-r2*2*tan(grad2-90); + shiftX3=tan(grad-90)*y-r3*2*tan(grad-90); + shiftX4=tan(grad2-90)*y-r4*2*tan(grad2-90); + + + + // konstante x basis mit Rundung (tangetial punkte) / trueX= reale breite + bx1L=r3-r3*rf1+shiftX3/2; + bx1R=r4-r4*rf2-shiftX4/2; + bx2L=r1-r1*rf1-shiftX1/2; + bx2R=r2-r2*rf2+shiftX4/2; + + bxL=sign(basisX)*tan(90-grad2)*(y/2); + bxR=-sign(basisX)*tan(90-grad)*(y/2); + x=is_list(x)?trueX?basisX==-1?x[0]-bx2L-bx2R:x[0]-bx1L-bx1R:x[0]-bxL-bxR:trueX?basisX==-1?x-bx2L-bx2R:x-bx1L-bx1R:x-bxL-bxR; + trueX1=x+bx1L+bx1R; // real x1 breite + trueX2=x+bx2L+bx2R; // real x2 breite + + p1=-x/2+shiftX1/2-r1*1/tan(grad); + p2=x/2+shiftX2/2-r2*1/tan(grad2); + p3=-x/2-shiftX3/2+r3*1/tan(grad); + p4=x/2-shiftX4/2+r4*1/tan(grad2); + x1=abs(p3)+abs(p4); + x2=abs(p1)+abs(p2); + + + + cTrans=is_list(center)?([center.x?bool(center.x,false)<0?-x: + 0: + x,center.y?bool(center.y,false)<0?-y: + 0: + y] + /2): + + + + (center?[basisX==1?tangent?-p3+(p3-p4)/2: + (bx1L-bx1R)/2: + basisX==-1?tangent?-p1+(p1-p2)/2: + (bx2L-bx2R)/2: + 0,sign(basisX)*y/2]: + tangent?basisX==1?[x/2+shiftX3/2-r3*1/tan(grad),y/2]:// center= false + [x/2-shiftX1/2+r1*1/tan(grad),y/2]: + basisX==1?[bx1L+x/2,y/2]: + basisX==-1?[bx2L+x/2,y/2]: + [x/2,y/2]); + + + k1=kreis(rand=0,r=r1,t=[-x/2+r1*rf1+shiftX1/2,y/2-r1]+cTrans,grad=180-grad,rot=grad-180,fn=is_undef(fn[0%len(fn)])?undef:fn[0%len(fn)]/360*(180-grad),fs=fs[0%len(fs)],center=false); + k2=kreis(rand=0,r=r2,t=[x/2-r2*rf2+shiftX2/2,y/2-r2]+cTrans,grad=grad2,rot=-45+45,fn=is_undef(fn[1%len(fn)])?undef:fn[1%len(fn)]/360*grad2,fs=fs[1%len(fs)],center=false); + k3=kreis(rand=0,r=r3,t=[-x/2+r3*rf1-shiftX3/2,-y/2+r3]+cTrans,grad=grad,rot=-225+45,fn=is_undef(fn[2%len(fn)])?undef:fn[2%len(fn)]/360*grad,fs=fs[2%len(fs)],center=false); + k4=kreis(rand=0,r=r4,t=[x/2-r4*rf2-shiftX4/2,-y/2+r4]+cTrans,grad=180-grad2,rot=grad2 ,fn=is_undef(fn[3%len(fn)])?undef:fn[3%len(fn)]/360*(180-grad2),fs=fs[3%len(fs)],center=false); + + union(){ + if(oblong){ + polygon(oblongP,paths=[[for (i=[0:len(oblongP)-1])i]],convexity=5); + //Points(concat(k1,k2,k4,k3)); + } + else polygon(concat(k1,k2,k4,k3),convexity=5); + if(messpunkt){ + Pivot([p1,y/2]+cTrans,active=[1,0,0,1,1],messpunkt=messpunkt); + Pivot([p2,y/2]+cTrans,active=[1,0,0,1,1],messpunkt=messpunkt); + Pivot([p3,-y/2]+cTrans,active=[1,0,0,1,1],messpunkt=messpunkt); + Pivot([p4,-y/2]+cTrans,active=[1,0,0,1,1],messpunkt=messpunkt); + } + + } + + if(r1+r2>abs(trueX2)||r3+r4>abs(trueX1))Echo("Quad x too small or r too big",color="red"); + if(r1+r1*sin(90-grad)+r3+r3*sin(grad-90)>abs(y)||r2+r2*sin(grad2-90)+r4+r4*sin(90-grad2)>abs(y))Echo("Quad y too small or r too big",color="red"); + + InfoTxt("Quad",["TangentsizeX1",x1,"sizeX2",x2,"real",str(trueX1,"/",trueX2),"r",r],name); + + HelpTxt("Quad",["x",x,"y",y,"rad",r,"grad",grad,"grad2",grad2,"fn",fn,"center",center,"name",name,"messpunkt",messpunkt,"trueX",trueX,"centerX",centerX,"tangent",tangent,"fs",fs],help); +} + +/** \name Linse \page polygons +Linse() creates a convex lens shape +\param dia length of the lens +\param r radii of the lense arcs +\param dicke thickness [left,right] +\param deg edge angle [45,45] +\param messpunkt show center points +\param fn fragments (optional) +\param fs fa fragmen size and angle +*/ + +//Linse(); + + +module Linse(dia=10,r,dicke,deg=45,name,messpunkt=$messpunkt,fn,fs=fs,fa=fa,help){ + +InfoTxt("Linse",["Dicke",idicke,"Kreisgrad",str(grad/2+grad2/2,"°/",[grad,grad2]/2,"°"),"r",r],name); + +deg=is_list(deg)?deg:[1,1]*deg; + +dicke=is_num(dicke)?dicke/2*[1,1]:dicke; + +r=is_undef(r)?is_undef(dicke)?[dia/2/sin(deg[0]),dia/2/sin(deg[1])]: + [(dicke[0]^2 + (dia/2)^2)/dicke[0]/2,(dicke[1]^2 + (dia/2)^2)/dicke[1]/2] + :is_list(r)?r:[r,r]; + +tx=Kathete(r[0],dia/2); +tx2=Kathete(r[1],dia/2); + +grad=2*asin((dia/2)/r[0]); +grad2=2*asin((dia/2)/r[1]); +idicke=(r[0]-tx) + (r[1]-tx2); +ifn=is_undef(fn)?fs2fn(r=r[0],fs=fs,fa=fa,grad=grad,minf=5):fn; +ifn2=is_undef(fn)?fs2fn(r=r[1],fs=fs,fa=fa,minf=5,grad=grad2):fn; + +Echo("Linse r too small or dia too big",color="red",condition=!is_num(tx+tx2)); + +half=[r[0]==1/0,r[1]==1/0]; + + +points=concat( + !half[0]?kreis(rand=0,r=r[0],grad=grad,t=[tx*sign(r[0]),0],fn=ifn,endPoint=half[1]):[], + !half[1]?kreis(rand=0,r=r[1],grad=grad2,rot=-180,t=[-tx2*sign(r[1]),0],fn=ifn2,endPoint=half[0]):[] + ); + + +if(is_num(tx+tx2)){polygon(points); + if(messpunkt){ + if(!half[0])Pivot([tx,0],active=[1,0,0,1,0],messpunkt=messpunkt); + Pivot([0,dia/2],active=[1,0,0,1,1],messpunkt=messpunkt); + if(!half[1])Pivot([-tx2,0],active=[1,0,0,1,1],messpunkt=messpunkt); + + } + +} + + HelpTxt("Linse",[ + "dia",dia, + "r",r, + "dicke",dicke, + "deg",deg, + "name",name, + "messpunkt=",messpunkt, + "fn",fn, + "fs",fs], + help); +} + +/** \name SternDeg +SternDeg() creates a polygon star with defined angle +\param e number tips +\param r radius tip +\param deg tip angle ↦ r2 +\param r2 optional radius 2 +\param d circle wall (optional) +\param fn,fs,fa fragments for d circle +\param help help +*/ +module SternDeg(e=5,r=10,deg=36,r2,d=0,fn,fs=fs,fa=fa,help){ +fn=fn?fn:fs2fn(r=d/2,fs=fs,fa=fa); +points=d?[each sternDeg(e,r,deg,r2), + for(i=[0:fn-1])[cos(i*360/fn),sin(i*360/fn)]*d/2 + ]:sternDeg(e,r,deg,r2); + +path=[ + [for(i=[0:e*2-1])i], + if(d)[for(i=[0:fn-1])i+e*2] + ]; + +polygon(points,path); + + +HelpTxt("SternDeg",["e",e,"r",r,"deg",deg,"r2",r2,"d",d,"fn",fn,"fs",fs,"fa",fa],help); +} + +//SternDeg(d=25); + + +module Stern(e=5,r1=10,r2=5,mod=2,delta=+0,center=1,name,help){ + name=is_undef(name)?is_undef($info)?false:$info:name; + + star= + let(schritt=360/(e*mod)) + [for(i=[0:e*mod])i%mod=180?[0,0]:centerDist; + +l=(is_list(l)?l:[l,l]) - (edge?cDl:[0,0]); + +if(h0)color("green")translate([-r11,l[1]])rotate([90])linear_extrude(l[1]+lap,center=false,convexity=5)children();//l[1] + if(l2)color("green")rotate(gradR11-grad21)translate([-r11,lap])rotate([90])linear_extrude(l2+lap*2,center=false,convexity=5)children();//l2 + } + translate([hDelta,0])rotate(gradR11)translate([-r11-r21,0])rotate((l2?0:lap))rotate_extrude(angle=-gradR2-(l2?0:lap)-(mitte?0:lap/2))translate([r21,0]){ + $idx=false; + $info=name; + children(); + } + } + + if(mitte)translate([h,0])rotate([90])linear_extrude(mitte+lap*2,center=true,convexity=5)children(); + + translate([x1,-y1]){ + translate([0,-yh])rotate(-grad20){ + rotate_extrude(angle=-gradR10+grad20)translate([-r10,0])children();//r1 + if(l[0]>0)color("orange")translate([-r1,+lap])rotate([90])linear_extrude(l[0]+lap,center=false,convexity=5)children();//l[0] + if(l2)color("orange")rotate(-gradR10+grad20)translate([-r10,l2+lap])rotate([90])linear_extrude(l2+lap*2,center=false,convexity=5)children();//l2 + } + translate([hDelta,0])rotate(-gradR10)translate([-r10-r20,0])rotate(l2?0:-lap)rotate_extrude(angle=gradR2+(l2?0:lap)+(mitte?0:lap/2))translate([r20,0])children(); + } +} + +MO(!$children); +HelpTxt("Schlaufe",["grad",grad,"r",r,"r2",r2,"mitte",mitte,"grad2",grad2,"l",l,"h",h,"lap",lap,"center",center,"edge",edge,"name",name],help); +} + + +module Bevel(z=0,r=.5,on=!$preview,grad=45,fillet=0,fn=12,messpunkt=messpunkt,help){ + + diff=fillet?sin(grad)*r:tan(grad)*r; + + + if(on)difference(){ + children(index=0); + minkowski(convexity=5){ + difference(){ + $info=false; + $idx=1; + Tz(z>0?500+z-diff:-500+z+diff) cube(1000,true); + children(index=0); + } + if($children==2) Tz(z>0?diff:-diff)R(z>0?180:0)children (1); + else if(!fillet)R(z>0?0:180)Kegel(d1=0,d2=r*2,fn=fn,grad=grad,name=false); + else Tz(z>0?r:-r)R(z>0?180:0)RotEx(cut=1,fn=fn)Kehle(2D=true,rad=r,fn2=fn); + } +}else +children(index=0); + +if (messpunkt&&$children<2){ +%Grid(e=[2,2,1],es=is_bool(messpunkt)?10:messpunkt,name=false)Tz(z)if(!fillet)color("orange",alpha=.75){ + R(z>0?180:0)Kegel(d2=0,d1=r*2,fn=fn,grad=grad,name=false); + R(z>0?0:180)cylinder(.5,r=r*1,$fn=fn); +} + else color("green",alpha=.75)R(z>0?180:0)Tz(-r+diff)RotEx(cut=1,fn=fn)Kehle(2D=true,rad=r,fn2=fn,spiel=.5); + +%Tz(z)if(!fillet)color("orange",alpha=.75){ + R(z>0?180:0)Kegel(d2=0,d1=r*2,fn=fn,grad=grad,name=false); + R(z>0?0:180)cylinder(.5,r=r*1,$fn=fn); +} + else color("green",alpha=.75)R(z>0?180:0)Tz(-r+diff)RotEx(cut=1,fn=fn)Kehle(2D=true,rad=r,fn2=fn,spiel=0.5); +} +if($children==2)%Tz(z){Grid(e=[2,2,1],es=is_bool(messpunkt)?10:messpunkt,name=false) + R(z>0?180:0)color("chartreuse",alpha=.75)children(index=1); + R(z>0?180:0)color("chartreuse",alpha=.75)children(index=1); + + } + +HelpTxt("Bevel",[ + "z",z, + "r",r, + "on",on, + "grad",grad, + "fillet",fillet, + "fn",fn, + "messpunkt",messpunkt] + ,help); + +} + + + + +module LinEx2(bh=5,h=1,slices=10,s=1,ds=+0.010,dh=+0,fs=1,fh=0.780,twist=0,ft=1,dt=0,hsum=0,lap=0.001,fn=fn,name,help,startSlices,basetwist,rot=0){ + basetwist=is_undef(basetwist)?(bh+lap)*twist:basetwist; + startSlices=is_undef(startSlices)?slices:startSlices; + $helpM=0; + $info=0; + s=is_list(s)?s:[s,s]; + hsum=hsum?hsum:h; + + if(slices-1)rotate(-twist*h)Tz(h)scale([s[0],s[1],1])LinEx2(bh=bh,slices=slices-1,s=s*fs-[ds,ds],h=h*fh-dh,ds=ds,dh=dh,hsum=hsum+h*fh-dh,fs=fs,fh=fh,name=name,startSlices=startSlices,twist=twist*ft-dt,ft=ft,dt=dt,fn=fn,help=help,rot=rot+twist*h,basetwist=basetwist,lap=lap)children(); + + Color(1/startSlices*slices)rotate(-basetwist)Tz(bh)linear_extrude(h+lap,twist=twist*(h+lap),scale=s,convexity=5,$fn=fn)children(); + if(slices==startSlices){ + linear_extrude(bh+lap,twist=basetwist,convexity=5,$fn=fn)children(); + MO(!$children); + + } + + if(!(slices-1)){ + InfoTxt("LinEx2",["Höhe",hsum+lap+bh,"Twist",basetwist+rot+twist*h],name); + HelpTxt("LinEx2",["bh",bh,"h",h,"slices",slices,"s",s,"ds",ds,"dh",dh,"fs",fs,"fh",fh,"twist",twist,"ft",ft,"dt",dt,"lap",lap,"fn",fn,"name",name],help); + } + +} + +/** Row() + * \page Generator + * \name module Row() + * \brief Row will recursivly create a Row of objects with changing size (d+e*step) by keeping the gap equal + * \param e number of objects + * \param dist distance of objects + * \param step Change of object size + * \param d Start diameter + * \param cut create cuts of cut size +*/ + + +module Row(e=15,dist=2,step=.1,d=+1,cut=.25,dir=+1,center=true,name,help,child){ + + /* Row will recursivly create a Row of objects with changing size (d+e*step) + / by keeping the gap equal + */ + child=is_undef(child)?$children:child; + $d=d; + $r=d/2; + $info=is_undef(name)?is_undef($info)?true:$info:name; + $helpM=is_undef(help)?is_undef($helpM)?false:$helpM:help; + $idx=e-1; + cut=child?false:is_num(cut)?cut:cut==true?0.02:false; + if(e>1)T(d+dist+step/2) + if($children)Row(e=e-1,d=d+step,dist=dist,step=step,cut=cut,dir=dir<2?sign(dir*-1):dir,center=center,name=$info,help=$helpM,child=child)children(); + else Row(e=e-1,d=d?d+step:0,dist=dist,step=step,cut=cut,dir=dir<2?sign(dir*-1):dir,center=center,name=$info,help=$helpM,child=child); + + if(!$children&&d)cylinder(100,d=$d,$fn=24,center=center); + if($children)children(); + if(cut&&!child) T(-cut/2,dir>0?dir>1?0:0:-viewportSize,center?-viewportSize/2:0)color(alpha=0.0)cube([cut,viewportSize,viewportSize]); + if(e==1)InfoTxt("Row",["last d",str($d,cut?str(" Cut is ",cut):"")],name); + + + HelpTxt("Row",[ + "e",e, + "dist",dist, + "step",step, + "d",d, + "cut",cut, + "dir",dir, + "center",center, + "name",$info], + $helpM); + + if($helpM&&!$idx)echo("Row will recursivly create a Row of objects with changing size $d=(d+e*step) by keeping the gap (dist) equal"); +} + +/** \page Generator +Rundrum() extrudes a shape around +\name Rundrum +\brief Rundrum uses rotate_extrude and linear_extrude to suround a Quad or circle +## Examples + Rundrum() circle(); + + Rundrum(eck=3,r=[10,20,30])Star(e=5); + + + * @param x,y size + * @param r the edge radius vector for n-gon possible + * @param twist twist the linear sections + * @param grad angle for square to match Quad + * @param grad2 second angle for square to match Quad + * @param lap overlap + * @param fn number of fragments for edges ¼ for squares + * @param name name + * @param help help=true + +*/ + +//Rundrum()circle(); + +module Rundrum(x=+40,y,r=10,eck=4,twist=0,grad=90,grad2=90,lap=0.005,fn=fn,fs=fs,fa=fa,size,rad,name,help){ + +$info=name; +$idxON=false; + +$fa=fa; +$fs=fs; +$fn=fn; + +rI=is_undef(rad)?r:rad; +size=is_list(size)?size:[size,size]; + + // WIP + Echo("Angle with different radii not implemeted yet",condition=(r1!=r2||r2!=r3||r3!=r4)&&(grad2!=90||grad!=90)); + + r1=is_list(rI)?rI[0]:rI; + r2=is_list(rI)?rI[1]:rI; + r3=is_list(rI)?rI[2]:rI; + r4=is_list(rI)?rI[3]:rI; + + r=is_list(rI)?rI[0]:rI; + y=is_undef(size.y)?is_list(x)?x[1]:is_undef(y)?x:y + :size.y; + x=is_undef(size.x)?is_list(x)?x[0]:x + :size.x; + + //grad2=grad-20;// WIP + shift=tan(grad-90)*y; + grad=grad?grad:shift>0?atan(shift/y):-atan(-shift/y); + shiftx=shift-r*2*tan(grad-90); + shiftx2=tan(grad2-90)*y-r*2*tan(grad2-90); + shiftYLang=Hypotenuse(shiftx,y-2*r); + shiftYLang2=Hypotenuse(shiftx2,y-2*r); + if(eck==4&&grad!=90&&name)echo(str(name," Rundrum grad=",grad,"° ShiftX=",shiftx,"mm (+-",shiftx/2,"mm) Lot(x)=",x*sin(grad),"mm")); + //rx=r?r*(r/(sin(grad)*r)):0; + function rx(r=r,grad=grad)=r*1/sin(grad); + + +if(eck==4&&twist==0) + if(grad==90&&grad2==90){ + $info=is_undef(name)?$info:name; + $tab=is_undef($tab)?1:b($tab,false)+1; + //Ecken + T(-x/2+r1,y/2-r1)rotate(90)RotEx(90,fn=fn/4,cut=true)T(r1)children();// R1 + union(){ + $info=false; + $helpM=false; + $idx=true; // disable help + T(x/2-r2,y/2-r2)RotEx(90,fn=fn/4,cut=true)T(r2)children();// R2 + T(-x/2+r3,-y/2+r3)rotate(180)RotEx(90,fn=fn/4,cut=true)T(r3)children();// R3 + T(x/2-r4,-y/2+r4)rotate(-90)RotEx(90,fn=fn/4,cut=true)T(r4)children();// R4 + //Graden + //X + T((r1-r2)/2,y/2)R(90,0,90)linear_extrude(x-r1-r2+lap,center=true,convexity=5)children(); + T((r3-r4)/2,-y/2)R(90,0,-90)linear_extrude(x-r3-r4+lap,center=true,convexity=5)children(); + //Y + T(-x/2,(r3-r1)/2)R(90,0,180)linear_extrude(y-r1-r3+lap,center=true,convexity=5)children(); + T(x/2,(r4-r2)/2)R(90,0,+0)linear_extrude(y-r2-r4+lap,center=true,convexity=5)children(); + } + + } +else T(-shiftx/2*0){ + $info=is_undef(name)?$info:name; + $tab=is_undef($tab)?1:b($tab,false)+1; + //plus x + T(x/2-rx(r2,grad2)+shiftx2/2,y/2-r2)rotate(90-grad2)rotate_extrude(angle=grad2,convexity=5,$fn=0,$fa = grad2/(fn/4), $fs = 0.1)Ecke(r2)children(); + union(){ + $idx=true; // disable help + $helpM=0; + $info=0; + T(x/2-rx(r4,grad2)-shiftx2/2,-y/2+r4)rotate(-90)rotate_extrude(angle=180-grad2,convexity=5,$fn=0,$fa = (180-grad2)/(fn/4), $fs = 0.1)Ecke(r4)children(); + //minus x + T(-x/2+rx(r1)+shiftx/2,y/2-r1)rotate(90)rotate_extrude(angle=180-grad,convexity=5,$fn=0,$fa = (180-grad)/(fn/4), $fs = 0.1)Ecke(r1)children(); + T(-x/2+rx(r3)-shiftx/2,-y/2+r3)rotate(-90)rotate_extrude(angle=-grad,convexity=5,$fn=0,$fa = grad/(fn/4), $fs = 0.1)Ecke(r3)children(); + + + //linear x -+ + T(+x/2-rx((r2+r4)/2,grad2)+shiftx2/2,y/2-r)rotate(90-grad2)T(+r)R(90,0,0)Tz(-lap/2)linear_extrude(shiftYLang2+lap,convexity=5,center=false,$fn=fn)children(); + T(-x/2+rx(r1/2+r3/2)-shiftx/2,-y/2+r)rotate(90-grad)T(-r)R(90,0,180)Tz(-lap/2)linear_extrude(shiftYLang+lap,convexity=5,center=false,$fn=fn)children(); + + //linear y -+ + T(-x/2+rx()+shiftx/2-lap/2,y/2+0)R(90,0,90)linear_extrude(x-rx(r1)-rx(r2,grad=grad2)+lap+shiftx2/2-shiftx/2,convexity=5,center=false,$fn=fn)children(); + T(+x/2-rx(grad=grad2)+lap/2-shiftx2/2,-y/2)R(90,0,-90)linear_extrude(x-rx()-rx(grad=grad2)+lap-shiftx2/2+shiftx/2,convexity=5,center=false,$fn=fn)children(); + } + if(2*r>x||2*r>y){ + echo(); + Echo(str("››»!!!«‹‹ ",name," Rundrum WARNUNG !!! Radius zu groß !!!"),color="red"); + echo(); + + } + + if(name) if((2*r==x||2*r==y)&&x!=y)echo(str(name," Rundrum Halbkreis")); + if(name) if(2*r==x&&2*r==y)echo(str(name," Rundrum Vollkreis")); + + } + else{ + for(i=[0:eck-1]){ + r=is_list(rI)?rI[i%len(rI)]:r; + rNext=is_list(rI)?rI[(i+1)%len(rI)]:r; + l=[Kathete(Umkreis(eck,x-rNext),x-rNext),Kathete(Umkreis(eck,x-r),x-r)]; + + $tab=is_undef($tab)?1:b($tab,false)+1; + $info=is_undef(name)?$info:name; + $idx=i*2; + stepDeg=360/eck; + rotate(i*stepDeg)T(Umkreis(eck,x-r))rotate(-180/eck)rotate_extrude(angle=stepDeg,$fn=fn,convexity=5)intersection(){ + T(r)rotate(i*(twist/eck))children(); + translate([0,-150])square(300); + } + union(){ + $helpM=0; + $info=0; + $idx=i*2+1; + //rotate(i*stepDeg+180/eck)T(x) R(-90)linear_extrude(l[0]+lap,center=false,twist=twist/eck,$fn=fn,convexity=5)rotate(+twist/eck+i*(twist/eck))children(); + rotate(i*stepDeg+180/eck)T(x,l[0]+lap) R(90)linear_extrude(vSum(l)+lap*2,center=false,twist=twist/eck,$fn=fn,convexity=5)rotate(+twist/eck+i*(twist/eck))children(); + } + } + + } +MO(!$children); + + module Ecke(r=r){ + render()intersection(){ + T(r)children(); + translate([0,-150])square(300); + } + } + +HelpTxt("Rundrum",["x",x,"y",y,"rad",rI,"eck",eck,"twist",twist,"grad",grad,"lap",lap,"fn",fn,"fs",fs,"fa",fa,"size",size,"name",name],help); +} + +/** \page Objects +Torus() creates a torus with optional child(); + +\param trx radius torus +\param d,r diameter or radius rim (use $d,$r in children) +\param rot rotate 2D children +\param a,grad angle torus (a is centered) +\param fn,fn2 fragments +\param fs,fs2 fragmentsize +\param dia outer diameter torus optional to trx +\param id inner diameter torus optional to trx +\param center center z +\param end add Ends +\param trxEnd,gradEnd end Torus radius and angle +\param lap overlap of extrusions +*/ + +//Torus(grad=130,end=+2,trxEnd=-3,fn=0,lap=.1,center=-1); + + + +module Torus(trx=+6,d=4,a=360,fn,fn2=0,r,rot=0,grad=0,dia,id,center=true,end=0,gradEnd=90,trxEnd=0,endRot=0,endspiel=+0,lap=0,fs=fs,fs2=fs,name,help) + rotate(grad?bool(center,false)<0?-grad:0:-a/2){ + + end=is_undef(spheres)?is_bool(end)?end?-1:0:end:spheres;//compatibility + d=is_undef(r)?d:r*2; + $d=d; + $r=d/2; + fn2=fn2==0?ceil(fs2fn(r=$r,fs=fs2,minf=12)/2)*2:fn2; + endRot=is_list(endRot)?endRot:[endRot,endRot]; + trx=dia?dia/2-d/2 + :id?id/2+d/2:trx; + grad=grad?grad:a; + a=end==-1&&!trxEnd? grad-(asin(abs($r)/trx)*2)*sign(grad): + grad; + // end==-1&&!$children? a-(asin($r/trx)*2)*sign(a): + // a; + + $idxON=false; + + InfoTxt("Torus",["Innen∅",2*trx-d,"Mitten∅",2*trx,"Aussen∅",2*trx+d,"∅d",d],info=name); + HelpTxt("Torus",["trx",trx,"d",d,"a",a,"fn",fn,"fn2",fn2,"r",r,"rot",rot,"grad",grad,"dia",dia,"id",id,"center",center,"end",end,"gradEnd",gradEnd,"trxEnd",trxEnd,"endRot",endRot,"name",name,"$d",$d,"lap",lap,"fs",fs,"fs2",fs2,"name",name],help); + + + rotate(end==-1? (asin(abs($r)/trx))*sign(grad): + 0){ + $idx=true; + $info=is_undef(name)?is_undef($info)?false:$info:name; + translate([0,0,center?0:d/2])rotate(end||trxEnd?-lap:0) RotEx(grad=end||trxEnd?a+lap*2:a,fn=fn,$fs=fs,cut=1,help=false,center=0){ + $idx=0; + $tab=is_undef($tab)?1:b($tab,false)+1; + if($children)T(x=trx)R(0,0,rot)children(); + else T(x=trx)R(0,0,rot)circle(d=abs(d),$fn=fn2); + } + + if(end&&a!=360&&!trxEnd){ + if($children){ + rotate(a)translate([trx,0,center?0:d/2])scale([1,abs(end),1])R(0,endRot[1])RotEx(cut=sign(end*grad),grad=180*sign(end),fn=max(fn/2,6),help=false)rotate(endRot[1])children(); + rotate(+0)translate([trx,0,center?0:d/2])rotate(180)scale([1,abs(end),1])R(0,-endRot[0])RotEx(cut=sign(end*grad),grad=180*sign(end),fn=max(6,fn/2),$fs=fs,help=false)rotate(endRot[0])children(); + } + else{ + rotate(a-sign(grad)*minVal)translate([trx,0,center?0:d/2])scale([1,abs(end),1])R(90)Halb(sign(grad)>0?1:0)sphere(d=abs(d),$fn=fn2); + rotate(sign(grad)*minVal)translate([trx,0,center?0:d/2])scale([1,abs(end),1])R(90)Halb(sign(grad)>0?0:1)sphere(d=abs(d),$fn=fn2); + } + } + + if(trxEnd)translate([0,0,center?0:d/2]){ // End Ringstück + if($children){ + T(trx-trxEnd)rotate(gradEnd*sign(-trxEnd)){ + rotate(end?-lap*sign(trxEnd):0)RotEx(grad=(gradEnd+(end?lap:0))*sign(trxEnd),cut=+0,fn=fn?fn/360*gradEnd:0,$fs=fs)T(trxEnd)rotate(rot)children(); + if(end)translate([trxEnd,0,0])rotate(180)scale([1,abs(end),1])R(0,-endRot[0])RotEx(cut=sign(end*gradEnd),grad=180*sign(gradEnd*end),fn=fn?max(6,fn/2):0,$fs=fs,help=false)rotate(endRot[0])children(); + } + rotate(180+grad)T(-trx+trxEnd)rotate(180){ + RotEx(grad=(gradEnd+(end?lap:0))*sign(trxEnd),cut=+0,fn=fn?fn/360*gradEnd:0,$fs=fs)T(trxEnd)rotate(rot)children(); + if(end)rotate((gradEnd)*sign(trxEnd))translate([trxEnd,0,0])scale([1,abs(end),1])R(0,endRot[1])RotEx(cut=sign(end*gradEnd),grad=180*sign(gradEnd*end),fn=fn?max(6,fn/2):0,$fs=fs,help=false)rotate(endRot[1])children(); + } + } + else{ + T(trx-trxEnd)rotate((gradEnd)*sign(-trxEnd)){ + rotate(end?-lap*sign(trxEnd):0)RotEx(grad=(gradEnd+(end?lap:0))*sign(trxEnd),fn=fn/360*gradEnd,$fs=fs,cut=+0)T(trxEnd)rotate(rot)circle(d=d,$fn=fn2); + if(end)translate([trxEnd,0,0])rotate(180)scale([1,abs(end),1])RotEx(cut=sign(end*gradEnd),grad=180*sign(gradEnd*end),fn=fn/8,$fs=fs,help=false)rotate(rot)circle(d=d,$fn=fn2); + } + rotate(180+grad)T(-trx+trxEnd)rotate(180){ + RotEx(grad=(gradEnd+(end?lap:0))*sign(trxEnd),cut=+0,fn=fn/360*gradEnd,$fs=fs)T(trxEnd)rotate(rot)circle(d=d,$fn=fn2); + if(end)rotate((gradEnd)*sign(trxEnd))translate([trxEnd,0,0])scale([1,abs(end),1])RotEx(cut=sign(end*gradEnd),grad=180*sign(gradEnd*end),fn=fn/8,$fs=fs,help=false)rotate(rot)circle(d=d,$fn=fn2); + } + } + } + } +} + + +/* Roof +// opt = straight / voronoi + + +//Roof(10,h=1,base=5,floor=true,twist=50,scale=[0.3,1])circle(5,$fn=3); + +//Roof(25,[1,1],deg=-60,fn=60)circle(10,$fn=50); +Roof(25,[1,1],deg=-45)offset(1,$fs=.2,$fn=0)polygon([ +[0,0], +[10,0], +[10,10], +[5,5], +[0,10] +]); +//*/ + +//Roof(10,[1,1],fn=10,deg=-45)Quad(50,grad=45,grad2=45,r=8,fs=1.5); + +//Roof(10,2,twist=15)square(10); + + +module Roof(height,h,base=0,deg=45,opt=1,floor=false,center=false,twist=0,scale=1,fn=0,convexity=5,lap=0.0001,on=true,name,help,slices,segments,fs=fs){ + + +deg=is_list(deg)?deg:[deg,deg]; +s=[deg[0]%90?tan(deg[0]):1,deg[1]%90?tan(deg[1]):1]; +iopt=is_list(opt)?opt:[opt,opt]; +opt=iopt;//[ s[0]<0?0:iopt[0], s[1]<0?0:iopt[1] ]; +floor=is_list(h)?true:floor; +h=is_list(h)?h:[floor?h:0,h]; +lap=is_list(lap)?lap:[h[0]?lap:0,lap]; +//iSize=max(viewportSize,max(printBed)*2); +ifn=$fn; +base=height&&is_num(h[1])&&is_num(h[0])?height-h[0]-h[1]:base; +ofs=[s[0]<0?-h[0]*tan(90-deg[0]):0,s[1]<0?-tan(90-deg[1])*h[1]:0]; + +on=version()[0]>2021?on:0; +$idxON=false; + +InfoTxt("Roof",["h",h,"deg",str(deg,"° (",s,")")],name); +if(twist)InfoTxt("Roof",["twist",str(twist/base,"°/mm"),"base",base],name,$tab=is_undef($tab)?1:$tab+1); + + +Echo("Roof is experimental - use Dev Snapshot version and activate",color="warning",condition=version()[0]<2022); + + if(base)Tz(on?(center?0:h[0]?h[0]:0):0){ + $tab=is_undef($tab)?1:b($tab,false)+1; + $idx=is_undef($idx)?0:$idx; + Tz(center?0:-lap[0])rotate(twist/base*lap[0])linear_extrude(base+(on?vSum(lap):h[0]+h[1]),center=b(center,true),twist=twist/base*(base+(on?vSum(lap):h[0]+h[1])),scale=scale,convexity=convexity,$fn=fn,slices=slices,segments=segments,$fs=fs){ + $fn=ifn; + children(); + } + } + + if(on){ + $idx=is_undef($idx)?base?1:0:$idx; + $noInfo=true; + $info=false; + //top + if(scale&&(h[1]||is_undef(h[1])))Tz( (center?base/2:base+(h[0]?h[0]:0))+(s[1]<0?h[1]:0) )intersection(){ + scale([1,1,s[1]])roof(method=opt[1]?"voronoi":"straight",$fn=fn,$fs=fs,convexity=convexity)offset(delta=ofs[1]){ + $fn=ifn; + scale(scale)rotate(-twist)children(); // experimental feature comment out if not activated in preferences + } + //if(h[1])translate([0,0,(h[1]+iSize/2)*sign(s[1])])cube([iSize,iSize,iSize],true);// if using difference + //if(h[1])cube([iSize,iSize,h[1]*2],true); // for intersection + + //if(h[1])translate([0,0,(h[1]+iSize/2)*sign(s[1])])rotate(-twist)linear_extrude(iSize,center=true,convexity=convexity)offset(delta=1)scale(scale)children();// if using difference + if(h[1])translate([0,0,sign(s[1])>0?0:-h[1]])linear_extrude(h[1],center=false,convexity=convexity)offset(delta=1+sign(s[1])>0?0:h[1]*tan(-90+deg[1]))scale(scale)rotate(-twist)children();// if using intersection + + } + + //bottom + if(floor&&(h[0]||is_undef(h[0])))Tz((center?-base/2:(h[0]?h[0]:0))+(s[0]<0?-h[0]:0))intersection(){ + scale([1,1,-s[0]])roof(method=opt[0]?"voronoi":"straight",$fn=fn,$fs=fs,convexity=convexity)offset(delta=ofs[0]){ + $fn=ifn; + $idx=(scale&&(h[1]||is_undef(h[1])))||base?1:0; + children(); // experimental feature comment out if not activated in preferences + } + //if(h[0])cube([iSize,iSize,h[0]*2],true);//for intersection + //if(h[0])translate([-iSize/2,-iSize/2,-h[0]])mirror([0,0,1])cube(iSize);//for difference + //if(h[0])translate([0,0,(-h[0]-iSize/2)]*sign(s[0]))cube(iSize,true);//for difference + + //if(h[0])translate([0,0,(-h[0]-iSize/2)]*sign(s[0]))linear_extrude(iSize,center=true,convexity=convexity)offset(delta=1)children();//for difference + if(h[0])translate([0,0,sign(s[0])>0?-h[0]:0])linear_extrude(h[0],center=0,convexity=convexity)offset(delta=1+sign(s[0])>0?0:h[0]*tan(-90+deg[0]))children();//for intersection + } + } + + +HelpTxt("Roof",["height",height,"h",h,"base",base,"deg",deg,"opt",opt,"floor",floor,"center",center,"twist",twist,"scale",scale,"fn",fn,"convexity",convexity,"lap",lap,"on",on,"name",name,"slices",slices,"segments",segments,"fs",fs],help); +} + + + +/** \page Generator + \name LinEx + LinEx() linear extrudes child polygon + \param h height + \param h2 height bottom + \param h22 heigt top + \param scale scale bottom + \param scale2 scale top + \param twist twist center + \param twistcap twist top/bottom + \param slices slices + \param $d $r polygon size for angle calculation + \param grad calculate scale from $d/$r for angle + \param grad2 angle (optional) for top + \param center center result + \param end rotate extrude ends + \param fnEnd number of fragments for end + \param lap overlap with center + \param scaleCenter scale center + \param gradC angle center ↦ scaleCenter + \param convexity convexity + \param name name to identify + \param help activate help +*/ + + //LinEx(25,2,end=true,gradC=88,$d=5)circle($r); + //LinEx(25,2,end=true,scaleCenter=[0.8,0.7],scale=[.8,1],$d=[7,9])square($r); + + + + +module LinEx(h=5,h2=0,h22,scale=0.85,scale2,twist,twistcap=1,slices,$d,$r=5,grad,grad2,mantelwinkel=0,center=false,rotCenter=false,end=0,fnEnd,name,help,n,convexity=5,lap=0.0001,scaleCenter=1,gradC,fn){ + + +$info=is_undef(name)?is_undef($info)?false:$info:name; +$helpM=0; +$idxON=false; + +lap=is_list(lap)?lap:[lap,lap]; +ifn=$fn; +end=is_bool(end)?end?[1,1]:[0,0]:is_list(end)?end:[end,end]; +fnEnd=fn?[fn,fn]:is_list(fnEnd)?fnEnd:[fnEnd,fnEnd]; +name=is_undef(n)?name:n; + +$r=is_undef($d)?$r:$d/2; +$d=2*$r; +h=max(0,h); +h22=abs(is_undef(h22)?is_list(h2)?h2[1]:h2:h22); +h2=abs(is_list(h2)?h2[0]:h2); +hc=max(0,h-h2-h22); +twistcap=hc>0?is_list(twistcap)?twistcap:[twistcap,twistcap]: +[0,0]; +gradC=is_undef(gradC)?gradC:is_list(gradC)?gradC:[gradC,gradC]; +scaleCenter=is_undef(gradC)?scaleCenter: + is_list($r)?[($r.x-(hc/tan(gradC.x)))/$r.x,($r.y-(hc/tan(gradC.y)))/$r.y]: + [($r-(hc/tan(gradC.x)))/$r,($r-(hc/tan(gradC.y)))/$r]; + +scale2=is_undef(grad2)? + is_undef(grad)? + is_undef(scale2)?h22?scale:1:scale2 + :is_list(grad)?is_list($r)?[($r[0]-(h22/tan(grad[0])))/($r[0]),($r[1]-(h22/tan(grad[1])))/($r[1])]: + [($r-(h22/tan(grad[0])))/($r),($r-(h22/tan(grad[1])))/($r)]: + is_list($r)?[($r.x-(h22/tan(grad)))/($r.x),($r.y-(h22/tan(grad)))/($r.y)]: + ($r-(h22/tan(grad)))/($r): + is_list(grad2)? + is_list($r)?[($r[0]-(h22/tan(grad2[0])))/($r[0]),($r[1]-(h22/tan(grad2[1])))/($r[1])]:[($r-(h22/tan(grad2[0])))/($r),($r-(h22/tan(grad2[1])))/($r)]:($r-(h22/tan(grad2)))/($r); +scale=h2?is_undef(grad)?scale: + is_list(grad)? + is_list($r)?[($r[0]-(h2/tan(grad[0])))/($r[0]),($r[1]-(h2/tan(grad[1])))/($r[1])]: + [($r-(h2/tan(grad[0])))/($r),($r-(h2/tan(grad[1])))/($r)]: + is_list($r)?[($r.x-(h2/tan(grad)))/($r.x),($r.y-(h2/tan(grad)))/($r.y)]: + ($r-(h2/tan(grad)))/($r): + 1; + + + +grad=h2?is_list(scale)? + is_list($r)?[atan(h2/($r[0]-$r[0]*scale[0])),atan(h2/($r[1]-$r[1]*scale[1]))]: + [atan(h2/($r-$r*scale[0])),atan(h2/($r-$r*scale[1]))]: + is_list($r)?[atan(h2/($r.x-$r.x*scale)),atan(h2/($r.y-$r.y*scale))]: + atan(h2/($r-$r*scale)): + 0; + +grad2=h22?is_list(scale2)? + is_list($r)?[atan(h22/($r[0]-$r[0]*scale2[0])),atan(h22/($r[1]-$r[1]*scale2[1]))]: + [atan(h22/($r-$r*scale2[0])),atan(h22/($r-$r*scale2[1]))]: + is_list($r)?[atan(h22/($r.x-$r.x*scale2)),atan(h22/($r.y-$r.y*scale2))]: + atan(h22/($r-$r*scale2)): + 0; + +mantelwinkel=is_undef(twist)?mantelwinkel:atan(twist*PI*$d/360/hc); +twist=is_undef(twist)?mantelwinkel?360*tan(mantelwinkel)*hc/(2*PI*$r):0:twist; +segments=is_undef(slices)?0:slices*8; + +/* +slices=is_undef(slices)?$preview?twist?fn: + 1: + max(1,round(min(abs(twist)/hc*10,hc/l(2))) ): + slices; + +*/ + + InfoTxt("LinEx", + [ "core h",str(hc,"mm - twist per mm= ",twist/(hc),"°, Fase für $d= ",$d,"mm ist ",grad,"°/",grad2,"° d=",vMult($d,scale),"/",vMult(vMult($d,scale2),scaleCenter),"mm - r= ",vMult($r,scale),"/",vMult(vMult($r,scale2),scaleCenter),"mm \n Mantelwinkel für $d/$r=",$d,"/",$r,"mm⇒ ",mantelwinkel,"° twist=",twist,"°") + , scaleCenter!=1?str("\n scaled center $d/$r= ",vMult($d*scaleCenter),"/",vMult($r*scaleCenter)," base angle= ", + is_list($r)&&is_list(scaleCenter)?[atan(hc/($r.x-scaleCenter.x*$r.x)),atan(hc/($r.y-scaleCenter.y*$r.y))]: + is_list($r)?[atan(hc/($r.x-scaleCenter*$r.x)),atan(hc/($r.y-scaleCenter*$r.y))]: + is_list(scaleCenter)?[atan(hc/($r-scaleCenter.x*$r)),atan(hc/($r-scaleCenter.y*$r))]: + atan(hc/($r-vMult(scaleCenter,$r))),"°",", slices" ) : "slices",slices ],name); + + + + Echo(str(name," LinEx Höhe center=",hc,"mm"),color="red",condition=hc<0); + + if(is_list(grad2)?$r*tan(min(grad2[0],grad2[1]))<(is_list($r)?[h22,h22]:h22)&&min(grad2[0],grad2[1])<90&&min(grad2[0],grad2[1])>0:$r*tan(grad2)<(is_list($r)?[h22,h22]:h22)&&grad2<90&&grad2>0)Echo(str(name," LinEx Höhe h22=",h22," mm zu groß oder winkel/$r zu klein min=",atan(h22/$r),"° max=",is_list(grad2)?$r*tan(min(grad2[0],grad2[1])):$r*tan(grad2),"mm"),color="red"); + + if(is_list(grad)?min($r)*tan(min(grad))0: + min($r)*tan(grad)0)Echo(str(name," LinEx Höhe h2=",h2," mm zu groß oder winkel/$r zu klein min=",atan(h2/$r),"° max=",$r*tan(min(grad)),"mm"),color="red"); + + HelpTxt("LinEx",["h",h,"h2",h2,"h22",h22,"scale",scale,"scale2",scale2,"twist",twist,"twistcap",twistcap,"slices",slices,"$d",$d,"grad",grad,"grad2",grad2,", mantelwinkel",mantelwinkel,"center",center,"rotCenter",rotCenter,"end",end,"fnEnd",fnEnd,"name",name,"convexity",convexity,"lap",lap,"scaleCenter",scaleCenter],help); + + + + rotate(center?0:rotCenter?-twist/2:-twist/2+(twistcap[0]&&hc?-twist/hc*h2:0)) + T(z=center?-h/2:0){ + +if(version()[0]>2021){ + union(){ + $info=false; + $idx=is_undef($idx)?true:$idx; + $noInfo=true; + //capoben + if(h22)T(z=h-h22)rotate(-twist/2)linear_extrude(h22+(end[1]?lap[1]:0),scale=scale2,twist=twistcap[1]?twist/(hc)*h22:0,convexity=convexity,slices=is_undef(slices)?slices:max(1,slices/hc*h22),$fn=0,segments=segments)scale(scaleCenter){ + $fn=ifn; + children(); + } + + //capunten + if(h2)Tz(h2)rotate(twist/2)mirror([0,0,1])linear_extrude(h2+(end[0]?lap[0]:0),scale=scale,twist=twistcap[0]?-twist/(hc)*h2:0,convexity=convexity,slices=is_undef(slices)?slices:max(1,slices/hc*h2),$fn=0,segments=segments){ + $fn=ifn; + children(); + } + } + + //center + Tz(h2-lap[0]){ + //$idx=is_undef($idx)?0:$idx; + $tab=is_undef($tab)?1:b($tab,false)+1; + rotate(twist/2)linear_extrude(hc+lap[0]+lap[1],scale=scaleCenter,convexity=convexity,twist=twist,slices=slices,center=false,segments=segments)children(); + } + } else { + union(){ + $idx=true; + //capoben + if(h22)T(z=h-h22)rotate(-twist/2)linear_extrude(h22+(end[1]?lap[1]:0),scale=scale2,twist=twistcap[1]?twist/(hc)*h22:0,convexity=convexity,slices=max(1,slices/hc*h22),$fn=0)scale(scaleCenter){ + $fn=ifn; + children(); + } + + //capunten + if(h2)Tz(h2)rotate(twist/2)mirror([0,0,1])linear_extrude(h2+(end[0]?lap[0]:0),scale=scale,twist=twistcap[0]?-twist/(hc)*h2:0,convexity=convexity,slices=max(1,slices/hc*h2),$fn=0){ + $fn=ifn; + children(); + } + } + + //center + Tz(h2-lap[0]){ + //$idx=is_undef($idx)?0:$idx; + $tab=is_undef($tab)?1:b($tab,false)+1; + rotate(twist/2)linear_extrude(hc+lap[0]+lap[1],scale=scaleCenter,convexity=convexity,twist=twist,slices=slices,center=false)children(); + } + + } + + + if(end[0]){ // Ende Unten + $idx=true; + rotate(twist/2+(twistcap[0]?twist/(hc)*h2:0))rotate(sign(end[0])>+0?[-90,0,-90]:[-90,0,0]) RotEx(cut=true,grad=180,fn=fnEnd[0])scale(scale)rotate(sign(end[0])>0?90:0)children(); + } + if(end[1]){ // Ende Oben + $idx=true; + Tz(h)rotate(-twist/2-(twistcap[1]?twist/(hc)*h22:0))rotate(sign(end[1])>+0?[-90,0,-90]:[-90,0,0])RotEx(cut=true,grad=-180,fn=fnEnd[1]) + scale(scale2*scaleCenter)rotate(sign(end[1])>0?90:0)children(); + } + + } + MO(!$children); + +} + + + + + + + + +}//fold // // ΔΔ Generator ΔΔ \ \\ +{//fold // \∇∇ Basic Objects ∇∇/ // + + +/* +points=[[0,0,-2],for(i=[0:35])[sin(i*10),cos(i*10),0],for(i=[0:35])[sin(i*10),cos(i*10),5],[0,0,7]]; +points1=[for(i=[0:36])[sin(i*10),cos(i*10),0]*1.5,for(i=[0:36])[sin(i*10),cos(i*10),5],for(i=[0:36])[sin(i*10)*0.75,cos(i*10)*1.5,10]]; +pointsE1=[[0,0,-2],for(i=[0:35])[sin(i*10),cos(i*10),0],for(i=[0:35])[sin(i*10),cos(i*10),5]]; +pointsE2=[for(i=[0:35])[sin(i*10),cos(i*10),0],for(i=[0:35])[sin(i*10),cos(i*10),5],[0,0,7]]; + + +//Points(points1,loop=36,start=36*2); +//echo(points1[36]); +union(){ +PolyH(points,loop=36,pointEnd=true,end=true,name="pointy"); +T(10)PolyH(pointsE1,loop=36,pointEnd=1,end=true,name="point∇"); +T(-10)PolyH(pointsE2,loop=36,pointEnd=2,end=true,name="pointΔ");//WIP +T(0,-10)PolyH(points1,loop=37,pointEnd=0,end=true); +T(0,10)PolyH(octa(5)); +} +// */ + +// PolyH(concat([[0,0,-10]],kreis(rand=0,z=0,endPoint=false),[[0,0,10]]),fn,pointEnd=true); + + +/** \page Generator +module PolyH() creates a polyhedron +\name PolyH +\brief creates a polyhedron + ## Example +points=[[0,0,-2],for(i=[0:35])[sin(i*10),cos(i*10),0],for(i=[0:35])[sin(i*10),cos(i*10),5],[0,0,7]]; +PolyH(points,loop=36,pointEnd=true,end=true); + * \param points points for polyhedron + \param loop number of points per loop (hull if undef) + \param end top bottom faces + \param pointEnd if single point start, end or both (1,2,true) + \param convexity convexity + \param faceOpt Quad or Tri faces + \param flip flip normals + +*/ + + +module PolyH(points,loop,end=true,pointEnd=false,convexity=5,faceOpt=+0,flip=true,name,help){ +loop=is_undef(loop)||loop<3?1:loop; +points=assert(!is_undef(points))points; +lp=len(points); +pointEnd=is_list(pointEnd)?pointEnd==[1,0]?1 + :pointEnd==[0,1]?2 + :pointEnd==[1,1]?true:false + :pointEnd; +loops=pointEnd?pointEnd==1||pointEnd==2?(lp-1)/loop: + (lp-2)/loop: + lp/loop; + +fBottom=pointEnd==2||b(pointEnd,bool=true)==false?[[for(i=flip?[loop -1:-1:0]:[0:loop-1])i]]:[]; +fTop= pointEnd==1||b(pointEnd,bool=true)==false?[[for(i=flip?[0:loop -1]:[loop-1:-1:0])i+lp-(loop)]]:[]; + +fBodyFlip=loops>1?[for(lev=[0:loops -2],i=[0:loop -1])[ + i +loop*lev, + (i +1)%loop+loop*lev, + (i +1)%loop+loop*(lev+1), + i +loop*(lev+1) +]]:[]; + +fBody=loops>1?[for(lev=[0:loops -2],i=[0:loop -1])[ + i +loop*(lev+1), + (i +1)%loop+loop*(lev+1), + (i +1)%loop+loop*lev, + i +loop*lev +]]:[]; + + +fBody1=loops>1?[for(lev=[0:loops -2],i=[0:loop -1])each[[ + + i +loop*lev, + (i +1)%loop+loop*lev, + //(i +1)%loop+loop*(lev+1), + i +loop*(lev+1) +], +[ + //i +loop*lev, + (i +1)%loop+loop*lev, + (i +1)%loop+loop*(lev+1), + i +loop*(lev+1) +]] +]:[]; + +fBody2=loops>1?[for(lev=[0:loops -2],i=[0:loop -1])each[[ + + //i +loop*(lev+1), + i +loop*lev, + (i +1)%loop+loop*lev, + (i +1)%loop+loop*(lev+1), + +], +[ + i +loop*lev, + //(i +1)%loop+loop*lev, + (i +1)%loop+loop*(lev+1), + i +loop*(lev+1) +]] +]:[]; + + + +faces=loop>1?end?concat( + fBottom, + pointEnd==2?[for(i=[0:loop -1])[lp-i -2,lp-1,lp-(i+1)%loop -2]]:fTop, + faceOpt?faceOpt==-1||faceOpt==2?fBody2:fBody1:flip?fBodyFlip:fBody + ): + faceOpt?faceOpt==-1||faceOpt==2?fBody2:fBody1:flip?fBodyFlip:fBody: + [[for(i=[0:lp-1])i]] +; + +pointyFaces=(pointEnd==true||pointEnd==1)&&loops>=1?[ +if(pointEnd==true||pointEnd==1) for(i=[0:loop -1])[(i + 1)%loop + 1,i +1,0],//bottom +if(pointEnd==true||pointEnd==2) for(i=[0:loop -1])[lp-i -2,lp-1,lp-(i+1)%loop -2],//top +if(loops>1)for(lev=[0:loops -2],i=[0:loop -1])let(pE=1)[ + pE + i +loop*lev, + pE + (i +1)%loop+loop*lev, + pE + (i +1)%loop+loop*(lev+1), + pE + i +loop*(lev+1) +] +]:[]; + + +if(loop>1)polyhedron(points,(pointEnd==true||pointEnd==1)&&loop>1?pointEnd==1?concat(pointyFaces,fTop): + pointyFaces: + faces,convexity=convexity); + else hull()polyhedron(points,faces,convexity=convexity); + +InfoTxt("PolyH",["loops",loops,"points",lp],loop>1?name:false); +InfoTxt("PolyH using hull—",["points",lp],loop==1?name:false); + + +HelpTxt("PolyH",["points",[[0,0,0],[1,2,3]],"loop",loop,"end",end,"pointEnd",pointEnd,"convexity",convexity,"faceOpt",faceOpt,"flip",flip,"name",name],help); + +} + +/** \page Objects \name Isosphere +Isoshpere creates an isosphere +\param r radius +\param d diameter (optional) +\param q resoluton +\param help help +*/ +//Isosphere(10); + +module Isosphere(r=1,d,q=70,help){ + r=is_undef(d)?r:d/2; +/* Kogan, Jonathan (2017) "A New Computationally Efficient Method for Spacing n Points on a Sphere," Rose-Hulman Undergraduate Mathematics Journal: Vol. 18 : Iss. 2 , Article 5. + Available at: https://scholar.rose-hulman.edu/rhumj/vol18/iss2/5 */ + function sphericalcoordinate(x,y)= [cos(x )*cos(y ), sin(x )*cos(y ), sin(y )]; + function NX(n=70,x)= + let(toDeg=57.2958,PI=acos(-1)/toDeg, + start=(-1.+1./(n-1.)),increment=(2.-2./(n-1.))/(n-1.) ) + [ for (j= [0:n-1])let (s=start+j*increment ) + sphericalcoordinate( s*x*toDeg, PI/2.* sign(s)*(1.-sqrt(1.-abs(s)))*toDeg)]; + function generatepoints(n=70)= NX(n,0.1+1.2*n); + + a= generatepoints(q); + //scale(r)hull()polyhedron(a,[[for(i=[0:len(a)-1])i]]); + scale(r)hull()polyhedron(a,[for(i=[0:len(a)-1])[0,1,i]]); + +HelpTxt("Isosphere",["r",r,"q",q],help); +} + +// Was KreisSeg( Was TorusSeg( +module RingSeg( +grad=90, +size=4, +h, +rad=1.0, +r=10, +spiel=.5, +fn=fn, +fn2, +name, +help +){ + HelpTxt("RingSeg",["grad",grad,"size",size,"h",h,"rad",rad,"r",r,"spiel",spiel,"fn",fn,"fn2",fn2,"name",name],help); + $info=name; + rad2=rad+spiel;//spiel + +h=assert(is_num(size))is_undef(h)?size:h; + winkel2=asin(rad2/(r+size/2-rad)); + winkel1=asin(rad2/(r-size/2+rad)); + +fn2=is_undef(fn2)?fn:fn2; +fnS=fn2; + +union(){ + $helpM=false; +difference(){ + Torus(grad=grad,end=+0,trx=r,d=size,fn=fn)Quad(size,h,r=rad,fn=fn2); + //base part + linear_extrude(h+5,center=true,convexity=5)polygon([ + [0,0], + (r-size/2 +rad) *[sin(90-winkel1), cos(90-winkel1)],// mittelpunkt sphere1 + (r+size/2 -rad) *[sin(90-winkel2), cos(90-winkel2)],// mittelpunkt sphere2 + (r+size/2 +5) *[sin(90-winkel2), cos(90-winkel2)], + [r+size/2 +5,-rad], + ]); + +// angeled part + linear_extrude(h+5,center=true,convexity=5)polygon([ + [0,0], + (r-size/2 +rad) *[sin(-grad +90 +winkel1), cos(-grad +90 +winkel1)],// mittelpunkt sphere1 + (r+size/2 -rad) *[sin(-grad +90 +winkel2), cos(-grad +90 +winkel2)],// mittelpunkt sphere2 + (r+size/2 +5) *[sin(-grad +90 +winkel2), cos(-grad +90 +winkel2)], + (r+size/2 +5) *[sin(90-grad-5),cos(90-grad-5)], + ]); +} + +//End cabs + hull(){ + rotate(asin(rad2/(r+size/2-rad))) T(r+size/2-rad)MKlon(tz=h/2-rad)OctaH(rad,n=fnS); + rotate(asin(rad2/(r-size/2+rad))) T(r-size/2+rad)MKlon(tz=h/2-rad)OctaH(rad,n=fnS); + } + + hull(){ + rotate(grad-asin(rad2/(r+size/2-rad))) T(r+size/2-rad)MKlon(tz=h/2-rad)OctaH(rad,n=fnS); + rotate(grad-asin(rad2/(r-size/2+rad))) T(r-size/2+rad)MKlon(tz=h/2-rad)OctaH(rad,n=fnS); + } + } +} + + +/** \name Ring \page Objects +Ring() creates a ring +\param h height 0 for 2D +\param dicke rim thickness +\param d,r diameter radius +\param id ir inner diameter/radius +\param grad angle +\param rcenter center rim on d/r +\param center center h +\param fn,fs fraqment number, size +\param name name +\param 2D makes a 2D ring +\param help help +\param cd if false d or r (old - use rcenter instead) +*/ +//Ring(r=10,ir=5,rcenter=0); + + +module Ring(h=5,dicke,d=10,r,id=6,ir,grad=360,rcenter,center=false,fn,fs=fs,name,2D=0,help,cd=1,rand){ + + dicke=is_undef(dicke)?rand:dicke; + id=is_undef(id)?d-dicke*2:id; + r=is_undef(r)?d/2:r; + ir=is_undef(ir)?id/2:ir; + rcenter=is_undef(rcenter)?!abs(cd):rcenter; + rand=is_undef(dicke)?rcenter?(r-ir)*2:r-ir:dicke*sign(cd==0?1:cd); + 2D=is_parent(parent= needs2D)?true:2D; + if(2D||!h)Kreis(rand=rand,rcenter=rcenter,r=r,grad=grad,fn=fn?fn:undef,fs=fs,rot=0,center=center,name=0,help=0); + else rotate([h>0?0:180])linear_extrude(abs(h),center=center,convexity=5)Kreis(rand=rand,rcenter=rcenter,r=r,grad=grad,center=center,fn=fn?fn:undef,fs=fs,rot=0,name=0,help=0); + +InfoTxt("Ring",[str("Aussen∅= ",rcenter?d+abs(rand):rand>0?d:d-rand*2,"mm — Mitte∅= ",rcenter?d:d-rand,"mm — Innen∅"),str(rcenter?d-abs(rand):rand>0?d-(rand*2):d,"mm groß — Rand=",rand,"mm und ",2D||!h?"2D":str(h," hoch") )],name); + +HelpTxt("Ring",[ + "h",h, + "dicke",dicke, + "d",d, + "r",r, + "id",id, + "ir",ir, + "grad",grad, + "rcenter",rcenter, + "center",center, + "fn",fn, + "fs",fs, + "name",name, + "2D",2D, + "cd",cd, + ],help); + +} + +module HypKehleD(grad=40,steps=15,l=10,l2,l3,d=2.5,d2,fill=false,exp=1,fn=24,name,help){ + exp=is_num(exp)?[exp,exp]:is_bool(exp)?[1,1]:exp; + d3=is_undef(d3)?d:d3; + l= is_list(l)?len(l)==3?l: + concat(l,l[0]): + [l,l,l]; + + l3=is_undef(l3)?l[2]:l3; + l2=is_undef(l2)?l[1]:l2; + HypKehle(grad=90-grad,l=l2,l2=l3,steps=steps,d1=d,d2=d2,exp=exp[1],fill=fill,fn=fn); + R(0,180)HypKehle(grad=90+grad,l=l[0],l2=l3,d1=d,d2=d2,steps=steps,exp=exp[0],fill=fill,fn=fn); + + HelpTxt("HypKehleD",["grad",grad,"steps",steps,"l",l,"l2",l2,"l3",l3,"d",d,"d2",d2,"fn",fn,"fill",fill,"exp",exp,"name",name],help); +} + + + +module HypKehle(l=15,grad=90,d1=3,d2,l2,steps=20,fn=24,fill=false,exp=1,center=false,name,help){ + + rot=1; + d2=is_undef(d2)?d1:d2; + $d=d1; + $r=d1/2; + l2=is_undef(l2)?l:l2; + $info=false; + $idxON=false; + $tab=is_undef($tab)?1:b($tab,false)+1; + +R(center?-grad/2:0) +for(i=[0:steps-1]){ + Color(1/(steps*1.5)*i,$idxON=false)hull() + union(){ + $idx=i; + Tz(pow(i,exp)*l/pow(steps-1,exp))R((grad +(180-grad)/(steps-1)*i)*rot +(rot?0:180)) + if($children)linear_extrude(.1,scale=0)children(0); + else rotate(180/fn)cylinder(.1,d1=d1,d2=0,$fn=fn); + + if(fill){ + $info=false; + if($children)R(0,90)RotEx(cut=true,fn=fn)rotate(90)children(); + else Isosphere(d=is_num(fill)?fill:max(d1,d2),$fn=fn); + } + + Color($idxON=false) R(grad)Tz(pow((steps-1)-i,exp)*l2/pow(steps-1,exp)) R( (180-grad)/(steps-1)*i*rot +180) + if($children){ + $info=$children>1?1:0; + linear_extrude(.1,scale=0)mirror([0,1])children($children>1?1:0); + } + else rotate(180/fn)cylinder(.1,d1=d2,d2=0,$fn=fn); + } +} +if(!fill&&!$children)R(0,0,90)Isosphere(d=is_num(fill)?fill:max(d1,d2),$fn=fn); +HelpTxt("HypKehle",["l",l,"grad",grad,"d1",d1,"d2",d2,"l2",l2,"steps",steps,"fn",fn,"fill",fill,"exp",exp,"center",center,"name",name],help); +} + +/** \name Rohr \page Objects +Bogen() creates a bended pipe or children +\param grad angle +\param rad bend radius +\param l,l1,l2 straight length l⇒ [l1,l2] +\param fn fn2 fs fraqments +\param tcenter tangent +\param center centern +\param lap overlap +\param d diameter (if no children) +\param id inner diameter +\param messpunkt show bend center + +*/ + +//Rohr()Quad(); +//Rohr(); +//Rohr(id=5); + +module Rohr(grad=90,rad=5,d=8,l,l1=10,l2=12,fn=0,fn2=0,fs=fs,dicke=+1,rand,name,center=true,messpunkt=messpunkt,lap=minVal,id,spiel,help) +{ +//Echo(str("Rohr parameter mismatch d:",d,"-id:",id,"-dicke:",dicke),color="redring",condition=is_num(d)&&is_num(id)&&is_num(dicke)&&d-id-dicke*2); + +Echo("Rohr id given - dicke calculated!",color="info",condition=is_num(id)&&$info); + +//calD=is_num(id)&&is_num(dicke)? id+dicke*2 :assert(d)d; +dicke=assert(d)is_num(id)?(d-id)/2:is_num(rand)?rand:dicke; + +lap=is_num(spiel)?-spiel:lap; + + Bogen(grad=grad,rad=rad,l=l,l1=l1,l2=l2,fn=fn,name=name,help=0,center=center,messpunkt=messpunkt,lap=lap,fs=fs){ + if($children)Rand(dicke)children(); + else polygon( kreis(r=d/2,rand=dicke,fn=fn2)); + } + + HelpTxt(titel="Rohr",string=["grad",grad,"rad",rad,"d",d,"l",l,"l1",l1,"l2",l2,"fn",fn,"fn2",fn2,"fs",fs,"dicke",dicke,"name",name,"center",center,"messpunkt",messpunkt,"lap",lap,"id",id],help=help); + InfoTxt(name="Rohr",string=concat(dicke>0?["ID",d-dicke*2]:["OD",d-dicke*2],["d",d],["dicke",dicke]),info=name); + +} + + +module Kugelmantel(d=20,rand=n(2),fn=fn,help) +{ + difference() + { + sphere(d=d,$fn=fn); + sphere(d=d-2*rand,$fn=fn); + + } + +HelpTxt("Kugelmantel",["d",d, + "rand",rand, + "fn",fn, +],help); +} + +/** \page Objects +\name Kegelmantel +Kegelmantel() creates a cone blanket +\param d,d2 diameter +\param v, grad ratio or angle +\param h height optional to d2 +\param rand wallthickness horizontal +\param loch center hole +\param center center +\param fn fragments +\param name,help name,help +*/ + //Kegelmantel(h=3,rand=-1); + //Kegelmantel(rand=1); + + +module Kegelmantel(d=10,d2=5,v=1,rand=n(2),loch=4.5,grad=0,h=0,center=false,fn=0,fs=fs,name,help) +{ + v=grad?tan(grad):v; + translate([0,0,center?d>d2?(d2-d)/4*v:(d-d2)/4*v:0]) difference() + { + if(rand>0) Kegel(d1=d,d2=d2,v=v,h=h,name=name,fn=fn,fs=fs); + if(rand<0) Kegel(d1=d-rand*2,d2=d2-rand*2,v=v,h=h,name=name,fn=fn,fs=fs); + //T(z=-.001) Kegel(d1=d-2*rand,d2=0,v=v,n=0); + if(d20?d:d-rand*2,d2=0,v=v,name=0,fn=fn,fs=fs); + if(d0?d2:d2-rand*2,v=v,name=0,fn=fn,fs=fs); + if(loch>0)cylinder(1000,d=loch,center=true,$fn=fn,$fs=fs); + } + InfoTxt("Kegelmantel",["wandstärke", sin(atan(v))*rand],name); + HelpTxt("Kegelmantel",[ + "d",d, + "d2",d2, + "v",v, + "rand",rand, + "loch",loch, + "grad",grad, + "h",h, + "center",center, + "fn",fn, + "fs",fs, + "name",name], + help); + +} + + +module Freiwinkel(w=60,h=1) + T(0,+1.0){ + R(z=w/2-90) T(-6,+0,2.0)minkowski() + { + cube([20,5,h],false); + sphere(0.8,$fn=fn); + } + R(z=-w/2+90) T(-14,+0,2.0)minkowski() + { + cube([20,5,h],false); + sphere(0.8,$fn=fn); + } + + } + + + +module Twins(h=1,d,d11=10,d12,d21=10,d22,l=20,r=0,fn=fn,center=0,sca=+0,2D=false,help) +{ + d11=d?d:d11; + d12=d?d:is_undef(d12)?d11:d12; + d21=d?d:d21; + d22=d?d:is_undef(d22)?d21:d22; + + 2D=h?2D:true; + + if(!2D) rotate([0,0,center?r:0])translate([center?-l/2:0,0,0]){ + rotate([0,-sca,0])cylinder(h,d11*.5,d12*.5,$fn=fn); + rotate([0,0,center?0:r])translate([l,0,0])rotate([0,sca,0])cylinder(h,d21*.5,d22*.5,$fn=fn); } + + if(2D) rotate([0,0,center?r:0])translate([center?-l/2:0,0,0]){ + rotate([0,-sca,0])circle(d=d11,$fn=fn); + rotate([0,0,center?0:r])translate([l,0,0])rotate([0,sca,0])circle(d=d21,$fn=fn); } + +HelpTxt("Twins",["h",h,"d",d,"d11",d11,"d12",d12,"d21",d21,"d22",d22,"l",l,"r",r,"fn",fn,"sca",sca,"2D",2D],help); +} + + + +module Torus2(m=5,trx=10,a=1,rq=1,d=5,w=2,name,new=true,help)//m=feinheit,trx = abstand mitte,rq = sin verschiebung , a=amplitude, w wellen +{ + +//if(new&&w==2)rotate(90/w)WaveEx(grad=360,trx=trx-a/2*1,try=trx+a/2*1,f=w,tf=w,fv=0,tfv=0,r=d/2,ta=a/2,a=-rq/2); +if(new)rotate(-90/w)WaveEx(grad=360,trx=trx,try=trx,f=w,tf=-w,fv=0,tfv=180,r=d/2,ta=a,a=rq/2,fn=360/m); + +if(!new)echo("

    For Torus2 use 'new=true' (WaveEx)"); +Echo("obsolete Torus2 use WaveEx()",color="red",useVersion>23); +if(new)echo("

    Torus2 is using WaveEx"); +if(!new)rotate ([0,0,0])for (i=[0:m:360]) + { + + hull() + { + rotate ([0,0,i])translate([trx+(sin(w*i)*a),0,0])rotate([90,0,0])cylinder(.01,d1=sin(w*i)*rq+d,d2=0,$fn=200/m,center=false); + + rotate ([0,0,i-m])translate([trx+(sin(w*(i-m))*a),0,0])rotate([90,0,0])cylinder(.01,d1=sin(w*(i-m))*rq+d,$fn=200/m,d2=0,center=false); + } + } + + + InfoTxt("Torus2",["Wellen",w,"amplitude",a,"Radius",trx],name); + HelpTxt("Torus2",["m",m,"trx",trx,"a",a,"rq",rq,"d",d,"w",w,"name",name],help); +} + + +/** \name Kegel +\page Objects +Kegel() creates a cone +\param d or d1 base diameter +\param d2 top diameter +\param v slope +\param grad slope in degree +\param h height (optional) +\param r1,r2 optional ⇒ d1,d2 +\param rad edge radius +\param x0 center can move outside for negative form +\param lap overlap extrusion +\param fn,fs fragments, fragment size +\param center center +\param name,help name help +*/ + +//Kegel(rad=[.5,1],d=8,grad=53,d2=0.1,center=+0); + +//Kegel(rad=0.2*[1,1,1,1],x0=2,d=10,d2=5); + +//Kegel(5,2,rad=-[.5,.25],lap=[1,1]); + +//Kegel(5,2,rad=[.5,-.25],lap=[0,+1],2D=1); + + +module Kegel(d,d2=0,d1,v=1,grad=0,h=0,r1,r2,rad=0,x0=0,lap=0,fn,fn2,fs=fs,fa=fa,center=false,2D=false,name,help,deg) +{ +grad=is_num(deg)?deg:grad; + +2D=is_parent(needs2D)?true:2D; +lap=is_list(lap)?lap:[is_list(rad)&&rad[0]<0?max(.1,lap):lap,is_list(rad)&&rad[1]<0?max(+0.1,lap):lap]; +dHelp=d?d:d1?d1:r1?2*r1:0; +r2=r2?r2:d2?d2/2:0; +v=grad?min(100000,max( -100000,tan(grad)) ):h&&r2?h/(dHelp/2-r2):v; +d2=h&&(is_num(d)||is_num(d1)||is_num(r1))?h/-v*2+(is_num(r1)?2*r1:is_num(d)?d:d1):is_num(r2)?2*r2:d2; +d1=is_undef(d1)&&is_undef(d)&&is_undef(r1)&&h?h/v*2+(is_num(r2)?2*r2:d2):is_num(r1)?r1*2:is_undef(d1)?is_num(d)?d:0:d1; +height=abs((d1-d2)/2*v); + +rList=is_list(rad)?concat(rad[0],rad[1],rad[2]?min(height,rad[2]):0,rad[3]?min(height,rad[3]):0) + :[rad,rad,0,0]; +Echo(str("rad[2]+rad[3]>height ",rad[2],"+",rad[3],"=",rad[2]+rad[3],">",height),color="redring",condition=rad[2]+rad[3]>height); + +x0=is_num(x0)?(x0max(d1,d2)/2)&&x0>0?[x0,x0]:[0,0]:x0; + +deg=grad?grad:atan(v); + +c=abs(max(d1,d2)-(max(x0)+rList[d1>d2?2:3])*2); +hc=abs(c/2*v); +ri=c*hc/(2*Hypotenuse(c/2,hc)+c); + + +rLim=[ min(ri, height) , min(height, abs(min(d1,d2)/2-max(x0)-rList[d1>d2?3:2])*(1+tan(abs(90-abs(deg)))) ) ]; + + +rad=[min( rList[0],abs(rLim[d1>d2?0:1]) ), min( rList[1],rLim[d1>d2?1:0] ), rList[2], rList[3] ]; + + +pointsEdge=[ +[x0[0],0],[d1/2,0], +[d2/2,height],[x0[1],height] +]-[for([0:3])[0,1]*(center?height/2:0)]; + + +// with lap +pointsEdgeLap=[ +[x0[0],-lap[0]],if(lap[0])[d1/2,-lap[0]], [d1/2,0], +[d2/2,height],if(lap[1])[d2/2,height+lap[1]], [x0[1],height+lap[1]] +]-[for([0:5])[0,1]*(center?height/2:0)]; + +// for negative r (TODO calc x1 and x2 ) +pointsEdge2= +let(r1=rad[0],r2=rad[1], x1=r1<0?max(d2,d1)/2+abs(r1):d1/2, x2=r2<0?max(d1,d2)/2+abs(r2):d2/2 ) +[ +[x0[0],-lap[0]],if(lap[0])[x1,-lap[0]],if(r1<0)[x1,0],[d1/2,0], +[d2/2,height],if(r2<0)[x2,height],if(lap[1])[x2,height+lap[1]],[x0[1],height+lap[1]] +]-[for([0:7])[0,1]*(center?height/2:0)]; + + +points=min(rad)<0?polyRund(pointsEdge2,r=[rad[2],if(lap[0])0,if(rad[0]<0)0, abs(rad[0]), abs(rad[1]),if(rad[1]<0)0,if(lap[1])0, rad[3]],fs=fs,fa=fa,minF=5,fn=fn2) + :max(lap)>0&&max(rad)>0?polyRund(pointsEdgeLap,r=[rad[2],if(lap[0])0, abs(rad[0]), abs(rad[1]),if(lap[1])0, rad[3]],fs=fs,fa=fa,minF=5,fn=fn2) + :max(rad)>0?polyRund(pointsEdge,r=[rad[2], rad[0], rad[1], rad[3]],fs=fs,fa=fa,minF=5,fn=fn2) + :max(lap)?pointsEdgeLap:pointsEdge; + +/* +ideg=[deg+90,deg]; +points2=[ WIP +[0,0], +each arc(r=rad[0],deg=ideg[0],t=[d1/2-(rad[0]*cos(ideg[0])),rad[0] ],rot=-90,fn=fs2fn(rad[0],grad=ideg[0],fs=fs,minf=5)), +each arc(r=rad[1],deg=ideg[1],t=[d2/2,height-rad[1] ],rot=90-deg,fn=fs2fn(rad[1],grad=ideg[0],fs=fs,minf=5)), +[0,height] +]; +*/ + + +if(2D&&(d1||d2))polygon(points); + else { + if((max(rad)||min(rad)||max(lap))&&(d1||d2) || (d1||d2)&&max(x0)){ + RotEx(fn=fn?fn:fs2fn(r=max(d1,d2)/2,fs=fs),fs=fs,fa=fa)polygon(points); + }else { + + if(d1-d2&&!(d2<0))cylinder (abs((d1-d2)/2*v),d1=d1,d2=d2,$fn=fn,$fs=fs,center=center); + //if(d2>d1)cylinder (abs((d2-d1)/2*v),d1=d1,d2=d2,$fn=fn,center=center); + if(d1==d2&&d2!=0)cylinder (h?h:10,d1=d1,d2=d2,$fn=fn,$fs=fs,center=center); + } + if(!d1&&!d2&&is_undef(r1))color("magenta")%cylinder(5,5,0,$fn=fn,$fs=fs,center=center); +} + + if(d2<0||d1<0)Echo(str("‼ negativ ∅",name," Kegel d1=",negRed(d1)," d2=",negRed(d2)),color="red"); + InfoTxt("Kegel",["höhe",height,"Kegelverhältniss",str((d1-d2)/height, "= 1:", v/2),"Steigung",str(v*100,"/",1/v*100,"% = ",atan(v),"°/",90-atan(v),"°"),"Spitzenwinkel",str(2*(90-atan(v)),"°"),"d1",negRed(d1),"d2",negRed(d2)],name); + + HelpTxt("Kegel",["d",d,"d2",d2,"d1",d1,"v",v,"grad",grad,"h",h,"r1",r1,"r2",r2,"rad",rad,"x0",x0,"lap",lap,"fn",fn,"fn2",fn2,"fs",fs,"fa",fa,"center",center,"2D",2D,"name=",name],help); +} + + + +module MK(d1=12,d2=6,v=19.5,fn=fn) +{ +//Basis +// Obererdurchmesser +//kegelverjüngung +cylinder ((d1-d2)/2*v,d1=d1,d2=d2,$fn=fn); + echo(str("»»»››› Konushöhe=",(d1-d2)/2*v)); +} + +/// Fillet +//Kehle(dia=-20,rad=1); + +//Kehle(rad=5); + + + +module Kehle(rad=2.5,dia,r,l=20,angle=360,grad=0,a=90,ax=90,fn=0,fn2,fs=fs,fa=fa,r2=0,spiel,lap=spiel,center=false,2D=false,end=false,fase=false,fillet,help) +{ + 2D=is_parent(needs2D)?true:2D; + fillet=is_list(fillet)?fillet:[fillet,fillet]; + fase=is_bool(fase)?fase?1:0:fase; + end=is_bool(end)?end?1:0:end; + angle=grad?grad:angle; + spiel=is_undef(spiel)?is_list(lap)?lap + :[lap,lap] + :is_list(spiel)?spiel + :[spiel,spiel]; + center=center?true:false; + dia=is_undef(r)?dia:2*r; + $info=false; + + if(is_undef(dia)&&l&&!2D&&rad>0){ + difference(){ + Tz(fase&&$preview?.05:0)scale([1,1,sign(l)])linear_extrude(height=abs(l) -(fase&&$preview?.1:0),$fn=fn,convexity=5,center=center) + { + difference() + { + translate([-spiel[0],-spiel[1]]) square([sin(-90+ax)*rad+rad+spiel[0],sin(a-90)*rad+rad+spiel[1]]); + T(rad,rad)rotate(r2)circle(rad,$fn=is_undef(fn2)?round(fs2fn(r=rad,minf=16,fs=fs,grad=360,fa=fa)/4)*4:fn2); + } + } + if(fase)T(x=rad,y=rad)Tz(center?-l/2:0)Kegel(d2=0,d1=Hypotenuse(rad+spiel[0],rad+spiel[1])*2,fn=fn2,fs=fs); + if(fase>1)T(x=rad,y=rad)Tz(center?l/2:l)R(180)Kegel(d2=0,d1=Hypotenuse(rad+spiel[0],rad+spiel[1])*2,fn=fn2,fs=fs); + } + + if(is_num(fillet[0]))intersection(){ + Tz(center?-l/2:0)R(45,90)T(0,-fillet[0])RotEx(90,cut=true,fn=fn/360*90,fs=fs)T(fillet[0])rotate(-45)Kehle(2D=true,a=ax,ax=a,fn2=fn2,fs=fs,rad=rad,spiel=spiel); + T(-spiel[0],-spiel[1],-500)cube([rad+spiel[0],rad+spiel[1],600]); + } + if(is_num(fillet[1]))intersection(){ + Tz(center?l/2:l)R(-45,-90)T(0,-fillet[1])RotEx(90,cut=true,fn=fn/360*90,fs=fs)T(fillet[1])rotate(-45)Kehle(2D=true,a=a,ax=ax,fn2=fn2,fs=fs,rad=rad,spiel=spiel); + T(-spiel[0],-spiel[1],l-100)cube([rad+spiel[0],rad+spiel[1],600]); + } + + + + + if(end==2)R(x=-90)T(y=center?0:-l/2) MKlon(ty=l/2)RotEx(grad=90,cut=1,fn=fn,fs=fs)Kehle(a=a,ax=ax,rad=rad,spiel=spiel,2D=true,fn2=fn2,fs=fs,help=false); + if(end==-2)R(x=-90)T(y=center?0:-l/2) MKlon(ty=l/2)R(90,0,90)RotEx(grad=90,cut=1,fn=fn,fs=fs)Kehle(a=ax,ax=a,rad=rad,spiel=spiel,2D=true,fn2=fn2,fs=fs); + if(end==1)Tz(center?-l/2:0)R(-90)RotEx(grad=90,cut=1,fn=fn,fs=fs)Kehle(a=a,ax=ax,rad=rad,spiel=spiel,2D=true,fn2=fn2,fs=fs); + } + + if(2D&&rad>0)translate([is_num(dia)?dia/2:0,0])difference(){ + translate([-spiel[0],-spiel[1]]) square([sin(-90+ax)*rad+rad+spiel[0],sin(a-90)*rad+rad+spiel[1]]); + T(rad,rad)rotate(r2)circle(rad,$fn=is_undef(fn2)?round(fs2fn(r=rad,minf=16,fs=fs,grad=360)/4)*4:fn2,$fs=fs); + } +// dia + if(!is_undef(dia)&&!2D&&rad>0){ + rotate(center?-180-angle/2:0)difference(){ + rotate(fase&&$preview?.05:0)rotate_extrude(angle=angle-(fase&&$preview?.1:0),$fn=fn?fn:dia?fs2fn(minf=24,r=dia/2,fs=fs,fa=fa):0,convexity=5,$fs=fs,$fa=fa) + difference() + { + T(dia/2)translate([-spiel[0],-spiel[1]])square([sin(-90+ax)*rad+rad+spiel[0],sin(a-90)*rad+rad+spiel[1]]); + T(dia/2)T(rad,rad)rotate(r2)circle(rad,$fn=is_undef(fn2)?round(fs2fn(r=rad,minf=16,fs=fs,grad=360,fa=fa)/4)*4:fn2,$fs=fs); + if(dia>-rad*2)T(-200,-100)square(200); + } + if(fase&&angle)T(dia/2+rad,z=rad)R(-90*sign(dia))Kegel(d2=0,d1=Hypotenuse(rad+spiel[0],rad+spiel[1])*2,fn=fn2,fs=fs); + if(fase>1&&angle)rotate(angle)T(dia/2+rad,z=rad)R(90*sign(dia))Kegel(d2=0,d1=Hypotenuse(rad+spiel[0],rad+spiel[1])*2,fn=fn2,fs=fs); + } + + + + if(angle)rotate(center?-180-angle/2:0){ + if(is_num(fillet[0]))intersection(){// fillet[0] + T(dia/2,minVal*sign(dia))R(45,0,-90)T(0,-fillet[0])rotate(dia<0?[0,0,90]:[0])RotEx(90,cut=true,fn=fn/360*90,fs=fs)T(fillet[0])rotate(-45)Kehle(2D=true,a=a,ax=ax,fn2=fn2,rad=rad,spiel=spiel,fs=fs); + RotEx(fn=fn,fs=fs)T(dia/2)translate([-spiel[0],-spiel[1]])square([rad+spiel[0],rad+spiel[1]]); + } + if(is_num(fillet[1]))intersection(){// fillet[1] + rotate(angle)T(dia/2,-minVal*sign(dia))rotate([135,0,90])T(0,-fillet[1])R(z=dia<0?90:0)RotEx(90,cut=true,fn=fn/360*90,fs=fs)T(fillet[1])rotate(-45)Kehle(2D=true,a=ax,ax=a,fn2=fn2,rad=rad,spiel=spiel,fs=fs); + RotEx(fn=fn,fs=fs)T(dia/2)translate([-spiel[0],-spiel[1]])square([rad+spiel[0],rad+spiel[1]]); + } + + if(end>0) T(dia/2,+minVal*sign(dia)) rotate(dia<0?0:-90) RotEx(grad=90,cut=1,fn=fn)Kehle(a=a,ax=ax,rad=rad,spiel=spiel,2D=true,fn2=fn2,fs=fs); + if(end==2) rotate(angle)T(dia/2,-minVal*sign(dia))rotate(dia<0?-90:0) RotEx(grad=90,cut=1,fn=fn)Kehle(a=a,ax=ax,rad=rad,spiel=spiel,2D=true,fn2=fn2,fs=fs); + if(end<0) T(dia/2,minVal*sign(dia)) rotate(-90) R(-90,dia<0?-180:-90)RotEx(grad=90,cut=1,fn=fn)Kehle(a=ax,ax=a,rad=rad,spiel=[spiel.y,spiel.x],2D=true,fn2=fn2,fs=fs); + if(end==-2) rotate(angle)T(dia/2,-minVal*sign(dia))R(dia<0?-180:90)R(y=90) RotEx(grad=90,cut=1,fn=fn)Kehle(a=ax,ax=a,rad=rad,spiel=[spiel.y,spiel.x],2D=true,fn2=fn2,fs=fs); + + + } + } +HelpTxt("Kehle",["rad",rad,"dia",dia,"l",l,"angle",angle,"grad",grad,"a",a,",ax=",ax,"fn",fn,"fn2",fn2,"fs",fs,"fa",fa,"r2",r2,"spiel",spiel,"center",center, "2D",2D,"end",end,"fase",fase,"fillet",fillet],help); + +} + + + +module Sinuskoerper +( +h=10, +d=33, +rand=2, +randamp=1, +amp=1.5, +w=4, +randw=4, +detail=3, +vers=0, +fill=0, +2D=0, +twist=0, +scale=1 +) +{ + if(!2D)linear_extrude(h,convexity=5,twist=twist,scale=scale)for (i=[0:detail:359.9]) + + { + j=i+detail; + hull() + { + rotate(i) T(d/2+amp*sin(i*w))circle(d=rand+randamp*sin((i+vers)*randw),$fn=36); + rotate(j) T(d/2+amp*sin(j*w))circle(d=rand+randamp*sin((j+vers)*randw),$fn=36); + if(fill)circle(d=d/2,$fn=36); + + } + + } + if(2D)for (i=[0:detail:359.9]) + + { + j=i+detail; + hull() + { + rotate(i) T(d/2+amp*sin(i*w))circle(d=rand+randamp*sin((i+vers)*randw),$fn=36); + rotate(j) T(d/2+amp*sin(j*w))circle(d=rand+randamp*sin((j+vers)*randw),$fn=36); + if(fill)circle(d=d/2,$fn=36); + } + + } +} + + + + +module Dreieck(h=10,ha=10,ha2=0,s=1,name,c=0,2D=0,grad=0) +{ + s=grad?tan(grad/2)*2*(sqrt(3)/2):s; + //echo(*2);atan(((ha/(sqrt(3)/2)*s)/2)/ha) + + + r=(sqrt(3)/3)*ha/(sqrt(3)/2); + r2=(sqrt(3)/3)*(ha2?ha2:ha)/(sqrt(3)/2); + if(!2D)T(c?h/2:0,z=c?ha/2-r:ha-r) R(0,-90) scale([1,s,1])cylinder(h=h,r1=r,r2=r2,$fn=3); + if(2D)T(x=c?ha/2-r:ha-r) R(0,0) scale([1,s,1])circle(r=r,$fn=3); + + + if(name)echo(str("»»» »»» ",name," Dreieck Höhe= ", ha," Breite= ",ha/(sqrt(3)/2)*s," Winkel= ",2*atan(s/2/(sqrt(3)/2)) )); +} + + + + +module GewindeV1(d=20,s=1.5,w=5,g=1,fn=3,r=0,gd=1.75,detail=5,tz=0,name)//depreciated +{ + + + difference() + { + children(); + color("orange")translate([0,0,tz])for (i=[0:detail:w*360]) + { + j=i+detail; + hull() + { + R(z=i)Polar(g,(d-gd)/2,n=0)T(z=i/(360/s))R(90)R(z=r)cylinder(.1,d=gd,$fn=fn); + R(z=j)Polar(g,(d-gd)/2,n=0)T(z=j/(360/s))R(90)R(z=r)cylinder(.1,d=gd,$fn=fn); + } + + } + } + + if(name)echo(str("»»» »»» ",name," Gewinde aussen∅= ",d,"mm — Center∅= ",d-gd,"mm")); + if(r||(fn!=3&&fn!=6)) Echo ("!!! Check Aussendurchmesser !!!",color="red"); + +} + + +/** \name Bogen \page Objects +Bogen() creates a bended cylinder or children +\param grad angle +\param rad bend radius +\param l,l1,l2 straight length l⇒ [l1,l2] +\param fn fn2 fs fraqments +\param tcenter tangent +\param center centern +\param lap,spiel overlap +\param d diameter (if no children) +\param messpunkt show bend center +\param 2D make 2D +*/ +//Bogen(2D=1,lap=+0,fn=0); +//Bogen(); + +module Bogen(grad=90,rad=5,l,l1=10,l2=12,fn,center=true,tcenter=false,name,d=3,fn2=0,fs=fs,lap=minVal,spiel,help,messpunkt=messpunkt,2D=false) +{ + $fn=fn; + $fs=fs; + $fa=fa; + $helpM=0; + $info=0; + $idxON=false; + ueberlapp=is_num(spiel)?-spiel:lap; + l1=is_undef(l)?l1+ueberlapp:is_list(l)?l[0]+ueberlapp:l+ueberlapp; + l2=is_undef(l)?l2+ueberlapp:is_list(l)?l[1]+ueberlapp:l+ueberlapp; + 2D=is_parent(needs2D)&&!$children?2D?b(2D,false): + 1: + b(2D,false); + + c=sin(abs(grad)/2)*rad*2;// Sekante + w1=abs(grad)/2; // Schenkelwinkel + w3=180-abs(grad); // Scheitelwinkel + a=(c/sin(w3/2))/2; + hc=grad!=180?Kathete(a,c/2):0; // Sekante tangenten center + hSek=Kathete(rad,c/2); //center Sekante + bl=PI*rad/180*grad;//Bogenlänge + + mirror([grad<0?1:0,0,0])rotate(center?0:tcenter?-abs(grad)/2:+0)T(tcenter?grad>180?hSek+hc:-hSek-hc:0)rotate(tcenter?abs(grad)/2:0) T(center?0:tcenter?0:-rad){ + if(!2D) T(rad)R(+90,+0)Tz(-l1+ueberlapp){ + $idx=0; + $tab=is_undef($tab)?1:b($tab,false)+1; + color("green") linear_extrude(l1,convexity=5) + if ($children)mirror([grad<0?1:0,0,0])children(); + else circle(d=d,$fn=fn2); + //color("lightgreen",.5) T(0,0,l1)if(messpunkt&&$preview)R(0,-90,-90)Dreieck(h=l1,ha=pivotSize,grad=5,n=0);//Pivot(active=[1,1,1,0]); + } + else T(rad)R(0,+0)T(0,-ueberlapp)color("green")T(-d/2)square([d,l1]); + + if(grad)if(!2D) rotate_extrude(angle=-abs(grad)-0,$fa = fn?abs(grad)/fn:fa, $fs = $fs,$fn=0,convexity=5)intersection(){ + $idx=1; + $fn=fn; + $fa=fa; + T(rad) + if ($children)mirror([grad<0?1:0,0,0])children(); + else circle(d=d,$fn=fn2); + translate([0,-500])square(1000); + } + else Kreis(rand=d,grad=abs(grad),center=false,r=rad+d/2,fn=fn,fs=fs,name=0,help=0); + + + if (!2D)R(z=-abs(grad)-180) T(-rad,-ueberlapp)R(-90,180,0){ + $idx=2; + color("darkorange")linear_extrude(l2,convexity=5) + if ($children)mirror([grad<0?1:0,0,0])children(); + else circle(d=d,$fn=fn2); + + //color("orange",0.5)if(messpunkt&&$preview)T(0,0,l2)R(0,-90,-90)Dreieck(h=l2,ha=pivotSize,grad=5,n=0);//Pivot(active=[1,1,1,0]); + } + else R(z=-abs(grad)-180) T(-rad,-ueberlapp) color("darkorange")T(-d/2)square([d,l2]); + + union(){//messpunkt + color("yellow") Pivot(active=[1,0,0,1],messpunkt=messpunkt); + if(grad!=180)color("blue")mirror([0,grad<0?1:0,0]) translate(RotLang(90+grad/2,hc+hSek))Pivot(active=[1,0,0,1],messpunkt=messpunkt); + if(grad>180)color("lightblue")mirror([0,grad<0?1:0,0]) translate(RotLang(90+grad/2,-hc-hSek))Pivot(active=[1,0,0,1],messpunkt=messpunkt); + } + } + + + if(name&&!$children)echo(str("»»» »»» ",name," Bogen ",grad,"° Durchmesser= ",d,"mm — Innenmaß= ",2*max(rad,d/2)-d,"mm Außenmaß= ",2*max(rad,d/2)+d)); + + if(name)echo(str(name," Bogen ",grad,"° Radius=",rad,"mm Sekantenradius= ",hSek,"mm — Tangentenschnittpunkt=",hSek+hc,"mm TsSekhöhe=",hc,"mm Kreisstücklänge=",bl," inkl l=",bl+l1+l2,"mm")); + + if(!$children&&name&&!2D)Echo("Bogen missing Object! using circle",color="warning"); + + HelpTxt("Bogen",["grad",grad,"rad",rad,"l",l,"l1",l1,"l2",l2,"fn",fn,"center",center,"tcenter",tcenter,"name",name,"d",d,"fn2",fn2,"fs",fs,"lap",lap,"messpunkt",messpunkt,"2D",2D],help); + +} + + + + +module W5(kurv=15,arms=3,detail=.3,h=50,tz=+0,start=0.7,end=13.7,topdiameter=1,topenddiameter=1,bottomenddiameter=+2,inv=0) +{ + + Polar(e=arms)for (i=[start:detail:end]) + { + + + j=i+detail; + hull() + { + R(z=i*kurv)T(i,0,tz*-2*h/(2*PI*(i)))R(inv*180)cylinder(h/(2*PI*(i)),d1=n(topenddiameter)+i/end*n(bottomenddiameter),d2=n(topdiameter),$fn=fn); + R(z=j*kurv)T(j,0,tz*-2*h/(2*PI*(j)))R(inv*180)cylinder(h/(2*PI*(j)),d1=n(topenddiameter)+j/end*n(bottomenddiameter),d2=n(topdiameter),$fn=fn); + } + } + + +} + +fonts=[ +"Bahnschrift", +"Alef", +"Amiri", +"Arial", +"Caladea", +"Calibri", +"David CLM", +"David libre", +"Deja Vu Sans", +"Ebrima", +"Echolon", +"Forelle", +"Frank Ruehl CLM", +"Frank Ruhl Hofshi", +"Franklin Gothic Medium", +"Gabrielle", +"Gabriola", +"Gadugi", +"Gentium Basic", +"Gentium Book Basic", +"Georgia", +"Impact", +"Ink Free", +"Liberation Mono", +"Liberation Sans", +"Liberation Sans Narrow", +"Liberation Serif", +"Linux Biolinum G", +"Linux Libertine Display G", +"Linux Libertine G", +"Lucida Console", +"Noto Sans", +"OpenSymbol", +"Palatino Linotype", +"Politics Head", +"Reem Kufi", +"Rubik", +"SamsungImagination", +"Segoe Print", +"Segoe Script", +"Segoe UI", +"SimSun", +"Sitka Banner", +"Sitka Display", +"Sitka Heading", +"Sitka Small", +"Sitka Subheading", +"Sitka Subheading", +"Sitka Text", +"Source Code Pro", +"Source Sans Pro", +"Source Serif Pro", +"Tahoma", +"Times New Roman", +"Trebuchet MS", +"Unispace", +"Verdana", +"Yu Gothic", +"Yu Gothic UI", +"cinnamon cake", +"gotische", +"Webdings", +"Wingdings", +"EmojiOne Color", +"Yellowtail", +"Hazeer Cello" + +]; + + +styles=[ + +"Condensed", +"Condensed Oblique", +"Condensed Bold", +"Condensed Bold Oblique", +"Condensed Bold Italic", +"SemiCondensed", +"SemiLight Condensed", +"SemiLight SemiCondensed", +"SemiBold SemiCondensed", +"SemiBold Condensed", +"Light Condensed", +"Light SemiCondensed", +"SemiLight", +"Light", +"ExtraLight", +"Light Italic", +"Bold", +"Bold SemiCondensed", +"Semibold", +"Semibold Italic", +"Bold Italic", +"Bold Oblique", +"Black", +"Black Italic", +"Book", +"Regular", +"Italic", +"Medium", +"Oblique", +]; + + +/* +Text("123ABCiiII",spacing=.9,radius=20,textmetrics=1,center=+1,cy=false,viewPos=true); +%circle(20); +// */ +//Cring(txt="iiiAAA",tSpacing=1.0); + +/** \name Text +\page Objects +Text() creates text + +##Example +Text(123,h=0); +Text(text="WWiiABCiiXX",radius=10); + +\param text textstring or number +\param size text size +\param h text height Z for 2D h=0 +\param cx,cy,cz center center modes +\param spacing text spacing +\param fn,fs text resolution +\param radius polar text arrangement +\param rot rotation vector for text +\param font text font (name or number) echo(fonts) +\param style text style ( name or number) echo(styles) +\param help show help +\param name text name +\param textmetrics use textmetrics +\param viewPos show letter positions +\param trueSize="body" text size = body height allow the use of pt() point, hp=size of letters "hp",cap=cap height, text=current text, font=current font + + +*/ +//Text("fhpbdlqQPXMALTfF",size=10,trueSize="cap",cy=+0); +//%square([100,10]); + +//Text("HTAMpqf",radius=20,rot=0); +//Text("HTAMMMMMM",trueSize="textl",size=20,textmetrics=0,spacing=1); + +/* // max function +color("blue")Text(h=2,"Hallo",size=[40,10]); +color("red")Text(h=2,"123456ABCDEF",size=[40,10]); +square([40,10]); +//*/ + +//Text("AA",radius=10,cy=0,center=1,viewPos=true); + +module Text(text="»«",size=5,h,cx,cy,cz,center=0,spacing=1,fn,fs=fs,radius=0,rot=[0,0,0],font="Bahnschrift:style=bold",style,help,name,textmetrics=true,viewPos=false,trueSize="body") +{ +inputSize=size; +text=str(text); +lenT=len(text); +textmetrics=version()[0]<2022||is_undef(textmetrics().position[0])?false:textmetrics; + +Echo(str("Sizing inactive trueSize=",trueSizeSW),color="warning",condition=trueSize!="size"&&( (!textmetrics&&trueSize!="body")||(is_num(useVersion)&&useVersion<22.208) ) ); + +trueSizeSW=is_num(useVersion)&&useVersion<22.208?"size":is_list(inputSize)?assert(inputSize.y)"textMax":trueSize; + + +style=is_string(style)?style:styles[style]; +font=is_num(font)?fonts[font]:font; +fontstr=is_undef(style)?font:str(font,":style=",style); + +hp=textmetrics?textmetrics(text="hpbdlq",font=fontstr,size=1,spacing=spacing).size.y:1; +cap=textmetrics?textmetrics(text="HTAME",font=fontstr,size=1,spacing=spacing).size.y:1; +textSize=textmetrics?textmetrics(text=text,font=fontstr,size=1,spacing=spacing).size:[lenT*spacing,1]; +fontS=textmetrics?fontmetrics(font=fontstr,size=1).nominal:1; + +//echo(textSize,inputSize.x/textSize.x,inputSize.y/textSize.y); +size=trueSizeSW=="body"?inputSize*.72: + trueSizeSW=="hp"?inputSize/hp: + trueSizeSW=="cap"?inputSize/cap: + trueSizeSW=="text"?inputSize/textSize.y: + trueSizeSW=="textl"?inputSize/textSize.x: + trueSizeSW=="font"?inputSize/(fontS.ascent-fontS.descent): + trueSizeSW=="textMax"?min(inputSize.x/textSize.x,inputSize.y/textSize.y): + inputSize; + + h=is_parent(needs2D)?0:is_undef(h)?size:h; + cx=center?is_undef(cx)?1:cx:is_undef(cx)?0:cx; + cy=center?is_undef(cy)?1:cy:is_undef(cy)?0:cy; + cz=center?is_undef(cz)?1:cz:is_undef(cz)?0:cz; + + + txtPos=textmetrics?textmetrics(text=text,font=fontstr,size=size,spacing=spacing).position.x:0; + txtSizeX=textmetrics?textmetrics(text=text,font=fontstr,size=size,spacing=spacing).size.x:size*spacing*lenT; + txtSizeY=textmetrics?textmetrics(text=text,font=fontstr,size=size,spacing=spacing).size.y:size; + fontSize=[for(i=[0:max(lenT-1,0)])textmetrics? + textmetrics(text=stringChunk(txt=text,length=i),font=fontstr,size=size,spacing=spacing).advance.x + textmetrics(text=text[i],font=fontstr,size=size,spacing=1).advance.x/2*(cx?1:1) + : + (size*spacing)*i]; + + + valign=cy?b(cy,false)<0?"bottom": + b(cy,false)>1?"top": + "center": + "baseline"; + + halign=bool(cx,false)>0?"center" + :bool(cx,false)<0?"right" + :"left"; + + if(text) + if(!radius){ + if(h) + rotate(rot)translate([0,0,cz?-abs(h)/2:h<0?h:0]) linear_extrude(abs(h),convexity=10){ + text(str(text),size=size,halign=halign,valign=valign,font=fontstr,spacing=spacing,$fn=fn,$fs=fs); + } + else rotate(rot)translate([0,0,cz?-h/2:0])text(text,size=size,halign=halign,valign=valign,spacing=spacing,font=fontstr,$fn=fn,$fs=fs); + } + else if (lenT){ + iRadius=radius+(cy?-txtSizeY/2:0); + rotate((center?textmetrics?gradB(txtSizeX/2+txtPos,iRadius) + :gradB(max(fontSize),iRadius)/2 + :0)) + for(i=[0:lenT-1])rotate(-gradB(fontSize[i],iRadius)) + if(h) + translate([0,radius,0])rotate(rot)Tz(cz?-abs(h)/2:h<0?h:0){ + %color("Chartreuse")if(viewPos&&$preview)translate([0,-1])rotate(-30)circle($fn=3);// pos Marker + linear_extrude(abs(h),convexity=10)text(text[i],size=size,halign=true?"center":"left",valign=valign,font=fontstr,$fn=fn,$fs=fs); + } + else translate([0,radius,cz?-h/2:0])rotate(rot)text(text[i],size=size,halign=true?"center":"left",valign=valign,font=fontstr,$fn=fn,$fs=fs); + } + + InfoTxt("Text",["font",font,"style",style,"trueSize",trueSizeSW,"size",str(inputSize," ⇒ ",size)],name); + + HelpTxt("Text",[ +"text",str("\"",text,"\""), +"size",inputSize, +"h",str(h," /*0 for 2D*/"), +"cx",cx, +"cy",cy, +"cz",cz, +"center",center, +"spacing",spacing, +"fn",fn, +"fs",fs, +"radius",radius, +"rot",rot, +"font",str("\"",font,"\""), +"style",str("\"",style,"\""), +"name",name, +"textmetrics",textmetrics, +"viewPos",viewPos, +"trueSize",str("\"",trueSize,"\""," /* body,size,hp,cap,text,textl,font (textMax) */") +],help); + + +} + + + +/** \name Pille +\page Objects +Pille() creates a capsule +\param l length +\param d diameter +\param rad rad2 edge radius +\param r radius ↦ d +\param center center +\param fn, fn2 fragments +\param loch leave center hole +\param grad degree +\param deg edge angle +\param chamfer chamfer adjactant if deg <90 or move round +\param 2D polygon +\param x0 center x dist +\param name, help name, help +*/ + +//Pille(d=13,rad=5,l=30,deg=90,chamfer=1); + + +module Pille( +h=10, +d,//+5, +rad, +rad2, +r, +center=true, +fn, +fn2, +fs=fs, +fa=fa, +fs2, +loch=false, +grad=360, +deg=90, +chamfer=true, +2D=false, +x0=0, +l, +name, +help +){ +2D=is_parent(needs2D)&&!$children?2D?b(2D,false): + 1: + b(2D,false); + +deg=is_list(deg)?deg:[deg,deg]; + +l=is_undef(l)?h:l; + +r=assert(is_num(l),"Pille h is undef")is_undef(r)?is_undef(d)?l/2:d/2:r; +rad=is_undef(rad)?2*r-90?[[max(0,abs(r)-(1-cos(rgrad))*rad[0]-(1-sin(abs(rgrad)))*abs(rad[0])*( rgrad==90?0:tan(rgrad) )),0]]:[], + [ + if(!loch)[x0[0],0], + if(!loch)[x0[1],l] + ], + chamfer[1]&°[1]<90&°[1]>-90?[[max(0,abs(r)-(1-cos(rgrad2))*rad2-(1-sin(abs(rgrad2)))*abs(rad2)*( deg[1]==90?0:tan(rgrad2) )),l]]:[], + + rad2==0?[[d/2,l]]:Kreis(r=rad2,rand=0,grad=rgrad2,t=[d/2-rad2,(chamfer[1]?l-rad2+ausgleich2:l-sin(rgrad2)*rad2)],fn=fn2[1],center=false,rot=90-rgrad2), + rad[0]==0?[[d/2,0]]:Kreis(r=rad[0],rand=0,grad=rgrad,t=[d/2-rad[0],(chamfer[0]?rad[0]-ausgleich:sin(rgrad)*rad[0])],fn=fn2[0],center=false,rot=90) +); + +if(!2D)if(rgrad==90&&rgrad2==90)Tz(center?-l/2:0)//RotEx(grad=grad,fn=fn) + rotate_extrude(angle=grad,$fn=fnO,$fs=fs[0],$fa=fa)polygon(points); + else Tz(center?-l/2:0)//RotEx(grad=grad,fn=fn) + rotate_extrude(angle=grad,$fn=fnO,$fs=fs[0],$fa=fa)polygon(clampToX0(points)); +if(2D)T(0,center?-l/2:0)polygon(points); + + InfoTxt("Pille",["Länge",l,"Rundung",str(rad[0],"/",rad2,str(rad[0]>d/2?" Spitz":rad[0]==d/2?" Rund":" Flach","/",rad2>d/2?"Spitz":rad2==d/2?"Rund":"Flach")),"Durchmesser",d,"Radius",d/2,"Grad",str(grad,"°")],name); + + HelpTxt("Pille",["h",h,"d",d,"fn",fn,"fn2",fn2,"fs",fs,"fs2",fs2,"center",center,"name",name,"rad",rad,"rad2",rad2,"loch",loch,"grad",grad,"deg",deg,"chamfer",chamfer,"2D",2D,],help); +} + + + +/** \page Objects + \name Disphenoid + Disphenoid() creates a disphenoid + \param h height + \param l length + \param b width + \param r edge radius + \param ty,tz,delta distortion + \param fn fragments + \param help activate help +*/ + +module Disphenoid(h=15,l=25,b=20,r=1,ty=0,tz=0,delta=[0,0],fn=36,help){ + delta=is_list(delta)?delta:[delta,delta]; + + points=[ + [-l/2+r+delta[0],b/2-r+ty,0], + [-l/2+r-delta[0],-b/2+r+ty,0], + [l/2-r+delta[1],0,h/2-r+tz], + [l/2-r-delta[1],0,-h/2+r+tz], + ]; + + + faces=[ + [1,0,2], + [0,1,3], + [2,3,1], + [3,2,0], + ]; + + + + minkowski(){ + polyhedron(points,faces,convexity=5); + sphere(r,$fn=fn); + } + + HelpTxt("Disphenoid",["h",h,"l",l,"b",b,"r",r,"ty",ty,"tz",tz,"delta",delta,"fn",fn],help); +} + + + + + +module GewindeV2(dn=10,s,w=0,g=1,winkel=+60,rot2=0,r1=0,kern,fn=1,detail=fn,spiel=spiel,name,tz=0,preset=0,h=10,translate=[0,0,0],rotate=[0,0,0],d=0,gd=0,r=0,center=true,help,p=1.5,endMod=true){ + +s=is_undef(s)?p:s;//Steigung +p=s; + + r1=r1?r1:p/sin(winkel/2)/2-0.01; //overlap preventing + rh=Kathete(r1,p/2); //Gangtiefe + + +spiel=rot2==0?spiel:0; // spiel only for symetrische +dn=$children?dn+spiel*2:dn; +kern=!is_undef(kern)?kern:dn-2*rh+spiel; + + +function profil(rot=0)= + 0? vollwelle(fn=1,extrude=-1,x0=+0,h=1,xCenter=1,r=0.2,r2=0.5,l=p-.1) // test vollwelle + : kreis(r=r1,rand=+0,fn=fn,grad=winkel,sek=winkel==360?1:0,rot=rot2); + + +function RotEx(rot=0,punkte=profil(rot=60),verschieb=dn/2,steigung=1,detail=detail)=[for(rotation=[0:detail*rot/360])for(i=[0:len(punkte)-1]) + concat((punkte[i][0]+verschieb)*sin(rotation*360/detail),punkte[i][1]+rotation/detail*steigung,(punkte[i][0]+verschieb)*cos(rotation*360/detail)) +]; + + +function faces(punkte=RotEx(),fn=len(profil())-1)=[ +for(i=[0:fn-2])[0,i+1,i+2], +for(i=[0:len(punkte)-2-fn])[fn+1+i,1+i,+i], +for(i=[0:len(punkte)-2-fn])[fn+i,fn+1+i,+i], +for(i=[1:fn])[len(punkte)-i+0,len(punkte)-i-1,len(punkte)-1] +]; +Echo("‼ using old GewindeV2 ‼",color="warning"); + if(d||gd||r){GewindeV1(d=d,s=s,w=w?w:5,g=g,tz=tz,gd=gd?gd:1.75,fn=fn==1?3:fn,r=r)children();//Kompatibilität + Echo("‼ using old GewindeV1 ‼",color="warning"); + } + else if(false)R(90)polyhedron(RotEx(rot=100,steigung=p),faces(punkte=RotEx(rot=100)),convexity=15); //test for polyhedron only + else if(preset==0){ + w=w?w:h/p*360; + add=center?p/2:0; + difference(){ + if($children)children(); + translate(translate)rotate(rotate)Tz(-add+tz)intersection(){ + union(){ + Col(6) Polar(g,n=0) difference(){ + R(90)polyhedron(RotEx(rot=w,steigung=p),faces(punkte=RotEx(rot=w)),convexity=15); + if(endMod&&is_num(rh))Tz(h)rotate(-90+w%360-w%(360/detail))T(dn/2)cylinder(p,d=rh*2-spiel,center=true,$fn=4); + if(endMod&&is_num(rh))rotate(-90)T(dn/2)cylinder(p,d=rh*2-spiel,center=true,$fn=4); + } + if(rot2==0)Col(9) Tz(-p/2) rotate(-90)cylinder(w/360*p+p,d=kern,center=false,$fn=detail); + } + if(rot2==0)Col(8) rotate(-90)cylinder(2*w/360*p+p,d=dn-spiel,center=true,$fn=detail); + } + } + +HelpTxt("GewindeV2",["dn",dn,"s",s,"w",w,"g",g,"winkel",winkel,"rot2",rot2,", r1",r1,",kern",kern,"fn",fn,"detail",detail,"spiel",spiel,"name",name,"tz",tz,"preset",preset,"h",h,"translate",translate,"rotate",rotate,"d",d,"gd",gd,"r",r,"center",center,"p",p,"endMod",endMod],help&&!preset); + + + +if(name)echo(str("Gangtiefe=",rh,"mm - Gangflanke(r1)=",r1,"mm - Steigung=",p,"mm - Höhe=",w/360*p,"mm+",p)); +if(name)echo(str(name,rot2==0?$children?" Innen": " Aussen":" Undefiniertes","gewinde ∅=",dn-spiel," (",dn,") Kern=",kern)); + if(winkel==360)Echo(str(" ∅ Diameter Warning!"),color="warning"); + } + +else if(preset==1){// ½ Zoll Gewinde + if($children) GewindeV2(dn=20.95,w=w,h=h,kern=19,winkel=55,p=1.814286,preset=0,fn=1,translate=translate,rotate=rotate)children(); + if(!$children) GewindeV2(dn=20.95,w=w,h=h,winkel=55,p=1.814286,preset=0,fn=1,translate=translate,rotate=rotate,help=help); + + echo(str(" ½ Zoll Gewinde ")); +} + +else if(preset==2){// ¾ Zoll Gewinde + if($children) GewindeV2(dn=26.44,w=w,h=h,kern=24.5,winkel=55,p=1.814286,preset=0,fn=1,translate=translate,rotate=rotate)children(); + if(!$children) GewindeV2(dn=26.44,w=w,h=h,winkel=55,p=1.814286,preset=0,fn=1,translate=translate,rotate=rotate); + + echo(str(" ¾ Zoll Gewinde ")); +} + +else if(preset=="M3"){// M3 Gewinde + if($children) GewindeV2(dn=3,w=w,h=h,p=.5,preset=0,fn=1,translate=translate,rotate=rotate)children(); + if(!$children) GewindeV2(dn=3,w=w,h=h,p=.5,preset=0,fn=1,translate=translate,rotate=rotate); + + echo(str(" M3 Gewinde ")); +} +else if(preset=="M6"){// M6 Gewinde + if($children) GewindeV2(dn=6,w=w,h=h,p=1,preset=0,fn=1,translate=translate,rotate=rotate)children(); + if(!$children) GewindeV2(dn=6,w=w,h=h,p=1,preset=0,fn=1,translate=translate,rotate=rotate); + + echo(str(" M6 Gewinde ")); +} + +} + + + + +module Laser3D(h=4,layer=10,var=0.002,name,on=-1){ + + if(on==1)for (i=[0:h/layer:h]){ + c=i/h; + T(z=i/h*var) color([c,c,c]) projection(cut=true)T(z=-i)children(); + } + + if(on==-1) for(i=[+0.0:h/layer:h]){ + + color([i/h,i/h,i/h])T(z=i*+0.01) intersection(){ + T(-500,-500,i) cube([1000,1000,layer]); + T(z=-i*0.000) children(); + } + } + + if(on==0) children(); + + T(z=-.48)color([0,0,0])cube([1000,1000,1],true); + + MO(!$children); + InfoTxt("Laser3D",["color resolution=",str(h/layer,"mm")],name); + +} + +/** \name Elllipse +Ellipse creates an ellipse with optional children +\param x first semi axis can be [x,x] (absolute values) +\param y second semi axis can be [y,y] +\param z optional +\param rand thickness for 2D +\param fn fs fa fraqment resolution +*/ + +module Ellipse(x=2,y=2,z=0,rand=1,fn,fs=fs,fa=fa,help){ + + + x=is_list(x)?x:[x,x]; + y=is_list(y)?y:[y,y]; + z=is_list(z)?z:[z,z]; + //ToDo z rot; + fn=fn?fn:fs2fn(r=max(max(x),max(y),max(z)),fs=fs,fa=fa); + //function rota(i)=-atan2(sin(i)*y,cos(i)*x)+90; + function rot(i)= + let(i=i%360) + atan2(cos(i)*(i>=180?x[0]:x[1]),sin(i)*(i>=90&&i<270?y[0]:y[1])); + + for (n=[0:fn-1]){ + $idx=n; + step=360/fn; + i=step*n; + j=step*(n+1); + + if($children) Color(1/fn*n)hull(){ + T(sin(i)*(i>=180?x[0]:x[1]),cos(i)*(i>=90&&i<270?y[0]:y[1]),cos(i)*(i>=90&&i<270?z[0]:z[1]))rotate(rot(i))children(); + union(){ + $idx=$idx+1; + T(sin(j)*(i>=180?x[0]:x[1]),cos(j)*(i>=90&&i<270?y[0]:y[1]),cos(j)*(i>=90&&i<270?z[0]:z[1]))rotate(rot(j))children(); + } + } + if(!$children)hull(){ + T(sin(i)*(i>=180?x[0]:x[1]),cos(i)*(i>=90&&i<270?y[0]:y[1]))rotate(rot(i))circle(rand/2,$fn=36); + T(sin(j)*(i>=180?x[0]:x[1]),cos(j)*(i>=90&&i<270?y[0]:y[1]))rotate(rot(j))circle(rand/2,$fn=36); + } + + } + MO(!$children,warn=true); + HelpTxt("Ellipse",["x",x,"y",y,"z",z,"rand",rand,"fn",fn,"fs",fs,"fa",fa],help); +} + + + +module WStrebe(grad=45,grad2,h=20,d=2,d2=0,rad=3,rad2=0,sc=0,angle=360,lap=.2,fn=fn,2D=false,center=true,rot=0,help){ + + rad2=rad2?rad2:rad; + d2=d2?d2:d; + grad2=is_undef(grad2)?grad:grad2; + + if(!2D)R(0,center?0:grad)Tz(center?0:h/2){ + + rotate(rot)R(180)Halb(1)Tz(-h/2)R(0,-grad2) Strebe(rad=rad2,rad2=rad,d=d2,d2=d,h=h,grad=grad2,single=false,name=0,help=0,2D=0,sc=sc,angle=angle,lap=lap,fn=fn); //oben + Tz(.1)Halb(1)Tz(-h/2-.1)R(0,-grad) Strebe(rad=rad,rad2=rad2,d=d,d2=d2,h=h,grad=grad,single=false,name=0,help=0,2D=0,sc=sc,angle=angle,lap=lap,fn=fn);//unten + } + + + + if(2D)R(0,0,center?0:-grad)T(0,center?0:h/2){ + mirror([0,1,0])Halb(1,y=1,2D=true)T(0,-h/2)R(0,0,grad2) Strebe(rad=rad2,d=d2,d2=d,h=h,grad=grad2,single=false,n=0,help=0,2D=2D,sc=sc,angle=angle,lap=lap,fn=fn); + Halb(1,y=1,2D=true)T(0,-h/2)R(0,0,grad) Strebe(rad=rad,d=d,d2=d2,h=h,grad=grad,single=false,n=0,help=0,2D=2D,sc=sc,angle=angle,lap=lap,fn=fn);//unten + } +HelpTxt("WStrebe",["grad",grad,"grad2",grad2,"h",h,"d",d,"d2",d2,"rad",rad,"rad2",rad2,"sc",sc,"angle",angle,"lap",lap,"fn",fn,"2D",2D,"center",center,"rot",rot],help); + +} + +/// Strebe + +module Strebe(h=20,d=5,d2,rad=4,rad2,sc=0,grad=0,skew=0,single=false,angle=360,spiel,fn=fn,fn2=fn?fn/4:undef,center=false,name,2D=false,lap=.2,help){ + + fn2=is_list(fn2)?fn2:[fn2,fn2]; + rad2=is_undef(rad2)?is_list(rad)?rad[1]: + rad: + rad2; + rad=is_list(rad)?rad[0]:rad; + d2=is_undef(d2)?d:d2; + skew=skew?skew:tan(grad); + grad=atan(skew); + sc=sc?sc:d/(d*cos(grad)); + winkel=h==rad+rad2?90: + atan((single?(h-rad): + (h-rad-rad2))/(d2/2-d/2)); + lap=is_undef(spiel)?is_list(lap)?lap:[1,1]*lap:spiel*[1,1]; + + grad1=winkel>0?180-winkel:abs(winkel);//90;//VerbindugsWinkel unten + grad2=180-grad1;//VerbindugsWinkel oben + //assert(h>=(rad+rad2),str("Strebe too short h=",h,"<",rad,"+",rad2," for rad")); + + + if (!2D && !is_parent(needs2D))//search(["Rundrum"], parentList())[0] ) + M(skewzx=skew) Tz(center ? -h/2 : 0) scale([sc, 1, 1]) + rotate(-angle/2) rotate_extrude(angle=angle, convexity=5, $fn=fn) + Strebe(skew=0, h=h, d=d, d2=d2, rad=rad, rad2=rad2, sc=1, grad=0, single=single, lap=lap, fn2=fn2, name=0, 2D=2, help=false); + + + InfoTxt("Strebe",[ + "Neigungs ∡",str(atan(skew),"°"), + "center ∡",str(single||rad!=rad2?"~":"=",winkel,"°"), + "Scale",sc, + " dSkew",str(d,"/",d*sc*cos(grad),"-",d2,"/",d2*sc*cos(grad),"mm"), + "Parent",parentList() + ],name); + + +if (2D || is_parent(needs2D))//search(["Rundrum"], parentList())[0] ) + M(skewyx=skew)T(0,center?-h/2:0){ + if(grad1>90) Echo(str("Strebe ∅",d,"mm is d=",(d/2-rad+sin(grad1)*rad)*2),color="warning"); + if(grad2>90) Echo(str("Strebe ∅",d2,"mm is d2=",(d2/2-rad2+sin(grad2)*rad2)*2),color="warning"); + Echo(str("Strebe too short h=",h,"<",rad,"+",rad2," for rad"),color="warning",condition=h<(rad+rad2)); + + points= concat( + 2D==2?[[0,h+lap[1]]]:single?[[-d2/2,h]]: kreis(fn=fn2[1],rand=0,r=rad2,grad=-grad2,rot=+grad2,center=false,sek=true,t=[-d2/2-abs(sin(winkel))*rad2,h-rad2]), // open L + + 2D==2?[[+0,h+lap[1]]]:[[single?-d2/2:-d2/2-rad2,h+lap[1]]], + + [[single?d2/2:d2/2+rad2,h+lap[1]]], + + single?[[d2/2,h]]: kreis(fn=fn2[1],rand=0,r=rad2,grad=-grad2,rot=0,center=false,sek=true,t=[d2/2+abs(sin(winkel))*rad2,h-rad2]),// open R + + kreis(fn=fn2[0],rand=0,r=rad,grad=-grad1,rot=grad1-180,center=false,sek=true,t=[d/2+abs(sin(winkel))*rad,rad]), // unten R + + [[d/2+rad,0-lap[0]]], + + 2D==2?[[0,-lap[0]]]:[[-d/2-rad,0-lap[0]]], + + 2D==2?[[+0,0]]:kreis(fn=fn2[0],rand=0,r=rad,grad=-grad1,rot=180,center=false,sek=true,t=[-d/2-abs(sin(winkel))*rad,rad]));// unten L + + + scale([sc,1])polygon(points,convexity=5); + +} + +HelpTxt("Strebe",["h",h,"d",d,"d2",d2,"rad",rad,"rad2",rad2,"sc",sc,"grad",grad,"skew",skew,"single",single,"angle",angle,"lap",lap,"fn",fn,"fn2",fn2,"name",name,"2D",str(2D,"/*2 for halb*/")],help); + +} + + + +/// Bezier() creates a Bezier shape polygon or 3D + +//RotEx(cut=true)Bezier(mpRot=true); + +module Bezier( +p0=[+0,+10,0], +p1=[15,-10,0], +p2, +p3=[0,-10,0], +w=1,//weighting +max=1.0, +min=+0.0, +fn=50, +fn2=fn, +ex,//extrude X +pabs=false, //p1/p2 absolut/relativ p0/p3 +messpunkt=true, +mpRot, +twist=0, +scale=1, +hull=true, +points, +d, +name, +help + +){ + mpRot=is_undef(mpRot)?search(["RotEx"],parentList())[0]?true: + mpRot: + mpRot; + //echo(search(["RotEx"],parentList())[0],parentList()); + + messpunkt=is_bool(messpunkt)?messpunkt?pivotSize:0:messpunkt;//$info?messpunkt:0; + 3D=is_list(points)||d&&!$children?true:false; + p0=v3(p0); + p3=v3(p3); + p1=v3(pabs?p1*w:v3(p1)*w+p0); + p2=is_undef(p2)?p1:v3(pabs?p2*w:v3(p2)*w+p3); + + $fn=hull?fn:$fn; + $fa=fa; + $fs=fs; + + + if($children){ + twist=v3(twist); + $helpM=0; + $info=is_undef(name)?is_undef($info)?false:$info:name; + step=((max-min)/fn); + for (t=[min:step:max-step]){ + + $rot=vektorWinkel(Bezier(t,p0,p1,p2,p3),Bezier(t+step,p0,p1,p2,p3))+twist/(max-step)*t; + $tab=true; + $idx=t; + if (hull) Color(1/(max-step)*t,$idxON=false)hull(){ + translate(Bezier(t,p0,p1,p2,p3))rotate($rot)scale(1-(1-scale)/(max-step)*t)children(); + union(){ + $idx=t+step; + $rot=t>=max-step?vektorWinkel(p2,p3)+twist: // last segment + vektorWinkel(Bezier(t+step,p0,p1,p2,p3),Bezier(t+step*2,p0,p1,p2,p3))+twist/(max-step)*(t+step); + translate(Bezier(t+step,p0,p1,p2,p3))rotate($rot)scale(1-(1-scale)/(max-step)*(t+step))children(); + } + } + else Color(1/(max-step)*t,$idxON=false) + translate(Bezier(t,p0,p1,p2,p3))rotate($rot)scale(1-(1-scale)/(max-step)*t)children(); + + } + +} + if(!$children&&3D==false){ + if (is_undef(ex)) polygon([for (t=[min:((max-min)/fn):(max+(max-min)/fn)-((max-min)/fn)])Bezier(t, + [p0[0],p0[1]], + [p1[0],p1[1]], + [p2[0],p2[1]], + [p3[0],p3[1]] + )]); + + else polygon(concat( + [[0,p0[1]]], + [for (t=[min:((max-min)/fn):(max+(max-min)/fn)-((max-min)/fn)])Bezier(t, + [p0[0]+ex,p0[1]], + [p1[0]+ex,p1[1]], + [p2[0]+ex,p2[1]], + [p3[0]+ex,p3[1]] )], + [[0,p3[1]]] + )); + + + } + + if(3D){ + points=is_undef(points)?arc(r=d/2,deg=360,fn=fn2,z=0): + len(points[0])==3?points: + [for(iPoint=points)concat(iPoint,0)]; + + loop=len(points); + path=[for (t=[min:((max-min)/fn):(max+(max-min)/fn)-((max-min)/fn)])Bezier(t,p0,p1,p2,p3)]; + if(name&&!$children)Echo(str(name," No Bezier object using polygon! path length=",pathLength(path)),color="green"); + PolyH(pathPoints(points=points,path=path,scale=scale,twist=twist),loop=loop,name=false); + + } + + + + %if(messpunkt){ + ex=is_undef(ex)?0:ex; + vpr=mpRot?[90,0,0]:$vpr; + Pivot(mpRot?[p0[0]+ex,0,p0[1]]:p0+[ex,0,0],messpunkt,txt="p0",vpr=vpr); + Pivot(mpRot?[p1[0]+ex,0,p1[1]]:p1+[ex,0,0],messpunkt/2,txt=str("p1",p1==p2?" ":""),vpr=vpr); + Pivot(mpRot?[p2[0]+ex,0,p2[1]]:p2+[ex,0,0],messpunkt/2,txt="p2",vpr=vpr); + Pivot(mpRot?[p3[0]+ex,0,p3[1]]:p3+[ex,0,0],messpunkt,txt="p3",vpr=vpr); + d=b(messpunkt,false)/20; + %Line(mpRot?[p0[0]+ex,0,p0[1]]:p0+[ex,0,0],mpRot?[p1[0]+ex,0,p1[1]]:p1+[ex,0,0],d=d,center=true); + %Line(mpRot?[p3[0]+ex,0,p3[1]]:p3+[ex,0,0],mpRot?[p2[0]+ex,0,p2[1]]:p2+[ex,0,0],d=d,center=true); + + } + + if(name&&!$children&&!3D)Echo(str("No Bezier object using polygon!"),color="green"); + +HelpTxt("Bezier",[ + "p0",p0, + "p1",p1, + "p2",p2, + "p3",p3, + "w/*weighting*/",w, + "max",max, + "min",min, + "fn",fn, + "fn2",fn2, + "ex/*extrude X*/",ex, + "pabs/*p1/p2 absolut/relativ */",pabs, + "messpunkt",messpunkt, + "mpRot",mpRot, + "twist",twist, + "hull",hull, + "points",points?"points":undef, + "d/*for 3D*/",d, + "name",name] + ,help); +} + + + + +module Ttorus(r=20,twist=360,angle=360,pitch=0,scale=1,r2,fn=fn,help){ + + scale=is_list(scale)?scale:[scale,scale,scale]; + r2=is_undef(r2)?r:r2; + diff=r2-r; + + for (i=[0:fn-1]){//(i=[0:360/fn:angle-.005]){ + step=angle/fn; + rdiff=diff/fn; + j=i+1;//j=i+360/fn; + //$info=i?0:$info; + //$helpM=i?0:$helpM; + $idx=i; + Color(i/fn,$idxON=false) hull(){ + rotate(i*step)translate([r+rdiff*i,0,i*pitch/360*abs(step)]) rotate([0,i*twist/360*step,0])scale([1,1,1]+(scale-[1,1,1])/fn*(i))children(); + rotate(j*step)translate([r+rdiff*j,0,j*pitch/360*abs(step)]) rotate([0,j*twist/360*step,0])union(){ + $info=false; + $helpM=false; + $idx=j; + scale([1,1,1]+(scale-[1,1,1])/fn*(j))children(); + } + } + } + +MO(!$children); +Echo("use Coil()",color="info",condition=!$children); + +HelpTxt("Ttorus",[ + "r",r, + "twist",twist, + "angle",angle, + "pitch",pitch, + "scale",scale, + "r2",r2, + "fn=",fn],help); +} + +/** \page Modifier +\name Kontaktwinkel +Kontaktwinkel(d=1)Torus(d=$d,winkel=60); cuts children at contact angle + +\param winkel contact angle +\param d r diameter/radius of children +\param baseD calculates d for desired base diameter +\param center cut both sides if true +\param 2D cuts 2D +\param inv inverts cut +\param centerBase move Object so cut is at center if true +*/ + +module Kontaktwinkel(winkel=50,d,baseD,r,center=false,2D=0,inv=false,centerBase=0,name,help){ +grad=-winkel+90; +d=is_num(baseD)?(baseD/2)/sin(winkel)*2:is_undef(r)?is_undef(d)?0:d:2*r; + +h=assert(d,"baseD or d or r not set!")sin(grad)*d/2; +b=sqrt(pow(d/2,2)-pow(h,2)); +viewportSize=is_undef(viewportSize)?1000:max(d*2,100,viewportSize); + + +centerBase=b(centerBase,false); +$d=d; +$r=d/2; + if(!2D){ + if(!inv) Tz(centerBase==1?h: + centerBase==-1?-h: + 0)intersection(){ + children(); + T(z=center?0:-h)cylinder(center?h*2:viewportSize,d=viewportSize,center=b(center,true),$fn=6); + } + if(inv)Tz(centerBase==1?-h:centerBase==-1?h:0) intersection(){ + children(); + difference(){ + cube(viewportSize,center=true); + T(z=center?0:h-viewportSize)cylinder(center?h*2:viewportSize,d=viewportSize,center=b(center,true),$fn=6); + } + } + } + if(2D){ + if(!inv)T(y=centerBase==1?h:centerBase==-1?-h:0)intersection(){ + children(); + T(center?0:-viewportSize/2,center?0:-h)square([viewportSize,center?h*2:viewportSize],center=b(center,true)); + } + if(inv)T(y=centerBase==1?-h:centerBase==-1?h:0) intersection(){ + children(); + difference(){ + square(viewportSize,center=true); + T(center?0:-viewportSize/2,center?0:h-viewportSize)square([viewportSize,center?h*2:viewportSize],center=b(center,true)); + } + } + + } + +MO(!$children); +InfoTxt("Kontaktwinkel",["∅",d,"radius",r,"winkel",str(winkel,"°"),"Höhe",h,"Kontakt Radius",b,"2×",b*2],name); +HelpTxt("Kontaktwinkel",["winkel",winkel,"d",d,"baseD",baseD,"r",r,"center",center,"2D",2D,"inv",inv,"centerBase",centerBase,"name",name],help); +} + + + +/// creates Octahedron with n spherical subdivision + +module OctaH(r=1,n=0,d,help){ + +HelpTxt("OctaH",["r",r,"n",n,"d",d],help); + + scaling=is_list(r)||is_list(d)?true:false; // if subdiv needs sep scaling + r=is_list(r)?[for(i=[0:5]) i%2? -abs(r[i%len(r)]): // neg quadrant + abs(r[i%len(r)])]: //pos quadrants + is_undef(d)?[r, -r, r, -r, r, -r]: + is_list(d)?[for(i=[0:2]) each[d[i%len(d)] , -d[i%len(d)] ]] /2: + // d.y /2, -d.y /2, + // d.z /2, -d.z /2]: + [d /2, -d /2, d /2, -d /2, d /2, -d /2]; + + faces=[ + [0,2,4], + [2,1,4], + [1,3,4], + [3,0,4], + [2,0,5], + [1,2,5], + [3,1,5], + [0,3,5], + + ]; + if(n==0)polyhedron(octa(r),faces); + + else OctaSphere(r,n,d); + module OctaSphere(r=10,n=10,d){ + // based on Hans Loeblich alternative spheres + // https://github.com/thehans/FunctionalOpenSCAD + // MIT license + + + data=sphere_subdiv(divs=max(1,floor(n/4)), poly=OCTAHEDRON(1)); + polyhedron(data[0],data[1]); + + + // sum a vector of vectors. vsum([]) == undef + function vsum(v,i=0) = len(v)-1 > i ? v[i] + vsum(v, i+1) : v[i]; + // angle between two vectors (2D or 3D) + function anglev(v1,v2) = acos( (v1*v2) / (norm(v1)*norm(v2) ) ); + function flatten(l) = [ for (a = l) for (b = a) b ]; + //function unit(v) = v / norm(v); // convert vector to unit vector + // spherical linear interpolation + function slerp(p0,p1,t) = let(a = anglev(p0,p1)) (sin((1-t)*a)*p0 + sin(t*a)*p1) / sin(a); + + function OCTAHEDRON(r) = [octa(r),faces]; + + +// [ [[0,0,r[5]],[r[0],0,0],[0,r[2],0],[r[1],0,0],[0,r[3],0],[0,0,r[4]]], +// [ [0,3,4],[0,1,2],[0,2,3],[0,4,1], +// [5,2,1],[5,3,2],[5,4,3],[5,1,4] ] ]; + + + // subdivide faces, splitting edges into integer number of divisions + // input faces must be triangles with vertices on the unit sphere + function sphere_subdiv(divs=1, poly) = + let( + R = r[0],//d == undef ? r : d/2, // optional radius or diameter + d = divs, // shorthand + pv = poly[0], // points vector + tv = poly[1], // triangle index vector + newpoints = [for (t = tv) let(p = [pv[t[0]], pv[t[1]], pv[t[2]]]) + for (i=[0:1:d], j=[0:1:d-i]) if (i+j!=0 && i!=d && j!=d) // skip original corner points + let(subv=[for (vi=[0:2]) let(k=d-i-j, ii=[i,j,k], + j1=ii[(vi+1)%3], n=ii[vi]+j1, + p0=p[vi], p1=p[(vi+1)%3], p2=p[(vi+2)%3], + p_i=slerp(p0,p1,n/d), p_j=slerp(p0,p2,n/d) + ) slerp(p_i,p_j,j1/n) + ]) + vsum(subv) + ], + Tn = function(n) n*(n+1)/2, // triangular numbers + Td = Tn(d+1), // total points for subdivided face + np = Td - 3, // new points per original face + lp = len(pv), + allpoints = concat(pv, newpoints/3), + // Given original triangle point indices t, + // and indices i,j for subdivided basis vectors, { i => (tri[0],tri[1]), j => (tri[0],tri[2]) } + // convert to absolute point index of resulting full point set. + pij = function(n,t,i,j) i+j==0 ? t[0] : i==d ? t[1] : j==d ? t[2] : + lp + n*np + Td - Tn(d+1-i) + j - (i==0 ? 1 : 2), + faces = flatten([for (n = [0:1:len(tv)-1]) let(t = tv[n]) [ + for (i=[0:1:d-1], j=[0:1:d-1-i]) [ pij(n,t,i,j), pij(n,t,i+1,j), pij(n,t,i ,j+1) ], + for (i=[1:1:d-1], j=[0:1:d-1-i]) [ pij(n,t,i,j), pij(n,t,i,j+1), pij(n,t,i-1,j+1) ] + ] ]) + )[scaling?[for(i=[0:len(allpoints)-1])[ + allpoints[i].x>0?allpoints[i].x*r[0]:allpoints[i].x*-r[1], + allpoints[i].y>0?allpoints[i].y*r[2]:allpoints[i].y*-r[3], + allpoints[i].z>0?allpoints[i].z*r[4]:allpoints[i].z*-r[5], + ]] + :R*allpoints + , faces]; + } +} + + + + +/** \page Objects +Prisma() rounded cube (square prism) + \name Prisma + * \brief creates a prism with optional round edges + \param x1 size x bottom (can be list) + \param y1 size y bottom + \param z size z + \param c1 vertical corner diameter can be bigger then s + \param s edge diameter + \param rad edge radius (only for simple) + \param x2,y2 optional size top + \param x2d,y2d delta to shift top + \param c2 for tapered vertical corner + \param fnC fragments vertical corner + \param fnS fragments corner + \param fs fragment size + \param center center [x,y,z] + \param r corner radius (simple only) + \param deg edge contact angle [bottom,top] + \param optimize uses Pill (like in simple), allows deg and rad but slower than hull(simple) +*/ + +//Prisma(r=[1,2,3,4]); + +module Prisma(x1=12,y1,z,c1=5,s=1,x2,y2,x2d=0,y2d=0,rad,c2=0,vC=[0,0,1],cRot=0,fnC=0,fnS=0,fs=fs,center=false,r,deg=[50,90],optimize=false,name,help){ + + + helpX1=x1; + helpY1=y1; + helpX2=x2; + helpY2=y2; + helpZ=z; + helpS=s; + helpC1=c1; + + simple=(x1==x2||is_undef(x2))&&(y1==y2||is_undef(y2))&&!x2d&&!y2d&&!c2&&vC==[0,0,1]&&!optimize?true:false; + + center=is_list(center)?v3(center):[1,1,center]; + rad=is_undef(rad)?[s,s]/2:is_list(rad)?rad:[rad,rad]; + r=is_undef(r)?c1/2*[1,1,1,1]:is_list(r)?r:[r,r,r,r]; + + x=is_list(x1)?x1[0]:x1; + y=is_list(x1)?x1[1]:is_undef(y1)?x1:y1; + + hErr=optimize?0:s/2-cos(90/ceil((is_num(fnS)&&fnS?fnS:fs2fn(r=s/2,fs=fs,grad=360))/2))*s/2; // missing sphere piece + z=(is_undef(x1[2])?is_undef(z)?x:z:x1[2])+ (simple?0:hErr*2); + s=min(x,y,is_undef(z)?0:z,max(vSum(rad),0)); + c1=min(max(r[0]*2,0),x,y); + + cylinderh=c1?minVal:0; + + x1=c1-s>0?vC[1]?max(x-cylinderh-s,minVal):max(x-c1,minVal):max(x-s,minVal); + y1=c1-s>0?vC[0]?max(y-cylinderh-s,minVal):max(y-c1,minVal):max(y-s,minVal); + + h=vC[0]||vC[1]?c1?max(z-c1,minVal):max(z-s,minVal):c2?minVal:z-s-cylinderh; + //h=z-s-cylinderh; + + cylinderd2=c2?c2:c1; + + y2=is_list(x2)?c1-s>0?vC[0]?max(x2[1]-cylinderh-s,minVal):max(x2[1]-c1,minVal):max(x2[1]-s,minVal) + :is_undef(y2)?y1:c1-s>0?vC[0]?max(y2-cylinderh-s,minVal):max(y2-c1,minVal):max(y2-s,minVal); + x2=is_undef(x2)?x1 + :is_list(x2)?c1-s>0?vC[1]?max(x2[0]-cylinderh-s,minVal):max(x2[0]-c1,minVal):max(x2[0]-s,minVal):c1-s>0?vC[1]?max(x2-cylinderh-s,minVal):max(x2-c1,minVal):max(x2-s,minVal); + + + +CubePoints = [ + [-x1/2,-y1/2, 0 ], //0 + [ x1/2,-y1/2, 0 ], //1 + [ x1/2, y1/2, 0 ], //2 + [-x1/2, y1/2, 0 ], //3 + [-x2/2+x2d,-y2/2+y2d, h ], //4 + [ x2/2+x2d,-y2/2+y2d, h ], //5 + [ x2/2+x2d, y2/2+y2d, h ], //6 + [-x2/2+x2d, y2/2+y2d, h ]]; //7 + +CubeFaces = [ + [0,1,2,3], // bottom + [4,5,1,0], // front + [7,6,5,4], // top + [5,6,2,1], // right + [6,7,3,2], // back + [7,4,0,3]]; // left + + if(simple) T(center.x?0:x/2,center.y?0:y/2)hull() { + $info=false; + + if(r[0]==r[1]&&r[2]==r[3]&&r[1]==r[2])for(px=[-1,1]*(x-c1)/2,py=[-1,1]*(y-c1)/2)translate([px,py,0])Pille(l=z,d=max(minVal*4,c1),rad=rad,deg=deg,fs=fs,fn2=is_num(fnS)?fnS/4:undef,fn=fnC,center=center.z,name=name); + + else{ + translate([-x/2+r[0],-y/2+r[0],0])Pille(l=z,r=max(minVal,r[0]),rad=rad,deg=deg,fs=fs,fn2=is_num(fnS)?fnS/4:undef,fn=fnC,center=center.z,name=name); + translate([ x/2-r[1],-y/2+r[1],0])Pille(l=z,r=max(minVal,r[1]),rad=rad,deg=deg,fs=fs,fn2=is_num(fnS)?fnS/4:undef,fn=fnC,center=center.z); + translate([ x/2-r[2], y/2-r[2],0])Pille(l=z,r=max(minVal,r[2]),rad=rad,deg=deg,fs=fs,fn2=is_num(fnS)?fnS/4:undef,fn=fnC,center=center.z); + translate([-x/2+r[3], y/2-r[3],0])Pille(l=z,r=max(minVal,r[3]),rad=rad,deg=deg,fs=fs,fn2=is_num(fnS)?fnS/4:undef,fn=fnC,center=center.z); + + } + } + + else + T(center.x?0:x/2,center.y?0:y/2)translate([0,0,vC[0]||vC[1]?c1?c1/2:s/2:s/2+minVal/2-(center.z?z/2:hErr)])minkowski(){ + polyhedron( CubePoints, CubeFaces,convexity=5 ); + if(c1-s>0&&!optimize)rotate(a=90,v=vC)rotate(cRot)cylinder(c2?max(z-s-minVal,minVal):minVal,d1=c1-s,d2=cylinderd2-s,center=c2?false:true,$fn=round(fnC/4)*4,$fs=fs); + if(s){ + if(!optimize)sphere(d=s,$fn=round(fnS/4)*4,$fs=fs);//OctaH(d=s,n=fnS);// + else Pille(vSum(rad),deg=deg,rad=rad,d=c1,fs=fs,fn2=is_num(fnS)?fnS/4:undef,fn=fnC); + } + } + vx=((x1+s)-(x2+s))/2/(z-s); + vy=((y1+s)-(y2+s))/2/(z-s); + InfoTxt("Prisma",["SteigungX/Y",str(vx*100,"/",vy*100,"%"),"grad",str(atan(vx),"/",atan(vy),"°")],name); + if(vSum(rad)>z)Echo(str(name," Prisma Σrad>z ! ",vSum(rad)," ⇒ ",s),color="red"); + if(max(rad)*2>x)Echo(str(name," Prisma rad*2>x ! ",max(rad)*2," ⇒ ",s),color="red"); + if(max(r)*2>x)Echo(str(name," Prisma 2r>x ! ",max(r)*2," ⇒ ",c1),color="red"); + if(max(rad)*2>y)Echo(str(name," Prisma rad*2>y ! ",max(rad)*2," ⇒ ",s),color="red"); + if(max(r)*2>y)Echo(str(name," Prisma 2r>y ! ",max(r)*2," ⇒ ",c1),color="red"); + + if(s>c1&&c1)Echo(str(name," Prisma s>c1 ! ⇒ C-Rundung = s "),color="warning"); + +HelpTxt("Prisma",["x1",helpX1,",y1",helpY1,",z",helpZ,"c1",helpC1,"s",helpS,"x2",helpX2,"y2",helpY2,"x2d",x2d,"y2d",y2d,"rad",rad,"c2",c2,"vC",vC,"cRot",cRot,"fnC",fnC,",fnS",fnS,"fs",fs,"center",center,"deg",deg,"optimize",optimize,"name",name],help); +} + + +/** \name Spirale +\page Polygons + module Spirale() + * \brief creates a spiral polygon + * ## Examples: + * Spirale(); + * Spirale(center=0,end=false,diff=5,grad=360); + * Spirale(center=0,end=false,diff=-10,scale=0.5,hull=false,grad=360)circle(1); + * \param grad angle of rotation for the spiral + * \param diff difference for 360° + * \param radius,r1 start radius + * \param r2 if given calculates diff for grad + * \param rand the width of the spiral + * \param fn fraqments for the spiral path + * \param exp exponential change + * \param center centers diff around radius + * \param end if end circles applied false, true, 1 or 2 + * \param scale scale the end of the spiral + * \param name name + * \param help=true for help +*/ + +/* +Spirale(exp=1.0,diff=4,radius=10,grad=360,r2=undef,fn=200); +Tz(-.1)Color()circle(10); +Tz(-0.09)Color(.1)circle(6); +// */ + + +module Spirale(grad=400*1,diff=2,radius=10,r1,r2,rand=n(2),$d,detail,fn=fn,exp=1,center=false,hull=true,end=2,old=false,scale=1,name,help){ + detail=fn;//compatibility + advance=grad/detail; + rand=is_undef($d)?rand:$d; + $d=rand; + radius=is_undef(r1)?radius:center&&is_num(r2)?r1-r2/2:r1; + iDiff=is_undef(r2)?diff:center?(radius-r2)/grad*360*2:(radius-r2)/grad*360; + //diff=is_undef(r2)?diff:center?(radius-r2)/grad*360*2:(radius-r2)/grad*360; + + + + // * // recursive calculation + function expDiff(diff=iDiff)=assert(exp>0)pow( (abs(diff/360*grad)), exp )*sign(diff); + + function diffAdj(f=1)= + let(ratio=expDiff(iDiff*f)/(iDiff/360*grad)) + exp>1?ratio<=1+0.00000001?f: + diffAdj(f-f/100): + ratio>=1-0.00000001?f: + diffAdj(f+ f/100) + ; + + //echo(expDiff(iDiff*diffAdj())/(iDiff/360*grad),diffAdj()); + diff=is_undef(r2)?pow(abs(iDiff),1/exp)*sign(iDiff): + iDiff*(exp==1?1:diffAdj()); + // */ + + /* + diff=is_undef(r2)?pow(iDiff,1/exp): + pow(iDiff/360*grad,1/exp); +// */ + + //center=is_undef(r2)?center:false; + + +/* +pointsOld=!$children?center?[ + for(i=[0:fn])RotLang(i*-grad/fn,diff/2/360*grad+radius-rand/2-pow(i*(diff/360*grad)/(fn),exp)), + for(i=[fn:-1:0])RotLang(i*-grad/fn,diff/2/360*grad+radius+rand/2-pow(i*(diff/360*grad)/(fn),exp))] + :[// center=false +for(i=[0:fn])RotLang(i*-grad/fn,radius-rand/2-pow(i*(diff/360*grad)/(fn),exp)), +for(i=[fn:-1:0])RotLang(i*-grad/fn,radius+rand/2-pow(i*(diff/360*grad)/(fn),exp))] + :[0];// $children=true ⇒ deactivate point calculation +*/ + +path=[ + for(i=[0:fn])RotLang( + i*-grad/fn, (center?diff/2/360*grad:0) + radius- pow( abs(diff/360*grad)*i/fn,exp)*sign(diff) ) +]; + +points=concat( + pathPoints(points=[[ rand/2,0]], path=path, 2D=true, scale=scale), + pathPoints(points=[[-rand/2,0]], path=path, 2D=true, scale=scale, rev=true) + ); + + +if(!$children&&!old)rotate(center?-grad/2:0)union(){ + rotate(-90) polygon(points); + if(b(end,false)>0) rotate(0)T((center?diff/2/360*grad:0)+radius)circle(d=rand,$fn=0); + if(b(end,false)<0||end==2) rotate(grad)T((center?diff/2/360*grad:0)+radius-pow(abs(grad/360*diff),exp)*sign(diff))circle(d=rand*scale,$fn=0); + +} + +if(!$children&&old)// compatibility old version + for(i=[center?-grad/2:0:advance:(center?grad/2:grad)-minVal]){ + j=i+advance; + Color(i/((center?grad/2:grad)-minVal))hull(){ + rotate(i)T(radius-pow(i/360*diff,exp))circle(d=rand,$fn=36); + rotate(j)T(radius-pow(j/360*diff,exp))circle(d=rand,$fn=36); + } + } + +if ($children) for(i=[center?-grad/2:0:advance:(center?grad/2:grad)-minVal]){ + j=i+advance; + $idx=i; + if(hull) Color(i/((center?grad/2:grad)-minVal),$idxON=false) hull(){ + + rotate(i)T(radius-pow(i/360*diff,exp))children(); + rotate(j)T(radius-pow(j/360*diff,exp))union(){$idx=j;children();} + } + else { + if(i==0||i==-grad/2)rotate(i)T(radius-pow(i/360*diff,exp))children(); + rotate(j)T(radius-pow(j/360*diff,exp))children(); + + } + + + } + + //langold=( 2*radius-diff )* PI/360*grad;echo(langold); + lang=pathLength(path); + randEnd=end==true||b(end,false)>0?rand/2 + (end==2?rand/2*scale :0) : 0; + InfoTxt("Spirale", ["Länge ",lang+randEnd ],name); + + HelpTxt("Spirale",[ + "grad",grad, + "diff",diff, + "radius",radius, + "r1",r1, + "r2",r2, + "rand",rand, + "$d",$d, + //detail=",detail," + "fn",fn, + "exp",exp, + "center",center, + "hull",hull, + "end",end, + "old",old, + "scale",scale, + "name",name], + help); +} + + + + +module Box(x=8,y,z=5,d2,c=3.5,s=1.5,eck=4,outer=true,fnC=36,fnS=24,help){ + red=c>s?c:s; + + x=is_num(y)||outer?x: + Umkreis(eck,x-red)+red; + d2=is_undef(d2)?x: + outer?d2: + Umkreis(eck,d2-red)+red; + + hErr=s/2-cos(90/ceil(fnS/2))*s/2+.00001; // missing sphere piece + z=z+hErr*2; + + T(z=z/2-hErr) minkowski(){ + if(is_num(y))cube([x -red, y -red, z-s-minVal],center=true); + else cylinder(h=z -s -minVal, d1=x -red, d2=d2 -red, $fn=eck, center=true); + if(c>s)cylinder(minVal,d=c-s,center=true,$fn=fnC); + //OctaH(d=s,n=fnS); + sphere(d=s,$fn=fnS); + } + +HelpTxt("Box",["x",x,"y",y,"z",z,"d2",d2,"c",c,"s",s,"eck",eck,"outer",outer,"fnC",fnC,"fnS",fnS],help); +} + + + + + +module Kassette(r1=2,r2,size=20,h=0,gon=3,fn=fn,fn2=36,r=+0,grad=90,grad2=90,spiel=0.003,mitte=true,sizey=0,basis=1,2D=false,name,help) +{ + r2=is_undef(r2)?r1:r2; +HelpTxt("Kassette",["r1",r1,"r2",r2,"size",size,"h",h,"gon",gon,"fn",fn,",fn2=",fn2,"r",r,"grad",grad,"grad2",grad2,"spiel",spiel,"mitte",mitte,"sizey",sizey,"basis",basis,"2D",2D,"name",name],help); + if(help){ + echo("r1 r2 size — radius unten, oben und durchmesser"); + echo("h gon fn fn2 r — höhenzusatz, ecken, fn, fn2 des profils und eckradius"); + echo(" spiel mitten sizey name— , spielüberlappung Innenpolygon, mitten loch bei gon=2 und y-weite bei gon=4, name=name für Info"); + } + +sizey=sizey?sizey:is_list(size)?size.y:size; +size=is_list(size)?size.x:size; + + r1I=min(r1,size/2-2*r2);//unten innen radius when mitte=1 + points=concat( + kreis(r=r1,grad=-90,fn=fn2/4,rand=0,rot=-90,center=false,t=[size/2+r1,r1]), //r1 unten + [[r1+size/2,-basis]], //unten aussen + [[0,-basis]],//unten mitte + [mitte?[0,r1+r2+h]:[0,0]], //oben mitte + mitte?[[size/2-r2,r1+r2+h]]:Kreis(r=r1I,grad=-90,fn=fn2/4,rand=0,rot=+180,center=false,t=[size/2-r2*2-r1I,r1I]), + kreis(r=r2,rot=mitte?0:-90,grad=mitte?90:180,fn=mitte?fn2/4:fn2/2,rand=0,center=false,t=[size/2-r2,h+r1])// r2 oben + ); + + + if(2D)polygon(points,convexity=5); + else{ + + if(gon>2) + Rundrum(eck=gon,r=r,x=(size-r2*2)/(gon==4?1:2),y=(sizey-r2*2),fn=fn,grad=grad,grad2=grad2,help=0,name=name)intersection(){ + T(-size/2+r2)polygon(points,convexity=5); + if(mitte) translate([-r,-250])square(500); + } + + if(gon<3)RotEx(help=0,fn=fn)polygon(points,convexity=5); + + if(mitte&&gon>2){ + if(gon!=4)translate([0,0,-basis])rotate(gon==4?45:0)linear_extrude(basis+h+r2+r1,convexity=5) + Rund(r,fn=fn)circle(r=Umkreis(gon,(size-r2*2))/2+spiel,$fn=gon); + if(gon==4)translate([0,0,-basis])linear_extrude(basis+h+r2+r1,convexity=5)offset(spiel)Quad(x=size-r2*2,y=sizey-r2*2,grad=grad,grad2=grad2,r=r,help=0,name=0,fn=fn); + } + } +if(name)echo(str(is_bool(name)?"":"

    ",name," Kassette - Höhe=",h+r1+r2,"mm (+",basis," basis)")); + if(h<0)echo(str("

    ",name," Kassette h=",h,"mm ⇒ NEGATIV!")); + +} + +/** +\name Gewinde() +Gewinde is a preloader for GewindeV4 and presets +\param presets e.g. "M2" or "M6" - metric ISO, "BSW1" for ½", "BSW2" for ¾" - "Flasche" for PCO28 Flasche2 with p=4 +*/ module Gewinde( @@ -2958,31 +9613,37 @@ breite, rad1, rad2, winkel=60, -wand=+1, +wand, +dicke=1, mantel, h, gb, innen=false, grad=180*7, -start=fn/3,// Einfädelstrecke +start,// Einfädelstrecke +startL,//length start end, korrektur=true,// verbreiterung durch gangwinkel profil=false, fn2=4, -fn=fn, +fn, +fs=fs, +fa=fa, cyl=true, tz=0, konisch=0, center=true, rund=false, ratio, -spiel=.15, +spiel=.1, name, help, s,w=0,g=1,rot2=0,r1=0,detail=fn,name,preset=0,translate=[0,0,0],rotate=[0,0,0],d=0,gd=0,r=0,help,endMod=true,new ){ - +dicke=is_undef(wand)?dicke:wand; // backward compatibility + + $info=is_undef($info)?false:$info; iso_Gewinde=[ //name,pSteigung,dn ["M1",0.25,1], ["M1.2",0.25,1.2], @@ -3009,34 +9670,35 @@ s,w=0,g=1,rot2=0,r1=0,detail=fn,name,preset=0,translate=[0,0,0],rotate=[0,0,0],d other_Gewinde=[//search0, pSteigung,dn,winkel,name -["search","p-Steigung[1]","dn[2]","kern[3]","breite[4]","rad1[5]","rad2[6]","winkel[7]","name[8]"], // Spalten -["BSW1",1.814,20.955,20.955-0.640327*1.814*2,undef,0.13732908*1.814,0.13732908*1.814,55,"½-Zoll"],//halb Zoll -["BSW2",1.814,26.441,26.441-0.640327*1.814*2,undef,0.13732908*1.814,0.13732908*1.814,55,"¾-Zoll"],// 3/4 Zoll -["Flasche",3.18,27.43,24.95,.05,.4,.4,65,"PCO-28"],// Flasche 28mmHalsring -["Flasche2",4,27.43,24.95,.05,.4,.4,65,"PCO-28 P4"],// Flasche Badeschaum +["search","p-Steigung[1]","dn[2]","kern[3]","breite[4]","rad1[5]","rad2[6]","winkel[7]","name[8]","grad[9]"], // Spalten +["BSW1",1.814,20.955,20.955-0.640327*1.814*2,undef,0.13732908*1.814,0.13732908*1.814,55,"G½-Zoll"],//halb Zoll +["BSW2",1.814,26.441,26.441-0.640327*1.814*2,undef,0.13732908*1.814,0.13732908*1.814,55,"G¾-Zoll"],// 3/4 Zoll +["BSW3",1.337,16.66,16.66-0.640327*1.337*2,undef,0.13732908*1.337,0.13732908*1.337,55,"G⅜-Zoll"],// 3/8 Zoll +["Flasche" ,3.18, 27.43,24.95, 1, 0.4, 0.4, 40,"PCO-28 TPI8",810],// Flasche 28mmHalsring TPI=8 +["Flasche2" ,4.23, 27.43,24.95, 1, 0.4, 0.4, 40,"PCO-28 TPI6"],// Flasche Badeschaum TPI=6 ]; // Zeilennr für Suchbegriff [preset] zeile=preset[0]=="M"?search([preset],iso_Gewinde)[0]: search([preset],other_Gewinde)[0]; - - + + if(is_num(useVersion) && useVersion<19.88 && is_undef(new) || new==false){// old Version Echo(str("Using GewindeV2,useVersion=",useVersion),color="warning"); if($children)GewindeV2(dn=dn,s=s,w=w,g=g,winkel=winkel,rot2=rot2,r1=r1,kern=kern,fn=fn<20?fn:1,detail=detail,spiel=spiel,name=name,tz=tz,preset=preset,h=is_undef(h)?grad/360*p:h,translate=translate,rotate=rotate,d=d,gd=gd,r=r,center=center,help=help,p=p,endMod=endMod)children(); else GewindeV2(dn=dn,s=s,w=w,g=g,winkel=winkel,rot2=rot2,r1=r1,kern=kern,fn=fn<20?fn:1,detail=detail,spiel=spiel,name=name,tz=tz,preset=preset,h=is_undef(h)?grad/360*p:h,translate=translate,rotate=rotate,d=d,gd=gd,r=r,center=center,help=help,p=p,endMod=endMod); } else if(is_num(zeile)){ // presets - + //metric if(preset[0]=="M"){ GewindeV4( p=iso_Gewinde [zeile][1], dn=iso_Gewinde[zeile][2]+(innen?spiel*2:0), grad=grad,h=h,winkel=60,name=iso_Gewinde[zeile][0], - innen=innen,wand=wand,mantel=mantel,cyl=cyl,tz=tz,start=start, - end=end,fn=fn,fn2=fn2,center=center,rund=rund,ratio=ratio,spiel=spiel,profil=profil,help=help); + innen=innen,dicke=dicke,mantel=mantel,cyl=cyl,tz=tz,start=start, + end=end,fn=fn,fs=fs,fa=fa,fn2=fn2,center=center,rund=rund,ratio=ratio,spiel=spiel,profil=profil,help=help) if($children)difference(){ children(); if(innen)Tz(center?tz-iso_Gewinde[zeile][1]/2: @@ -3053,24 +9715,23 @@ other_Gewinde=[//search0, pSteigung,dn,winkel,name kern=is_undef(other_Gewinde[zeile][3])?undef:other_Gewinde[zeile][3]+(innen?spiel*2:0), breite=is_undef(breite)?other_Gewinde [zeile][4]:breite, rad1=is_undef(rad1)?other_Gewinde [zeile][5]:rad1, - rad2=is_undef(rad1)?other_Gewinde [zeile][6]:rad2, + rad2=is_undef(rad2)?other_Gewinde [zeile][6]:rad2 , winkel=other_Gewinde [zeile][7], - wand=wand,mantel=mantel,innen=innen,grad=grad,h=h, + dicke=dicke,mantel=mantel,innen=innen, + grad=is_undef(grad)?other_Gewinde [zeile][9]:grad, + h=h, start=start,end=end,center=center,profil=profil,fn2=fn2, - fn=fn,cyl=cyl,tz=tz,rund=rund,ratio=ratio,spiel=spiel, + fn=fn,fs=fs,fa=fa,cyl=cyl,tz=tz,rund=rund,ratio=ratio,spiel=spiel, name=other_Gewinde[zeile][8], - help=help); - + help=help)children(); + } } - - - } else{ info=$info; Polar(g,r=innen?g%2?0:180/g:0,name=false){ - $tab=$tab-1; + $tab=is_undef($tab)?0:$tab-1; $info=info; GewindeV4(p=p, dn=dn, @@ -3079,18 +9740,21 @@ other_Gewinde=[//search0, pSteigung,dn,winkel,name rad1=rad1, rad2=rad2, winkel=winkel, - wand=wand, + dicke=dicke, mantel=mantel, h=h, gb=gb, innen=innen, grad=grad, start=start,// Einfädelstrecke + startL=startL,// lenght start end=end, korrektur=korrektur,// verbreiterung durch gangwinkel profil=profil, fn2=fn2, fn=fn, + fa=fa, + fs=fs, cyl=cyl, tz=tz, konisch=konisch, @@ -3100,101 +9764,136 @@ other_Gewinde=[//search0, pSteigung,dn,winkel,name spiel=spiel, name=name, g=g, - help=help); + help=help) + if($children)difference(){ + children(); + if(innen)Tz((center?tz-p/2:tz)-0.01)cylinder((is_undef(h)?grad*p/360+p:h)+0.011,d=dn+spiel*2,$fn=fn); + } } - Echo(str("Gewinde preset=",preset," Not found!"),color="red",condition=preset); - if($children)difference(){ - children(); - if(innen)Tz(center?tz-p/2:tz-0)cylinder(is_undef(h)?grad*p/360+p:h,d=dn+spiel*2,fn=fn); - } - + Echo(str("Gewinde preset=",preset," Not found! \n BSW1 BSW2 \n Flasche Flasche2 M1-M30 "),color="red",condition=preset); + } - } +//GewindeV4(cyl=0,konisch=10); +//Gewinde(cyl=0,winkel=120,g=3); + module GewindeV4( -dn=6, -p=1, -kern, -breite, -rad1, -rad2, -winkel=60, -wand=+1, -mantel, -h, -gb, -innen=false, -grad=180*7, -start=fn/3,// Einfädelstrecke -end, -korrektur=true,// verbreiterung durch gangwinkel -profil=false, -fn2=4, -fn=fn, -cyl=true, -tz=0, -konisch=0, -center=true, -rund=false, -ratio, -spiel=.1,//unused used at Gewinde innen=true -g=1,// only for autosize +dn=6,// Diameter nominal +p=1,// Pitch per revolution +kern,// Core diameter (⇐ dn) +breite,// thickness of crest rounding +rad1, // rounding radius 1 (⇐ p g rund breite) +rad2,// rounding radius 2 (⇐ p g rund breite) +winkel=60,// inclusive thread angle e.g 29 for ACME or 55 for BSW can be list [10,40] for buttress +wand,// wall thickness (⇐ mantel) +dicke=1,// wall thickness (⇐ mantel) +mantel,// inner or outer shell diameter (↦ wand) +h, // height (↦ grad) +gb, // thread path height (⇐ p) +innen=false, // inner or outer thread +grad=180*7,// degres (⇐ h) +start,// Einfädelstrecke// primed start angle +startL,// length of start +end, // angle for primed End +endL, // length of end +korrektur=true,// verbreiterung durch gangwinkel// correction of profil angle according to pitch +profil=false, // show profile polygon used +fn2=4, // profile roundingfragments +fn,// thread fragments per revolution +fs=fs, +fa=fa, +cyl=true,// add cylinder (h,d=Kern); +tz=0, // move thread z +konisch=0,// tapered thread angle +center=true,// center thread +rund=false, // round thread (↦ rad1 rad2) +ratio,// ratio between threads and space (↦ breite) +spiel=.1,//unused used at Gewinde innen=true// clearance only for presets inner threads +g=1,// number thread starts only for autosizing name, help ){ + $p=p; + konisch=innen?konisch:-konisch; halbWinkel=is_list(winkel)?winkel:[winkel/2,winkel/2]; Kwinkel=[90-halbWinkel[0],90-halbWinkel[1]];// Komplement winkel //winkel=is_list(winkel)?[90-winkel[0],90-winkel[1]]:[90-winkel/2,90-winkel/2]; gver=pow(g,1.5);//autocalc for g - center=is_num(center)?center:center==true?1:0; - start=round(start); - end=is_undef(end)?start:round(end); - kern=is_undef(kern)?innen?round((dn-p*1.08/gver)*100)/100:round((dn-p*1.225/gver*+1)*100)/100:kern; + center=is_num(center)?center:center==true?1:0; + + + kern=is_undef(kern)? + winkel==60?innen?round((dn-p*1.08/gver)*100)/100:round((dn-p*1.225/gver*+1)*100)/100 + :runden(innen?dn-p/g/1.6/tan(max(halbWinkel)):dn-p/g/1.42/tan(max(halbWinkel)),2) + :kern; + $kern=kern; dn=is_undef(dn)?innen?round((kern+p*1.08/gver)*100)/100:round((kern+p*1.225/gver)*100)/100:dn; - wand=is_undef(mantel)?innen?wand:wand>kern/2?0:wand:abs(mantel-kern)/2; + $dn=dn; + fn=is_undef(fn)||fn==0?fs2fn(r=max(kern,dn)/2,fs=fs,minf=36,fa=fa):ceil(fn); + start=ceil(is_undef(start)?is_num(startL)?fn/360*gradB(b=startL,r=innen?kern/2:dn/2):fn/3:fn/360*start); + end=is_undef(end)?start:is_num(endL)?fn/360*gradB(b=endL,r=innen?kern/2:dn/2):ceil(fn/360*end); + dicke=is_undef(wand)?dicke:wand; + wand=is_undef(mantel)?innen?dicke + :dicke>kern/2?0:dicke + :max(.001,(innen?mantel-dn:kern-mantel)/2); + d1=innen?-kern:dn;//Gewindespitzen d2=innen?-dn:kern;//Gewindetäler grad=max(//windungen - is_undef(h)?grad-(grad%(360/fn)):(h-p)/p*360-(((h-p)/p*360)%(360/fn)), + is_undef(h)?grad-(grad%(360/fn)):(h-p)/p*360-(((h-p)/p*360)%(360/fn)-360/fn), 360/fn*(start+end)) ; - mantel=is_undef(mantel)?innen?d2-wand*2:wand?kern-wand*2:kern/2+0.0001:innen?-max(mantel,0.0001):max(mantel,0.0001);//innenloch /aussenmantel + winkelP=atan(p/((d1+d2)/2*PI));//Steigungswinkel profilkorrekturY=korrektur?1/sin(90+winkelP):1; gb=is_undef(gb)?p/profilkorrekturY:gb; // gangBreite axial + + //innenloch /aussenmantel + mantel=(is_undef(mantel)?innen?d2-wand*2 + :wand?kern-wand*2 + :kern/2+0.0001 + :innen?-max(mantel,dn+0.0001) + :max(mantel,0.0001)) + ( 2*p*tan(abs(konisch)) ) ; + $mantel=mantel; gangH=(d1-d2)/2; // gang Höhe radial (H) + $gangH=gangH; h=grad*p/360+p; + $h=h; flankenBreite=[tan(halbWinkel[0])*gangH,tan(halbWinkel[1])*gangH]; - - breite=is_undef(ratio)||!ratio?is_undef(breite)?gb/g/8: + gi=grad<360/g?1:g; + breite=runden( + is_undef(ratio)||!ratio?is_undef(breite)?gb/gi/8: breite: - (gb/g-flankenBreite[0]-flankenBreite[1])/2*(b(ratio,false)); + (gb/gi-flankenBreite[0]-flankenBreite[1])/2*(b(ratio,false)) + ,8); // runden - breite2=gb/g -breite -flankenBreite[0] -flankenBreite[1]; + breite2=gb/gi -breite -flankenBreite[0] -flankenBreite[1]; rad1Max=min(breite /2/tan(Kwinkel[0]/2),breite /2/tan(Kwinkel[1]/2)); - rad2Max=min(breite2/2/tan(Kwinkel[0]/2),breite2/2/tan(Kwinkel[1]/2)); + rad2Max=min(breite2/2/tan(Kwinkel[0]/2),breite2/2/tan(Kwinkel[1]/2))-.005; - Echo(str(name," Gewinde rad1 zu groß",rad1,">",rad1Max),color="red", + Echo(str(name," Gewinde rad1 zu groß ",rad1,">",rad1Max),color="red", condition=is_num(rad1)&&rad1>rad1Max); - Echo(str(name," Gewinde rad2 zu groß",rad2,">",rad2Max),color="red", + Echo(str(name," Gewinde rad2 zu groß ",rad2,">",rad2Max),color="red", condition=is_num(rad2)&&rad2>rad2Max); rad1=min(rad1Max,b(rund,false)==1||b(rund,false)==2?rad1Max: - is_undef(rad1)?p/20/g: + is_undef(rad1)?p/20/gi: rad1); rad2=min(rad2Max,b(rund,false)==1||b(rund,false)==3?rad2Max: - is_undef(rad2)?p/10/g: + is_undef(rad2)?p/10/gi: rad2); - step=180/max(start,end,1); + stepStart=180/max(start,1); + stepEnd=180/max(end,1); + InfoTxt(innen?" Innengewinde ":" Außengewinde ",[ @@ -3202,6 +9901,7 @@ InfoTxt(innen?" Innengewinde ":" Außengewinde ",[ "Steigung",p, "Kern",kern, "Mantel",mantel, + "Wanddicke",wand, "Winkel",winkel[0]==winkel[1]?halbWinkel[0]*2:halbWinkel, "Gangwinkel",winkelP, "h",h, @@ -3210,16 +9910,16 @@ str(grad/360," Windungen ("),str(grad,"°)"), ,name); /*tangYold=[rad1*sin(winkel[0])-tan(90-winkel[0])*(rad1-cos(winkel[0])*rad1), - rad1*sin(winkel[1])-tan(90-winkel[1])*(rad1-cos(winkel[1])*rad1)];//*/ + rad1*sin(winkel[1])-tan(90-winkel[1])*(rad1-cos(winkel[1])*rad1)];// */ tangY=[tan(Kwinkel[0]/2)*rad1,tan(Kwinkel[1]/2)*rad1]; -Echo(str(name," Gewinde Überlappung! breite2",negRed(breite2)),color=breite==0?"warning":"red",condition=0>=breite2); +Echo(str(name," Gewinde Überlappung! breite2=",negRed(breite2)),color=breite==0?"warning":"red",condition=0>=breite2); //Echo(str(name," Gewinde Zero breite2",negRed(breite2)),color="red",condition=0==breite2); Echo(str(name," Gewinde breite=",breite," is bigger (",(tangY[0]+tangY[1]), ") rad1(",rad1,"),rad1 max=",rad1Max, - " p/16= ",p/16),condition=tangY[0]+tangY[1]>breite); + " p/16= ",p/16),condition=runden(tangY[0]+tangY[1],8)>breite); //,if (breite==0&&rad1>p/16)echo(str("",name," Gewinde breite=0 rad1>p/16= ",p/16)); @@ -3231,18 +9931,21 @@ HelpTxt("Gewinde", ,"rad1",rad1 ,"rad2",rad2 ,"winkel",halbWinkel[0]==halbWinkel[1]?halbWinkel[0]*2:halbWinkel -,"wand",wand +,"dicke",dicke ,"mantel",abs(mantel) ,"h",h ,"gb",gb // gang breite gesamt ,"innen",innen ,"grad",grad -,"start",start// Einfädelstrecke +,"start",start // Einfädelstrecke in grad +,"startL",startL // length start ,"end",end ,"korrektur",korrektur// verbreiterung durch gangwinkel ,"profil",profil // 2D Ansicht ,"fn2",fn2 ,"fn",fn +,"fs",fs +,"fa",fa ,"cyl",cyl ,"tz",tz ,"konisch",konisch @@ -3250,20 +9953,30 @@ HelpTxt("Gewinde", ,"rund",rund ,"ratio",ratio ,"spiel",spiel +,"g",g ,"name",name ],help); -points=[ - for(i=[0:max(start+1,end+1,5)])vollwelle(fn=fn2,l=gb,h=start?gangH*(0.5+sin(i*step-90)/2):gangH,r=rad1,r2=rad2,tMitte=breite, - grad=start?[max(Kwinkel[0]*sin(i*.5*step+0),1),max(Kwinkel[1]*sin(i*.5*step+0),1)]: +pointsStart=[ + for(i=[0:max(start +1,5)])vollwelle(fn=fn2,l=gb,h=start?gangH*(0.5+sin(i*stepStart-90)/2):gangH,r=rad1,r2=rad2,tMitte=breite, + grad=start?[max(Kwinkel[0]*sin(i*.5*stepStart+0),1),max(Kwinkel[1]*sin(i*.5*stepStart+0),1)]: Kwinkel, - grad2=[-konisch,konisch],extrude=d2/2,x0=mantel/2,xCenter=-1) + grad2=[-konisch,konisch],extrude=d2/2,x0=mantel/2,xCenter=-1,minF=fn2) ]; +pointsEnd=[ + for(i=[0:max(end +1,5)])vollwelle(fn=fn2,l=gb,h=end?gangH*(0.5+sin(i*stepEnd-90)/2):gangH,r=rad1,r2=rad2,tMitte=breite, + grad=end?[max(Kwinkel[0]*sin(i*.5*stepEnd+0),1),max(Kwinkel[1]*sin(i*.5*stepEnd+0),1)]: + Kwinkel, + grad2=[-konisch,konisch],extrude=d2/2,x0=mantel/2,xCenter=-1,minF=fn2) + ]; + +points=concat(pointsStart,pointsEnd); + -profilnr=start; +profilnr=max(start+1,5); pointskorr=[for(i=[0:len(points[profilnr])-1])[points[profilnr][i][0],points[profilnr][i][1]*profilkorrekturY]]; -detail=fn*grad/360; +detail=round(fn*grad/360); function faces1(points,start=0)=[[for(i=[0:len(points)-1])i+start]];//bottom @@ -3294,36 +10007,88 @@ function faces6(points,start=+0)=[for(i=innen?[len(points)-1]:[-1]) function RotEx(rot=0,points=points,verschieb=tan(konisch),steigung=p,detail=fn,start=start,end=end)= [for(rotation=[0:detail*rot/360])for(i=innen?[0:len(points[0])-1]:[len(points[0])-1:-1:0]) [ // Punkt -if(rotation0) Tz(-.01)cylinder(h=h+.02,d1=d2-wand*2,d2=(d2-wand*2)*scaleGrad(grad=90+konisch,h=h+.02,r=d2/2-wand),$fn=fn,$fs=fs,$fa=fa); + } + } + //Ring(h=h,rand=wand,d=abs(d2),cd=innen?-1:1); } + } +children(); } + +/** \name Coil \page Objects +Coil() creates a coil +\param r radius of the coil +\param d diameter of the coil wire +\param r2 end radius for conical coils +\param od id optional outer inner diameter ↦ r and d +\param grad windings +\param p pitch +\param h height ↦ p or grad +\param points allows other profiles as points +\param twist twist profile towards end +\param scale profile towards end +\param fn fs fs fraqment number size angle +\param fn2 fragmentsize for d (if undef then fs fa is used) +\param center centers coil +\param rot rotate profile +\param open creates end surfaces +\param rev revers path +\param convexity convexity of polyhedron +\param name name +\param help help +*/ + +//Coil(h=20,scale=1,center=+1,grad=undef,fn2=4,rot=45,rev=0); + + module Coil( r=20, d=5, @@ -3333,35 +10098,60 @@ id, grad=3*360, p, pitch=10, +h, points, twist=0, scale=1, -fn=fn,fn2=36, -open=true, +fn,fn2,fs=fs,fa, +center=true, +rot=0, +open=true,//open Path +rev=true, +convexity=15, +name, help){ d=is_num(od)&&is_num(id)?(od-id)/2 : d; r=is_undef(points)?is_num(od)?(od-d)/2:is_num(id)?(id+d)/2:r:r; r2=is_undef(r2)?r:r2; -points=is_undef(points)?kreis(d=d,rand=0,fn=fn2):points; - -Echo("Coil using points od id or d can't compute",color="warning",condition=points&&od||points&&id); +fn=is_undef(fn)||fn<1?fs2fn(fs=fs,r=max(abs(r),abs(r2)),fa=fa,minf=36):fn; +fn2=is_undef(fn2)||fn<4?fs2fn(fs=fs,r=d/2,minf=12):fn2; +p=is_undef(p)?pitch:p; +$d=d; +Echo("Coil using points - od, id, h or d can't compute",color="warning",condition=points&&od||points&&id); Echo("Coil intersecting",color="warning",condition=!points&&norm([(r-r2)/grad*360,pitch])":"",name," DRing dist=",id+r[0]*2+d,"mm innen h=",l+2*r[0]+id/2,"mm")); -HelpTxt("DRing",[ - "d",d, - "id",id, - "r",r, - "l",l, - "grad",grad, - "fn",fn, - "centre",center, - "name",name] - ,help); -} - - - -module Nut(e=2,es=10,a=6,b=6,base=1,h=1,s,center=true,shift=0,winkel,grad,name,help){ - grad=is_undef(winkel)?assert(grad!=0)grad:assert(winkel!=0)winkel; - s=is_undef(s)?is_num(grad)&&is_num(b)?e*(a+b-2*h*tan(90+grad)): - is_undef(es)?assert( is_num(b) && is_num(a),"define a + b")a+b: - e * es: - s; - - es=is_num(grad)&&is_num(b)?a+b-2*h*tan(90+grad): - s/e; - - b=is_undef(grad)?is_undef(b)?es-a: - b: - 2*(h*tan(90+grad))+es-a; - - - points=[[s,base],[s,0],[0,0],[0,base], -for(i=[0:e-1])each[ - [b/2+i*es,base], - [es/2-a/2+shift+i*es,h+base], - [es/2+a/2+shift+i*es,h+base], - [(es-b/2)+i*es,base]] - ]; - path=[[for(i=[0:len(points)-1])i]]; - // echo (points,path); - - - translate(center?[-s/2,-base]:[0,0]) polygon(points,path,convexity=10); - winkel1=atan(h/(es/2-a/2-b/2+shift)); - winkel2=atan(h/(es/2-a/2-b/2-shift)); - - InfoTxt("Nut",concat(["winkel",str(winkel1,shift?str(" /",winkel2):"","°"), - "Länge",s, - "Abstand",es], - "Abstand a",negRed(es-a), - "Abstand b",negRed(es-b), - grad?["b",negRed(b)]:[]) - ,name); - - HelpTxt("Nut",[ - "e",e, - "es",es, - "a",a, - "b",b, - "base",base, - "h",h, - "s",s, - "center",center, - "shift",shift, - "grad",grad, - "name",name], - help); -} - - -// SicherungsRing -module SRing(e=4,id=3.5,od=10,h=.8,rand=n(3),reduction=.5,schlitz=-17,help){ -$info=false; -intersection(){ - LinEx(h,.2,scale=1.05)Rund(0.3)difference(){ - Kreis(od/2); - Rund(0.5) Stern(e,od/2-rand,id/2-reduction-1,mod=100,delta=schlitz); - rotate(180+180/e)intersection_for(i=[0:e-1])rotate(i*360/e)T(reduction)Kreis(id/2,fn=e*15); - } - Pille(h,d=od,rad=.3,center=false); -} -HelpTxt("SRing",[ -"e",e, -"id",id, -"od",od, -"h",h, -"rand",rand, -"reduction",reduction, -"schlitz",schlitz,] -,help); -} - - -module Bevel(z=0,r=.5,on=!$preview,grad=45,fillet=0,fn=12,messpunkt=messpunkt,help){ - - diff=fillet?sin(grad)*r:tan(grad)*r; +module SpiralCut(h=20,ir=1,or=50,width=.03,x,t=0,grad,cuts,radial=true,line,layer,axial,name,help){ + t=is_num(t)?[0,0,t]:t; + x=abs(is_undef(x)?width:x); + radial=is_undef(axial)?radial:!axial; + + layer=is_undef(layer)?l(1):layer; + line=is_undef(line)?n(1): + max(line,.1); + + r=min(ir,or); + sizeY=abs(or-ir); + + cuts=is_undef(cuts)?radial?ceil(h/layer): + floor(360/gradB(b=line*2+x,r=r + line/2)): + floor(cuts); + + winkel=is_undef(grad)? radial? gw: + 360/cuts: + grad; - if(on)difference(){ +Echo("outer diametern <= inner!",color="warning",condition=ir>=or); + + + if(radial) + if($children)difference(){ children(); - minkowski(convexity=5){ - difference(){ - Tz(z>0?500+z-diff:-500+z+diff) cube(1000,true); - children(); - } - if(!fillet)R(z>0?0:180)Kegel(d1=0,d2=r*2,fn=fn,grad=grad,name=false); - else Tz(z>0?r:-r)R(z>0?180:0)RotEx(cut=1,fn=fn)Kehle(2D=true,rad=r,fn2=fn); - } -}else -children(); + translate(t)for(i=[0:cuts-1])rotate(i*winkel)T(-x/2,r,i*layer)cube([x,sizeY,layer]); + } + else translate(t)for(i=[0:cuts-1])rotate(i*winkel)T(-x/2,r,i*layer)cube([x,sizeY,layer]); + else if($children)difference(){ // axial cuts + children(); + translate(t)for(i=[0:cuts-1])rotate(i*winkel)T(-x/2,r+line*sign(or-ir),0){ + if(h)cube([x,sizeY-line,h]); + else square([x,sizeY-line]); + } + } + else translate(t)for(i=[0:cuts-1])rotate(i*winkel)T(-x/2,r+line*sign(or-ir),0){ + if(h)cube([x,sizeY-line,h]); + else square([x,sizeY-line]); + } + + if($preview)if(!radial){ + if(or>ir)color("chartreuse",alpha=.3)translate(t) rotate(90)%cylinder(max(.01,h),r=r,$fn=cuts); + else color("skyblue",alpha=.3)translate(t) rotate(90)%Ring(max(.01,h),r=r-line,rand=-(sizeY-line),fn=cuts,name=false,help=false); + } -if (messpunkt){ -%Grid(e=[2,2,1],es=is_bool(messpunkt)?10:messpunkt,name=false)Tz(z)if(!fillet)color("orange",alpha=.75){ - R(z>0?180:0)Kegel(d2=0,d1=r*2,fn=fn,grad=grad,name=false); - R(z>0?0:180)cylinder(.5,r=r*1,$fn=fn); -} - else color("green",alpha=.75)R(z>0?180:0)Tz(-r+diff)RotEx(cut=1,fn=fn)Kehle(2D=true,rad=r,fn2=fn,spiel=.5); +if(radial)InfoTxt("SpiralCut — Radial",["Winkel",winkel,"Layer",layer,"Cuts",cuts,"width",x,"ir",ir,"or",or],name); +else InfoTxt("SpiralCut — Axial",["Winkel",winkel,"line",line,"Cuts",cuts,"width",x,"ir",ir,"or",or],name); -%Tz(z)if(!fillet)color("orange",alpha=.75){ - R(z>0?180:0)Kegel(d2=0,d1=r*2,fn=fn,grad=grad,name=false); - R(z>0?0:180)cylinder(.5,r=r*1,$fn=fn); -} - else color("green",alpha=.75)R(z>0?180:0)Tz(-r+diff)RotEx(cut=1,fn=fn)Kehle(2D=true,rad=r,fn2=fn,spiel=0.5); -} -HelpTxt("Bevel",[ - "z",z, - "r",r, - "on",on, - "grad",grad, - "fillet",fillet, - "fn",fn, - "messpunkt",messpunkt] - ,help); - -} - -module SpiralCut(layer=l(1),h=12,x=.025,ir=1,or=5,winkel,name,help){ - - winkel=is_undef(winkel)? 360-360/PHI:winkel ; - cuts=ceil(h/layer)-1; - - for(i=[0:cuts]){ - rotate(i*winkel)T(-x/2,ir,i*layer)cube([x,or-ir,layer]); - } - -InfoTxt("SpiralCut",["Winkel",winkel,"Layer",layer,"Cuts",cuts],name); - HelpTxt("SpiralCut",[ - "layer",layer, "h",h, - "x",x, "ir",ir, "or",or, - "winkel",winkel, + "width",x, + "t",t, + "grad",winkel, + "cuts",cuts, + "radial",radial, + "line",line, + "layer",layer, "name",name], help); } +/// creates a zylinder with sin waveform surface + + +module Zylinder(h=20,r=10,d,fn,fnh,grad=360,grad2=89,f=10,f2=5,f3=0,a=.5,a3=0,fz=0,az=0,deltaFz=0,deltaF=0,deltaF2=0,deltaF3=0,twist=0,winkelF3=0,scale=+1,sphere=0,lz,altFaces,center=false,lambda,fnE,name,help){ + +altFaces=is_undef(altFaces)?grad==360?6:1:altFaces; + + a=is_undef(a)?0:a; + r=is_undef(d)?is_undef(r)?0: + r: + d/2; + lambda=is_list(lambda)?lambda:[lambda,lambda]; + f=is_undef(lambda[0])?is_undef(f)?0: + f: + round(PI*2*abs(r)/lambda[0]); + f2=is_undef(lambda[1])?is_undef(f2)?0: + f2: + round(abs(h)/lambda[1]*2)/2; + fn =max(is_undef(fn) && is_undef(fnE)?f *2 : is_undef(fnE)?fn :fnE*f ,3); + fnh=max(is_undef(fnh) && is_undef(fnE)?f2 *2 : is_undef(fnE)?fnh :fnE*f2,1); + + ifn=grad==360?fn +0:fn; + + stepRot=grad/ifn; + stepH=h/fnh; +InfoTxt("Zylinder",["f",f,"f2",f2,"a",a,"lamda f",(2*PI*r)/f,"λ-f2",h/f2,"λ-f3",(2*PI*r)/f3,"λ-fz",h/fz,"r",str(r+a+a3+az,"/",r-a-a3-az),"d",str((r+a+a3+az)*2,"/",(r-a-a3-az)*2)],name); + +points=[for(z=[0:fnh],rot=[0:ifn])RotLang( + rot=rot*stepRot+twist*z/fnh+winkelF3*sin(rot*stepRot*f3+deltaF3), + l=(1+(scale-1)*z/fnh)*(a*cos(rot*stepRot*f+deltaF)*cos(z*f2*360/fnh+deltaF2)+az*sin(z*fz*360/fnh+deltaFz)), + lz=lz, + z=sphere?undef:z*stepH, + e=z*grad2/fnh + )+ +RotLang( + rot=rot*stepRot+twist*z/fnh, + l=(1+(scale-1)*z/fnh)*(r+a3*cos(rot*stepRot*f3)), + lz=h, + z=sphere?undef:0,//z*stepH, + e=z*grad2/fnh + ) + +]; +//echo(points); +//Points(points); + +faces=[ +if(altFaces==0)each[for(i=[-1:len(points)-fn-2])[i,i+1,i+2+fn,i+fn+1]],//0 +if(altFaces==1)each[for(i=[0:1:len(points)-ifn -3])each[ //1 + if(i%2)[i,i+ifn+2,i+ifn+1]else [i,i+1,i+ifn+1] , + if(i%2)[i+0,i+1,i+ifn+2] else [i+1,i+ifn+2,i+ifn+1] , + //if(i=180?e.x:e.x+1; + + +InfoTxt("Knurl",["knurls",e,"size",realSize,"deg",[for (i=[0:len(sizeZ)-1])str("\n",atan2(-sizeZ[i],realSize.x/2+delta[i%len(delta)].x),"° | ",atan2(-sizeZ[i],(realSize.y/2+delta[i%len(delta)].y)),"°")],"edge",str((180-360/e.x),"°"),"CordDist",depthCord],name); + +function KnurlP(r=10,h=20,depth=1,e=[10,10],scale=1,scaleZ=1,twist=0,grad=360,delta=[0,0],alt=0,depthCord=depthCord)=[ +let( + cP=grad>=180?0:1, //centerPoint + //alt=is_list(alt)?alt:[1], + depth=is_list(depth)?depth:[depth], + delta=is_list(delta[0])?delta:[delta], + step=grad/e.x, + stepZ=h/e.y/2, + scaleRot=scaleZ, + rot=grad/e.x/2 + ) + for(z=[0:e.y*2]) + let( + r=scale==1?r:r-r*(1-scale)/e.y/2*z, + + stepZ=scaleZ==1?stepZ:stepZ-stepZ*(1-scaleZ)/e.y/2*z/2, + depth=scaleZ==1?depth:depth-depth*(1-scaleZ)/e.y/2*z/2, + delta=scaleZ==1?delta:delta-delta*(1-scaleZ)/e.y/2*z/2, + stepRot=scaleRot==1?twist/e.y/2*z:twist/e.y/2*z-twist/e.y/2*(1-scaleRot)/e.y/2*z/2 + )each[ + if(z%2==0&&cP==1)[0,0,z*stepZ],// center + if(z%2) for(i=[0:grad==360?(e.x -1):e.x]) + let( + rot=(i=180?fBody:fBody2 +); + +polyhedron(points,faces,convexity=convexity); +HelpTxt("Knurl",["r",r,"h",h,"size",size,"depth",depth,"e",e,"scale",scale,"scaleZ",scaleZ,"twist",twist,"grad",grad,"delta",delta,"alt",alt,"convexity",convexity,"name",name],help); +} + +/** \name KnurlTri +\page Objects +KnurlTri() creates a triangle knurled cylinder or cone + +\param e number of sides of the base polygon and levels +\param r radius of base polygon +\param h height of knurl +\param depth height of surface tetrahedrons +\param deltaH move center in Z +\param scale scales +\param lambda size tetrahedron +*/ + +//KnurlTri(); + + +module KnurlTri(e=[16,9],r=10,h=30,depth=[1,+1],deltaH=[0,0],scale=1,lambda,name,help){ +lambda=is_num(lambda)?[lambda,lambda*(sqrt(3)/2)]:lambda; +e=is_undef(lambda)?is_list(e)?e:[e,round(h/sqrt((sehne(r=r,n=e)*sqrt(3)/2)^2 - (r-Inkreis(e,r))^2 ) )] + : [round(360/gradS(s=lambda.x,r=r)),round(h/lambda.y)]; +s=sehne(r=r,n=e[0]); +depth=is_list(depth)?depth:is_undef(depth)?s*sqrt(6)/3*[1,1]:[depth,depth]; +deltaH=is_list(deltaH)?deltaH:[deltaH,deltaH]; +winkel1=360/e[0]; +levelH=h/e[1]; + + +ir=Inkreis(e[0],r); +InfoTxt("KnurlTri",["Sehne",s,"winkel",2*atan2(s/2,norm([r-ir,levelH])),"Triangle Radius",str(norm([r-ir,levelH])/1.5,"/",s*sqrt(3)/3),"depth",depth,"e",e,"levelH",levelH],name); +HelpTxt("KnurlTri",["e",e,"r",r,"h",h,"depth",depth,"deltaH",deltaH,"scale",scale,"lambda",lambda],help); + +points=[ +for(level=[0:e[1]]) +let( +ri=r+r*(scale-1)/e[1]*level, +hCell=norm([ri - Inkreis(e[0],r+r*(scale-1)/e[1]*(level+1)) , levelH] ), +//hCell2=norm([Inkreis(e[0],ri) - r+r*(scale-1)/e[1]*(level+1) , levelH] ), +depth=depth+depth*(scale-1)/e[1]*level, +tilt1=atan2( Inkreis(e[0],ri)-(r+r*(scale-1)/e[1]*(level+1)), levelH ), +tilt2=atan2( ri - Inkreis(e[0],(r+r*(scale-1)/e[1]*(level+1))), levelH ), +zero1=[-sin(tilt1)*(hCell/3+deltaH[0]),cos(tilt1)*(hCell/3+deltaH[0])], +zero2=[-sin(tilt2)*(hCell/1.5+deltaH[1]),cos(tilt2)*(hCell/1.5+deltaH[1])], +extr1=[cos(tilt1)*depth[0],sin(tilt1)*depth[0]], +extr2=[cos(tilt2)*depth[1],sin(tilt2)*depth[1]] +) + +each[ + each arc(r=ri,fn=e[0]-1,deg=360-winkel1,z=level*levelH,rot=level%2?+0:winkel1/2), + if(level0 +rotDeg=[degC,-degC];// rotate fillets + +irad=[ +is_undef(rad[0])?min(maxRad[0],abs(hc/2/tan(deg[0]/2)) ):min(max(0,rad[0]),maxRad[0]), +is_undef(rad[1])?min(maxRad[1],abs(hc/2/tan(deg[1]/2)) ):min(max(0,rad[1]),maxRad[1]) +]; + +center=is_list(center)?center:[1,1,1]*b(center,false); + + +r2=[ + abs(deg[0])==90?r[0]+irad[0]*sign(deg[0]): + r[0]+h2[0]*tan(deg[0]), + abs(deg[1])==90?r[1]+irad[1]*sign(deg[1]): + r[1]+h2[1]*tan(deg[1]) +]; +iext=is_list(extrude)?extrude:is_num(extrude)?[extrude,extrude]:extrude?[500,500]:[0,0]; +extrude=[r2[0]>0?iext[0]:0,r2[1]>0?iext[1]:0]; +ifn360=fn?fn:fs2fn(fs=fs,r=max(r2[0],r2[1],max(r)) ); +ifn=fn?ceil(fn/2)-1:fs2fn(fs=fs,r=max(r2[0],r2[1],max(r)),grad=ly?90:180)-1; + +radFn=[fs2fn(fs=fs,fa=fa,r=irad[0],grad=deg[0]-degC,minf=3),fs2fn(fs=fs,fa=fa,r=irad[1],grad=deg[1]+degC,minf=3)]; + + +// WIP move fillets for tangential +delta=[irad[0]*tan(rotDeg[0]/2) * [sin(deg[0]),cos(deg[0]) ],irad[1]*tan(rotDeg[1]/2) * [sin(deg[1]),cos(deg[1]) ]]; +radDeltaH=[tan(deg[0]/2)*irad[0],tan(deg[1]/2)*irad[1]]+[delta[0].y,delta[1].y]; +radDeltaX=-[delta[0].x,delta[1].x]; + +Echo(str("d is list and rad>0 WIP not fully implemented! degC=",degC,"°"),color="warning",condition=d[0]!=d[1]&&max(irad)>0); + +Echo(str(name," Loch h2=",h2," to big for h=",h," min h=",vSum(h2)),condition=h-vSum(h2)<0); + +Echo(str(name," Loch h2=",ih2," to big for deg=",deg," with r=",r," ⇒ limited to h2=",h2),color="warning",condition=min(deg)<0&&(r[0]hc+1e-16-abs(radDeltaH[1])||vSum(radDeltaH)>hc+1e-16); + +// INFO +hCinfo=hc-vSum(radDeltaH);// needs checking +degCinfo=max(irad)&°C?str(degC," ! WIP"):degC; + +InfoTxt("Loch",concat(["d",[r2[0],r,r2[1]]*2,"length-X",[r2[0]*2+lx,r*2+lx*[1,1],r2[1]*2+lx],"centerH",hCinfo],d[0]-d[1]?["degC",str(degCinfo,"°")]:[]),name); + +HelpTxt("Loch",["h",h,"h2",h2,"d",d,"l",l,"d2",d2,"deg",deg,"rad",rad,"extrude",extrude,"center",center,"fn",fn,"fs",fs,"fa",fa,"cuts",cuts,"2D",2D,"name",name],help); + +function langL(r=5,l=0,z=undef,fn=ifn,fs=0,fa=fa)=l&&!ly?concat( + arc(r=r,deg=180,fn=fs?fs2fn(r=r,grad=180,fa=fa,fs=fs):fn,t=[0,0],rot=90,z=z), + arc(r=r,deg=180,fn=fs?fs2fn(r=r,grad=180,fa=fa,fs=fs):fn,t=[l,0],rot=-90,z=z) + ) + :ly?concat( + arc(r=r,deg=90,fn=fs?fs2fn(r=r,grad=90,fa=fa,fs=fs):fn,t=[l,ly],rot=0,z=z), + arc(r=r,deg=90,fn=fs?fs2fn(r=r,grad=90,fa=fa,fs=fs):fn,t=[0,ly],rot=90,z=z), + arc(r=r,deg=90,fn=fs?fs2fn(r=r,grad=90,fa=fa,fs=fs):fn,t=[0,0],rot=180,z=z), + arc(r=r,deg=90,fn=fs?fs2fn(r=r,grad=90,fa=fa,fs=fs):fn,t=[l,0],rot=-90,z=z) + ) + :arc(r=r,deg=360-360/(ifn360),fn=ifn360-1,z=z); + +stepRad=[(deg[0]-degC)/radFn[0],(deg[1]+degC)/(radFn[1])]; + + + +points=concat( + extrude[0]?langL(r2[0],l,-extrude[0]):[], // ext + langL(r2[0],l,0), // base + // center round bottom + irad[0]? + [for(i=[radFn[0]:-1:0]) each langL(r[0]+radDeltaX[0]+(irad[0]-irad[0]*cos(i*stepRad[0]+rotDeg[0]))*sign(deg[0]),l,z=h2[0]+(radDeltaH[0]-irad[0]*sin(i*stepRad[0]+rotDeg[0]))*sign(deg[0]) )] + :langL(r[0],l,h2[0]), // else center bottom +// center round top + irad[1]? + [for(i=[0:radFn[1]]) each langL(r[1]+radDeltaX[1]+(irad[1]-irad[1]*cos(i*stepRad[1]+rotDeg[1]))*sign(deg[1]),l,z=h2[0]+hc-(radDeltaH[1]-irad[1]*sin(i*stepRad[1]+rotDeg[1]))*sign(deg[1]) )] + : langL(r[1],l,h2[0]+hc), // else center top + langL(r2[1],l,h), // top + extrude[1]?langL(r2[1],l,h+extrude[1]):[] // ext + ); + + + + points2D=[ + if(extrude[0])[-r2[0],0-extrude[0]], + if(extrude[0])[ r2[0],0-extrude[0]], + [ r2[0],0], + if(!irad[0]||!deg[0])[ r[0],h2[0]], + if(irad[0]&°[0])each arc(r=-irad[0],deg=-deg[0]+rotDeg[0],t=[r[0]+radDeltaX[0],h2[0]] + sign(deg[0])*[irad[0],radDeltaH[0]],rot=deg[0]>0?deg[0]:180+deg[0],rev=false,fn=radFn[0]), + if(!irad[1]||!deg[1])[ r[1],h2[0]+hc], + + if(irad[1]&°[1])each arc(r=-irad[1],deg=-deg[1]+rotDeg[1],t=[r[1]+radDeltaX[1],h2[0]+hc] + sign(deg[1])*[irad[1],-radDeltaH[1] ],rot=-rotDeg[1] + (deg[1]>0?0:180),rev=false,fn=radFn[1]), + + [ r2[1],vSum(h2)+hc], + if(extrude[1])[ r2[1],vSum(h2)+hc+extrude[1]], + if(extrude[1])[-r2[1],vSum(h2)+hc+extrude[1]], + [-r2[1],vSum(h2)+hc], + if(!irad[1]||!deg[1])[-r[1],h2[0]+hc], + if(irad[1]&°[1])each arc(r=-irad[1],deg=-deg[1]+rotDeg[1],t=[-r[1]-radDeltaX[1],h2[0]+hc] - sign(deg[1])*[irad[1],radDeltaH[1] ],rot=deg[1]>0?180+deg[1]:deg[1],rev=false,fn=radFn[1]), + if(!irad[0]||!deg[1])[-r[0],h2[0]], + if(irad[0]&°[0])each arc(r=-irad[0],deg=-deg[0]+rotDeg[0],t=[-r[0]-radDeltaX[0],h2[0]] - sign(deg[0])*[irad[0],-radDeltaH[0]],rot=-rotDeg[0]+ (deg[0]>0?180:0),rev=false,fn=radFn[0]), + [-r2[0],0] + ]; + +// Points(points,help=1); +if(is_parent(needs2D)||2D)T(center.x?0:r.x,center.y?-h/2:0)polygon(points2D); +else +T(center.x?center.x==2?0: + center.x==3?-lx: + -lx/2: + d[0]/2, + center.y?center.y==2?0 + :center.y==3?-ly + :-ly/2 + :d[0]/2, + center.z?-h/2:0){ + $info=false; + PolyH(points=points,loop=ly?4*ifn+4:lx?ifn*2+2:ifn360,flip=0); + if(cuts&&max(r2)-max(r)>=1&&max(deg)>=5&&h>1)difference(){ + gapH=[deg[0]==0?0:1/sin(deg[0]),deg[1]==0?0:1/sin(deg[1])]*.5; + cutWidth=0.03; + + if(l)T(l/2){ + Linear(e=round(cuts==2?l-max(d)/2:l+max(d)/2),es=1,center=true)Tz(h/2)cube([cutWidth,abs(max(r2*2)),abs(h)-1],true); + if(cuts==2){ + //Tz(h/2)cube([abs(max(r2*2))+l,cutWidth,abs(h)-1],true); + MKlon(tx=-l/2)Polar(floor((r+line(2))*PI),-cutWidth/2,end=180)Tz(.5)cube([cutWidth,abs(max(r2)),abs(h)-1]); + } + } + else Polar(floor((min(r)+line(2))*PI*2),-cutWidth/2)Tz(.5)cube([cutWidth,abs(max(r2)),abs(h)-1]); + Tz(+gapH[0] -(deg[0]?line(2)/tan(deg[0]):0))Loch(h=h -vSum(gapH) +(deg[0]?line(2)/tan(deg[0]):0)+(deg[1]?line(2)/tan(deg[1]):0),h2=h2,d=d +[1,1]*line(2)*2,l=l,d2=undef,deg=deg,rad=rad-[1,1]*line(2),center=[2,1,0],fn=24,cuts=false,extrude=true); + } + } + +} + + + +/// chamfer cube + +//Ccube(); + + +module Ccube(size=20,c=2,c2,center=true,sphere=false,grad=0,help){ + c2=is_undef(c2)?0.5773*c:c2;//Eulerkonst? + s=is_list(size)?size:[size,size,size]; + scaleS=max(s[0]-c,s[1]-c,s[2]-c); + maxVal=max(size)*2; +// center=is_list(center)?v3(center) +// :center?[0,0,0] +// :[1,1,1]; + + //sc=[Hypotenuse(s[0],s[2])-c,Hypotenuse(s[0],s[0])-c,Hypotenuse(s[2],s[0])-c]; + sc1=[Hypotenuse(s[0]-c,s[0]-c)/2+Hypotenuse(s[1]-c,s[1]-c)/2,Hypotenuse(s[0]-c,s[0]-c)/2+Hypotenuse(s[1]-c,s[1]-c)/2,maxVal]; + sc2=[Hypotenuse(s[2]-c,s[2]-c)/2+Hypotenuse(s[0]-c,s[0]-c)/2,maxVal,Hypotenuse(s[0]-c,s[0]-c)/2+Hypotenuse(s[2]-c,s[2]-c)/2]; + sc3=[maxVal,Hypotenuse(s[2]-c,s[2]-c)/2+Hypotenuse(s[1]-c,s[1]-c)/2,Hypotenuse(s[1]-c,s[1]-c)/2+Hypotenuse(s[2]-c,s[2]-c)/2]; + + + sce=[2*norm(s-[c,c,c])-c2,1*norm(s-[c,c,c])-c2,2*norm(s-[c,c,c])-c2 + ]; + + + + translate( vMult(center(center),s/2) )intersection(){ + cube(s,center=true); + rotate([0,0,45])cube(sc1,center=true); + rotate([0,45,0])cube(sc2,center=true); + rotate([45,0,0])cube(sc3,center=true); + + + Color()rotate([0,0,45])R(grad+90-54.74)cube(sce,center=true); + Color()rotate([0,0,-45])R(grad+90-54.74)cube(sce,center=true); + Color()rotate([0,0,135])R(grad+90-54.74)cube(sce,center=true); + Color()rotate([0,0,-135])R(grad+90-54.74)cube(sce,center=true); + if(sphere)Color(0.1) scale([1/scaleS*s[0],1/scaleS*s[1],1/scaleS*s[2]])sphere(norm(s/2)-c-sphere); + + } + HelpTxt("Ccube",[ + "size",size, + "c",c, + "c2",c2, + "center",center, + "sphere",sphere, + "grad",grad],help); +} + + +/** +\name WaveEx +\page Objects +WaveEx is a wavey extrusion +\param grad degree 0 straight 360 torus +\param h height if straight +\param r ry radius +\param f fy frequency +\param a ay amplitude +\param fv,fvy frequency shift +\param trx try torus radius +\param tf tfy torus frequency +\param tfv,tfvy torus frequency shift +\param ta tay torus amplitude +\param fn fn2 fragments +\param rot rotation +\param scale scaley scale +\param close close ends +\param p pitch +\param name help name help +*/ + +module WaveEx(grad=0,h=50,r=5,ry,f=0,fy,a=1,ay,fv=0,fvy,trx=20,try,tf=0,tfy=0,tfv=0,tfvy=0,ta=1,tay,fn=fn,fn2=fn,rot=0,scale=1,scaley,close=true,p=0,name,help){ + ay=is_undef(ay)?a:ay; + fy=is_undef(fy)?f:fy; + ry=is_undef(ry)?r:ry; + scaley=is_undef(scaley)?scale:scaley; + fvy=is_undef(fvy)?fv:fvy; + try=is_undef(try)?trx:try; + tay=is_undef(tay)?ta:tay; + close=grad>=360?p?true:false:close; + + + twist=0; + rotate=rot; + + pointsLin=!grad?[for(i=[0:fn],j=[0:fn2])concat( kreis(rot=rotate+twist/fn*i,fn=fn2,rand=0,r=(1+(scale-1)/fn*i)*(r+sin(i*f*360/fn+fv)*a),r2=(1+(scaley-1)/fn*i)*(ry+sin(i*fy*360/fn+fvy)*ay),t=[trx+ta*sin(i*tf*360/fn+tfv),try+tay*cos(i*tfy*360/fn+tfvy)])[j],[i*h/fn])]:0; + + + function RotEx(rot=grad,punkte=Kreis(rot=rotate+twist/fn,fn=fn2,rand=0,r=(1+(scale-1)/fn)*(r+sin(0*f*360/fn+fv)*a),r2=(1+(scaley-1)/fn)*(ry+sin(0*fy*360/fn+fvy)*ay),t=[0,0]),verschieb=trx,verschiebY=try,p=-p,detail=fn*grad/360)=[for(rotation=[detail:-1:0])for(i=[0:len(punkte)-1]) + concat( + (punkte[i][0]+cos(f*rotation*grad/detail+fv)*a*cos(i*360/fn2)+verschieb)*sin(rotation*grad/detail)+sin(tfv+rotation*grad/detail*(tf+1))*ta, + punkte[i][1]+cos(fy*rotation*grad/detail+fvy)*-ay*sin(i*360/fn2)+rotation/detail*p*grad/360+sin(tfvy+rotation*grad/detail*(tfy+0))*tay, + (punkte[i][0]+cos(f*rotation*grad/detail+fv)*a*cos(i*360/fn2)+verschiebY)*cos(rotation*grad/detail)+cos(tfv+rotation*grad/detail*(tf+1))*ta + ) + ]; + pointsRot=RotEx(rot=grad); + + points=grad?pointsRot:pointsLin; + + //pointsMod=[for(i=[0:len(points)-1])[points[i][0]*1.0,points[i][1]*1,points[i][2]*1]]; + + //faces1=[for(i=[0:len(points)-fn2-3])each[[i,i+1,i+fn2+1],[i+1,i+fn2+2,i+fn2+1]]];// Triangle faces×2 + bottom=[[for(i=[0:fn2-1])(fn2-1)-i]]; + top =[[for(i=[len(points)-fn2:len(points)-1])i]]; + faces2=[for(i=[0:len(points)-fn2-3])[i,i+1,i+fn2+2,i+fn2+1]];// Quad face version + + rotate(grad?[-90,0,-90-(360-grad)/2]:[0,0,0])polyhedron(points=points,faces=close?concat( + faces2, + bottom, + top + ):faces2,convexity=5); + + HelpTxt("WaveEx",["grad",grad,"h",h,"r",r,"ry",ry,"f",f,"fy",fy,"a",a,"ay",ay,"fv",fv,"fvy",fvy,"trx",trx,"try",try,"tf",tf,"tfy",tfy,"tfv",tfv,"tfvy",tfvy,"ta",ta,"tay",tay,"fn",fn,"fn2",fn2,",rot",rot,"scale",scale,"scaley",scaley,"close",close,"p",p,"name",name],help); + + if(help)echo(str("r=radius, f=frequenz, fv=freqverschiebung, a=amplitude, trx=translatetRadiusX, p=steigung")); + + +} + + + + +module REcke(h=5,r=5,rad=.5,rad2,single=0,grad=90,center=false,fn=fn,help){ +rad2=is_undef(rad2)?rad:rad2; + radius=TangentenP(180-grad,r,r); + radius2=TangentenP(180-grad,r+Hypotenuse(rad,rad),r-rad); + + translate([0,0,center?-h/2:0])difference(){ + if(grad==90)T(-rad,-rad)cube([r+rad,rad+r,h]); + else translate([-rad*tan(90-grad/2),-rad]) rotate_extrude(angle=grad,convexity=5)square([radius2,h]); + translate(RotLang(90-grad/2,radius))rotate(grad/2+180)Strebe(angle=200-grad,h=h,single=single,2D=0,rad=rad,rad2=rad2,d=2*r,help=0,name=0,fn=fn); + } +HelpTxt("REcke",["h",h,"r",r,"rad",rad,"rad2",rad2,"single",single,"grad",grad,"center",center,"fn",fn],help); + if(grad!=90)Echo("WIP grad!=90",color="warning"); +} + + +/** +\name SBogen +SBogen() creates an S-shape double counter arc between parallels +\param dist distance between verticals +\param r1 r2 radii +\param grad connecton angle +\param l1 l2 lower and upper length +\param center center on x +\param fn,fs,fa fraqments +\param messpunkt show arc center +\param 2D make 2D +\param extrude extrude in 2D from x=0 +\param grad2 angle endsection +\param x0 set x axis origin=0 +\param lRef reference for l1 l2 0=center -1/1 lower/upper tangentP -2/2 tangent+grad2 -3/3 radius center +\param name help name help +\param lap overlap for 3D +*/ + +//SBogen(2D=true); +//SBogen(extrude=10, grad2=[26,-40]*1,r1=2,l1=20,lRef=+3,messpunkt=true); + +module SBogen(dist=10,r1=10,r2,grad=45,l1=15,l2,center=1,fn,fs=fs,fa=fa,messpunkt=false,2D=0,extrude=false,grad2=0,x0=0,lRef=0,name,help,spiel,lap=0){ + lap=is_undef(spiel)?lap:spiel; + center=is_bool(center)?center?1:0:sign(center); + r2=is_undef(r2)?r1:r2; + l2=is_undef(l2)?l1:l2; + 2D=is_parent(needs2D)&&!$children?2D?b(2D,false): + 1: + b(2D,false); +// echo(parent_module(1),$parent_modules); + grad2=is_list(grad2)?grad2:[grad2,grad2]; + extrudeTrue=extrude; + extrude=is_bool(extrude)?0:extrude*sign(dist); + gradN=grad; // detect negativ grad + grad=abs(grad);// negativ grad done by mirror + y=(grad>0?1:-1)*(abs(dist)/tan(grad)+r1*tan(grad/2)+r2*tan(grad/2)); + + yRef=lRef?lRef>0?(lRef> 2?0: tan((grad- (lRef> 1?grad2[1]:0) )/2)*r2)-y/2 // move polygon circles to keep fixpoint according lRef + :(lRef<-2?0:-tan((grad- (lRef<-1?grad2[0]:0) )/2)*r1)+y/2 + :0; + + yrest=y-abs(sin(grad))*r1-abs(sin(grad))*r2;//y ohne Kreisstücke + distrest=dist-r2-r1+cos(grad)*r1+cos(grad)*r2;//dist ohne Kreisstücke + + l2m=Hypotenuse(distrest,yrest)/2+minVal;// Mittelstück + + dist=grad>0?dist:-dist; + $fn=fn; + $fa=fa; + $fs=fs; + $idxON=false; + $info=is_undef($info)?is_undef(name)?1:name:$info; + + grad2Y=[-l1+y/2-yRef+r1*sin(grad2[0]),l2-y/2-yRef-r2*sin(grad2[1])]; // Abstand Kreisende zu Punkt l1/l2 + grad2X=[r1-r1*cos(grad2[0])-tan(grad2[0])*grad2Y[0],-r2+r2*cos(grad2[1])-tan(grad2[1])*grad2Y[1]];// Versatz der Punkte durch grad2 + + + KreisCenterR1=[[-abs(dist)/2+extrude+r1,-y/2+yRef],[extrude+r1-abs(dist),-y/2-l2+yRef],[extrude+r1,-y/2+l1+yRef]]; + KreisCenterR2=[[abs(dist)/2+extrude-r2,y/2+yRef],[extrude-r2,y/2-l2+yRef],[abs(dist)+extrude-r2,y/2+l1+yRef]]; + + + selectKC=center?center>0?0: + 1: + 2; + + + endPunkte=center?center==1?[extrude-abs(dist/2)+grad2X[0],extrude+abs(dist/2)+grad2X[1]]:[extrude-abs(dist)+grad2X[0],extrude+grad2X[1]]:[extrude+grad2X[0],extrude+abs(dist)+grad2X[1]]; + + + InfoTxt(parent_module(search(["Anschluss"],parentList(+0))[0]? + search(["Anschluss"],parentList(+0,start=0))[0]: + 1) + + ,["ext",str(endPunkte[0],"/",endPunkte[1])," 2×=",str(2*endPunkte[0],"/",2*endPunkte[1]),"Kreiscenter",str(KreisCenterR1[selectKC],"/",KreisCenterR2[selectKC]) + ],name); + + + + if(grad&&!extrudeTrue)mirror(gradN<0?[1,0]:[0,0])translate(center?[0,0,0]:[dist/2,l1]){ + translate([dist/2,y/2,0])T(-r2)rotate(grad2[1])T(r2)Bogen(rad=r2,grad=grad+grad2[1],center=false,l1=l2-y/2,l2=l2m,help=0,name=0,messpunkt=messpunkt,2D=2D,fn=fn,fs=fs,d=2D,lap=lap) + if($children){ + + $idx=is_undef($idx)?0:$idx; + $tab=is_undef($tab)?1:b($tab,false)+1; + children(); + } + else circle($fn=fn,$fs=fs); + T(-dist/2,-y/2) mirror([1,0,0])rotate(180)T(r1)rotate(-grad2[0])T(-r1)Bogen(rad=r1,grad=-grad-grad2[0],center=false,l1=l1-y/2,l2=l2m,help=0,name=0,messpunkt=messpunkt,2D=2D,fn=fn,fs=fs,d=2D,lap=lap) + if($children){ + $idx=1; + children(); + } + else circle($fn=fn,$fs=fs); + } + + if(!grad&&!extrudeTrue) //0 grad Grade + if(!2D)T(0,center?0:l1+l2)R(90)linear_extrude(l1+l2,convexity=5,center=center?true:false) + if($children)children(); + else circle($fn=fn); + else T(center?0:-2D/2) square([2D,l1+l2],center?true:false); + + + + + + if(extrudeTrue){ + + + points=center?center==1?concat(//center=1 + [[x0*sign(dist),l2]],[[extrude+abs(dist)/2+grad2X[1],l2+0]], + kreis(r=-r2,rand=0,grad=abs(grad)+grad2[1],rot=-90-grad2[1],center=false,fn=fn,fs=fs,fa=fa,t=[abs(dist)/2+extrude-r2,y/2+yRef]), // ok + kreis(r=-r1,rand=0,grad=-abs(grad)-grad2[0],fn=fn,fs=fs,fa=fa,rot=90+abs(grad),center=false,t=[-abs(dist)/2+extrude+r1,-y/2+yRef]), // ok + [[extrude-abs(dist)/2+grad2X[0],-l1]], + [[x0*sign(dist),-l1]] + ): concat(//center==-1||>1 + [[x0*sign(dist),0]],[[extrude+grad2X[1],0]], + kreis(r=-r2,rand=0,grad=abs(grad)+grad2[1],rot=-90-grad2[1],center=false,fn=fn,fs=fs,fa=fa,t=[extrude-r2,y/2-l2+yRef]), // ok + kreis(r=-r1,rand=0,grad=-abs(grad)-grad2[0],fn=fn,fs=fs,rot=90+abs(grad),center=false,t=[extrude+r1-abs(dist),-y/2-l2+yRef]), // ok + [[extrude-abs(dist)+grad2X[0],-l2-l1]], + [[x0*sign(dist),-l2-l1]] + ): + concat(//center==0 + [[x0*sign(dist),l2+l1]],[[extrude+abs(dist)+grad2X[1],l2+l1]], + kreis(r=-r2,rand=0,grad=abs(grad)+grad2[1],rot=-90-grad2[1],center=false,fn=fn,fs=fs,fa=fa,t=[abs(dist)+extrude-r2,y/2+l1+yRef]), // ok + kreis(r=-r1,rand=0,grad=-abs(grad)-grad2[0],fn=fn,fs=fs,fa=fa,rot=90+abs(grad),center=false,t=[extrude+r1,-y/2+l1+yRef]), // ok + [[extrude+grad2X[0],0]], + [[x0*sign(dist),0]] + ); + + + + if(dist>0&&gradN>0) polygon(points,convexity=5); + if(dist<0||gradN<0)mirror([1,0]) polygon(points,convexity=5); + + } + + + if(messpunkt&&is_num(extrude)){ + Pivot(KreisCenterR1[selectKC],messpunkt=messpunkt,active=[1,0,0,1]); + Pivot(KreisCenterR2[selectKC],messpunkt=messpunkt,active=[1,0,0,1]); + //echo(KreisCenterR1,KreisCenterR2); + } + + + + //Warnings + Echo(str(name," SBogen has no 2D-Object"),color=Hexstring([1,0.5,0]),size=4,condition=!$children&&!2D&&!extrudeTrue); + Echo(str(name," SBogen width is determined by var 2D=",2D,"mm"),color="info",size=4,condition=2D==1&&!extrudeTrue&&(is_undef($idx)||!$idx)&&$info); + + Echo(str(name," SBogen r1/r2 to big middle <0"),condition=l2m<0); + Echo(str(name," SBogen radius 1 negative"),condition=r1<0); + Echo(str(name," SBogen radius 2 negative"),condition=r2<0); + Echo(str(name," SBogen r1/r2 to big or angle or dist to short"),condition=grad!=0&&r1-cos(grad)*r1+r2-cos(grad)*r2>abs(dist)); + Echo(str(name," SBogen angle to small/ l1+l2 to short =",l1-y/2+yRef,"/",l2-y/2-yRef),condition=l1-y/2+yRef<0||l2-y/2-yRef<0); + //Help + HelpTxt("SBogen",["dist",dist,"r1",r1,"r2",r2,"grad",grad,"l1",l1,"l2",l2,"center",center,"fn",fn,"messpunkt",messpunkt,"2D",2D,"extrude",extrude,"grad2",grad2,"x0",x0, "lRef", lRef, "lap",lap," ,name=",name],help); + +} + module Buchtung(size=[10,5],l=10,r=2.5,rmin=0,center=true,fn=fn,fn2=fn,phase=360,deltaPhi=-90,help){ size=is_list(size)?size:[size,size]; rmin=is_list(rmin)?rmin:[rmin,rmin,rmin,rmin]; r=is_list(r)?r:[r,r,r,r]; - + loop=len(quad(fn=fn2)); points=[ for (i=[0:fn]) let( zscale=l/(fn), - rscale=r-rmin) - each quad(size,r=(1+sin(i*phase/fn+deltaPhi))/2*rscale+rmin,z=i*zscale,fn=fn2) + rscale=r-rmin, + ir=(1+sin((i*phase/fn+deltaPhi)%360))/2*rscale+rmin + ) + each quad(size,r=ir,z=i*zscale,fn=fn2) ]; /* @@ -3664,9 +11179,10 @@ module Buchtung(size=[10,5],l=10,r=2.5,rmin=0,center=true,fn=fn,fn2=fn,phase=360 } } } -//*/ +// */ -translate(center?[0,0,-l/2]:[0,0.0,0]+size/2)PolyH(points,loop=floor(fn2/4)*4+4,name=false); +//translate(center?[0,0,-l/2]:[0,0.0,0]+size/2)PolyH(points,loop=floor(fn2/4)*4+4,name=false); +translate(center?[0,0,-l/2]:[0,0.0,0]+size/2)PolyH(points,loop=loop,name=false); HelpTxt("Buchtung",[ @@ -3681,132 +11197,200 @@ HelpTxt("Buchtung",[ help); } +/** \name QuadAnschluss \page Objects +QuadAnschluss() creates a transision between two rounded rectangles (wall) -module CyclGetriebe(z=20,modul=1.5,w=45,h=4,h2=.5,grad=45,achse=3.5,achsegrad=60,light=false,lock=false,center=true,lRand=n(2),d=0,rot=0,linear=false,preview=true,spiel=0.075,fn=fn,name,help){ - $info=false; - center=is_bool(center)?center?1:0:center; - preview=$preview?preview:true; - linear=linear==true?1:linear; - r=z/4*modul; - mitteR=(r-modul/2)/2+achse/4; - rand=r-achse/2-modul/2-lRand*2; - - if(!linear){T(center?0:z/4*modul)T(y=center>1?z/4*modul:0)rotate(rot)difference(){ - LinEx(h=h,h2=h2,$d=z/2*modul,mantelwinkel=w,slices=preview?(h-1)*2:2,grad=d>r*2?-grad:grad) - if($preview&&!preview) Kreis(d=d>r*2?d:$d,rand=d>r*2?d/2-r:r-d/2); - else render()CycloidZahn(modul=modul,z=z/2,d=d,spiel=spiel,fn=fn); - if(achse) Tz(-.01)LinEx(h=h+.02,h2=h2,$d=achse,grad=-achsegrad)circle(d=$d); - if(light)Tz(-0.01)Polar(light)T(mitteR)LinEx(h=h+.02,h2=h2,$r=rand,grad=-60)T(-mitteR)Rund(min(rand/light,rand/2-0.1),fn=18)Kreis(r=mitteR,rand=rand,grad=min(360/light-15,320),grad2=max(360/light-40,10),rcenter=true,fn=z/light); - if(lock)LinEx(h=h,h2=h2,$r=1.65,grad=-60)WStern(help=0,r=$r); - } - InfoTxt("CyclGetriebe",["Wälzradius",z/4*modul],name); - } - - if (linear)T(0)intersection(){M(skewzx=-tan(w))T(0,-linear)LinEx(h,.5,$r=linear,grad=[90,45],grad2=[90,45])T(0,linear)CycloidZahn(z=z/2,modul=modul,linear=linear,center=center,spiel=spiel); -} - //Color()T(mitteR,0,4)circle(d=rand); +\param rad rad2 bottom top radius can be list of 4 +\param size, size2 bottom top size +\param h height of transition between bottom top values +\param l l2 straight profile start and end [bottom,top] or l l2 this is also used to make a chamfer +\param dicke dicke2 wall thickness bottom top (dicke2 optional) +\param t translate top quad x or [x,y] +\param chamfer chamfer bevel (in l) num or [bottom,top] or [[bot out,bot in],[top out,top in]] +\param chamferDeg angle of chamfer num or list [bottom,top] or [[bot out,in],[top out,in]] +\param fn,fs fraqment number, size +\param name,help name, help +*/ -HelpTxt("CyclGetriebe",[ - "z",z, -"modul",modul, -"w",w, -"h",h, -"h2",h2, -"grad",grad, -"achse",achse, -"achsegrad",achsegrad, -"light",light, -"lock",lock, -"center",center, -"lRand",lRand, -"d",d, -"rot",rot, -"linear",linear, -"preview",preview, -"spiel",spiel, -"fn",fn, -"name",$info] -,help); +//QuadAnschluss(1,5,5,12); -} +//QuadAnschluss(1,5,5,12,dicke=2,chamfer=0.5); +//QuadAnschluss(dicke=2,chamfer=[[0,1],[1,0]],l=1.5); + +//QuadAnschluss(dicke=2,chamfer=[[0,1],[1,0]],size=0,rad=[1,2,3,4],l=3,chamferDeg=60); + +//Cut()QuadAnschluss(5,8,25,20,h=20,dicke=4,dicke2=1.5,chamferDeg=[[25,70],[45,40]],chamfer=.5); -module CycloidZahn(modul=1,z=10,d=0,linear=false,center=false,spiel=+0.05,fn=fn,kreisDivisor=3.50,name,help){ - //if(is_undef(UB)) echo(str("

    include ub.scad> ")); - - z1=z%1?floor(z)+0.4999999:z; - z=z%1?floor(z)+0.5:z; - l=modul*PI*z-spiel*2; - r=modul*z/2;//Wälzkreis - spielwinkel=spiel/(r*2*PI)*360; - rot=90/z; - kreis=Umkreis(z*2,z*modul/2+modul/kreisDivisor+(d>r*2?spiel:-spiel)); - $info=false; - if(!linear)Polar(z%1?2:1,end=z%1?180+rot:360,r=z%1?0:180/(z*4)) - Rund(modul/10,fn=18){ - intersection (){ - rotate(-spielwinkel) Cycloid(modul=modul,z=z1,d=d,fn=fn); - rotate(rot+spielwinkel) Cycloid(modul=modul,z=z1,d=d,fn=fn); - if(d=0)difference(){ - - - if(linear){ - T(center?-l/2:0)Rund(modul/10,fn=18)intersection(){ - T(2.5*-modul*PI/4) Klon(tx=modul*PI/4) intersection(){ - T(-modul*PI/4-spiel*2) Cycloid(modul=modul,z=z1+2,d=d,linear=linear,fn=fn); - T(0)Cycloid(modul=modul,z=z1+2,d=d,linear=linear,fn=fn); - } - T(0,-(linear==true?1:linear)) square([l,(linear==true?1:linear)+modul/3.5]); + PolyH( points(h=h, l=l, chamfer=[chamferBot[0],chamferTop[0]], + chamferH=[chamferBotHmin[0],chamferTopHmin[0]]), + loop=ifn +4,flip=0,name=false); + + if(dicke>0)Tz(-.01) + PolyH(points(ofs=-[dicke,dicke2], h=h, l=l+[.01,.01], + chamfer=-[chamferBot[1],chamferTop[1]], + chamferH=[chamferBotHmin[1],chamferTopHmin[1]]), + loop=ifn+4,flip=0,name=false); } + if(dicke<0)difference(){ + PolyH(points(ofs=-[dicke,dicke2], h=h, l=l, + chamfer=[chamferBot[0],chamferTop[0]], + chamferH=[chamferBotHmin[0],chamferTopHmin[0]]), + loop=ifn+4,flip=0,name=false); + + Tz(-.01)PolyH(points(h=h, l=l+[.01,.01], + chamfer=-[chamferBot[1],chamferTop[1]], + chamferH=[chamferBotHmin[1],chamferTopHmin[1]]), + loop=ifn+4,flip=0,name=false); } -InfoTxt("CycloidZahn",["Zähne=",z*2,linear?str(" Länge=",l):str(" Wälzkreis r=",r)," spiel",spiel],name); -HelpTxt("CycloidZahnrad",["modul",modul,"z",z," d",d," linear",linear,"center",center,"spiel",spiel,"fn",fn,"kreisDivisor",kreisDivisor,"name",name],help); + } +/** \name Anschluss \page Objects +Anschluss() creates a transision between diameter or thickness +\param h height +\param d1 d2 in out diameter +\param rad rad2 radius of the bend +\param grad degree of the transition +\param r1 r2 optional to d1 d2 +\param center center height -1 1 0 +\param grad2 end section angle +\param wand thickness +\param 2D make 2D +\param x0 move x start +\param hRef reference for h 0=center, -1/1 lower\upper tangential, -2/2 tang+grad2 , -3/3 rad center +\param fn,fs,fa fragments +*/ + + +//Anschluss(wand=1); -module Anschluss(h=10,d1=10,d2=15,rad=5,rad2,grad=30,r1,r2,center=true,fn=fn,fn2=36,grad2=0,x0=0,wand,2D=false,name,help){ - +module Anschluss(h=10,d1=10,d2=15,rad=5,rad2,grad=30,r1,r2,center=true,fn=0,fs=fs,fa=fa,fn2=0,grad2=0,x0=0,wand,2D=false,name,help,old=false,dicke,hRef=0){ + + wand=is_undef(dicke)?wand:dicke; center=is_bool(center)?center?1:0:center; rad2=is_undef(rad2)?is_list(rad)?rad[1]:rad:rad2; rad=is_list(rad)?rad[0]:rad; r1=is_undef(r1)?d1/2:r1; r2=is_undef(r2)?d2/2:r2; - l1=is_list(h)?h[0]:h/2; + l1=assert(h,"h can't be undef")is_list(h)?h[0]:h/2; l2=is_list(h)?h[1]:h/2; grad2=is_list(grad2)?grad2:[grad2,grad2]; 2D=is_parent(needs2D)?true:2D; $helpM=false; if (!wand){ - if(2D)SBogen(extrude=sign(r2-r1)*(center?center==1?(r1+r2)/2:r2:r1),grad=abs(grad),dist=r2-r1,l1=l1,l2=l2,r1=rad,r2=rad2,center=center,fn=fn2,grad2=grad2,name=name,x0=x0,messpunkt=false); + if(2D)SBogen(extrude=(center?center>0?(r1+r2)/2:r2:r1),grad=abs(grad),dist=r2-r1,l1=l1,l2=l2,r1=rad,r2=rad2,center=center,fn=fn2,fs=fs,fa=fa,grad2=grad2,name=name,x0=x0,lRef=hRef,messpunkt=false); else - RotEx(fn=fn) - SBogen(extrude=sign(r2-r1)*(center?center==1?(r1+r2)/2:r2:r1),grad=abs(grad),dist=r2-r1,l1=l1,l2=l2,r1=rad,r2=rad2,center=center,fn=fn2,grad2=grad2,name=name,x0=x0,messpunkt=false); + RotEx(fn=fn,fs=fs,fa=fa,cut=x0<0?true:false) + SBogen(extrude=(center?center>0?(r1+r2)/2:r2:r1),grad=abs(grad),dist=r2-r1,l1=l1,l2=l2,r1=rad,r2=rad2,center=center,fn=fn2,fs=fs,fa=fa,grad2=grad2,name=name,x0=x0,lRef=hRef,messpunkt=false); - /*if(r1r1?wand:-wand),rad2=rad2+(r2>r1?-wand:wand),grad=grad,center=center,fn=fn,fn2=fn2,grad2=grad2,x0=x0,2D=2D,name=0,help=0); - Tz($preview&&!center&&wand<0?h*-0.005:0) Anschluss(h=wand<0&&$preview?h*1.01:h,r1=r1,r2=r2,rad=rad,rad2=rad2,grad=grad,center=center,fn=fn,fn2=fn2,grad2=grad2,x0=x0,2D=2D,name=name,help=0); + Tz($preview&&!center&&wand<0?-0.05:0) Anschluss(h=wand<0&&$preview?h*1.01:h,r1=r1,r2=r2,rad=rad,rad2=rad2,grad=grad,center=center,fn=fn,fn2=fn2,grad2=grad2,x0=wand>0?x0:x0-0.1,2D=2D,name=name,help=0); - if (wand>0)Tz($preview&&!center?h*-0.005:0) Anschluss(h=wand>0&&$preview?h*1.01:h,r1=r1-wand,r2=r2-wand,rad=rad+(r2>r1?wand:-wand),rad2=rad2+(r2>r1?-wand:wand),grad=grad,center=center,fn=fn,fn2=fn2,grad2=grad2,x0=x0,2D=2D,name=0,help=0); + if (wand>0)Tz($preview&&!center?-0.05:0) Anschluss(h=wand>0&&$preview?h*1.01:h,r1=r1-wand,r2=r2-wand,rad=rad+(r2>r1?wand:-wand),rad2=rad2+(r2>r1?-wand:wand),grad=grad,center=center,fn=fn,fn2=fn2,grad2=grad2,x0=x0-0.1,2D=2D,name=0,help=0); } + + if(!old&&wand) + if(!2D)RotEx(fn=fn,fs=fs,fa=fa)Ansch(); + else Ansch(); + + module Ansch()render()difference(){ // new generation + if(wand<0)SBogen(extrude=(center?center>0?(r1+r2)/2:r2:r1)-wand,grad=abs(grad),dist=r2-r1,l1=l1,l2=l2,r1=rad+(r2>r1?wand:-wand),2D=0,r2=rad2+(r2>r1?-wand:wand),center=center,fn=fn2,fs=fs,fa=fa,grad2=grad2,name=name,x0=x0,lRef=hRef,messpunkt=false); + + SBogen(extrude=(center?center>0?(r1+r2)/2:r2:r1),grad=abs(grad),dist=r2-r1,l1=l1,l2=l2,r1=rad,2D=0,r2=rad2,center=center,fn=fn2,fs=fs,fa=fa,grad2=grad2,name=name,x0=wand>0?x0:x0-.1,lRef=hRef,messpunkt=false); + + if(wand>0)SBogen(extrude=(center?center>0?(r1+r2)/2:r2:r1)-wand,grad=abs(grad),dist=r2-r1,l1=l1,l2=l2,r1=rad+(r2>r1?wand:-wand),2D=0,r2=rad2+(r2>r1?-wand:wand),center=center,fn=fn2,fs=fs,fa=fa,grad2=grad2,name=name,x0=x0-0.1,lRef=hRef,messpunkt=false); + } HelpTxt("Anschluss",[ @@ -3823,430 +11407,14 @@ module Anschluss(h=10,d1=10,d2=15,rad=5,rad2,grad=30,r1,r2,center=true,fn=fn,fn2 "fn2",fn2, "grad2",grad2, "x0",x0, - "wand",wand, + "hRef",hRef, + "dicke",dicke, "2D",2D, "name",name] ,help); } -//union(){ -//r=1; -// r2=1; -// grad=70; -// h=undef; -// mitte=2; -// extrude=+9.34; -// xCenter=-1; -//polygon([for(i=[0:27])vollwelle(fn=5,l=18,grad=grad,h=h,r=r,r2=r2,mitte=mitte,xCenter=xCenter,grad2=50,extrude=extrude)[i]]); -//T(0,0,-0.1)color("green")Vollwelle(fn=5,l=18,grad=grad,h=h,r=r,mitte=mitte,r2=r2,xCenter=xCenter,grad2=+50,extrude=extrude); -//T(0,2.4)color("red")square([8.68,1],center=0); -//*T(extrude-h,1)color("red")square([h,1],center=0); -//*T(5,4)square([r2-sin(90-grad)*r2,1]); -//*T(5+6.5,1)square([r-sin(90-grad)*r,1]); -// -//} - - - -function vollwelle(r=1,r2,grad=+60,grad2=+0,h=0,l,extrude=+5,center=true,xCenter=1,fn=12,x0=0,mitte=0,tMitte,g2End=[1,1])= -let( - fn=is_list(fn)?fn:[fn,fn], - grad=is_list(grad)?grad:[grad,grad], - grad2=is_list(grad2)?[max(grad2[0],-grad[0]),max(grad2[1],-grad[1])]:[max(grad2,-grad[0]),max(grad2,-grad[0])], - sc=1,// scaling r center - r2=is_undef(r2)?r:r2, - - //r mittelpunkt verschiebung für tangenten Kontakt -/* tangY=[r*sin(grad[0])-tan(90-grad[0])*(r-cos(grad[0])*r), - r*sin(grad[1])-tan(90-grad[1])*(r-cos(grad[1])*r)],//*/ - - mitte=max(0,is_undef(tMitte)?mitte:tMitte - tan(grad[0]/2)*r - tan(grad[1]/2)*r), - w=grad[0]-90,//del=echo(w,grad[0]-90), - wOben=(2*grad[1]-180)/2, - hR=r-sin(90-grad[0])*r, - hRO=r-sin(90-grad[1])*r, - hR2=r2-sin(90-grad[0])*r2, - hR2O=r2-sin(90-grad[1])*r2, - h=max(hR+hR2,hRO+hR2O,h), - hDiv=h-(hR+hR2), - hDivOben=h-(hRO+hR2O), - //hDiv=is_undef(h)?0:w>0?h-(sin(w)*r+sin(w)*r2):h-((sin(w)*r+sin(w)*r2))*0, - y=2*cos(w)*r*sc+(hDiv*-tan(w)*2), - yOben=2*cos(wOben)*r*sc+(hDivOben*-tan(wOben)*2), - y2Oben=2*cos(wOben)*r2, - y2=2*cos(w)*r2, - - x= sin(w)*r+hDiv*1, - x2= sin(w)*r2 , - l1=is_undef(l)?y/2+y2/2+sin(grad2[0])*r2+mitte/2:is_list(l)?is_undef(l[0])?y/2+y2/2+sin(grad2[0])*r2+mitte/2:l[0]:l/2, - l2=is_undef(l)?yOben/2+y2/2+sin(grad2[1])*r2+mitte/2:is_list(l)?is_undef(l[1])?yOben/2+y2/2+sin(grad2[1])*r2+mitte/2:l[1]:l/2, - extrude=xCenter==0?extrude-hDiv/2 - :xCenter>0?extrude-x-r - :xCenter<-1?xCenter<-2?extrude+x2+cos(grad2[1])*r2 - :extrude+x2+cos(grad2[0])*r2 - :extrude+x2+r2, - - trans=[+0,center?0:l1],// all points translation - g2End=is_list(g2End)?g2End:[g2End,g2End], - yKL1=l2-(yOben/2+y2Oben/2+mitte/2+sin(grad2[1])*r2), // Abstand Kreisende bis l2 - yKL0=l1+(-y/2-y2/2-mitte/2-sin(grad2[0])*r2), // Abstand Kreisende bis l1 - g2EndX0=grad2[0]!=90? g2End[0]? yKL0*tan(grad2[0]): // End Punkt unten winkel verlängerung - 0: - 0, - g2EndX1=grad2[1]!=90? g2End[1]? yKL1*tan(grad2[1]): // End Punkt oben winkel verlängerung - 0: - 0 - ) -concat( - - [[extrude-x2-cos(grad2[1])*r2+g2EndX1,l2]]+[trans]//oben Kreis verl. - , kreis(r=r2,rand=0,rot=-90+grad2[1],center=false,grad=-grad[1]-grad2[1],t=[extrude-x2,yOben/2+y2Oben/2+mitte/2]+trans,fn=fn[0])//oben - , kreis(r=r,r2=r*sc,rand=0,rot=90-grad[1],grad=grad[1],t=[extrude+x,mitte/2]+trans,fn=fn[1],center=false)//mitte oben - , kreis(r=r,r2=r*sc,rand=0,rot=90,grad=grad[0],t=[extrude+x,-mitte/2]+trans,fn=fn[1],center=false)//mitte unten - , kreis(r=r2,rand=0,rot=grad[0]-90,center=false,grad=-grad[0]-grad2[0],t=[extrude-x2,-y/2-y2/2-mitte/2]+trans,fn=fn[0]) //unten - - ,[[extrude-x2-cos(grad2[0])*r2+g2EndX0,-l1]]+[trans]//unten Kreis verl. - ,[[x0,-l1]]+[trans]//unten - ,[[x0,l2]]+[trans]//oben - - ); - - -module Vollwelle(r=1,r2,grad=+60,grad2=+0,h,l,extrude=+5,center=true,xCenter=0,fn=12,x0=0,mitte=0,tMitte,g2End=[1,1],help,name){ - - // calc for geometry is done by function -- values here are only for console - fn=is_list(fn)?fn:[fn,fn]; - //grad=is_list(grad)?is_undef(h)?echo(str("

    Vollwelle define h"))[grad[0],grad[0]]:grad:[grad,grad]; - - grad=is_list(grad)?grad:[grad,grad]; - grad2=is_list(grad2)?grad2:[grad2,grad2]; - sc=1;// scaling r center - r2=is_undef(r2)?r:r2; - w=(2*grad[0]-180)/2; - wOben=(2*grad[1]-180)/2; - - - //r mittelpunkt verschiebung für tangenten Kontakt - tangY=[tan(grad[0]/2)*r,tan(grad[1]/2)*r]; - /*[r*sin(grad[0])-tan(90-grad[0])*(r-cos(grad[0])*r), - r*sin(grad[1])-tan(90-grad[1])*(r-cos(grad[1])*r)];//*/ - - - mitte=is_undef(tMitte)?mitte:tMitte- tangY[0] -tangY[1]; - -// echo(w); - // hDiv=is_undef(h)?0:w>0?h-(sin(w)*r+sin(w)*r2):h+(sin(w)*r-sin(w)*r2); - hR=r-sin(90-grad[0])*r; - hR2=r2-sin(90-grad[0])*r2; - hRO=r-sin(90-grad[1])*r; - hR2O=r2-sin(90-grad[1])*r2; - h=is_undef(h)?max(hR+hR2,hRO+hR2O):h; - hDiv=h-(hR+hR2); - - y=2*cos(w)*r*sc+(hDiv*-tan(w)*2); - yOben=2*cos(wOben)*r*sc+(hDiv*-tan(wOben)*2); - y2=2*cos(w)*r2; - - x= sin(w)*r+hDiv ; - x2= sin(w)*r2 +0; - l1=is_undef(l)?y/2+y2/2+sin(grad2[0])*r2+mitte/2:is_list(l)?is_undef(l[0])?y/2+y2/2+sin(grad2[0])*r2+mitte/2:l[0]:l/2; - l2=is_undef(l)?yOben/2+y2/2+sin(grad2[1])*r2+mitte/2:is_list(l)?is_undef(l[1])?yOben/2+y2/2+sin(grad2[1])*r2+mitte/2:l[1]:l/2; - - Echo(str(name," Vollwelle h ist minimal= ",h),color="green",condition=name&&h==(hR+hR2)); - - Echo(str(name," Vollwelle h zu klein! min=",(hR+hR2)),color="red",condition=h<(hR+hR2)); - Echo(str(name," Vollwelle tMitte zu klein! min=",(tangY[0]+tangY[1])),color="red",condition=mitte<0); - - - Echo("Vollwelle use Number for xCenter",color="red",condition=is_bool(xCenter)); - //xCenter=is_bool(xCenter)?0:xCenter; - extrudeUnchanged=extrude; - extrude=xCenter==0?extrude-hDiv/2:xCenter>0?extrude-x-r:xCenter<-1?xCenter<-2?extrude+x2+cos(grad2[1])*r2:extrude+x2+cos(grad2[0])*r2:extrude+x2+r2; - -/* replaced with function vollwelle - points=concat( - - //[[x0,-y/2-y2/2-sin(grad2[0])*r2-mitte/2+0]],//unten - [[extrude-x2-cos(grad2[0])*r2,-l1]],//unten Kreis verl. - [[x0,-l1]],//unten - //[[x0,y/2+y2/2+sin(grad2[1])*r2+mitte/2]],//oben - [[x0,l2]],//oben - [[extrude-x2-cos(grad2[1])*r2,l2]],//oben Kreis verl. - - Kreis(r=r2,rand=0,rot=-90+grad2[1],center=false,grad=-grad[1]-grad2[1],t=[extrude-x2,yOben/2+y2/2+mitte/2],fn=fn[0]),//oben - Kreis(r=r,r2=r*sc,rand=0,rot=90-grad[1],grad=grad[1],t=[extrude+x,mitte/2],fn=fn[1],center=false),//mitte oben - Kreis(r=r,r2=r*sc,rand=0,rot=90,grad=grad[0]*1,t=[extrude+x,-mitte/2],fn=fn[1],center=false),//mitte unten - Kreis(r=r2,rand=0,rot=grad[0]-90,center=false,grad=-grad[0]-grad2[0],t=[extrude-x2,-y/2-y2/2-mitte/2],fn=fn[0]) //unten - ); - - translate([0,center?0:l1])//(y2+y)/2+sin(grad2[0])*r2+mitte/2]) - polygon(points,convexity=5); -*/ - polygon(vollwelle(r=r,r2=r2,grad=grad,grad2=grad2,h=h,l=l,extrude=extrudeUnchanged,center=center,xCenter=xCenter,fn=fn,x0=x0,mitte=mitte,tMitte=tMitte,g2End=g2End)); - - minimum=[extrude-x2-r2*(grad2[0]<0?cos(grad2[0]):1),extrude-x2-r2*(grad2[1]<0?cos(grad2[1]):1)]; - maximum=[extrude+x+r,extrude+x+r]; - - InfoTxt("Vollwelle",[str("min=",grad2[0]==grad2[1]? - grad2[0]<0?extrude-x2-r2*cos(grad2[0]):extrude-x2-r2 - :str(extrude-x2-r2*(grad2[0]<0?cos(grad2[0]):1),"/",extrude-x2-r2*(grad2[1]<0?cos(grad2[1]):1)), - "(×2∅=",grad2[0]==grad2[1]? - grad2[0]<0?2*(extrude-x2-r2*cos(grad2[0])):2*(extrude-x2-r2) - :str(2*(extrude-x2-r2*(grad2[0]<0?cos(grad2[0]):1)),"/",2*(extrude-x2-r2*(grad2[1]<0?cos(grad2[1]):1))), - "mm) — max=",extrude+x+r," (×2∅=",(extrude+x+r)*2,"mm)- Y länge=",l1+l2,"(",l1,"/",l2,")",//,y+y2+sin(grad2[0])*r2+sin(grad2[1])*r2+mitte, - "mm Wellenhöhe="),grad2[0]==grad2[1]?maximum[0]-minimum[0]:maximum-minimum],info=name); - - HelpTxt("Vollwelle",[ - "r",r, - "r2",r2, - "grad",grad, - "grad2",grad2, - "h",h, - "l",l, - "extrude",extrudeUnchanged, - "center",center, - "xCenter",xCenter, - "fn",fn, - "x0",x0, - "mitte",is_undef(tMitte)?mitte:str(mitte,"/*(calc)*/"), - "tMitte",tMitte, - "g2End",g2End, - "name",name] - ,help); - -} - - - -module SQ(size=[10,10],fn=[10,2],diff=[0.0001,0.0001,0.0001,0.0001],center=true,help){ - - x=is_list(size)?size[0]:size; - y=is_list(size)?size[1]:size; - fnx=is_list(fn)?fn[0]:fn; - fny=is_list(fn)?fn[1]:fn; - diff=is_list(diff)?diff:[diff,diff,diff,diff]; - - points=[ - for(i=[0:fnx])[-x/2+x/fnx*i,-y/2+i%2*-diff[0]], - for(i=[0:fny])[x/2+i%2*diff[1],-y/2+y/fny*i], - for(i=[0:fnx])[x/2-x/fnx*i,y/2+i%2*diff[2]], - for(i=[0:fny])[-x/2-i%2*diff[3],y/2-y/fny*i], - - ] ; - - // echo(points); - path=[[for(i=[0:len(points)-1])i]]; - //echo (path); - translate(center?[0,0]:[x/2,y/2]) polygon(points,path); - - - if($info) echo(" in twisted extrusions use linear_extrude(segments=20)"); -HelpTxt("SQ",["size",[x,y],"fn",[fnx,fny],"diff",diff,"center",center] ,help); -} - -/* -union(){ // Gear TEST - z=6; -rot=+0.5; - -Cycloid(linear=+2,option=+0); -T(rot*PI*z-PI/4,z/2)rotate(-rot*360-90)Cycloid(option=+0,z=z,l=+0.00,d=1); -} -*/ - - -module Cycloid (modul=1,z=5,fn=36,option=+0,l=0,d=0,linear=false,name,help,zahn){ - z=is_undef(zahn)?z:zahn; - r=modul*z/2; - rCav=r; - e=z*2; - - linear=is_bool(linear)?linear==true?modul:false:linear; - //r=modul*e; - fn2=fn*abs(e); - r2=r/(e)-l; - r2Cav=r2; - step1=360/fn2; - step2=step1*e; - step2Cav=-step1*(e-1); - // delta=+180; - - -if(linear){ - if(name) echo(str(is_string(name)?"

    ":"",name," Zahnstangenlänge=",r*PI*2," Zahnabschnitt=",r*PI*2/z)); - box=[[PI*2*r,-linear],[0,-linear]]; - pointsEpi=[for(i=[0:fn2])[PI*2*r*i/fn2+r2*-sin(i*step2),r2-r2*cos(i*step2)]]; - pointsHyp=[for(i=[0:fn2])[PI*2*r*i/fn2+r2Cav*-sin(i*step2),-r2-r2Cav*-cos(i*step2)]]; - if(option==1)color("pink")polygon(concat(box,pointsEpi)); - if(option==-1)color("cyan")polygon(concat(box,pointsHyp)); - points=[for(z=[0:2:e-2])each[for(i=[fn*z:fn*(z+1)])pointsEpi[i] -,for(i=[fn*(z+1):fn*(z+2)])pointsHyp[i]]]; - if(!option)color("orange")polygon(concat(box,points)); -} - - -if(!linear){ - - if(d) InfoTxt("Cycloid",["ZahnkreisRadius",str(r,"mm"),"fn Kreis rot",str(180/e,"°"),"d",d,"fn",max(d*3,fn)],name); - else InfoTxt("Cycloid",["ZahnkreisRadius",str(r,"mm")],name); - - - pointsEX=[for(i=[0:fn2]) - let(iw=i%fn2) - [ - (r+r2)*cos(iw*step1)-r2*cos(iw*(step2+step1)), - (r+r2)*sin(iw*step1)-r2*sin(iw*(step2+step1)) - ] - ]; - pointsCAV=[for(i=[0:fn2]) - let(iw=i%fn2) - [ - (rCav-r2Cav)*cos(iw*step1)+r2Cav*cos(iw*step2Cav), - (rCav-r2Cav)*sin(iw*step1)+r2Cav*sin(iw*step2Cav) - ] - ]; - - -pointsRand=Kreis(r=d/2,rand=0,fn=max(d*3,fn)); - -if(option==1)color("pink")polygon( - d?concat(pointsRand,pointsEX):pointsEX - ,paths= - d?[[for(i=[0:len(pointsRand)-1])i], - [for(i=[len(pointsRand):len(pointsEX)-1+len(pointsRand)])i]]: - [[for(i=[0:len(pointsEX)-1])i]] - ,convexity=5 - -); -if(option==-1)color("cyan")polygon( - d?concat(pointsRand,pointsCAV):pointsCAV - ,paths= - d?[[for(i=[0:len(pointsRand)-1])i], - [for(i=[len(pointsRand):len(pointsCAV)-1+len(pointsRand)])i]]: - [[for(i=[0:len(pointsCAV)-1])i]] - ,convexity=5); - -points=[for(z=[0:2:e-1])each[for(i=[fn*z:fn*(z+1)])pointsEX[i], -for(i=[fn*(z+1):fn*(z+2)])pointsCAV[i] - ] - //,pointsEX[+0] - ]; -//if(!option)color("orange")rotate(180/e-90)polygon(points,convexity=5); -//rot=180+(d>r*2?90/z:-90/z)); - -if(!option)color("orange")rotate(-180/e) - polygon(d?concat(pointsRand,points):points - ,paths= - d?[[for(i=[0:len(pointsRand)-1])i], - [for(i=[len(pointsRand):len(points)-1+len(pointsRand)])i]]: - [[for(i=[0:len(points)-1])i]] - ,convexity=5); - -} -HelpTxt("Cycloid",["modul",modul,"z",z,"fn",fn,"option",option,"l",l,"d",d,"linear",linear,"name",name],help); -} - - - -module WKreis(e=12,d1=1,d2,grad=180,r,diff,fn=24,r1,r2,name,help){ - - d1=is_undef(r1)?d1:2*r1; - d2=is_undef(d2)&&is_undef(r2)?d1:is_undef(r2)?d2:2*r2; - r1=d1/2; - r2=d2/2; - winkel=360/(e*2); - - grad1=grad+winkel; // konvex - grad2=grad-winkel; // konkav - - diff=is_undef(diff)?0:diff; - - - sek1=sin(grad1/2)*d1; - sek2=sin(grad2/2)*d2; - - r=is_undef(r)?Umkreis(e*2,((sek1+sek2)/4)/tan(winkel/2))+(d2>d1?pow(abs(d1/d2-1),+7):0):r; //WIP - diff1=-d1/2*cos(grad1/2)+diff; - diff2=d2/2*cos(grad2/2)-diff; - - rEck=Umkreis(e*2,r); - rK1=Kathete(r,sin(grad1/2)*d1/2)+diff1; - rK2=Kathete(r,sin(grad2/2)*d2/2)+diff2; - umfang=PI*r*2; - umfang1=PI*(rK1)*2; - umfang2=PI*(rK2)*2; - umfangEck=e*(d1+d2); - - - wk=[for(i=[0:e-1])each concat( - kreis(r=-d2/2,rot=90-winkel/2+i*winkel*2,rand=0,grad=-grad2,sek=true,t=RotLang(-winkel/2+i*winkel*2,rK2),fn=fn) - , kreis(r=d1/2,rot=90+winkel/2+i*winkel*2,rand=0,grad=grad1,sek=true,t=RotLang(winkel/2+i*winkel*2,rK1),fn=fn) - )]; - - rotate(winkel/2-90) polygon(wk,convexity=5); - - InfoTxt("Wkreis",["länge",str(umfangEck,"mm - Umfang(r=",r,")=",umfang,"mm Grad=",grad1,"°/",grad2,"°"),"\n\tAußen r",str(rK1+d1/2," OD=",2*rK1+d1," — Umfang=",umfang1,"mm Kreismitte=",rK1),"\n\tInnen r",str(rK2-d2/2," ID =",2*rK2-d2," — Umfang=",umfang2,"mm Kreismitte=",rK2)],name); - -HelpTxt("Wkreis",[ - "e",e, - "d1",d1, - "d2",d2, - "grad",grad, - "r",r, - "diff",diff, - "fn",fn, - "r1",r1, - "r2",r2, - "name",name], -help); - -} - - -module Pin(l=10,d=5,cut=true,mitte=true,grad=60,lippe=0.4,spiel=.1,name,help){ -$info=false; - rdiff=lippe+spiel; -cut=is_list(cut)?cut:[cut,cut]; -pol=[is_bool(cut[0])?round(d):cut[0],is_bool(cut[1])?round(d):cut[1]]; - -l=is_num(l)?[l/2,l/2]:l; - -cuth=[min(d,l[0]*1.8),min(d,l[1]*1.8)]; - -hkomplett=l[0]+l[1]+2*tan(grad)*rdiff; - -mirror([0,0,1])difference(){ - union(){ - cylinder(l[0],d=d); - Tz(l[0])Kegel(d+rdiff*2,d,grad=grad); - Tz(l[0])R(180)Kegel(d+rdiff*2,d-1,grad=40); - if(mitte) Kegel(d+rdiff*2,d-1,grad=45); - } - if(cut[0]) Tz(l[0]+0.2)Polar(pol[0],d-1)LinEx(cuth[0],min(cuth[0]/2.5,+1.0),0,grad=45,$d=d,center=true)Tri(h=d,top=+1,center=1,grad=45,r=0.3,fn=24); - linear_extrude(200,center=true,convexity=3)Kreis(r=d,rand=d/2-rdiff+spiel); -} -difference(){ - union(){ - cylinder(l[1],d=d); - Tz(l[1])Kegel(d+rdiff*2,d,grad=grad); - Tz(l[1])R(180)Kegel(d+rdiff*2,d-1,grad=40); - if(mitte) Kegel(d+rdiff*2,d-1,grad=45); - } - if(cut[1]) Tz(l[1]+0.2)Polar(pol[1],d-1)LinEx(cuth[1],min(cuth[1]/2.5,1),0,grad=45,$d=d,center=true)Tri(h=d,top=+1,center=1,grad=45,r=0.3,fn=24); - linear_extrude(200,center=true,convexity=3)Kreis(r=d,rand=d/2-rdiff+spiel); -} - -//if(achse)cylinder(h=achse,d=d+rdiff*2,center=true); - -if(name)echo(str(is_string(name)?"

    ":"",name," Pin l=",l[0]+l[1]," reale höhe=",hkomplett,"mm halb=",l,"/",[l[0]+tan(grad)*rdiff,l[1]+tan(grad)*rdiff]," plus= ",2*tan(grad)*rdiff,"/",tan(grad)*rdiff)); - -HelpTxt("Pin",["l",l,"d",d,"cut",cut,"mitte",mitte,"grad",grad,"lippe",lippe,"spiel",spiel,"name",name],help); - -} - - - // WIP!! module Kextrude (r1=10,r2,grad=60,rad=1,breit=5,center=1,fn=fn,help)rotate(center?-grad/2:0){ $fn=fn; @@ -4283,20 +11451,1103 @@ HelpTxt("Kextrude",["r1",r1,"r2",r2,"grad",grad,"rad",rad,"breit",breit,"center" } -module Klammer(l=10,grad=250,d=4,rad2=5,offen=+25,breite=2.5,fn=fn,help){ + +module GewindeV3( +dn=5, +h=10, +kern=0,//Kerndurchmesser +p=1,//Steigung +w=0,//Windungen +profil=+0.00, //varianz gangbreite +gh=0.56,//Ganghöhe +g=1,//Gänge +scale=1, +name, +fn=36, +help +){ + //http://www.iso-gewinde.at +r=dn/2; +gh=gh?gh:(dn-kern)/2; +kern=gh?2*(r-gh):kern; + +p=p?p:(w/360)/h; +h=h?h:w/360*p; +w=w?w:(h/p)*360; +winkel=atan2((p/2),gh)*2; + +InfoTxt("GewindeV3",["dn∅",dn,"Steigung",str(p,"mm/U"),"Kern",kern,"Gangtiefe",gh,"Winkel~",str(winkel -22.5,"°(",winkel,"°)")],name); + + difference(){ + if($children) children(); + Col(6)linear_extrude(height=h,twist=-w,convexity=10,scale=scale,$fn=fn){ + if(g>1) Rund((r-gh/2)*+0.5)Polar(g)T(gh/2)scale([1,1.00+profil])circle(r-gh/2,$fn=fn); + if(g==1)T(gh/2)scale([1,1.00+profil])circle(r-gh/2,$fn=fn); + + } + } + HelpTxt("GewindeV3",["dn",dn,"h",h,",kern",kern,"p",p,"w",w,"profil",profil,"gh",gh,"g",g,"scale",scale,"name",name,"fn",fn],help); +} + +/** \page Objects +\name FlatMesh +\param size size +\param fz optional function(x,y) +\param base bottom +\param res resolution num or list +\param randSize to add noise +\param amp list for amplitudes [crossx, - ,x,y,diagonal,diagonal,radial,circular,randomX,randomY(opt)] +\param freq frequency list [crossx,crossy,x,y,diagonal,diagonal,radial,circular] +\param delta list for moving pattern [crossx, - ,x,y,diagonal,diagonal,radial,circular,randomX,randomY(opt)] +\param seed seed for noise +\param center v3 +\param fs size if resolution is number +\param bricks interlock y rand blocks +*/ + + +//FlatMesh(size=[15.5,12.123],res=10,f=[0,0,50,0,0,0,0],randSize=5,amp=[0.2,0,0.1,0,0,0,0.2],delta=[0,0,0,0,0,0],center=[1,1]); +/* +FlatMesh(amp=[1,0,1,1,0,0,0,0,0]); +T(20)color("red") FlatMesh(amp=[0,0,1,1,0.5,0.5,0,0,0],delta=[0,0,0,90,0,0,0,0,0,0,0]); +T(40)color("green")FlatMesh(amp=[0,0,0,0,0,0,1,0,0,0],delta=[0,0,0,0,0,0,0,0,0],res=1,center=[0,1,1]); +T(70)color("blue") FlatMesh(amp=[0,0,0,0,0,0,0,1,0,0],freq=[4],delta=[0,0, 0,0, 0,0, 0,90, 0,0],center=[1,1,1],res=2); + +//*/ + + +module FlatMesh(size=[20,30],fz,base=5,res=1,randSize=0,amp=[1],freq=[2],delta=[0],seed=42,faceOpt,center=[0,0,1],fs=1,bricks=false,help){ +center=v3(center); +size=is_num(size)?[size,size]:size; +amp=is_list(amp)?amp:[amp]; +freq=is_list(freq)?freq:[freq]; +res=is_num(res)?[round(res*size.x/fs),round(res*size.y/fs)]:res; +f=freq/max(res)*360; +delta=delta; +step=[size.x/res.x, size.y/res.y]; + +HelpTxt("FlatMesh",["size",size,"fz",fz,"base",base,"res",res,"randSize",randSize,"amp",amp,"freq",freq,"delta",delta,"seed",seed,"faceOpt",faceOpt,"center",center,"fs",fs,"bricks",bricks],help); + +//amp=[0.08,.15,.5,.5,.5,.5,.5];//[0,0,0,1,1,0,0];// +//f=[15,20,10,5,6,2]; +//delta=[1,1.5,2,1.75,.5,.3,.1]*3600*$t; + +randSize=is_num(randSize)?[1,1]*randSize:randSize; +//delta=[1,1.5,2,1.75,.5,.3,0,randSize.x,randSize.y];//*$t*1000; +deltaRand=[delta[8%len(delta)],delta[9%len(delta)]]; + +// random +function rand(x,y,amp=amp[8%len(amp)],randSize=randSize,delta=deltaRand,seed=seed)= + rands(-1,1,1, + seed+(round((delta.x+x+randSize.x/2)/randSize.x)*round((delta.y+y+randSize.y/2)/randSize.y)) )[0] * amp*sign(max(randSize)); + +fz=is_function(fz)?fz:function(x,y) + (amp[0%len(amp)]?sin(x*f[0%len(f)]+delta[0%len(delta)])*sin(y*f[1%len(f)]+delta[1%len(delta)]) *amp[0%len(amp)]:0)//cross + +(amp[2%len(amp)]?sin(x*f[2%len(f)]+delta[2%len(delta)]) *amp[2%len(amp)]:0)//x + +(amp[3%len(amp)]?sin(y*f[3%len(f)]+delta[3%len(delta)]) *amp[3%len(amp)]:0)//y + +(amp[4%len(amp)]?sin((x-y)*f[4%len(f)]+delta[4%len(delta)]) *amp[4%len(amp)]:0)// diagonal + +(amp[5%len(amp)]?sin((x+y)*f[5%len(f)]+delta[5%len(delta)]) *amp[5%len(amp)]:0)// diagonal + + + +(amp[6%len(amp)]?sin(norm([x-center.x*res.x/2,y-center.y*res.y/2])*f[6%len(f)]+delta[6%len(delta)]) *amp[6%len(amp)]:0)//radial + +(amp[7%len(amp)]?sin(atan2(x-center.x*res.x/2,y-center.y*res.y/2)*(freq[7%len(freq)])+delta[7%len(delta)]) *amp[7%len(amp)]*norm([x-center.x*res.x/2,y-center.y*res.y/2])/(max(res)/2):0)//circular + + //+rands(-1,1,1,x*y+delta[6])[0]*amp[6]// noise + ; + + +if(min(size)>0){ +points0=[ +for(y=[0:res.y],x=[0:res.x])[x*step.x,y*step.y,base+fz(x,y) +// +rand(x,y) +//Bricks ++(bricks? +rand(x,y,delta=[(round((y+randSize.y/2)/randSize.y)%2?1:-1)*randSize.x/4 ++rands(-1,1,1,round((y+randSize.y/2)/randSize.y+seed))[0]*randSize.x/10,0]) +:rand(x,y)) + + +//+rand(x,y,randSize=randSize*2,amp=amp[6]*1.5,delta=[1,0]*delta[7],seed=seed+12345) +//+rand(x,y,amp=amp[6]*2,randSize=randSize*3,delta=[0,1]*delta[8],seed=seed+5000) +], +]; + +pointsBox=[ +for(i=[ [ 0, 0, 1], [ 1, 0, 1], [ 1, 1, 1], [ 0, 1, 1] ]) [i.x*size.x, i.y*size.y, 0] +]; + +l0=len(points0); +faces0=[ +for(y=[0:res.y-1],x=[0:res.x -1])[x+1, x, x+res.x+1, x+res.x+2]+[1,1,1,1]*y*(res.x+1) +]; +faces0Tri1=[ +for(y=[0:res.y-1],x=[0:res.x -1])[x+1, x, x+res.x+1]+[1,1,1]*y*(res.x+1), +for(y=[0:res.y-1],x=[0:res.x -1])[x+1, x+res.x+1, x+res.x+2]+[1,1,1]*y*(res.x+1) +]; +faces0Tri2=[ +for(y=[0:res.y-1],x=[0:res.x -1])[x+1, x, x+res.x+2]+[1,1,1]*y*(res.x+1), +for(y=[0:res.y-1],x=[0:res.x -1])[x, x+res.x+1, x+res.x+2]+[1,1,1]*y*(res.x+1) +]; +facesBox=[ + +//for(i=[0:l0-res.x -3])[i+1,i ,i+res.x +1,i+res.x +2], + +[for(i=[0:3])i+l0],// bottom +[for(i=[0:res.x])i,l0+1,l0], // side y0 +[for(i=[0:res.x])l0-i-1,l0+3,l0+2],// side y +[for(i=[res.y:-1:0])i*(res.x +1),l0,l0+3],// side x0 +[for(i=[0:res.y])res.x+i*(res.x +1),l0+2,l0+1],// side x +]; + +//faces=concat(faces0,facesBox); +faces=concat( (is_undef(faceOpt)?faces0:faceOpt?faces0Tri1:faces0Tri2),facesBox); +points=concat(points0,pointsBox); + +translate([center.x?-size.x/2:0,center.y?-size.y/2:0,center.z?-base:0])polyhedron(points,faces,convexity=5); +} +} + + + +module Surface(x=20,y,zBase=5,deltaZ=.25,res=6,waves=false, +rand=true,seed=42,randsize=1,randSizeY,freqX=1,freqY,ampX=1,waveSkewX=+0,ampY,waveSkewY,ampRoundX=0,rfX=+1,ampRoundY,rfY,versch=[0,0],abs=false,exp=1,expY,sinDelta=0,sinDeltaY,mult=false,name,help){ + + +HelpTxt("Surface",[ + "x",x, + "y",y, + "zBase",zBase, + "deltaZ",deltaZ, + "res",res, + "waves", waves, + "rand",rand, + "seed",seed, + "randsize",randsize, + "randSizeY",randSizeY, + "freqX",freqX, + "freqY",freqY, + "ampX",ampX, + "waveSkewX",waveSkewX, + "ampY",ampY, + "waveSkewY",waveSkewY, + "ampRoundX",ampRoundX, + "rfX",rfX, + "ampRoundY",ampRoundY, + "rfY",rfY, + "versch",versch, + "abs",abs, + "exp",exp, + "expY",expY, + "sinDelta",sinDelta, + "sinDeltaY",sinDeltaY, + "mult",mult, + "name",name + + ],help); +/* +if(help){ + echo(str("Help Surface")); + echo(str(" Surface(x=",x,",y=",y,", zBase=",zBase," // mm size ")); + echo(str(" deltaZ=",deltaZ,", res=",res," // random change +− and resolution points/mm ")); + echo(str(" waves=",waves,", rand=",rand,", // pattern waves and/or random")); + echo(str(" seed=",seed,", randsize=",randsize,",randSizeY=",randSizeY,", //random seed, random size y strech")); + echo(str(" freqX=",freqX,", freqY=",freqY,", ampX=",ampX,",waveSkewX=",waveSkewX,", ampY=",ampY,", waveSkewY=",waveSkewY,", // wave frequenz and amplitude XY")); + echo(str(" ampRoundX=",ampRoundX,", rfX=",rfX,",ampRoundY=",ampRoundY,",rfY=",rfY,", // rounded Waveform ⇒ coarse, roundig factor")); + echo(str(" versch=",versch,", name=",name,", abs=",abs,", exp=",exp,", expY=",expY,", sinDelta=",sinDelta,", sinDeltaY=",sinDeltaY,"mult=",mult,",); // move wave pattern show info and abs values, exponent, move sin center waves only")); +}// */ + +y=is_undef(y)?x:y;//assert(x!=0&&y!=0) +randSizeY=assert(randsize!=0&&randSizeY!=0)is_undef(randSizeY)?1/randsize:1/randSizeY; +freqY=is_undef(freqY)?freqX:freqY; +ampY=is_undef(ampY)?ampX:ampY; +waveSkewY=is_undef(waveSkewY)?waveSkewX:waveSkewY; +ampRoundY=is_undef(ampRoundY)?ampRoundX:ampRoundY; +rfY=is_undef(rfY)?rfX:rfY; +expY=is_undef(expY)?exp:expY; +sinDeltaY=is_undef(sinDeltaY)?sinDelta:sinDeltaY; + + + +if(waves)InfoTxt("Surface",["λ X/Y",str(10/freqX,"/",10/freqY," mm - λ¼=",10/freqX/4,"/",10/freqY/4," mm")],name); + +rowl=assert(x>0)x; //frame x values +rowly=assert(y>0)y;//frame y values + +resolution=1/res;//[10,5,2.5,1,0.5,0.25,0.125] +//randSizeY=1/randSizeY; + + +random=rands(-deltaZ,deltaZ,((rowl+1)*(rowly+1)*randSizeY)/min(randsize,1),seed); + +/* +z1=0; +z2=0.5; +alternate=[for(h=[0:y+1])for(i=[0:x+0])h%2?i%2?deltaZ:deltaZ/2:i%2?deltaZ/2:deltaZ]; +alternate3=[for(h=[0:y+1])for(i=[0:x+0])h%4?i%3?z1:z2:i%2?z2:z1]; +function alternate2(x,y,z1=0.0,z2=0.5)=x%2?y%2?z1:z2:z2; +// +points0alternativ=[ +for(x=[-rowl/2+versch[0]:resolution:rowl/2+versch[0]]) + for(y=[-rowly/2+versch[1]:resolution:rowly/2+versch[1]]) + [x,y, + //alternate2((x+(rowl/2)),(y+(rowly/2)))] + //alternate[(x+rowl/2)+(rowl+0.5)*(y+rowly/2)]] + alternate3[(x+rowl/2)+(rowl+0)*(y+rowly/2)]] + ]; + +*/ + +points0=[ +for(x=[-rowl/2+versch[0]:resolution:rowl/2+versch[0]]) + for(y=[-rowly/2+versch[1]:resolution:rowly/2+versch[1]]) + [x,y, + (rand?random[randSizeY*(round((y+rowly/2-versch[1])/randsize)+round((x+rowl/2-versch[0])/randsize)*rowly)]:0) + +(waves?abs? + pow(ampY*abs(sinDeltaY+sin(y*36*freqY+x*36*freqX*waveSkewY)),expY) + *(mult?pow(ampX*abs(sinDelta+sin(x*36*freqX+y*36*waveSkewX*freqY)),exp):1) + +(mult?0:pow(ampX*abs(sinDelta+sin(x*36*freqX+y*36*waveSkewX*freqY)),exp)) + +ampRoundX*round(rfX*abs(sin(x*36*freqX+y*36*waveSkewX*freqY))) + +ampRoundY*round(rfY*abs(sin(y*36*freqY+x*36*freqX*waveSkewY))) + : + pow(ampY*(sinDeltaY+sin(y*36*freqY+x*36*freqX*waveSkewY)),expY) + *(mult?pow(ampX*(sinDelta+sin(x*36*freqX+y*36*waveSkewX*freqY)),exp):1) + +(mult?0:pow(ampX*(sinDelta+sin(x*36*freqX+y*36*waveSkewX*freqY)),exp)) + +ampRoundX*round(rfX*sin(x*36*freqX+y*36*waveSkewX*freqY)) + +ampRoundY*round(rfY*sin(y*36*freqY+x*36*freqX*waveSkewY)) + //+amplitude4*sin((y*0+x*1)*freqY) + //+amplitude3*cos((y-x)*freqY) + :0)] + ]; + + +resx=rowl*res;// /resolution; +resy=rowly*res;// /resolution; + +faces0=[ + for(row=[+0:resx-1]) + for(i=[row*resy-1:(row+1)*resy-2]) + [i+1+row,i+row+2,i+row+3+resy,i+row+2+resy] + ]; + + +points1=[ +[-rowl/2+versch[0],-rowly/2+versch[1],-zBase], +[-rowl/2+versch[0],rowly/2+versch[1],-zBase], +[rowl/2+versch[0],-rowly/2+versch[1],-zBase], +[rowl/2+versch[0],rowly/2+versch[1],-zBase], +]; + +end0=len(points0); +faces1=[[end0+3,end0+1,end0+0,end0+2]]; +fpointssideA=[for(i=[resy:-1:0])i]; +fpointssideB=[for(i=[0:resy+1:resx*(resy+1)])i]; +fpointssideC=[for(i=[(resy+1)*(resx+1)-1:-resy-1:resy])i]; +fpointssideD=[for(i=[len(points0)-resy-1:len(points0)-1])i]; + + +faces2=[concat(fpointssideA,[end0+0,end0+1])]; +faces3=[concat(fpointssideB,[end0+2,end0+0])]; +faces4=[concat(fpointssideC,[end0+1,end0+3])]; +faces5=[concat(fpointssideD,[end0+3,end0+2])]; + + + +points=concat(points0,points1); +faces=concat(faces0,faces1,faces2,faces3,faces4,faces5); + + + translate(-versch)Col(6)polyhedron(points,faces,convexity=5); + +} + + + + + +module RStern(e=3,r1=30,r2=10,rad1=5,rad2=+30,l,grad=0,rand=0,os=0,randh=2,r=0,fn=fn,messpunkt=messpunkt,infillh,spiel=.005,name,help){ + $helpM=0; + $info=0; + r1=r?TangentenP(grad,rad1,r):r1; + + winkel1=180-grad; + spitzenabstand=2*r1*sin(180/e); + winkel3=180-(2*((180-360/e)/2-winkel1/2)); + schenkelA= spitzenabstand/2/sin(winkel3/2); + winkel3h=Kathete(schenkelA,spitzenabstand/2); + spitzenabsth=Kathete(r1,spitzenabstand/2); + r2=r?spitzenabsth-winkel3h:r2; + + //infillh=$children?infillh:infillh?infillh:1; + infillh=$children?infillh:is_undef(infillh)?0:infillh; + //rand=$children?rand:grad<180?rand:rand?rand:1; + + // Winkelberechnung ZackenStern + abstandR1=2*r1*sin(180/e); + abstandR2=2*r2*sin(180/e); + hoeheR1=r1-Kathete(r2,abstandR2/2); + hypR1=Hypotenuse(abstandR2/2,hoeheR1); + gradR1=2*acos(hoeheR1/hypR1); + gradR2=2*asin((abstandR1/2)/hypR1); + + // RStern variablen + grad=grad?grad:180-gradR1; + g2=(grad-360/e); + + // Abstand Rundungen Zacken + + c1=sin(abs(grad)/2)*rad1*2;// Sekante 1 + w11=abs(grad)/2; // Schenkelwinkel1 + w31=180-abs(grad); // Scheitelwinkel1 + a1=(c1/sin(w31/2))/2; + hc1=grad!=180?Kathete(a1,c1/2):0; // Sekante1 tangenten center + hSek1=Kathete(rad1,c1/2); //center Sekante1 + + c2=sin(abs(g2)/2)*rad2*2;// Sekante 2 + w12=abs(g2)/2; // Schenkelwinkel2 + w32=180-abs(g2); // Scheitelwinkel2 + a2=(c2/sin(w32/2))/2; + hc2=g2!=180?Kathete(a2,c2/2):0; // Sekante2 tangenten center + hSek2=Kathete(rad2,c2/2); //center Sekante2 + + + + // RStern l variable + + lCalcA=[r1-TangentenP(grad,rad1,rad1),0]+RotLang(90+grad/2,rad1); + lCalcB=g2<0? + RotLang(-90+180/e,-r2+TangentenP(g2,rad2,rad2))-RotLang(-90+180/e-abs(g2)/2,rad2): + RotLang(-90+180/e,-r2-TangentenP(g2,rad2,rad2))+RotLang(-90+180/e+abs(g2)/2,rad2) + ; + + l=is_undef(l)?norm(lCalcA-lCalcB)/2+spiel/2:l; + //color("cyan")translate(lCalcA)Pivot();//Ende Bogen 1 + //color("magenta")translate(lCalcB)Pivot();//Ende Bogen 2 + + + if($children||!(grad<180))union(){ + Polar(e,r1,name=0)Bogen(grad=grad,rad=rad1,l=l,help=0,name=0,tcenter=1,fn=fn,messpunkt=messpunkt,lap=spiel)T(os){ + children(); + if(grad>=180)T(rand/2,randh/2)square([abs(rand),randh],true); + } + + Polar(e,-r2,r=e%2?0:180/e,re=0,name=0)Bogen(grad=g2,rad=rad2,l=l,help=0,name=0,tcenter=true,fn=fn,messpunkt=messpunkt,lap=spiel)T(-os){ + R(0,180)children(); + if(grad>=180)T(-rand/2,randh/2)square([abs(rand),randh],true); + } + + } +/* old Sternfill + if(grad<180){ + if(infillh)linear_extrude(infillh,convexity=5)offset(os,$fn=fn)Rund(rad1,rad2,fn=fn)Stern(e,r1,r2); + if(rand)linear_extrude(randh,convexity=5)Rand(rand)offset(os,$fn=fn)Rund(rad1,rad2,fn=fn)Stern(e,r1,r2); + } +*/ + if(grad<=180){ + if(infillh)linear_extrude(infillh,convexity=5)offset(os,$fn=fn)RSternFill(e=e,r1=r1-TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); + + if(rand)linear_extrude(randh,convexity=5)Rand(rand)offset(os,$fn=fn)RSternFill(e=e,r1=r1-TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); + + if(infillh==0)offset(os,$fn=fn)RSternFill(e=e,r1=r1-TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); + } + + if(grad>180){ + if(infillh)linear_extrude(infillh,convexity=5)offset(os,$fn=fn)RSternFill(e=e,r1=r1+TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); + + if(rand)linear_extrude(randh,convexity=5)Rand(rand)offset(os,$fn=fn)RSternFill(e=e,r1=r1+TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); + + if(infillh==0)offset(os,$fn=fn)RSternFill(e=e,r1=r1+TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); + } + + MO(!$children,warn=true); + + HelpTxt("RStern",["e",e,"r1",r1,"r2",r2,"rad1",rad1,"rad2",rad2,"l",l,"grad",grad,"rand",rand,"os",os,"randh",randh,"fn",fn,"messpunkt",messpunkt,"infillh",infillh,"spiel",spiel,"name",name],help); + + InfoTxt("RStern",["Grad",str(grad,"°"),"Grad2",str(g2,"°"),"Spitzenwinkel",str(gradR1,"°/",gradR2,"°"),"r1 bis Rundung", + // r1-hc1-hSek1+rad1 + r1-TangentenP(grad,-rad1,0)+2*rad1 + ,"r2 bis Rundung", + //r2+hc2+hSek2-rad2 + str(TangentenP(g2,rad2,r2) + ,"mm")],name); + +} + +module RSternFill( // needs checking + +e=8, //elements +d1=2, // diameter nipples(convex) +d2, // diameter nipples(concave) +r1=5, // radius 1 +r2, //radius 2 +grad1=180, // angle nipples 1 +grad2, // angle nipples 2 +fn=fn, +messpunkt=false, +help +){ +winkel=360/(e*2); + + + + //grad1=is_undef(grad)?grad1:grad; // konvex + grad2=is_undef(grad2)?grad1-winkel*2:grad2; // konkav + d2=is_undef(d2)?d1:d2; + + + sekD1X=sin(grad1/2)*d1/2; + sekD1Y=cos(grad1/2)*d1/2; + sekD2X=sin(grad2/2)*d2/2; + sekD2Y=-cos(grad2/2)*d2/2; + r=norm([sekD1X,r1+sekD1Y]);//connectionpoint radius + r2=is_undef(r2)?Kathete(r,sekD2X)-sekD2Y:r2; + if(messpunkt)rotate(-90){ + Pivot(p0=[sekD1X,r1+sekD1Y],txt="D1",active=[0,0,0,1,0,1]); + rotate(-winkel) Pivot(p0=[-sekD2X,r2+sekD2Y],txt="D2",active=[0,0,0,1,0,1]); + //Tz(.1)Color()circle(r,$fn=200); + } + + + + wk=[for(i=[0:e-1]) each concat( + kreis(r=-d2/2,rot=90-winkel/2+i*winkel*2,rand=0,grad=-grad2,sek=true,t=RotLang(-winkel/2+i*winkel*2,r2),fn=fn) + , kreis(r=d1/2,rot=90+winkel/2+i*winkel*2,rand=0,grad=grad1,sek=true,t=RotLang(winkel/2+i*winkel*2,r1),fn=fn) + )]; + + rotate(winkel/2-90)polygon(wk,convexity=5); + +if(help)echo(str("

    Help RSternFill(e=",e,",r1=",r1,", r2=",r2," ,d1=",d1," ,d2=",d2, ",grad1=",grad1," ,grad2=",grad2," ,fn=",fn,", messpunkt=",messpunkt," help);")); +} + + + + + +}//fold // Basic Objects ΔΔ +{//fold // \∇∇ Products ∇∇/ // + +/** \page Products \name Bayonet +Bayonet() creates a bayonett mount in out +\param d diameter (out side + spiel*2) +\param l length of groove ([l,l] lock z pos between) +\param h length to cut above +\param lock z lower to lock +\param e number of nibs/grooves +\param nibH height of nib +\param nibR radius [top,out] +\param nibMitte nib center +\param spiel changes outer diameter and nibR +\param lap overlapping nib +\param invert switch nib from inside to outside +\param part [0:nib, 1: groove] +\param fs segmentsize of groove +\param name help name help +*/ + +/* +Bayonet(part=0,invert=1,pos=+0); +Bayonet(part=1,invert=1,pos=+0); +//*/ + + +module Bayonet(d=20,l=8,h=15,lock=-0.5,e=3,nibH=1,nibR=[.5,.35],nibMitte=.25,spiel=spiel,lap=.25,invert=0,part=0,fs=fs,pos=0,name,help){ +pos=bool(pos,false); +lock2=.2; // radial lock +lock=is_list(lock)?lock:[lock,lock2]; +spielR=spiel; // radius change to add clearance for outer ring + +l=is_list(l)?l:l*[0.7,.3]; +fn=ceil(vSum(l)/fs); +r=d/2+(invert?0:spielR); +step=assert(is_num(d),"Bayonet d not a number!")l*gradB(b=1,r=r)/fn; +ifn=[floor(fn/2),ceil(fn/2)]; +// for flat on round error +adj=-d/2+distS(s=vSum(nibR)*2,r=d/2); +endPosZ=-spiel;//lock pos lower 0 + +deg=[atan2(-lock[0],l[0]),atan2(lock[0],l[1])]*(invert?-1:1);// profile angle +lockWinkel=-vSum(vMult(ifn,step)); +eINPUT=e; + +e=min(e,floor(360/(-lockWinkel+ gradB(b=nibMitte+ vSum(nibR) + nibH*tan(60)*2, r=r)/2) ) ); + +InfoTxt("Bayonet",["elements",e,"lockWinkel",lockWinkel],name); +Echo(str(name," Bayonet e= ",eINPUT," to high - limited to ",e),color="warning",condition=eINPUT>e); + +//nib + if(part==0)color("gold")Polar(e,d/2+(invert?spielR+adj*0: adj),rot=pos?lockWinkel*sign(pos):0,name=false)rotate([0,invert?-90:90])rotate_extrude()SWelle(nibR,h=nibH,deg=60,lap=[0,lap],ext=nibMitte/2); +//groove + if(part==1)color("steelblue"){ + Polar(e,rot=pos?-lockWinkel*sign(pos):0,name=false){ + rotate([0,0,invert?180:0]){ + rotate([90,0])PolyH(points,loop=len(profilP()),flip=invert?false:true); + translate([invert?-adj:adj,0,l[0]?0:lock[0]])linear_extrude(h,convexity=5)polygon(profilP(z=undef)); + } + + translate([(invert?d/2:d/2+spielR)+adj,0,l[0]?0:lock[0]])rotate([0,90,invert?180:0])rotate_extrude()SWelle(nibR+[spiel,-spiel],h=nibH,deg=60,ext=nibMitte/2); +//LockPos + rotate([0,0,lockWinkel])translate([(invert?d/2:d/2+spielR+adj),0,endPosZ])rotate([0,90,invert?180:0])rotate_extrude()SWelle(nibR+[spiel,-spiel]*.5,h=nibH-spiel/2,deg=60,ext=nibMitte/2); + + } + } + +function profilP(z=0,h=nibH)=vollwelle(r=nibR+[spiel,-spiel],h=h,extrude=(invert?-d/2:d/2+spielR),x0=(invert?-d/2:d/2+spielR)-lap,xCenter=-1,fn=3,z=z,mitte=nibMitte); + +points=[ +for(rot=[0:ifn[0]])each mPoints(profilP(),r=[sin(rot*180/ifn[0])*deg[0],-rot*step[0],0],t=[0,lock[0]*(1-transition(fn=ifn[0],i=rot)),0]), +for(rot=[0:ifn[1]])each mPoints(profilP(h=nibH-(1-transition(rot,ifn[1]))*lock[1]),r=[sin(rot*180/ifn[1])*deg[1],-(ifn[0]*step[0]+rot*step[1]),0],t=[0,endPosZ+(lock[0]-endPosZ)*transition(fn=ifn[1],i=rot),0]), + ]; + + +HelpTxt("Bayonett",["d",d,"l",l,"h",h,"lock",lock,"e",e,"nibH",nibH,"nibR",nibR,"spiel",spiel,"lap",lap,"invert",invert,"part",part,"fs",fs,"pos",pos,"name",name],help); + +} + + + + + + + +/** \page Products \name Filter +Filter() creates a fine mesh to filter (only FDM prints) +\param size [x,y]filter size +\param dist filter holes +\param h filter height +\param form 0 square 1 circle +\param rand rim (± outer inner) +\param rad corner radius for form 0 +\param randH height rim +\param stack interlace grid levels if false +\param layer layer +\param name help name help +*/ + +//Filter(rand=0,layer=.15,form=0,dist=.5,nozzle=.2); +//Filter(size=[10,10],h=1.0,rand=+0,form=1,stack=0,line=.5); +//Filter([10,20]); + +module Filter(size=10,dist=.25,h=5,form=1,rand=-.5,rad=1,randH=0,stack=false,layer=layer,line=line,name,help){ +//lines Size +ls=line;//n(2+min(.85,dist/nozzle),nozzle=nozzle); // gap max .85 nozzle width +2ls=line;//n(2,nozzle=nozzle); // End lines +//filter size [x,y] +size=is_num(size)?[size,size]:size; +//distance incl. line +es=dist+ls ; + +interlace=[1,-1]*es/4;//[-(dist>nozzle*3?es/4:es/8),(dist>nozzle*3?es/4:es/8)]; +level=rand?floor((h-layer*2)/layer/2):floor(h/layer/2); + +InfoTxt("Filter",["line",ls,"outside",size+(rand>0?[2,2]*rand:[0,0]),"inside",rand>0?size:size+rand*[2,2],"level",level,"filterTop",(rand?layer:0)+level*layer*2],name); +HelpTxt("Filter",["size",size,"dist",dist,"h",h,"form",form,"rand",rand,"rad",rad,"randH",randH,"stack",stack,"layer",layer,"line",line,"name",name],help); + + + +if(rand) + LinEx(max(h,randH),$info=false)Rand(rand){ + if(form==0)Quad(size,rad=rad); + if(form==1)scale([1,size.y/size.x])circle(d=size.x); + } + + + + intersection(){ + $info=false; + Tz(rand?layer*1.5:layer/2){ + Linear(level,es=layer*2,z=1){ + $idx2=$idx%2; + if(rand==0&&form==1){ + color("lightgrey")linear_extrude(layer-.001,center=true)difference(){ + Kreis(d=size.x,r2=size.y/2,rand=2ls); + T(level==1||stack?0:interlace[$idx2] )Linear(e=(size.x/es),es=es,center=true,x=1)T(y=(($idx%2+$idx2)%2?1:-1)*size.y/2)square([dist,size.y],true); + + } + color("darkgrey")Tz(layer) linear_extrude(layer-0.001,center=true)difference(){ + Kreis(d=size.x,r2=size.y/2,rand=2ls); + T(y=level==1||stack?0:interlace[$idx2] )Linear(e=(size.y/es),es=es,center=true,y=1)T(( ($idx%2+$idx2)%2?1:-1)*size.x/2)square([size.x,dist],true); + } + } + + + // X + color("lightgrey")T(level==1||stack?0:interlace[$idx%2] ) Linear(e=(size.x)/es+1,es=es,center=true){ + cube([ls ,size.y,layer-.001],true); + if(rand==0&&form==0) if($idx%2)T(-es/2,size.y/2- 2ls /2)cube([es+ls ,2ls ,layer-.001],true); + else T(es*1.5,-size.y/2+ 2ls /2)cube([es+ls ,2ls ,layer-.001],true); + } + // Y + color("darkgrey")Tz(layer)T(y=level==1||stack?0:interlace[$idx%2]) Linear(e=(size.y)/es+1,es=es,y=1,center=true){ + cube([size.x,ls ,layer-.001],true); + if(rand==0&&form==0)if($idx%2)T(size.x/2- 2ls /2,-es/2)cube([2ls ,es+ls,layer-.001],true); + else T(-size.x/2+ 2ls /2,es*1.5)cube([2ls ,es+ls ,layer-.001],true); + } + } + } + if(form==1)linear_extrude(h*3,center=true)offset(rand/2)scale([1,size.y/size.x])circle(d=size.x); + if(form==0)linear_extrude(h*3,center=true)offset(rand/2)Quad(size,rad=rad); + + + } +} + + +/// Klemmbaustein construction block Lego compatible +/// KBS(e=[2,4,1],male=true); for a default block + +module KBS(e=2,grad=2,center=true,male=true,female=false,rot=0,n=4,top=false,knob,knobH,fKnob,fKnobH,dist,bh,name,help){ +male=female?false:male; +d=is_undef(knob)?4.8:knob;//knobs on top of blocks +fd=is_undef(fKnob)?d:fKnob;//fknobs on bottom of blocks +h=is_undef(knobH)?2:knobH;// knob height + + +ks=is_undef(dist)?8.0:dist; // spacing +rand=1.5; +bh=is_undef(bh)?9.6:bh;// block height +roof_thickness=1;//1.05 +pin_diameter=3; //pin for bottom blocks with width or length of 1 +post_diameter=6.5; +reinforcing_width=1.5; +axle_spline_width=2.0; +axle_diameter=5; + +fh=is_undef(fKnobH)?bh/3-roof_thickness:fKnobH; + +e=is_list(e)?e:[e,e]; + + if(e.z)linear_extrude(e.z*bh,scale=1,convexity=5)hull()Grid(e=e,es=[ks,ks,0],center=center,name=false)square(d+rand*2,center=center); + if(male||female)Grid(e=e,es=[ks,ks,0],center=center,name=false){ + + if(male)translate([0,0,e.z?e.z*bh+h:h])rotate(180,[1,0])linear_extrude(h,scale=(d/2-h/tan(90-grad))/(d/2),convexity=5) circle(d=d); + // for holes on bottom + else { + h=fh; + d=fd; + + translate([0,0,(e.z?e.z*bh:0)-.001]){ + linear_extrude(h,scale=(d/2-(h)/tan(90+grad))/(d/2),convexity=5)rotate(180/n+rot)Rund(d/3)circle(d=Umkreis(n,d),$fn=n);//;square(d,center=center); + if(top)Tz(h-.001)linear_extrude(is_bool(top)?1:top,scale=0,convexity=5)scale((d/2-(h)/tan(90+grad))/(d/2))rotate(180/n+rot)Rund(d/3)circle(d=Umkreis(n,d),$fn=n); + } + } + } +InfoTxt("KBS",["size",str( + str(d+rand*2+ks*(e.x-1),"×",d+rand*2+ks*(e.y-1),e.z?str("×",e.z*bh):"") + ,grad?str(" diff ",grad,"° bei h=2mm ",tan(grad)*2): + "" + )],name); + +HelpTxt("KBS",["e",e,"grad",grad,"center",center,"male",male,"female",female,"rot",rot,"n",n,"top",top,"knob",knob,"knobH",knobH,"fKnob",fKnob,"fKnobH",fKnobH,"dist",dist,"bh",bh,"name",name],help); +} + + +/** \page Products \name GT2Pulley +GT2Pulley() creates a Pulley for GT2 Belts +\param h belt height +\param z number tooth +\param achse center hole diameter +\param center center pulley -1=outside 0 || false=inside 1 || true=center +\param fn fragments +\param name help name help +*/ + +// GT2Pulley(h=6.5,z=16,achse=5,center=-1); + +module GT2Pulley( +h=6,// Belt h +z=16,// teeth +achse=6.6,//hole +center=true, +fn=fn, +name, +help){ +d=2*z/PI+(0.63-0.254)*2+0.2; + + +center=is_bool(center)?center?1:0:center; +T(center?center<0?[0,0,h/2+1.1]: + [0,0,0]: + [z/PI,z/PI,h/2]){ +if($info)%Ring(h,d=2*z/PI,rand=-.63,center=true); +$info=false; +LinEx(h+1,center=true)GT(z=z,achse=achse,fn=fn); + difference(){ + MKlon(tz=-h/2-1.1){ + Pille(.5,d=d,rad2=0,center=false,fn=fn);//cylinder(.5,d=12); + Tz(0.499)Kegel(d1=d,d2=d-2.5,grad=25,fn=fn); + } + Loch(h=h+2.2,h2=.5,deg=45,rad=.25,center=true,d=achse,l=0,cuts=false,fn=fn); + *cylinder(h*3,d=achse,center=true); + *MKlon(tz=-h/2-1.3)Kegel(achse+0.75); + } +//%Ring(h,d=d,rand=1.38,center=true); + +} + +InfoTxt("GT2Pulley",["aussenH",h+2.2,"d",d,"radius Riemenmitte",z/PI],name); +HelpTxt("GT2Pulley",["h",h,"z",z,"achse",achse,"center",center,"fn",fn,"name",name],help); +} + + + +module Abzweig(r1=5,r2=20,rad=2,inside=false,d1,d2,spiel=spiel,fn=fn,help){ + + r1=is_undef(d1)?r1:d1/2; + r2=is_undef(d2)?r2:d2/2; + assert(r1<=r2,"r2>r1"); + fn2=fn/2; + //$fn=fn; + +function h(i)=Kathete(r2+rad,cos(i*360/fn)*(r1+rad))-rad; +function hIn(i)=Kathete(r2+rad,cos(i*360/fn)*(r1+rad*1.50))+rad; +sc=(r1+rad-rad*sin(asin((r1+rad)/(r2+rad))))/(r1+rad); + +rotate(inside?180:0,v=[0,1])intersection(){ + difference(){ + if(!inside)cylinder(r2+rad,r=r1+rad); + if(inside)scale([1+(1-sc),1])Tz(-r2*2+rad)cylinder(r2+rad,r=r1+rad); + cylinder((r2+rad)*3,r=r1-spiel,center=true); + if(!inside)R(90)cylinder((r1+rad)*3,r=r2-spiel,center=true,$fa=+1,$fn=undef); + Tz(inside?rad*3:rad)for(i=[0:fn]){ + step=360/fn; + hull(){ + Tz(inside?-hIn(i):h(i))rotate(i*step)T(r1+rad,z=-rad)Pille(l=.1+r2+(inside?rad*3:rad)-h(i),r=rad,rad=rad,rad2=0,center=false,name=false,fn=fn,fn2=fn2); + Tz(inside?-hIn(i+1):h(i+1))rotate((i+1)*step)T(r1+rad,z=-rad)Pille(l=.1+r2+(inside?rad*3:rad)-h(i+1),r=rad,rad=rad,rad2=0,center=false,name=false,fn=fn,fn2=fn2); + } + /*hull(){ hull(){ + Tz(inside?-hIn(i):h(i))rotate(i*step)T(r1+rad)R(90)sphere(r=rad); + Tz((inside?-1:1)*r2)rotate(i*step)T(r1+rad)R(90)cylinder(.5,r1=rad,r2=0); + } + hull(){ + Tz(inside?-hIn(i+1):h(i+1))rotate((i+1)*step)T(r1+rad)R(90)sphere(rad);//cylinder(.5,r1=rad,r2=0); + Tz((inside?-1:1)*r2)rotate((i+1)*step)T(r1+rad)R(90)cylinder(.5,r1=rad,r2=0); + } + } // end hull */ + } + } +if(!inside)scale([sc,1.00])cylinder(500,r=r1+rad,center=true); +if(inside)R(90) cylinder(500,r=r2+spiel,center=true); +} + +HelpTxt("Abzweig",["r1",r1,"r2",r2,"rad",rad,"inside",inside,"d1",d1,"d2",d2,"spiel",spiel,"fn",fn],help); +} + + +/** \name BB +\page Products +BB() creates a Ball bearing + +\param achse center hole axle (calculated) +\param od outer diameter (calculated) +\param h height (calculated) +\param r radius or roller distance from center (calculated) +\param ball ball or roller diameter (calculated) +\param rand wall thickness [outer,inner] +\param e number roller (calculated) +\param spiel clearance +\param support added support ring and support distance +\param top top&bottorm thickness (calculated) +\param cage roller cage +\param cyl support base form ring or cylinder +\param rad radius of rounding +\param pip print in place distance for cage +\param wFase,cFase roller with chamfer / center chamfer +\param center center +\param name help name help +*/ + +//Cut()BB(achse=10,od=undef,ball=4.6,center=0,cyl=0,spiel=0.1); + + +module BB( +achse=5, +od=20, +h, +r, +ball, +rand=1, +e, +spiel=0.125, +support=0.15, +top, +cage=false, +cyl=true, +rad=[.5,.5], +pip=pip, +wFase, +cFase, +center=true, +name, +help + +){ +rad=is_num(rad)?[rad,rad]:rad; +rand=is_list(rand)?rand:[rand,rand]; +top=is_undef(top)?rand[0]/2:top; +ball=max(is_undef(ball)?od/2-achse/2-vSum(rand)-spiel*2: + ball + ,2); // min ball size 2 +h=is_undef(h)?ball+top*2:h; +r=max(is_undef(r)?is_undef(od)?achse/2+ball/2+rand[1]+spiel: + is_undef(achse)?od-ball/2-rand[0]-spiel: + od/4+achse/4+(rand[1]-rand[0])/2: + r + ,ball/2+rand[1]); + +walzen=wFase?true:false; +wFase=is_undef(wFase)?ball/4:wFase; +cFase=is_undef(cFase)?0:is_bool(cFase)&&cFase?wFase:walzen?cFase:0; // center + +if(hball+top*2||walzen) Echo("BB Kugel = Walze!",color="green"); +achseDia=is_undef(achse)?r*2-ball-2*rand[1]-2*spiel:min(r*2-ball-2*rand[1]-2*spiel,achse); +oDia=is_undef(od)? r*2+ball+2*rand[0]+2*spiel:max(od,r*2+ball+2*rand[0]+2*spiel); +e=is_undef(e)?floor(360/gradS(r=r,s=ball+spiel)):min(e,floor(360/gradS(r=r,s=ball+spiel))); + +if(achse&&achse>r*2-ball-2*rand[1]-2*spiel+.0000001)Echo(str("BB Achse (",achse,") zu groß - limited↦ ",achseDia),color="red"); + +if(od&&odball+top*2?str(ball,"×",h-top*2):ball,"Anzahl",e],name); + + + + Tz(center?0:h/2){ + $info=false; + $helpM=false; +// Roller + Polar(e,r)if(h>ball+top*2||walzen) + if(cFase){ + MKlon(tz=-.001)Pille(h/2-top,d=ball,rad=[cFase,wFase],fn2=walzen?1:0,center=false); + cylinder(h=cFase*2,r=ball/2-cFase+.2,center=true); + } + else Pille(h-top*2,d=ball,rad=walzen?wFase:undef,fn2=walzen?1:0); + else sphere(d=ball); +// Rings + difference(){ + union(){ + //Pille(h,d=oDia,rad=rad[0]);//Body + Loch(h=h,l=0,d=oDia,h2=rad[0],rad=rad[0],deg=-45,center=true,cuts=0,extrude=0);//Body + Tz(center?0:-h/2)children(); + } + if(achseDia) Loch(h=h,l=0,d=achseDia,h2=rad[1],rad=rad[1],deg=45,center=true,cuts=0); + //Strebe(h,d=achseDia,rad=rad[1],center=true);// Achse + + if(h>ball+top*2||walzen)Torus(trx=r,d=ball+spiel*2) + if(!walzen)MKlon(mx=1)Pille(h-top*2+spiel*2,d=$d,2D=+1); + else if(cFase){ + MKlon(ty=-.001)Quad(ball+spiel*2,h/2-(top-spiel),rad=[wFase,wFase,cFase,cFase]+spiel*[1,1,0,0],fn=1,center=[1,0]); + square([ball-cFase*2+.4+spiel*4,cFase*2],center=true); + } + else Quad(ball+spiel*2,h-(top-spiel)*2,rad=wFase+spiel,fn=1); + + else Torus(trx=r,d=ball+spiel*2);////Rille + + MKlon(tz=h/2+1.25)Torus(trx=r,d=ball,fn2=6);//innenfase + if(walzen)Mklon(tz=h/2+sqrt(3)/2*(ball-wFase*2)-top-.001)Torus(trx=r,r=ball-wFase*2,fn2=6);//innenfase + MKlon(tz=h/2-top-.5)Ring(h+1,d=r*2,rand=walzen?ball-wFase*2+spiel*2:ball/2,rcenter=true,center=false);//Trennspalt + } + + if (cage) difference(){ + union(){ + if(h>ball+top*2||walzen)Torus(trx=r,d=ball+spiel*2-pip*2) + if(!walzen)MKlon(mx=1)Pille(h-top*2+spiel*2-pip*2,d=$d,2D=+1); + else if(cFase){ + MKlon(ty=-.001)Quad(ball+(spiel-pip)*2,h/2-(top-spiel),rad=[wFase,wFase,cFase,cFase]+(spiel)*[1,1,0,0],fn=1,center=[1,0]); + square([ball-cFase*2+.4+spiel*4-pip*2,cFase*2],center=true); + } + else Quad(ball+(spiel-pip)*2,h-(top-spiel-pip)*2,rad=(ball/2+spiel-pip)/2,fn=1); + + else Torus(trx=r,d=ball+spiel*2-pip*2); + Ring(h=h,d=r*2,rand=ball/2,rcenter=true,center=true); + } + Polar(e,r){ + if(h>ball+top*2||walzen)Pille(h-top*2+pip*2,d=ball+pip*2,rad=walzen?wFase+pip:undef,fn2=walzen?1:0); else sphere(d=ball+pip*2); + Tz(-h/2)cylinder(h=h,d=ball/2-.5+pip*2,center=true); + } + if(support) Tz(-h/2) Ring(h=top,d=r*2,rand=ball,rcenter=true,center=false); + } + +//supportbrim + if(support&&!cyl)difference(){ + Tz(-h/2)union(){ + Ring(h=walzen?top-support:top+.2,d=r*2,rand=ball/2-.5,rcenter=true,center=false); + if(walzen)Polar(e,r)Kegel(d2=ball-wFase*2-support*2,d1=ball-wFase*2-top*2); + } + + if(!walzen)if (h>ball+top*2) Tz(-h/2+top+ball/2)Polar(e,r)sphere(r=ball/2+support); + else Polar(e,r)sphere(r=ball/2+support); + } + if(cyl)Tz(-h/2){ + Polar(e,r){ + cylinder(h=h/2,d=ball/2-.5); + if(walzen)Tz(top+0.001)R(180)Kegel(d1=ball-wFase*2,d2=ball-wFase*2-top*2); + } + if(support)Ring(l(2),r=r,rand=n(2),rcenter=true); + } + } +HelpTxt("BB",["achse",achse,"od",od,"h",h,"r",r,"ball",ball,"rand",rand,"e",e,"spiel",spiel,"support",support,"top",top,"cage",cage,"cyl",cyl,"rad",rad,"pip",pip,"wFase",wFase,"cFase",cFase,"center",center,"name",name],help); +} + +/** \page Products +* \name Pin +Pin() creates a pin or Peg to fix or swivel with 45°(deg) lip +\param l length ↦ [bottom,top] +\param d diameter of core body +\param cut number incisions [bottom,top] +\param cutDepth depth of the cuts +\param cutDeg angle of cuts +\param mitte middle lip +\param lippe lip size (od=d+2×lip) +\param spiel lip height and clearance between connected parts +\param center center pin +\param deg lip angle +\param flat flat sides (true or num for thickness) +\param print orient for printing +\param fn fs fraqments number size + +*/ + +//Pin(l=[3,7],deg=[60,30]); +//Pin(10,flat=true,cut=4,grad=85); + +/* +difference(){ + cube(20); + Pin(spiel=0.2,cut=false); + } +Cut()Pin(); +//*/ + + +module Pin(l=10,d=5,cut=true,cutDepth=1,cutDeg,mitte=true,grad=60,lippe=0.25,spiel=0,center=true,deg=45,flat=false,print=false,fn=0,fs=fs,name,help){ +spiel2=0.1; +$info=false; +d=d; +id=d+spiel*2; +nib=is_num(lippe)?[lippe,lippe]:lippe; +rdiff=nib+[1,1]*(spiel+spiel2); + +rdiffCenter=(is_bool(mitte)?min(lippe):mitte)+spiel+spiel2; + +cut=is_list(cut)?cut:[cut,cut]; +deg=is_list(deg)?deg:[deg,deg]; +grad=is_list(grad)?grad:[grad,grad]; +pol=[is_bool(cut[0])?flat?round(d/2)*2 + :round(d) + :cut[0], + is_bool(cut[1])?flat?round(d/2)*2 + :round(d) + :cut[1]]; + +flat=is_bool(flat)?flat?cos(45)*id/2*2:0 + :flat; + +il=is_list(l)?l:[l/2,l/2];// input l +l=is_num(l)?[l/2+spiel2*tan(deg[0]),l/2+spiel2*tan(deg[1])]:l+spiel2*[tan(deg[0]),tan(deg[1])]; +hkomplett=[ + l[0]+(grad[0]<90?tan(grad[0])*rdiff[0]:10), + l[1]+(grad[1]<90?tan(grad[1])*rdiff[1]:10) + ]; + +cutDepth=is_num(cutDepth)?cutDepth*[1,1]:cutDepth; + +// cut width for flat +flatCut=[ +max(nib[0]*2+.2,Kathete(id/2,flat/2)*2-2 ), +max(nib[1]*2+.2,Kathete(id/2,flat/2)*2-2 ) +]; + +// notches cut Length +cutH=[ + min(hkomplett[0]-nib[0],rdiff[0]*(tan(grad[0])+tan(deg[0]) )+3-spiel+cutDepth[0]), + min(hkomplett[1]-nib[1],rdiff[1]*(tan(grad[1])+tan(deg[1]) )+3-spiel+cutDepth[0]) + ]; + + +cutH2=[min(cutH[0]/2,cutDepth[0]),min(cutH[1]/2,cutDepth[1])]; + +// wedge angle +cutDeg=is_num(cutDeg)?cutDeg*[1,1]:cutDeg; +degCut=is_undef(cutDeg)?[min(flat?90:120,360/pol[0]),min(flat?90:120,360/pol[1])]:cutDeg; + +Tz(print?flat?flat/2:id/2+max(nib):0)rotate(print?[0,90]:[0,0]) + translate([0,0,center?0:l[0]+tan(grad[0])*rdiff[0]]){ +//bottom + if(il[0])mirror([0,0,1])difference(){ + union(){ + cylinder(l[0]+.001,d=id,$fn=fn,$fs=fs); + Tz(l[0]-.001)Kegel(id+rdiff[0]*2,id,h=grad[0]==90?10:0,grad=grad[0],fn=fn,fs=fs); + if(deg[0])Tz(l[0])R(180)Kegel(id+rdiff[0]*2,id-1,grad=deg[0],fn=fn,fs=fs); + if(mitte) difference(){ + Kegel(id+rdiffCenter*2,id-1,grad=45,fn=fn,fs=fs); + linear_extrude(height=rdiffCenter*2,center=true,convexity=3)Kreis(r=id,rand=id/2-rdiffCenter+spiel+spiel2,fn=fn,fs=fs); + } + } + if(cut[0]) Tz(hkomplett[0]-cutH[0]+.01)Polar(pol[0],d-cutDepth[0]) + LinEx(cutH[0],cutH2[1],0,grad=45,$d=d,center=0) + offset(-spiel)T(-d/2)Tri(h=$d,top=+1,tang=0,center=0,grad=degCut[0],r=0.3,fn=12); + + Tz(rdiffCenter) linear_extrude(hkomplett[0],center=false,convexity=3)Kreis(r=id,rand=id/2-rdiff[0]+spiel+spiel2,fn=fn,fs=fs); + if(flat){ + MKlon(flat/2+d/2)cube([d-spiel*2,d*2,vSum(hkomplett)*3],true); + if(cut[0])Tz(l[0]-min(l[0]-0.5,3))R(0,-90)linear_extrude(id*2,center=true)Quad(hkomplett[0],flatCut[0],center=[0,1]); + } + } +//top + if(il[1])difference(){ + union(){ + cylinder(l[1]+.001,d=id,$fn=fn,$fs=fs); + Tz(l[1]-.001)Kegel(id+rdiff[1]*2,id,grad=grad[1],h=grad[1]==90?10:0,fn=fn,fs=fs); + if(deg[1])Tz(l[1])R(180)Kegel(id+rdiff[1]*2,id-1,grad=deg[1],fn=fn,fs=fs); + if(mitte)difference(){ + Kegel(id+rdiffCenter*2,id-1,grad=45,fn=fn,fs=fs); + linear_extrude(height=rdiffCenter*2,center=true,convexity=3)Kreis(r=id,rand=id/2-rdiffCenter+spiel+spiel2,fn=fn,fs=fs); + } + } + if(cut[1]) Tz(hkomplett[1]-cutH[1]+.01)Polar(pol[1],d-cutDepth[1]) + LinEx(cutH[1],cutH2[1],0,grad=45,$d=d,center=false) + offset(-spiel)T(-$d/2)Tri(h=$d,top=+1,center=+0,tang=0,grad=degCut[1],r=0.3,fn=12); + + Tz(rdiffCenter) linear_extrude(hkomplett[1],center=false,convexity=3)Kreis(r=id,rand=id/2-rdiff[1]+spiel+spiel2,fn=fn,fs=fs); + if(flat){ + MKlon(flat/2+d/2)cube([d-spiel*2,d*2,vSum(hkomplett)*2],true); + if(cut[1])Tz(l[1]-min(l[1]-0.5,3))R(0,-90)linear_extrude(id*2,center=true)Quad(hkomplett[1],flatCut[1],center=[0,1]); + } + } +} +//if(achse)cylinder(h=achse,d=d+rdiff*2,center=true); + +InfoTxt("Pin",["l",l[0]+l[1],"reale höhe",vSum(hkomplett),"halb",str(l,"/",hkomplett),"plusCap",str((tan(grad[0])+tan(grad[1]))*rdiff," (",tan(grad[0])*rdiff,"/",tan(grad[1])*rdiff,")"),"Lippe",lippe],name); + +HelpTxt("Pin",["l",l,"d",d,"cut",cut,"cutDepth",cutDepth,"cutDeg",cutDeg,"mitte",mitte,"grad",grad,"lippe",lippe,"spiel",spiel,"center",center,"deg",deg,"flat",flat,"print",print,"fn",fn,"fs",fs,"name",name],help); + +} + + + +//Klammer(grad=[100,130],rad2=[2,3])T($x/2)circle(d=$x); +//Klammer(grad=[100,130],rad2=[2,3]); + +module Klammer(l=10,grad=250,d=4,rad2=5,offen,breite=2.5,deg2=[12.5,12.5],fn=fn,help){ $x=breite; - w2=offen/2-90+grad/2; + $d=breite; + $r=breite/2; + grad=is_list(grad)?grad:grad/[2,2]; + deg2=is_num(offen)?[offen/2,offen/2]:is_list(deg2)?deg2:deg2*[1,1]; + w2=[deg2[0]-90+grad[0],deg2[1]-90+grad[1]]; l=is_list(l)?l:[l,l]; + rad2=is_list(rad2)?rad2:[1,1]*rad2; if($children){ - RotEx(grad,center=true,fn=fn)T(d/2)children(); //centerring + rotate(-(grad[1]-grad[0])/2)RotEx(vSum(grad),center=true,fn=fn)T(d/2)children(); //centerring + union(){ //arme $helpM=0; $info=0; MKlon(mz=0,my=1){ - rotate((grad-180.01)/2)T(0,rad2+breite+d/2)rotate(270-w2){ - RotEx(w2,fn=fn/2)T(rad2+breite)mirror([1,0])children();//Bogen - T(rad2)union(){ + rotate(($idx?grad[0]:grad[1])-90.01)T(0,($idx?rad2[0]:rad2[1])+breite+d/2)rotate(270-($idx?w2[0]:w2[1])){ + RotEx(($idx?w2[0]:w2[1]),fn=fn/2)T(($idx?rad2[0]:rad2[1])+breite)mirror([1,0])children();//Bogen + T($idx?rad2[0]:rad2[1])union(){ R(90)linear_extrude(height=$idx?l[0]:l[1])T(breite)mirror([1,0])children(); // Arm grade T(+breite/2,$idx?-l[0]:-l[1])rotate(180) RotEx(cut=true,grad=180,fn=fn/4)T(-breite/2)children(); //Endstück } @@ -4306,11 +12557,11 @@ module Klammer(l=10,grad=250,d=4,rad2=5,offen=+25,breite=2.5,fn=fn,help){ }else union(){ $info=0; $helpM=0; - Kreis(grad=grad,center=true,r=d/2,rand=-breite,fn=fn); + Kreis(grad=vSum(grad),rot=(grad[1]-grad[0])/2,center=true,r=d/2,rand=-breite,fn=fn); MKlon(mz=0,my=1){ - rotate((grad-180.01)/2)T(0,rad2+breite+d/2)rotate(180){ - Kreis(grad=w2,fn=fn/2,center=false,r=rad2,rot=-90,rand=-breite); - rotate(-w2)T(0,rad2){ square([$idx?l[0]:l[1],breite]); + rotate((grad[$idx]-90.01))T(0,($idx?rad2[0]:rad2[1])+breite+d/2)rotate(180){ + Kreis(grad=($idx?w2[0]:w2[1]),fn=fn/2,center=false,r=($idx?rad2[0]:rad2[1]),rot=-90,rand=-breite); + rotate(-($idx?w2[0]:w2[1]))T(0,($idx?rad2[0]:rad2[1])){ square([$idx?l[0]:l[1],breite]); T($idx?l[0]:l[1],breite/2)Kreis(grad=180,fn=fn/4,center=false,rot=-90,r=breite/2,rand=0); } } @@ -4327,6 +12578,7 @@ HelpTxt("Klammer",[ "d",d, "rad2",rad2, "offen",offen, + "deg2",deg2, "breite",breite, "fn",fn] ,help); @@ -4334,144 +12586,238 @@ HelpTxt("Klammer",[ } -module Welle(e=3,grad=200,r=5,r2,center=3,rand=2,fn=fn,overlap=0,name,help){ - - r2=is_undef(r2)?r:r2; - $x=rand; - w=(grad-180)/2; - y=2*cos(w)*r; - y2=2*cos(w)*abs(r2); - - T(0,center?center>1?center>2?y2/2:-y/2:0:y2)Linear(es=y+y2,e=e,x=0,y=1,center=center)union(){ - if(!$children){ - T(sin(w)*r,y/2) Kreis(grad=grad+overlap,r=r,fn=fn,rand=rand,rcenter=true,sek=true); - T(-sin(w)*r2,-y2/2) Kreis(grad=grad+overlap,fn=fn,r=-r2,rand=rand,rcenter=true,sek=true); - } - else { - - T(sin(w)*r,y/2) RotEx(grad=grad+overlap,fn=fn,center=true)T(r)children(); - union(){ - $info=0; - $helpM=0; - T(-sin(w)*r2,-y2/2)RotEx(grad=grad+overlap,fn=fn,center=true)T(-r2)children(); - } - - } - } - InfoTxt("Welle",["Wellenenhöhe r/r2=",str(r+sin(w)*r,"/",-r2-sin(w)*r2),"Abstand r/r2=",str(y,"/",y2),"Länge=",e*(y+y2)],name); -HelpTxt("Welle",[ - "e",e," - grad",grad," - r",r," - r2",r2," - center",center," - rand",rand," - fn",fn," - overlap",overlap," - name",name] - ,help); +/** \page Products \name CGear \brief CGear() makes a cycloidal gear using roof +\param z number teeth +\param h height optional list for helical [h] or fishbone [h,h] or [h,h,h] +\param module teeth modul size +\param deg angle +\param d shaft diameter +\param f fraction from gear +\param r optional r for twist angle calculation +\param chamfer chamfer height +\param deg2 bevel gear angle // experimental +\param spiel clearance +\param lap overlap +\param fn fs fraqments +\param help help +*/ + +//CGear(d=3,deg=-45,h=3); +//CGear(d=3,deg=-45,h=[3,3],deg2=40); + + + +module CGear(z=20,h=5,modul=3,deg=45,d=0,f=3,r,chamfer=.25,deg2=90,spiel=0.05,lap=.001,base=1,fn=$preview?6:36,fnd,fs=0.075,help){ + +iH=is_list(h)?h:[h/8*3,h/4,h/8*3]; +opt=len(iH); // 1 helical 2 fishbone 3 fishbone with center +iZ=z/f; +r=is_num(r)?r:iZ*modul/2; +$r=r; +chamfer=is_list(chamfer)?chamfer:[chamfer,chamfer]; +Echo("d unavailable for deg2!= 90",color="warning",condition=deg2!=90&&d); +id=deg2==90?d:0; + +//bottom +iScale0=scaleGrad(r=r,grad=deg2,h=iH[0]-(opt==1?vSum(chamfer):chamfer[0])); +//center +iScale1=opt==3?scaleGrad(r=r*iScale0,grad=deg2,h=iH[1]-(opt==2?chamfer[1]:0)):1; +//top +iScale2=opt==3?scaleGrad(r=r*iScale0*iScale1,grad=deg2,h=iH[2]-chamfer[1]) +:opt==2?scaleGrad(r=r*iScale0,grad=deg2,h=iH[1]-chamfer[1]):1; + +iScale=[iScale0,iScale1,iScale2]; + +baseScale=scaleGrad(r=r,grad=deg2,h=base); +stretch=deg2==90?1:1+1/tan(deg2); +//echo(iScale); +function twist(h)=gradB(r=r,b=tan(deg)*h); + +//bottom +rotate(twist(iH[0]-chamfer[0]*(opt==1?2:1)) / (opt==1?2:1) )Roof(iH[0],[1,opt==1?1:0]*chamfer[0],twist=twist(iH[0]-chamfer[0]*(opt==1?2:1)),scale=iScale[0],name=0) + if($children)children(); + else CycloidZahn(z=iZ,f=f,modul=modul,d=id,spiel=spiel,fn=fn,fnd=fnd,fs=fs,help=0,name=0,scale=stretch); +//center +if(opt==3)Tz(iH[0]-lap)linear_extrude(iH[1]+lap*2,convexity=10,scale=iScale[1])scale(iScale[0]) + if($children)children(); + else CycloidZahn(z=iZ,f=f,modul=modul,d=id,spiel=spiel,fn=fn,fnd=fnd,fs=fs,help=0,name=0,scale=stretch); + //top +if(opt>1)Tz(vSum(iH,end=len(iH)-2))Roof(iH[len(iH)-1],[0,1]*chamfer[1],twist=-twist(iH[len(iH)-1]-chamfer[1]),scale=iScale[2],name=0)scale(iScale[1]*iScale[0]) + if($children)children(); + else CycloidZahn(z=iZ,f=f,modul=modul,d=id,spiel=spiel,fn=fn,fnd=fnd,fs=fs,help=0,name=0,scale=stretch); + +if(deg2!=90&&base)intersection(){ + rotate(twist(base)+twist(iH[0]-chamfer[0]*(opt==1?2:1)) / (opt==1?2:1) ) + Tz(-base)Roof(base+chamfer[0],[1,0]*chamfer[0],twist=twist(base),scale=baseScale,name=0) + if($children)scale(baseScale)children(); + else scale(1/baseScale)CycloidZahn(z=iZ,f=f,modul=modul,d=id,spiel=spiel,fn=fn,fnd=fnd,fs=fs,help=0,name=0,scale=stretch); + Tz(-base)Kegel(h=base+chamfer[0],grad=-45,r1=(r-modul/5)/baseScale,name=0); + } + +HelpTxt("CGear",["z",z,"h",h,"modul",modul,"deg",deg,"d",id,"f",f,"chamfer",chamfer,"spiel",spiel,"lap",lap,"fn",fn,"fnd",fnd,"fs",fs],help); } -module Pille( -l=10, -d,//+5, -rad, -rad2, -r, -center=true, -fn=fn, -fn2=fn/4, -loch=false, -grad=360, -2D=false, -name, -help -){ -2D=is_parent(needs2D)&&!$children?2D?b(2D,false): - 1: - b(2D,false); - - -fn2=is_list(fn2)?fn2:[fn2,fn2]; -r=is_undef(r)?is_undef(d)?l/2:d/2:r; -rad=is_undef(rad)?2*rPille zu kurz! ",l-rad[0]+ausgleich-rad2+ausgleich2)); - -points=concat([ -if(!loch)[0,0], -if(!loch)[0,l]], -rad2==0?[[d/2,l]]:Kreis(r=rad2,rand=0,grad=grad2,t=[d/2-rad2,l-rad2+ausgleich2],fn=fn2[1],center=false,rot=90-grad2), -rad[0]==0?[[d/2,0]]:Kreis(r=rad[0],rand=0,grad=rgrad,t=[d/2-rad[0],rad[0]-ausgleich],fn=fn2[0],center=false,rot=90) - -); - -if(!2D)if(rgrad==90&&grad2==90)Tz(center?-l/2:0)RotEx(grad=grad,fn=fn)polygon(points); - else Tz(center?-l/2:0)RotEx(grad=grad,fn=fn)polygon(clampToX0(points)); -if(2D)T(0,center?-l/2:0)polygon(points); - - InfoTxt("Pille",["Länge",l,"Rundung",str(rad[0],"/",rad2,str(rad[0]>d/2?" Spitz":rad[0]==d/2?" Rund":" Flach","/",rad2>d/2?"Spitz":rad2==d/2?"Rund":"Flach")),"Durchmesser",d,"Radius",d/2,"Grad",str(grad,"°")],name); - - HelpTxt("Pille",["l",l,"d",d,"fn",fn,"fn2",fn2,"center",center,"name",name,"rad",rad,"rad2",rad2,"loch",loch,"grad",grad,"2D",2D,],help); +module CyclGear(z=20,modul=2,w=45,h=4,h2=.5,grad=45,achse=3.5,achsegrad=45,light=false,lock=false,center=true,lRand=wall(0.8,$info=false),lRandBase,d=0,rot,rotZahn=1,linear=false,preview=true,spiel=0.075,f=3,fn=24,lap=0,name,help){ +CyclGetriebe(z=z,modul=modul,w=w,h=h,h2=h2,grad=grad,achse=achse,achsegrad=achsegrad,light=light,lock=lock,center=center,lRand=lRand,lRandBase=lRandBase,d=d,rot=rot,rotZahn=rotZahn,linear=linear,preview=preview,spiel=spiel,f=f,fn=fn,lap=lap,name,help); } - -module Row(e=15,dist=2,step=.1,d=+1,cut=.25,dir=+1,center=true,name,help){ +module CyclGetriebe(z=20,modul=1.5,w=45,h=4,h2=.5,grad=45,achse=3.5,achsegrad=45,light=false,lock=false,center=true,lRand=wall(.5,$info=false),lRandBase,d=0,rot,rotZahn=1,linear=false,preview=true,spiel=0.075,f=2,fn=24,name,help,lap=0){ + //$info=false; + z=abs(round(z)); + rot=is_undef(rot)?90/z*rotZahn:rot; + center=is_bool(center)?center?1:0:center; + preview=$preview?preview:true; + linear=linear==true?1:linear; + r=z/f*modul/2; + mitteR=(r-modul/2)/2+achse/4; + rand=r-achse/2-modul/2-lRand*2; + lRandBase=is_undef(lRandBase)?lRand*1.85:lRandBase; - /* Row will recursivly create a Row of objects with changing size (d+e*step) - / by keeping the gap equal - */ - - $d=d; - $r=d/2; - $info=is_undef(name)?is_undef($info)?true:$info:name; - $helpM=is_undef(help)?is_undef($helpM)?false:$helpM:help; - $idx=e-1; - cut=is_num(cut)?cut:cut==true?0.02:false; - if(e>1)T(d+dist+step/2) - if($children)Row(e=e-1,d=d+step,dist=dist,step=step,cut=cut,dir=dir<2?sign(dir*-1):dir,center=center,name=$info,help=$helpM)children(); - else Row(e=e-1,d=d+step,dist=dist,step=step,cut=cut,dir=dir<2?sign(dir*-1):dir,center=center,name=$info,help=$helpM); - - if(!$children)cylinder(100,d=$d,$fn=24,center=center); - if($children)children(); - if(cut) T(-cut/2,dir>0?dir>1?0:0:-viewportSize,center?-viewportSize/2:0)color(alpha=0.0)cube([cut,viewportSize,viewportSize]); - if(e==1)InfoTxt("Row",["last d",str($d,cut?str(" Cut is ",cut):"")],name); - + if(!linear){ + T(center?0:-z/f/2*modul)T(y=center>1?z/f/2*modul:0)rotate(rot - (center>1?90:0))difference(){ + $info=false; + LinEx(h=h,h2=h2,$d=z/f*modul,mantelwinkel=w,slices=preview?(h-1)*2:2,grad=d>r*2?-grad:grad,lap=lap) + if($preview&&!preview) Kreis(d=d>r*2?d:$d,rand=d>r*2?d/2-r:r-d/2); + else CycloidZahn(modul=modul,z=z/f,f=f,d=d,spiel=spiel,fn=fn); + //center hole + if(achse) Tz(-.01)LinEx(h=h+.02,h2=h2,$d=achse,grad=-achsegrad)circle(d=$d,$fs=fs,$fn=0,$fa=2); - HelpTxt("Row",[ - "e",e," - dist",dist," - step",step," - d",d," - cut",cut," - dir",dir," - center",center," - name",$info], - $helpM); + if(light) Tz(-0.01)Polar(light)T(light>1?mitteR:0)LinEx(h=h+.02,h2=h2,$r=rand,grad=-60)T(light>1?-mitteR:0)Rund(min(rand/light,rand/2-0.1),fn=fn)Kreis(r=mitteR,rand=rand, + grad=min(360/light - gradS(s=lRand,r=mitteR+rand/2),320), + grad2=max(360/light - gradS(s=wall(lRandBase),r=mitteR-rand/2),2) + ,rcenter=true,fn=fn/light*2); + + if(lock)rotate(90)Tz(-0.01)LinEx(h=h+.02,h2=h2,$r=achse/2,grad=-60)WStern(f=is_num(lock)?lock:5,help=0,r=$r,fn=(is_num(lock)?lock:5)*15); + } + InfoTxt("CyclGetriebe",["Wälzradius",z/f*modul/2],name); + } - if($helpM&&!$idx)echo("Row will recursivly create a Row of objects with changing size $d=(d+e*step) by keeping the gap (dist) equal"); + + if (linear){ + $info=false; + M(skewzx=-tan(w))T(0,-linear)LinEx(h,.5,$r=linear,grad=[90,grad],grad2=[90,grad])T(0,linear)CycloidZahn(z=z/f,f=f,modul=modul,fn=fn,linear=linear,center=center,spiel=spiel); + } + //Color()T(mitteR,0,4)circle(d=rand); + +HelpTxt("CyclGetriebe",[ + "z",z, +"modul",modul, +"w",w, +"h",h, +"h2",h2, +"grad",grad, +"achse",achse, +"achsegrad",achsegrad, +"light",light, +"lock",lock, +"center",center, +"lRand",lRand, +"lRandBase",lRandBase, +"d",d, +"rot",rot, +"rotZahn",rotZahn, +"linear",linear, +"preview",preview, +"spiel",spiel, +"f",f, +"fn",fn, +"name",$info] +,help); + } +//DRing(d=5); + + +module DRing(d=4,id=20,r=.5,l=0,grad=180,fn=fn,center=true,name,help){ + $info=false; + $d=d; + r=is_list(r)?r:[r,d/2]; + + + translate(center?[0,0]:[0,d/2+r[0]+l])union(){ + if($children){ + DBogen(fn=fn/2,grad=grad,x=(id+d)+r[0]*2,rad2=max(r[1],.0001))children(); + union(){ + $info=false; + //RotEx(180,fn=fn/2)T((id+d)/2+r)children(); + T(y=-l)MKlon(tx=id/2)rotate(-90)RotEx(90,fn=fn/4)T(d/2+r[0])children(); + T(y=-d/2-r[0]-l)R(90,0,-90)linear_extrude(id,center=true)children(); + if(l)MKlon((id+d)/2+r[0])R(90)linear_extrude(l,center=false)children(); + } + } + else{ + //RotEx(180,fn=fn/2)T((id+d)/2+r[0]) circle(d=d,$fn=fn); + DBogen(fn=fn/2,grad=grad,x=(id+d)+r[0]*2,rad2=max(r[1],.0001))circle(d=d,$fn=fn); + T(y=-l)MKlon(tx=id/2)rotate(-90)RotEx(90,fn=fn/4)T(d/2+r[0])circle(d=d,$fn=fn); + if(l)MKlon((id+d)/2+r[0])R(90)linear_extrude(l,center=false) circle(d=d,$fn=fn); + T(y=-d/2-r[0]-l)R(90,0,-90) linear_extrude(id,center=true) circle(d=d,$fn=fn); + + } + if(name)%T(y=-d-r[0]-l-$vpd/100)Caliper(id,messpunkt=0); + } +InfoTxt("DRing",["dist",id+r[0]*2+d,"mm innen h=",str(l+2*r[0]+id/2,"mm")],name); +HelpTxt("DRing",[ + "d",d, + "id",id, + "r",r, + "l",l, + "grad",grad, + "fn",fn, + "centre",center, + "name",name] + ,help); +} + +/** \page Products +\name SRing +SRing() creates a self locking retaining ring +\param e number of arms +\param id target arbor diameter +\param od outer diameter +\param h thickness +\param rand rim +\param reduction smaller id/2 +\param schlitz ratio land/groove +*/ + + +// SicherungsRing +module SRing(e=4,id=3.5,od=10,h=.8,rand=1.5,reduction=.5,schlitz=-17,help){ +$info=false; +intersection(){ + LinEx(h,.2,scale=1.05)Rund(0.3)difference(){ + Kreis(od/2); + Rund(0.5) Stern(e,od/2-rand,id/2-reduction-1,mod=100,delta=schlitz); + rotate(180+180/e)intersection_for(i=[0:e-1])rotate(i*360/e)T(reduction)Kreis(id/2,fn=e*15); + } + Tz(-.005)Pille(h+.01,d=od,rad=min(.3,h/3),center=false); +} +HelpTxt("SRing",[ +"e",e, +"id",id, +"od",od, +"h",h, +"rand",rand, +"reduction",reduction, +"schlitz",schlitz,] +,help); +} + +/* +Bevel(5){ +cube(5); +R(180)VarioFill(dia=0,spiel=[.5,0],l=.5,fn=7); +}// */ + + module PCBcase( pcb=[20,40,1],/*[breite×länge×höhe]*/ h=20,/*höhe*/ @@ -4624,950 +12970,33 @@ clip",clip } -module Seg7(n=8,h=10,b=1,spiel=n(1),l,center=false,rund,name,help){ - spiel=spiel/sqrt(2); - l=is_undef(h)?l:h/2-b/2-spiel*2; - y=l/2; - x=b/2; - y2=y-x; - - /* - num=[for(n)each - if(n==0)[1,1,1,1,1,0,1] - else if(n==1) [0,1,0,1,0,0,0] - else if(n==2) [1,0,0,1,1,1,1] - else if(n==3) [0,1,0,1,1,1,1] - else if(n==4) [0,1,1,1,0,1,0] - else if(n==5) [0,1,1,0,1,1,1] - else if(n==6) [1,1,1,0,1,1,1] - else if(n==7) [0,1,0,1,0,0,1] - else if(n==8) [1,1,1,1,1,1,1] - else if(n==9) [0,1,1,1,1,1,1] - else if(is_list(n))n - ]; - */ - codetable=[ - [1,1,1,1,1,0,1] - ,[0,1,0,1,0,0,0] - ,[1,0,0,1,1,1,1] - ,[0,1,0,1,1,1,1] - ,[0,1,1,1,0,1,0] - ,[0,1,1,0,1,1,1] - ,[1,1,1,0,1,1,1] - ,[0,1,0,1,0,0,1] - ,[1,1,1,1,1,1,1] - ,[0,1,1,1,1,1,1] - ]; - num=is_list(n)?n:codetable[n]; - - points=[[0,y],[x,y2],[x,-y2],[0,-y],[-x,-y2],[-x,y2]]; - T(center?0:l/2+b/2+spiel,center?0:l+b/2+spiel*2){ - Grid(es=l+spiel*2,name=0)if(num[$idx[0]+$idx[1]*2])Rund(is_undef(rund)?0:rund?rund:b/2-minVal)polygon(points); - - Grid(es=l+spiel*2,e=[1,3,1],name=0)rotate(90)if(num[4+$idx[1]])Rund(is_undef(rund)?0:rund?rund:b/2-minVal)polygon(points); - } - if(name)echo(str(is_string(name)?"

    ":"",name," Seg7 Höhe=",l*2+b+spiel*4,"mm Breite=",l+b+spiel*2,"mm")); - - HelpTxt("Seg7",["n",n,"h",h,"b",b,"spiel",spiel*sqrt(2),"l",l,"center",center,"rund",rund,",name",name],help); -} - -module Zylinder(h=20,r=10,d,fn,fnh,grad=360,grad2=89,f=10,f2=5,f3=0,a=.5,a3=0,fz=0,az=0,deltaFz=0,deltaF=0,deltaF2=0,deltaF3=0,twist=0,winkelF3=0,scale=+1,sphere=0,lz,altFaces=1,center=false,lambda,name,help){ - a=is_undef(a)?0:a; - r=is_undef(d)?is_undef(r)?0: - r: - d/2; - lambda=is_list(lambda)?lambda:[lambda,lambda]; - f=is_undef(lambda[0])?is_undef(f)?0: - f: - round(PI*2*abs(r)/lambda[0]); - f2=is_undef(lambda[1])?is_undef(f2)?0: - f2: - round(abs(h)/lambda[1]*2)/2; - fn=max(is_undef(fn)?f*2:fn,3); - fnh=max(is_undef(fnh)?f2*2:fnh,1); - - stepRot=grad/fn; - stepH=h/fnh; -InfoTxt("Zylinder",["f",f,"f2",f2,"a",a,"lamda f",(2*PI*r)/f,"λ-f2",h/f2,"λ-f3",(2*PI*r)/f3,"λ-fz",h/fz,"r",str(r+a+a3+az,"/",r-a-a3-az),"d",str((r+a+a3+az)*2,"/",(r-a-a3-az)*2)],name); -points=[for(z=[0:fnh],rot=[0:fn])RotLang( - rot=rot*stepRot+twist*z/fnh+winkelF3*sin(rot*stepRot*f3+deltaF3), - l=(1+(scale-1)*z/fnh)*(a*cos(rot*stepRot*f+deltaF)*cos(z*f2*360/fnh+deltaF2)+az*sin(z*fz*360/fnh+deltaFz)), - lz=lz, - z=sphere?undef:z*stepH, - e=z*grad2/fnh - )+ -RotLang( - rot=rot*stepRot+twist*z/fnh, - l=(1+(scale-1)*z/fnh)*(r+a3*cos(rot*stepRot*f3)), - lz=h, - z=sphere?undef:0,//z*stepH, - e=z*grad2/fnh - ) - -]; -//echo(points); - -faces=[ -if(altFaces==0)each[for(i=[-1:len(points)-fn-2])[i,i+1,i+2+fn,i+fn+1]],//0 -if(altFaces==1)each[for(i=[0:1:len(points)-fn-3])each[ //1 - if(i%2)[i,i+fn+2,i+fn+1]else [i,i+1,i+fn+1] , - if(i%2)[i+0,i+1,i+fn+2] else [i+1,i+fn+2,i+fn+1] , - //if(i90&&i<=180)[r*pow(abs(sin(i)),2/n12),-r2*pow(abs(cos(i)),2/n22)], - if(i>180&&i<=270)[-r*pow(abs(sin(i)),2/n13),-r2*pow(abs(cos(i)),2/n23)], - if(i>270&&i)[-r*pow(abs(sin(i)),2/n14),r2*pow(abs(cos(i)),2/n24)], - ] - ]); - else{ - points=[for(fz=[0:fnz],f=[0:fn]) - let(i=f%fn*360/fn,j=fz*180/fnz) - each[ - - if(i<=90&&j<=90) [r*pow(sin(i),2/n11)*pow(sin(j),2/n31[1]),r2*pow(cos(i),2/n21)*pow(sin(j),2/n32[1]),r3*pow(cos(j),2/n3[1])], - if(i>90&&i<=180&&j<=90) [r*pow(abs(sin(i)),2/n12)*pow(sin(j),2/n31[1]),-r2*pow(abs(cos(i)),2/n22)*pow(sin(j),2/n32[1]),r3*pow(cos(j),2/n3[1])], - if(i>180&&i<=270&&j<=90)[-r*pow(abs(sin(i)),2/n13)*pow(sin(j),2/n31[1]),-r2*pow(abs(cos(i)),2/n23)*pow(sin(j),2/n32[1]),r3*pow(cos(j),2/n3[1])], - if(i>270&&i&&j<=90) [-r*pow(abs(sin(i)),2/n14)*pow(sin(j),2/n31[1]),r2*pow(abs(cos(i)),2/n24)*pow(sin(j),2/n32[1]),r3*pow(cos(j),2/n3[1])], - - if(i<=90&&j>90) [r*pow(sin(i),2/n11)*pow(sin(j),2/n31[0]),r2*pow(cos(i),2/n21)*pow(sin(j),2/n32[0]),-r3*pow(abs(cos(j)),2/n3[0])], - if(i>90&&i<=180&&j>90) [r*pow(abs(sin(i)),2/n12)*pow(sin(j),2/n31[0]),-r2*pow(abs(cos(i)),2/n22)*pow(sin(j),2/n32[0]),-r3*pow(abs(cos(j)),2/n3[0])], - if(i>180&&i<=270&&j>90) [-r*pow(abs(sin(i)),2/n13)*pow(sin(j),2/n31[0]),-r2*pow(abs(cos(i)),2/n23)*pow(sin(j),2/n32[0]),-r3*pow(abs(cos(j)),2/n3[0])], - if(i>270&&i&&j>90) [-r*pow(abs(sin(i)),2/n14)*pow(sin(j),2/n31[0]),r2*pow(abs(cos(i)),2/n24)*pow(sin(j),2/n32[0]),-r3*pow(abs(cos(j)),2/n3[0])], - - - ] - ]; - - - faces=[for(i=[0:len(points)-fn -3])[i+1,i,i+fn+1,i+2+fn]]; - //faces2=[[for(i=[0:fn-1])i],[for(i=[len(points)-fn:len(points)-1])i]]; - - polyhedron(points,faces,convexity=5); - - } - - - HelpTxt("Superellipse",["n",n,"r",r,"n2",n2,"r2",r2,"n3",n3,"n31",n31,"n32",n32,"r3",r3,"fn",fn,"fnz",fnz,"name",name],help); -} - - -module WaveEx(grad=0,h=50,r=5,ry,f=0,fy,a=1,ay,fv=0,fvy,tf=0,trx=20,try,tfy=0,tfv=0,tfvy=0,ta=1,tay,fn=fn,fn2=fn,rot=0,scale=1,scaley,close=true,p=0,name,help){ - ay=is_undef(ay)?a:ay; - fy=is_undef(fy)?f:fy; - ry=is_undef(ry)?r:ry; - scaley=is_undef(scaley)?scale:scaley; - fvy=is_undef(fvy)?fv:fvy; - try=is_undef(try)?trx:try; - tay=is_undef(tay)?ta:tay; - close=grad>=360?p?true:false:close; - - - twist=0; - rotate=rot; - - pointsLin=!grad?[for(i=[0:fn],j=[0:fn2])concat( kreis(rot=rotate+twist/fn*i,fn=fn2,rand=0,r=(1+(scale-1)/fn*i)*(r+sin(i*f*360/fn+fv)*a),r2=(1+(scaley-1)/fn*i)*(ry+sin(i*fy*360/fn+fvy)*ay),t=[trx+ta*sin(i*tf*360/fn+tfv),try+tay*cos(i*tfy*360/fn+tfvy)])[j],[i*h/fn])]:0; - - - function RotEx(rot=grad,punkte=Kreis(rot=rotate+twist/fn,fn=fn2,rand=0,r=(1+(scale-1)/fn)*(r+sin(0*f*360/fn+fv)*a),r2=(1+(scaley-1)/fn)*(ry+sin(0*fy*360/fn+fvy)*ay),t=[0,0]),verschieb=trx,verschiebY=try,p=-p,detail=fn*grad/360)=[for(rotation=[detail:-1:0])for(i=[0:len(punkte)-1]) - concat( - (punkte[i][0]+cos(f*rotation*grad/detail+fv)*a*cos(i*360/fn2)+verschieb)*sin(rotation*grad/detail)+sin(tfv+rotation*grad/detail*(tf+1))*ta, - punkte[i][1]+cos(fy*rotation*grad/detail+fvy)*-ay*sin(i*360/fn2)+rotation/detail*p*grad/360+sin(tfvy+rotation*grad/detail*(tfy+0))*tay, - (punkte[i][0]+cos(f*rotation*grad/detail+fv)*a*cos(i*360/fn2)+verschiebY)*cos(rotation*grad/detail)+cos(tfv+rotation*grad/detail*(tf+1))*ta - ) - ]; - pointsRot=RotEx(rot=grad); - - points=grad?pointsRot:pointsLin; - - //pointsMod=[for(i=[0:len(points)-1])[points[i][0]*1.0,points[i][1]*1,points[i][2]*1]]; - - //faces1=[for(i=[0:len(points)-fn2-3])each[[i,i+1,i+fn2+1],[i+1,i+fn2+2,i+fn2+1]]];// Triangle faces×2 - bottom=[[for(i=[0:fn2-1])(fn2-1)-i]]; - top =[[for(i=[len(points)-fn2:len(points)-1])i]]; - faces2=[for(i=[0:len(points)-fn2-3])[i,i+1,i+fn2+2,i+fn2+1]];// Quad face version - - rotate(grad?[-90,0,-90-(360-grad)/2]:[0,0,0])polyhedron(points=points,faces=close?concat( - faces2, - bottom, - top - ):faces2,convexity=5); - - HelpTxt("WaveEx",["grad",grad,"h",h,"r",r,"ry",ry,"f",f,"fy",fy,"a",a,"ay",ay,"fv",fv,"fvy",fvy,"tf",tf,"trx",trx,"try",try,"tfy",tfy,"tfv",tfv,"tfvy",tfvy,"ta",ta,"tay",tay,"fn",fn,"fn2",fn2,",rot",rot,"scale",scale,"scaley",scaley,"close",close,"p",p,"name",name],help); - - if(help)echo(str("r=radius, f=frequenz, fv=freqverschiebung, a=amplitude, trx=translatetRadiusX, p=steigung")); - - -} - - - - -module WStern(f=5,r=1.65,a=.25,r2,fn=fn,fv=0,name,help){ - - step=360/fn; - a=is_undef(r2)?a:(r2-r)/2; - r=is_undef(r2)?r:r+a; - points=[for(i=[0:fn])let(i=i%fn)[(r+a*cos(f*i*step+fv))*sin(i*step),(r+a*cos(f*i*step+fv))*cos(i*step)]]; - - - polygon(points); - InfoTxt("WStern",["OD",(r+a)*2,"ID",(r-a)*2],name); - HelpTxt("WStern",["f",f,"r",r,"a",a,"r2",r2,"fn",fn,"fv",fv,"name",name],help); - -} - - -module REcke(h=5,r=5,rad=.5,rad2,single=0,grad=90,fn=fn,help){ -rad2=is_undef(rad2)?rad:rad2; - radius=TangentenP(180-grad,r,r); - radius2=TangentenP(180-grad,r+Hypotenuse(rad,rad),r-rad); - - difference(){ - if(grad==90)T(-rad,-rad)cube([r+rad,rad+r,h]); - else translate([-rad*tan(90-grad/2),-rad]) rotate_extrude(angle=grad,convexity=5)square([radius2,h]); - translate(RotLang(90-grad/2,radius))rotate(grad/2+180)Strebe(angle=200-grad,h=h,single=single,2D=0,rad=rad,rad2=rad2,d=2*r,help=0,name=0,fn=fn); - } -if(help)echo(str("

    Help REcke(h=",h,",r=",r,",rad=",rad,",rad2=",rad2,",single=",single,",grad=",grad," ,fn=",fn," ,help")); - if(grad!=90)echo("

    WIP grad!=90"); -} - - - -module SBogen(dist=10,r1=10,r2,grad=45,l1=15,l2,center=1,fn=fn,messpunkt=false,2D=0,extrude=false,grad2=0,x0=0,name,help,spiel=0){ - center=is_bool(center)?center?1:0:sign(center); - r2=!is_undef(r2)?r2:r1; - l2=!is_undef(l2)?l2:l1; - 2D=is_parent(needs2D)&&!$children?2D?b(2D,false): - 1: - b(2D,false); -// echo(parent_module(1),$parent_modules); - grad2=is_list(grad2)?grad2:[grad2,grad2]; - extrudeTrue=extrude; - extrude=is_bool(extrude)?0:extrude; - gradN=grad; // detect negativ grad - grad=abs(grad);// negativ grad done by mirror - y=(grad>0?1:-1)*(abs(dist)/tan(grad)+r1*tan(grad/2)+r2*tan(grad/2)); - - yrest=y-abs(sin(grad))*r1-abs(sin(grad))*r2;//y ohne Kreisstücke - distrest=dist-r2-r1+cos(grad)*r1+cos(grad)*r2;//dist ohne Kreisstücke - - l2m=Hypotenuse(distrest,yrest)/2+minVal;// Mittelstück - - dist=grad>0?dist:-dist; - $fn=fn; - $fa=fa; - $fs=fs; - $idxON=false; - - grad2Y=[-l1+y/2+r1*sin(grad2[0]),l2-y/2-r2*sin(grad2[1])]; // Abstand Kreisende zu Punkt l1/l2 - grad2X=[r1-r1*cos(grad2[0])-tan(grad2[0])*grad2Y[0],-r2+r2*cos(grad2[1])-tan(grad2[1])*grad2Y[1]];// Versatz der Punkte durch grad2 - - - KreisCenterR1=[[-abs(dist)/2+extrude+r1,-y/2],[extrude+r1-abs(dist),-y/2-l2],[extrude+r1,-y/2+l1]]; - KreisCenterR2=[[abs(dist)/2+extrude-r2,y/2],[extrude-r2,y/2-l2],[abs(dist)+extrude-r2,y/2+l1]]; - - - selectKC=center?center>0?0: - 1: - 2; - - - endPunkte=center?center==1?[extrude-abs(dist/2)+grad2X[0],extrude+abs(dist/2)+grad2X[1]]:[extrude-abs(dist)+grad2X[0],extrude+grad2X[1]]:[extrude+grad2X[0],extrude+abs(dist)+grad2X[1]]; - - - InfoTxt(parent_module(search(["Anschluss"],parentList(+0))[0]? - search(["Anschluss"],parentList(+0,start=0))[0]: - 1) - - ,["ext",str(endPunkte[0],"/",endPunkte[1])," 2×=",str(2*endPunkte[0],"/",2*endPunkte[1]),"Kreiscenter",str(KreisCenterR1[selectKC],"/",KreisCenterR2[selectKC]) - ],name); - - - - if(grad&&!extrudeTrue)mirror(gradN<0?[1,0]:[0,0])translate(center?[0,0,0]:[dist/2,l1]){ - translate([dist/2,y/2,0])T(-r2)rotate(grad2[1])T(r2)Bogen(rad=r2,grad=grad+grad2[1],center=false,l1=l2-y/2,l2=l2m,help=0,name=0,messpunkt=messpunkt,2D=2D,fn=fn,d=2D,ueberlapp=spiel) - if($children){ - - $idx=is_undef($idx)?0:$idx; - $tab=is_undef($tab)?1:b($tab,false)+1; - children(); - } - else circle($fn=fn); - T(-dist/2,-y/2) mirror([1,0,0])rotate(180)T(r1)rotate(-grad2[0])T(-r1)Bogen(rad=r1,grad=-grad-grad2[0],center=false,l1=l1-y/2,l2=l2m,help=0,name=0,messpunkt=messpunkt,2D=2D,fn=fn,d=2D,ueberlapp=spiel) - if($children){ - $idx=1; - children(); - } - else circle($fn=fn); - } - - if(!grad&&!extrudeTrue) //0 grad Grade - if(!2D)T(0,center?0:l1+l2)R(90)linear_extrude(l1+l2,convexity=5,center=center?true:false) - if($children)children(); - else circle($fn=fn); - else T(center?0:-2D/2) square([2D,l1+l2],center?true:false); - - - - - - if(extrudeTrue){ - - points=center?center==1?concat(//center=1 - [[x0,l2]],[[extrude+abs(dist)/2+grad2X[1],l2+0]], - kreis(r=-r2,rand=0,grad=abs(grad)+grad2[1],rot=-90-grad2[1],center=false,fn=fn,t=[abs(dist)/2+extrude-r2,y/2]), // ok - kreis(r=-r1,rand=0,grad=-abs(grad)-grad2[0],fn=fn,rot=90+abs(grad),center=false,t=[-abs(dist)/2+extrude+r1,-y/2]), // ok - [[extrude-abs(dist)/2+grad2X[0],-l1]], - [[x0,-l1]] - ): concat(//center==-1||>1 - [[x0,0]],[[extrude+grad2X[1],0]], - kreis(r=-r2,rand=0,grad=abs(grad)+grad2[1],rot=-90-grad2[1],center=false,fn=fn,t=[extrude-r2,y/2-l2]), // ok - kreis(r=-r1,rand=0,grad=-abs(grad)-grad2[0],fn=fn,rot=90+abs(grad),center=false,t=[extrude+r1-abs(dist),-y/2-l2]), // ok - [[extrude-abs(dist)+grad2X[0],-l2-l1]], - [[x0,-l2-l1]] - ): - concat(//center==0 - [[x0,l2+l1]],[[extrude+abs(dist)+grad2X[1],l2+l1]], - kreis(r=-r2,rand=0,grad=abs(grad)+grad2[1],rot=-90-grad2[1],center=false,fn=fn,t=[abs(dist)+extrude-r2,y/2+l1]), // ok - kreis(r=-r1,rand=0,grad=-abs(grad)-grad2[0],fn=fn,rot=90+abs(grad),center=false,t=[extrude+r1,-y/2+l1]), // ok - [[extrude+grad2X[0],0]], - [[x0,0]] - ); - - if(dist>0&&gradN>0) polygon(points,convexity=5); - if(dist<0||gradN<0)mirror([1,0]) polygon(points,convexity=5); - - } - - - if(messpunkt&&is_num(extrude)){ - Pivot(KreisCenterR1[selectKC],messpunkt=messpunkt,active=[1,0,0,1]); - Pivot(KreisCenterR2[selectKC],messpunkt=messpunkt,active=[1,0,0,1]); - //echo(KreisCenterR1,KreisCenterR2); - } - - - - //Warnings - Echo(str(name," SBogen has no 2D-Object"),color=Hexstring([1,0.5,0]),size=4,condition=!$children&&!2D&&!extrudeTrue); - Echo(str(name," SBogen width is determined by var 2D=",2D,"mm"),color="info",size=4,condition=2D==1&&!extrudeTrue&&$idx==0); - - Echo(str(name," SBogen r1/r2 to big middle <0"),condition=l2m<0); - Echo(str(name," SBogen radius 1 negative"),condition=r1<0); - Echo(str(name," SBogen radius 2 negative"),condition=r2<0); - Echo(str(name," SBogen r1/r2 to big or angle or dist to short"),condition=grad!=0&&r1-cos(grad)*r1+r2-cos(grad)*r2>abs(dist)); - Echo(str(name," SBogen angle to small/ l1+l2 to short"),condition=l1-y/2<0||l2-y/2<0); - //Help - HelpTxt("SBogen",["dist",dist,"r1",r1,"r2",r2,"grad",grad,"l1",l1,"l2",l2,"center",center,"fn",fn,"messpunkt",messpunkt,"2D",2D,"extrude",extrude,"grad2",grad2,"x0",x0,"spiel",spiel," ,name=",name],help); - -} - - - - - - - - -module Tri90(grad,a=25,b=25,c,r=0,messpunkt=0,tang=true,fn=fn,name,help){ - - if (is_list(r)&&!tang)Echo("Tri90 Winkelfehler r is list & tang=false!",color="red"); - - b=is_undef(grad)?is_undef(c)?b:sqrt(pow(c,2)-pow(a,2)):tan(grad)*a; - grad=atan(b/a); - r1=is_list(r)?is_undef(r[0])?0:r[0]:r; - r2=is_list(r)?is_undef(r[1])?0:r[1]:r; - r3=is_list(r)?is_undef(r[2])?0:r[2]:r; - - gradB=90-grad; - - wA=90+grad; - wB=90+gradB; - wC=90; - a=tang?a:a+RotLang(90+grad/2,TangentenP(wB,r2))[0]; - btang=b+RotLang(+0-gradB/2,TangentenP(wA,r1))[1]; - - tA=[0,tang?b:btang]-RotLang(+0-gradB/2,TangentenP(wA,r1,r1)); - tB=[a,0]-RotLang(90+grad/2,TangentenP(wB,r2,r2)); - tC=RotLang(45,TangentenP(wC,r3,r3)); - -if(messpunkt){ - Col(6)union(){ // mittelpunkte - Pivot(tA,active=[1,0,0,1,1],size=messpunkt); - Pivot(tB,active=[1,0,0,1,1],size=messpunkt); - Pivot(tC,active=[1,0,0,1,1],size=messpunkt); - } - union(){ // tangentenpunkte - Pivot([0,0],active=[1,0,0,1,1,1],txt="C",size=messpunkt); - Pivot([0,b],active=[1,0,0,1,1],size=messpunkt); - Pivot([a,0],active=[1,0,0,1,1],size=messpunkt); - } - -} - - points=concat( - - r3==0?[[0,0]]:Kreis(rot=180,grad=wC,fn=fn,rand=0,r=r3,t=tC,center=false), - r1==0?[[0,b]]:Kreis(rot=270,grad=wA,fn=fn,rand=0,r=r1,t=tA,center=false), - r2==0?[[a,0]]:Kreis(rot=+180-wB,grad=wB,fn=fn,rand=0,r=r2,t=tB,center=false) - -); - - polygon(points,convexity=5); - -InfoTxt("Tri90",["a",str(a," b=",b," c=",Hypotenuse(a,b),"mm",r?str(" true a=",tB[0]+r2," b=",tA[1]+r1," c=",norm(tA-tB)+r1+r2):""," grad α=",grad,"° grad β=",gradB,"° γ=90° Höhe c=",a*sin(gradB))],name); -HelpTxt("Tri90",["grad",grad,"a",a,"b",b,"c",c,"r",r,"messpunkt",messpunkt,"tang",tang,"fn",fn,"name",name],help); - -} - - -module Tri(grad=60,l=20,l2,h=0,r=0,messpunkt=0,center=+0,top=0,tang=1,c,fn=fn,name,help){ - - Echo("WIP‼ c and tang=0",color="red",condition=is_num(c)&&!tang); - h=is_num(c)?c/tan(grad/2)/2:h; - l22=is_undef(l2)?l:l2; //wip - - w1=180-grad; //Supplementwinkel - w2=(360-w1)/2; - w3=(360-w1)/2; - - rot=w2/2; - - r1=is_list(r)?is_undef(r[0])?0: - r[0]: - r; - r2=is_list(r)?is_undef(r[1])?0: - r[1]: - r; - r3=is_list(r)?is_undef(r[2])?0: - r[2]: - r; - - - l2=h?1/cos(grad/2)*(!tang?h+TangentenP(w1,r1):h):l22; - l3=h?1/cos(grad/2)*(!tang?h+TangentenP(w1,r1):h):l; - - hc=h?h:l*cos(grad/2); - - t1=[TangentenP(w1,r1,r1),0]; - t2=RotLang(90-grad/2,l2)-RotLang(90-w2/2,TangentenP(w2,r2,r2)); - t3=RotLang(90+grad/2,l3)-RotLang(90+w3/2,TangentenP(w3,r3,r3)); - -points=concat( - kreis(rand=0,r=r1,grad=w1,t=t1,fn=fn/3), - kreis(rand=0,r=r2,rot=-rot+180,grad=w2,t=t2,fn=fn/3), - kreis(rand=0,r=r3,rot=rot+180,grad=w3,t=t3,fn=fn/3) -); - - - rotate(top?0:180)translate([center? - //-2*Kathete(l2,hc)/(2*sin(grad)):top? // center Umkreis - -(tang?hc+TangentenP(w1,r1):hc+2*TangentenP(w1,r1))/2:top? // center h - tang? - 0:-TangentenP(w1,r1) - :tang?-hc:h?-hc-TangentenP(w1,r1):-hc,0,0]){//Basis - polygon(points,convexity=5); - if(messpunkt){ - union(){//TangentenP - Pivot(active=[1,1,0,1],size=messpunkt); - translate(RotLang(90-grad/2,l2))rotate(90+w2/2)Pivot(active=[1,0,1,1],size=messpunkt); - translate(RotLang(90+grad/2,l3))rotate(90-w3/2)Pivot(active=[1,0,1,1],size=messpunkt); - } - - Col(6)union(){ // mittelpunkte - Pivot(t1,active=[1,0,0,1],size=messpunkt); - Pivot(t2,active=[1,0,0,1],size=messpunkt); - Pivot(t3,active=[1,0,0,1],size=messpunkt); - } - - } - } - - InfoTxt("Tri",["reale Höhe=",tang?hc-TangentenP(w1,r1):hc,"h",tang?hc:hc+TangentenP(w1,r1),"Basis",2*Kathete(l2,tang?hc:hc+TangentenP(w1,r1)),"Umkreis r",2*Kathete(l2,hc)/(2*sin(grad)),"c",l==l22?sin(grad/2)*l*2:"WIP"],name); - HelpTxt("Tri",["grad",grad,"l",l,"l2",l2,"h",h,"r",r,",messpunkt",messpunkt,",center=",center,"top",top,"tang",tang,"c",c,"fn",fn,"name",name],help); - -} - - - - - - - -module RStern(e=3,r1=30,r2=10,rad1=5,rad2=+30,l,grad=0,rand=0,os=0,randh=2,r=0,fn=fn,messpunkt=messpunkt,infillh,spiel=-.002,name,help){ - $helpM=0; - $info=0; - r1=r?TangentenP(grad,rad1,r):r1; - - winkel1=180-grad; - spitzenabstand=2*r1*sin(180/e); - winkel3=180-(2*((180-360/e)/2-winkel1/2)); - schenkelA= spitzenabstand/2/sin(winkel3/2); - winkel3h=Kathete(schenkelA,spitzenabstand/2); - spitzenabsth=Kathete(r1,spitzenabstand/2); - r2=r?spitzenabsth-winkel3h:r2; - - //infillh=$children?infillh:infillh?infillh:1; - infillh=$children?infillh:is_undef(infillh)?0:infillh; - //rand=$children?rand:grad<180?rand:rand?rand:1; - - // Winkelberechnung ZackenStern - abstandR1=2*r1*sin(180/e); - abstandR2=2*r2*sin(180/e); - hoeheR1=r1-Kathete(r2,abstandR2/2); - hypR1=Hypotenuse(abstandR2/2,hoeheR1); - gradR1=2*acos(hoeheR1/hypR1); - gradR2=2*asin((abstandR1/2)/hypR1); - - // RStern variablen - grad=grad?grad:180-gradR1; - g2=(grad-360/e); - - // Abstand Rundungen Zacken - - c1=sin(abs(grad)/2)*rad1*2;// Sekante 1 - w11=abs(grad)/2; // Schenkelwinkel1 - w31=180-abs(grad); // Scheitelwinkel1 - a1=(c1/sin(w31/2))/2; - hc1=grad!=180?Kathete(a1,c1/2):0; // Sekante1 tangenten center - hSek1=Kathete(rad1,c1/2); //center Sekante1 - - c2=sin(abs(g2)/2)*rad2*2;// Sekante 2 - w12=abs(g2)/2; // Schenkelwinkel2 - w32=180-abs(g2); // Scheitelwinkel2 - a2=(c2/sin(w32/2))/2; - hc2=g2!=180?Kathete(a2,c2/2):0; // Sekante2 tangenten center - hSek2=Kathete(rad2,c2/2); //center Sekante2 - - - - // RStern l variable - - lCalcA=[r1-TangentenP(grad,rad1,rad1),0]+RotLang(90+grad/2,rad1); - lCalcB=g2<0? - RotLang(-90+180/e,-r2+TangentenP(g2,rad2,rad2))-RotLang(-90+180/e-abs(g2)/2,rad2): - RotLang(-90+180/e,-r2-TangentenP(g2,rad2,rad2))+RotLang(-90+180/e+abs(g2)/2,rad2) - ; - - l=is_undef(l)?norm(lCalcA-lCalcB)/2-spiel/2:l; - //color("cyan")translate(lCalcA)Pivot();//Ende Bogen 1 - //color("magenta")translate(lCalcB)Pivot();//Ende Bogen 2 - - - if($children||!(grad<180))union(){ - Polar(e,r1,name=0)Bogen(grad=grad,rad=rad1,l=l,help=0,name=0,tcenter=1,fn=fn,messpunkt=messpunkt,ueberlapp=spiel)T(os){ - children(); - if(grad>=180)T(rand/2,randh/2)square([abs(rand),randh],true); - } - - Polar(e,-r2,r=e%2?0:180/e,re=0,name=0)Bogen(grad=g2,rad=rad2,l=l,help=0,name=0,tcenter=true,fn=fn,messpunkt=messpunkt,ueberlapp=spiel)T(-os){ - R(0,180)children(); - if(grad>=180)T(-rand/2,randh/2)square([abs(rand),randh],true); - } - - } -/* old Sternfill - if(grad<180){ - if(infillh)linear_extrude(infillh,convexity=5)offset(os,$fn=fn)Rund(rad1,rad2,fn=fn)Stern(e,r1,r2); - if(rand)linear_extrude(randh,convexity=5)Rand(rand)offset(os,$fn=fn)Rund(rad1,rad2,fn=fn)Stern(e,r1,r2); - } +/** \name CRing +\page Products +CRing() creates a C-shaped Ring with given inner diameter +\param id inner diameter +\param grad angle of the C +\param h height +\param rand thickness +\param rad corner radius +\param end end corner option 0:no 1:round 2:flat +\param txt surface text embossed +\param tSize text size +\param tPos text position [rot angle,h] +\param center center height and angle */ - if(grad<=180){ - if(infillh)linear_extrude(infillh,convexity=5)offset(os,$fn=fn)RSternFill(e=e,r1=r1-TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); - - if(rand)linear_extrude(randh,convexity=5)Rand(rand)offset(os,$fn=fn)RSternFill(e=e,r1=r1-TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); - - if(infillh==0)offset(os,$fn=fn)RSternFill(e=e,r1=r1-TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); - } - - if(grad>180){ - if(infillh)linear_extrude(infillh,convexity=5)offset(os,$fn=fn)RSternFill(e=e,r1=r1+TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); - - if(rand)linear_extrude(randh,convexity=5)Rand(rand)offset(os,$fn=fn)RSternFill(e=e,r1=r1+TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); - - if(infillh==0)offset(os,$fn=fn)RSternFill(e=e,r1=r1+TangentenP(grad,-rad1,-rad1),r2=TangentenP(g2,rad2,r2+rad2),d1=rad1*2,d2=rad2*2,fn=fn,grad1=grad,grad2=g2,help=false); - } - - MO(!$children,warn=true); - - HelpTxt("RStern",["e",e,"r1",r1,"r2",r2,"rad1",rad1,"rad2",rad2,"l",l,"grad",grad,"rand",rand,"os",os,"randh",randh,"fn",fn,"messpunkt",messpunkt,"infillh",infillh,"spiel",spiel,"name",name],help); - - InfoTxt("RStern",["Grad",str(grad,"°"),"Grad2",str(g2,"°"),"Spitzenwinkel",str(gradR1,"°/",gradR2,"°"),"r1 bis Rundung", - // r1-hc1-hSek1+rad1 - r1-TangentenP(grad,-rad1,0)+2*rad1 - ,"r2 bis Rundung", - //r2+hc2+hSek2-rad2 - str(TangentenP(g2,rad2,r2) - ,"mm")],name); - -} -module RSternFill( // needs checking - -e=8, //elements -d1=2, // diameter nipples(convex) -d2, // diameter nipples(concave) -r1=5, // radius 1 -r2, //radius 2 -grad1=180, // angle nipples 1 -grad2, // angle nipples 2 -fn=fn, -messpunkt=false, -help -){ -winkel=360/(e*2); - - - - //grad1=is_undef(grad)?grad1:grad; // konvex - grad2=is_undef(grad2)?grad1-winkel*2:grad2; // konkav - d2=is_undef(d2)?d1:d2; - - - sekD1X=sin(grad1/2)*d1/2; - sekD1Y=cos(grad1/2)*d1/2; - sekD2X=sin(grad2/2)*d2/2; - sekD2Y=-cos(grad2/2)*d2/2; - r=norm([sekD1X,r1+sekD1Y]);//connectionpoint radius - r2=is_undef(r2)?Kathete(r,sekD2X)-sekD2Y:r2; - if(messpunkt)rotate(-90){ - Pivot(p0=[sekD1X,r1+sekD1Y],txt="D1",active=[0,0,0,1,0,1]); - rotate(-winkel) Pivot(p0=[-sekD2X,r2+sekD2Y],txt="D2",active=[0,0,0,1,0,1]); - //Tz(.1)Color()circle(r,$fn=200); - } - - - - wk=[for(i=[0:e-1]) each concat( - kreis(r=-d2/2,rot=90-winkel/2+i*winkel*2,rand=0,grad=-grad2,sek=true,t=RotLang(-winkel/2+i*winkel*2,r2),fn=fn) - , kreis(r=d1/2,rot=90+winkel/2+i*winkel*2,rand=0,grad=grad1,sek=true,t=RotLang(winkel/2+i*winkel*2,r1),fn=fn) - )]; - - rotate(winkel/2-90)polygon(wk,convexity=5); - -if(help)echo(str("

    Help RSternFill(e=",e,",r1=",r1,", r2=",r2," ,d1=",d1," ,d2=",d2, ",grad1=",grad1," ,grad2=",grad2," ,fn=",fn,", messpunkt=",messpunkt," help);")); -} - - - -module GewindeV3( -dn=5, -h=10, -kern=0,//Kerndurchmesser -p=1,//Steigung -w=0,//Windungen -profil=+0.00, //varianz gangbreite -gh=0.56,//Ganghöhe -g=1,//Gänge -scale=1, -name, -fn=36, -help -){ - //http://www.iso-gewinde.at -r=dn/2; -gh=gh?gh:(dn-kern)/2; -kern=gh?2*(r-gh):kern; - -p=p?p:(w/360)/h; -h=h?h:w/360*p; -w=w?w:(h/p)*360; -winkel=atan2((p/2),gh)*2; - -InfoTxt("GewindeV3",["dn∅",dn,"Steigung",str(p,"mm/U"),"Kern",kern,"Gangtiefe",gh,"Winkel~",str(winkel -22.5,"°(",winkel,"°)")],name); - - difference(){ - if($children) children(); - Col(6)linear_extrude(height=h,twist=-w,convexity=10,scale=scale,$fn=fn){ - if(g>1) Rund((r-gh/2)*+0.5)Polar(g)T(gh/2)scale([1,1.00+profil])circle(r-gh/2,$fn=fn); - if(g==1)T(gh/2)scale([1,1.00+profil])circle(r-gh/2,$fn=fn); - - } - } - HelpTxt("GewindeV3",["dn",dn,"h",h,",kern",kern,"p",p,"w",w,"profil",profil,"gh",gh,"g",g,"scale",scale,"name",name,"fn",fn],help); -} - - -module LinEx2(bh=5,h=1,slices=10,s=1,ds=+0.010,dh=+0,fs=1,fh=0.780,twist=0,hsum=0,startSlices=0,fn=fn,name,help){ - $helpM=0; - $info=0; - s=is_list(s)?s:[s,s]; - hsum=hsum?hsum:h; - startSlices=startSlices?startSlices:slices; - if(slices-1)rotate(-twist*h)Tz(h)scale([s[0],s[1],1])LinEx2(bh=bh,slices=slices-1,s=s*fs-[ds,ds],h=h*fh-dh,ds=ds,dh=dh,hsum=hsum+h*fh-dh,fs=fs,fh=fh,name=name,startSlices=startSlices,twist=twist,fn=fn,help=help)children(); - - Color(1/startSlices*slices)rotate(-twist*bh)Tz(bh)linear_extrude(h+minVal,twist=twist*(h+minVal),scale=s,convexity=5,$fn=fn)children(); - if(slices==startSlices){ - linear_extrude(bh+minVal,twist=twist*bh,convexity=5,$fn=fn)children(); - MO(!$children); - - } - - if(!(slices-1)){ - InfoTxt("LinEx2",["Höhe",hsum+minVal+bh,"Twist",(hsum+bh)*twist],name); - HelpTxt("LinEx2",["bh",bh,"h",h,"slices",slices,"s",s,"ds",ds,"dh",dh,"fs",fs,"fh",fh,"twist",twist,"hsum",hsum,"startSlices",startSlices,"fn",fn,"name",name],help); - } - -} - - -module Surface(x=20,y,zBase=5,deltaZ=.25,res=6,waves=false, -rand=true,seed=42,randsize=1,randSizeY,freqX=1,freqY,ampX=1,waveSkewX=+0,ampY,waveSkewY,ampRoundX=0,rfX=+1,ampRoundY,rfY,versch=[0,0],abs=false,exp=1,expY,sinDelta=0,sinDeltaY,mult=false,name,help){ - - -HelpTxt("Surface",[ - "x",x, - "y",y, - "zBase",zBase, - "deltaZ",deltaZ, - "res",res, - "waves", waves, - "rand",rand, - "seed",seed, - "randsize",randsize, - "randSizeY",randSizeY, - "freqX",freqX, - "freqY",freqY, - "ampX",ampX, - "waveSkewX",waveSkewX, - "ampY",ampY, - "waveSkewY",waveSkewY, - "ampRoundX",ampRoundX, - "rfX",rfX, - "ampRoundY",ampRoundY, - "rfY",rfY, - "versch",versch, - "abs",abs, - "exp",exp, - "expY",expY, - "sinDelta",sinDelta, - "sinDeltaY",sinDeltaY, - "mult",mult, - "name",name - - ],help); -/* -if(help){ - echo(str("Help Surface")); - echo(str(" Surface(x=",x,",y=",y,", zBase=",zBase," // mm size ")); - echo(str(" deltaZ=",deltaZ,", res=",res," // random change +− and resolution points/mm ")); - echo(str(" waves=",waves,", rand=",rand,", // pattern waves and/or random")); - echo(str(" seed=",seed,", randsize=",randsize,",randSizeY=",randSizeY,", //random seed, random size y strech")); - echo(str(" freqX=",freqX,", freqY=",freqY,", ampX=",ampX,",waveSkewX=",waveSkewX,", ampY=",ampY,", waveSkewY=",waveSkewY,", // wave frequenz and amplitude XY")); - echo(str(" ampRoundX=",ampRoundX,", rfX=",rfX,",ampRoundY=",ampRoundY,",rfY=",rfY,", // rounded Waveform ⇒ coarse, roundig factor")); - echo(str(" versch=",versch,", name=",name,", abs=",abs,", exp=",exp,", expY=",expY,", sinDelta=",sinDelta,", sinDeltaY=",sinDeltaY,"mult=",mult,",); // move wave pattern show info and abs values, exponent, move sin center waves only")); -}//*/ - -y=is_undef(y)?x:y;//assert(x!=0&&y!=0) -randSizeY=assert(randsize!=0&&randSizeY!=0)is_undef(randSizeY)?1/randsize:1/randSizeY; -freqY=is_undef(freqY)?freqX:freqY; -ampY=is_undef(ampY)?ampX:ampY; -waveSkewY=is_undef(waveSkewY)?waveSkewX:waveSkewY; -ampRoundY=is_undef(ampRoundY)?ampRoundX:ampRoundY; -rfY=is_undef(rfY)?rfX:rfY; -expY=is_undef(expY)?exp:expY; -sinDeltaY=is_undef(sinDeltaY)?sinDelta:sinDeltaY; - - - -if(waves)InfoTxt("Surface",["λ X/Y",str(10/freqX,"/",10/freqY," mm - λ¼=",10/freqX/4,"/",10/freqY/4," mm")],name); - -rowl=assert(x>0)x; //frame x values -rowly=assert(y>0)y;//frame y values - -resolution=1/res;//[10,5,2.5,1,0.5,0.25,0.125] -//randSizeY=1/randSizeY; - - -random=rands(-deltaZ,deltaZ,((rowl+1)*(rowly+1)*randSizeY)/min(randsize,1),seed); /* -z1=0; -z2=0.5; -alternate=[for(h=[0:y+1])for(i=[0:x+0])h%2?i%2?deltaZ:deltaZ/2:i%2?deltaZ/2:deltaZ]; -alternate3=[for(h=[0:y+1])for(i=[0:x+0])h%4?i%3?z1:z2:i%2?z2:z1]; -function alternate2(x,y,z1=0.0,z2=0.5)=x%2?y%2?z1:z2:z2; -// -points0alternativ=[ -for(x=[-rowl/2+versch[0]:resolution:rowl/2+versch[0]]) - for(y=[-rowly/2+versch[1]:resolution:rowly/2+versch[1]]) - [x,y, - //alternate2((x+(rowl/2)),(y+(rowly/2)))] - //alternate[(x+rowl/2)+(rowl+0.5)*(y+rowly/2)]] - alternate3[(x+rowl/2)+(rowl+0)*(y+rowly/2)]] - ]; - -*/ - -points0=[ -for(x=[-rowl/2+versch[0]:resolution:rowl/2+versch[0]]) - for(y=[-rowly/2+versch[1]:resolution:rowly/2+versch[1]]) - [x,y, - (rand?random[randSizeY*(round((y+rowly/2-versch[1])/randsize)+round((x+rowl/2-versch[0])/randsize)*rowly)]:0) - +(waves?abs? - pow(ampY*abs(sinDeltaY+sin(y*36*freqY+x*36*freqX*waveSkewY)),expY) - *(mult?pow(ampX*abs(sinDelta+sin(x*36*freqX+y*36*waveSkewX*freqY)),exp):1) - +(mult?0:pow(ampX*abs(sinDelta+sin(x*36*freqX+y*36*waveSkewX*freqY)),exp)) - +ampRoundX*round(rfX*abs(sin(x*36*freqX+y*36*waveSkewX*freqY))) - +ampRoundY*round(rfY*abs(sin(y*36*freqY+x*36*freqX*waveSkewY))) - : - pow(ampY*(sinDeltaY+sin(y*36*freqY+x*36*freqX*waveSkewY)),expY) - *(mult?pow(ampX*(sinDelta+sin(x*36*freqX+y*36*waveSkewX*freqY)),exp):1) - +(mult?0:pow(ampX*(sinDelta+sin(x*36*freqX+y*36*waveSkewX*freqY)),exp)) - +ampRoundX*round(rfX*sin(x*36*freqX+y*36*waveSkewX*freqY)) - +ampRoundY*round(rfY*sin(y*36*freqY+x*36*freqX*waveSkewY)) - //+amplitude4*sin((y*0+x*1)*freqY) - //+amplitude3*cos((y-x)*freqY) - :0)] - ]; +Cring(txt="|-test-|",id=20,h=6,tSize=5,center=0 ,end=2,rad=0.6); +T(0,14)R(90,0,180)Text("test",h=1,size=5); +// */ +module Cring(id=20,grad=230,h=15,rand=3,rad=1,end=1,txt=undef,spacing=1,tSize=5,tPos=[0,0],tDepth=.35,center=true,fn=fn,fn2=36,help) +CRing(id,grad,h,rand,rad,end,txt,spacing,tSize,tPos,tDepth,center,fn,fn2,help); -resx=rowl*res;// /resolution; -resy=rowly*res;// /resolution; - -faces0=[ - for(row=[+0:resx-1]) - for(i=[row*resy-1:(row+1)*resy-2]) - [i+1+row,i+row+2,i+row+3+resy,i+row+2+resy] - ]; - - -points1=[ -[-rowl/2+versch[0],-rowly/2+versch[1],-zBase], -[-rowl/2+versch[0],rowly/2+versch[1],-zBase], -[rowl/2+versch[0],-rowly/2+versch[1],-zBase], -[rowl/2+versch[0],rowly/2+versch[1],-zBase], -]; - -end0=len(points0); -faces1=[[end0+3,end0+1,end0+0,end0+2]]; -fpointssideA=[for(i=[resy:-1:0])i]; -fpointssideB=[for(i=[0:resy+1:resx*(resy+1)])i]; -fpointssideC=[for(i=[(resy+1)*(resx+1)-1:-resy-1:resy])i]; -fpointssideD=[for(i=[len(points0)-resy-1:len(points0)-1])i]; - - -faces2=[concat(fpointssideA,[end0+0,end0+1])]; -faces3=[concat(fpointssideB,[end0+2,end0+0])]; -faces4=[concat(fpointssideC,[end0+1,end0+3])]; -faces5=[concat(fpointssideD,[end0+3,end0+2])]; - - - -points=concat(points0,points1); -faces=concat(faces0,faces1,faces2,faces3,faces4,faces5); - - - translate(-versch)Col(6)polyhedron(points,faces,convexity=5); - -} - - - -module Cring( +module CRing( id=20, grad=230, h=15, @@ -5575,34 +13004,40 @@ rand=3, rad=1, end=1, txt=undef, -tWeite, +//tWeite, +spacing=1, tSize=5, +tPos=[0,0], +tDepth=.35, center=true, fn=fn, fn2=36, help ){ center=center==true?1:center==false?0:center; -tWeite=is_undef(tWeite)?tSize*0.9:tWeite; +//tWeite=is_undef(tWeite)?tSize*0.9:tWeite; Tz(center>0?-h/2:0)rotate(center?-grad/2:0){ rad=min(rad,h/2,rand/2); - difference(){ - rotate_extrude(angle=grad,$fn=fn,convexity=5)T(id/2)Quad(rand,h,r=rad,center=false,fn=fn2,help=0,name=0); - if(txt!=undef)Tz(h/2-tSize/2)difference(){ - for(i=[0:len(txt)-1])rotate(grad/2+i*atan(tWeite/(id/2+rand))-(len(txt)-1)/2*atan(tWeite/(id/2+rand)))T(id/2+rand)R(90,0,90)Text(text=txt[i],h=1,cx=true,cz=true,size=tSize); - Col(4) cylinder(100,d=id+rand*2-n(1),center=true,$fn=fn); - } + difference(){ + rotate_extrude(angle=grad,$fn=fn,convexity=5)T(id/2)Quad(rand,h,r=rad,center=false,fn=fn2,help=0,name=0); + if(txt!=undef)Tz(h/2-tSize/2+tPos.y)difference(){ + rotate(grad/2-90+tPos.x)mirror([1,0])Text(text=txt,h=1,size=tSize,radius=id/2+rand,rot=[90],spacing=spacing,center=true,cy=+0,trueSize="size"); + //%union()for(i=[0:len(txt)-1])rotate(grad/2+i*atan(tWeite/(id/2+rand))-(len(txt)-1)/2*atan(tWeite/(id/2+rand)))T(id/2+rand)R(90,0,90)Text(text=txt[i],h=1,cx=true,cz=true,size=tSize); + Col(4) cylinder(100,d=id+rand*2-tDepth*2,center=true,$fn=fn); } - if(end==1){ + } + if(end==1){ T(id/2+rand/2)Pille(l=h,d=rand,rad=rad,center=false,fn=fn2,fn2=fn2/4,name=0); rotate(grad)T(id/2+rand/2)Pille(l=h,d=rand,rad=rad,center=false,fn=fn2,fn2=fn2/4,name=0); - } - if(end==2){ - T(id/2+rand/2,0,h/2)R(90)Tz(-rad)Prisma(c1=0,x1=rand,z=rad*2,y1=h,s=rad*2,fnS=fn2,name=0,help=0); - rotate(grad)T(id/2+rand/2,0,h/2)R(90)Tz(-rad)Prisma(c1=0,x1=rand,z=rad*2,y1=h,s=rad*2,fnS=fn2,name=0,help=0); - } + } + if(end==2){ + //T(id/2+rand/2,0,h/2)R(90)Tz(-rad)Prisma(c1=0,x1=rand,z=rad*2,y1=h,s=rad*2,fnS=fn2,name=0,help=0); + T(id/2+rand/2,0,h/2)R(90)Tz(-rad)Prisma(r=rad,rad=[rad/2,rad],x1=rand,z=rad*2,y1=h,s=rad*2,fnS=fn2,fnC=fn2,name=0,help=0,deg=90); + //rotate(grad)T(id/2+rand/2,0,h/2)R(90)Tz(-rad)Prisma(c1=0,x1=rand,z=rad*2,y1=h,s=rad*2,fnS=fn2,name=0,help=0); + rotate(grad)T(id/2+rand/2,0,h/2)R(90)Tz(-rad)Prisma(rad=[rad,rad/2],r=rad,deg=90,x1=rand,z=rad*2,y1=h,s=rad*2,fnS=fn2,fnC=fn2,name=0,help=0); + } } HelpTxt("Cring",[ "id", id, @@ -5612,8 +13047,11 @@ HelpTxt("Cring",[ "rad",rad , "end", end , "txt",txt , - "tWeite",tWeite , + //"tWeite",tWeite , + "spacing",spacing, "tSize", tSize, + "tPos",tPos, + "tDepth",tDepth, "center", center , "fn", fn, "fn2",fn2], @@ -5624,721 +13062,14 @@ HelpTxt("Cring",[ - -module Stern(e=5,r1=10,r2=5,mod=2,delta=+0,center=1,name,help){ - name=is_undef(name)?is_undef($info)?false:$info:name; - - star= - let(schritt=360/(e*mod)) - [for(i=[0:e*mod])i%mod Help Disphenoid( - h=",h," , - l=",l, - " ,b=",b, - " ,r=",r, - " ,tx=",tx, - " ,ty=",ty, - " ,tz=",tz, - "help);")); -} - - - -module Quad(x=20,y,r,r1,r2,r3,r4,grad=90,grad2=90,fn=fn,center=true,messpunkt=false,basisX=0,trueX=false,centerX,tangent=true,name,help){ - assert(grad!=0&&grad2!=0); - basisX=is_bool(basisX)?basisX?1:0:is_undef(centerX)?basisX:is_bool(centerX)?centerX?1:0:centerX; - - y=is_num(y)?y: - is_list(x)?x[1]: - x; - xNum=is_list(x)?x[0]:x; - rundung=runden(min(xNum,y)/PHI/2,2); - //r=is_undef(r)?[rundung,rundung,rundung,rundung]:is_list(r)?r:[r,r,r,r]; - - r1=is_num(r1)?r1:is_undef(r[0])?is_num(r)?r:rundung:r[0]; - r2=is_num(r2)?r2:is_undef(r[1])?is_num(r)?r:rundung:r[1]; - r3=is_num(r3)?r3:is_undef(r[2])?is_num(r)?r:rundung:r[2]; - r4=is_num(r4)?r4:is_undef(r[3])?is_num(r)?r:rundung:r[3]; - - - rf1=1/sin(grad); - rf2=1/sin(grad2); - shiftX1=tan(grad-90)*y-r1*2*tan(grad-90); - shiftX2=tan(grad2-90)*y-r2*2*tan(grad2-90); - shiftX3=tan(grad-90)*y-r3*2*tan(grad-90); - shiftX4=tan(grad2-90)*y-r4*2*tan(grad2-90); - - - - // konstante x basis mit Rundung (tangetial punkte) / trueX= reale breite - bx1L=r3-r3*rf1+shiftX3/2; - bx1R=r4-r4*rf2-shiftX4/2; - bx2L=r1-r1*rf1-shiftX1/2; - bx2R=r2-r2*rf2+shiftX4/2; - - bxL=sign(basisX)*tan(90-grad2)*(y/2); - bxR=-sign(basisX)*tan(90-grad)*(y/2); - x=is_list(x)?trueX?basisX==-1?x[0]-bx2L-bx2R:x[0]-bx1L-bx1R:x[0]-bxL-bxR:trueX?basisX==-1?x-bx2L-bx2R:x-bx1L-bx1R:x-bxL-bxR; - trueX1=x+bx1L+bx1R; // real x1 breite - trueX2=x+bx2L+bx2R; // real x2 breite - - p1=-x/2+shiftX1/2-r1*1/tan(grad); - p2=x/2+shiftX2/2-r2*1/tan(grad2); - p3=-x/2-shiftX3/2+r3*1/tan(grad); - p4=x/2-shiftX4/2+r4*1/tan(grad2); - x1=abs(p3)+abs(p4); - x2=abs(p1)+abs(p2); - - cTrans=center?[basisX==1?tangent?-p3+(p3-p4)/2: - (bx1L-bx1R)/2: - basisX==-1?tangent?-p1+(p1-p2)/2: - (bx2L-bx2R)/2: - 0,sign(basisX)*y/2]: - tangent?basisX==1?[x/2+shiftX3/2-r3*1/tan(grad),y/2]:// center= false - [x/2-shiftX1/2+r1*1/tan(grad),y/2]: - basisX==1?[bx1L+x/2,y/2]: - basisX==-1?[bx2L+x/2,y/2]: - [x/2,y/2]; - - - k1=Kreis(rand=0,r=r1,t=[-x/2+r1*rf1+shiftX1/2,y/2-r1]+cTrans,grad=180-grad,rot=grad-180,fn=fn/4,center=false); - k2=Kreis(rand=0,r=r2,t=[x/2-r2*rf2+shiftX2/2,y/2-r2]+cTrans,grad=grad2,rot=-45+45,fn=fn/4,center=false); - k3=Kreis(rand=0,r=r3,t=[-x/2+r3*rf1-shiftX3/2,-y/2+r3]+cTrans,grad=grad,rot=-225+45,fn=fn/4,center=false); - k4=Kreis(rand=0,r=r4,t=[x/2-r4*rf2-shiftX4/2,-y/2+r4]+cTrans,grad=180-grad2,rot=grad2 ,fn=fn/4,center=false); - - union(){ - polygon(concat(k1,k2,k4,k3),convexity=5); - if(messpunkt){ - Pivot([p1,y/2]+cTrans,active=[1,0,0,1,1],messpunkt=messpunkt); - Pivot([p2,y/2]+cTrans,active=[1,0,0,1,1],messpunkt=messpunkt); - Pivot([p3,-y/2]+cTrans,active=[1,0,0,1,1],messpunkt=messpunkt); - Pivot([p4,-y/2]+cTrans,active=[1,0,0,1,1],messpunkt=messpunkt); - } - - } - - if(r1+r2>abs(trueX2)||r3+r4>abs(trueX1))Echo("Quad x too small or r too big",color="red"); - if(r1+r1*sin(90-grad)+r3+r3*sin(grad-90)>abs(y)||r2+r2*sin(grad2-90)+r4+r4*sin(90-grad2)>abs(y))Echo("Quad y too small or r too big",color="red"); - - InfoTxt("Quad",["TangentsizeX1",x1,"sizeX2",x2,"real",str(trueX1,"/",trueX2),"r",r],name); - - HelpTxt("Quad",["x",x,"y",y,"r",r,"grad",grad,"grad2",grad2,"fn",fn,"center",center,"name",name,"messpunkt",messpunkt,"trueX",trueX,"centerX",centerX,"tangent",tangent],help); -} - - -module Linse(dia=10,r=7.07107,name,messpunkt=true,help){ - -InfoTxt("Linse",["Dicke",dick,"Kreisgrad",str(grad,"°")],name); - -tx=Kathete(r,dia/2); -grad=2*asin((dia/2)/r); -dick=2*(r-tx); - - - polygon(concat( kreis(rand=0,r=r,grad=grad,t=[tx,0]), kreis(rand=0,r=r,grad=grad,rot=-180,t=[-tx,0]))); - if(messpunkt){ - Pivot([tx,0],active=[1,0,0,1,0],messpunkt=messpunkt); - Pivot([0,dia/2],active=[1,0,0,1,1],messpunkt=messpunkt); - Pivot([-tx,0],active=[1,0,0,1,1],messpunkt=messpunkt); - - } - HelpTxt("Linse",[ - "dia",dia, - "r",r, - "name",name, - "messpunkt=",messpunkt], - help); -} - -module VorterantQ(size=20,ofs=.5,name){ -s=Umkreis(4,size/2-ofs); - -k1=Kreis(s,rand=0,grad=90); -versch=[for(i=[0:len(k1)])[-Inkreis(4,s),0]]; -offset= [for(i=[0:len(k1)])[ofs*sin(45+i*90/len(k1)),ofs*cos(45+i*90/len(k1))]]; -function offsetvert(fn=12)= [for(i=[0:fn])[ofs*sin(-45+i*90/fn),ofs*cos(-45+i*90/fn)+Inkreis(4,s)]]; -linse=concat(k1+versch+offset,-offsetvert(),-k1-versch-offset,offsetvert()); -polygon(linse); - -if(name)echo(str(name," VQ Radius=",s,"mm - Verschoben um",Inkreis(4,s)-ofs,"mm")); - -} - - -module GewindeV2(dn=10,s,w=0,g=1,winkel=+60,rot2=0,r1=0,kern,fn=1,detail=fn,spiel=spiel,name,tz=0,preset=0,h=10,translate=[0,0,0],rotate=[0,0,0],d=0,gd=0,r=0,center=true,help,p=1.5,endMod=true){ - -s=is_undef(s)?p:s;//Steigung -p=s; - - r1=r1?r1:p/sin(winkel/2)/2-0.01; //overlap preventing - rh=Kathete(r1,p/2); //Gangtiefe - - -spiel=rot2==0?spiel:0; // spiel only for symetrische -dn=$children?dn+spiel*2:dn; -kern=!is_undef(kern)?kern:dn-2*rh+spiel; - - -function profil(rot=0)= - 0? vollwelle(fn=1,extrude=-1,x0=+0,h=1,xCenter=1,r=0.2,r2=0.5,l=p-.1) // test vollwelle - : kreis(r=r1,rand=+0,fn=fn,grad=winkel,sek=winkel==360?1:0,rot=rot2); - - -function RotEx(rot=0,punkte=profil(rot=60),verschieb=dn/2,steigung=1,detail=detail)=[for(rotation=[0:detail*rot/360])for(i=[0:len(punkte)-1]) - concat((punkte[i][0]+verschieb)*sin(rotation*360/detail),punkte[i][1]+rotation/detail*steigung,(punkte[i][0]+verschieb)*cos(rotation*360/detail)) -]; - - -function faces(punkte=RotEx(),fn=len(profil())-1)=[ -for(i=[0:fn-2])[0,i+1,i+2], -for(i=[0:len(punkte)-2-fn])[fn+1+i,1+i,+i], -for(i=[0:len(punkte)-2-fn])[fn+i,fn+1+i,+i], -for(i=[1:fn])[len(punkte)-i+0,len(punkte)-i-1,len(punkte)-1] -]; -Echo("‼ using old GewindeV2 ‼",color="warning"); - if(d||gd||r){GewindeV1(d=d,s=s,w=w?w:5,g=g,tz=tz,gd=gd?gd:1.75,fn=fn==1?3:fn,r=r)children();//Kompatibilität - Echo("‼ using old GewindeV1 ‼",color="warning"); - } - else if(false)R(90)polyhedron(RotEx(rot=100,steigung=p),faces(punkte=RotEx(rot=100)),convexity=15); //test for polyhedron only - else if(preset==0){ - w=w?w:h/p*360; - add=center?p/2:0; - difference(){ - if($children)children(); - translate(translate)rotate(rotate)Tz(-add+tz)intersection(){ - union(){ - Col(6) Polar(g,n=0) difference(){ - R(90)polyhedron(RotEx(rot=w,steigung=p),faces(punkte=RotEx(rot=w)),convexity=15); - if(endMod)Tz(h)rotate(-90+w%360-w%(360/detail))T(dn/2)cylinder(p,d=rh*2-spiel,center=true,$fn=4); - if(endMod)rotate(-90)T(dn/2)cylinder(p,d=rh*2-spiel,center=true,$fn=4); - } - if(rot2==0)Col(9) Tz(-p/2) rotate(-90)cylinder(w/360*p+p,d=kern,center=false,$fn=detail); - } - if(rot2==0)Col(8) rotate(-90)cylinder(2*w/360*p+p,d=dn-spiel,center=true,$fn=detail); - } - } - -HelpTxt("GewindeV2",["dn",dn,"s",s,"w",w,"g",g,"winkel",winkel,"rot2",rot2,", r1",r1,",kern",kern,"fn",fn,"detail",detail,"spiel",spiel,"name",name,"tz",tz,"preset",preset,"h",h,"translate",translate,"rotate",rotate,"d",d,"gd",gd,"r",r,"center",center,"p",p,"endMod",endMod],help&&!preset); - - - -if(name)echo(str("Gangtiefe=",rh,"mm - Gangflanke(r1)=",r1,"mm - Steigung=",p,"mm - Höhe=",w/360*p,"mm+",p)); -if(name)echo(str(name,rot2==0?$children?" Innen": " Aussen":" Undefiniertes","gewinde ∅=",dn-spiel," (",dn,") Kern=",kern)); - if(winkel==360)Echo(str(" ∅ Diameter Warning!"),color="warning"); - } - -else if(preset==1){// ½ Zoll Gewinde - if($children) GewindeV2(dn=20.95,w=w,h=h,kern=19,winkel=55,p=1.814286,preset=0,fn=1,translate=translate,rotate=rotate)children(); - if(!$children) GewindeV2(dn=20.95,w=w,h=h,winkel=55,p=1.814286,preset=0,fn=1,translate=translate,rotate=rotate,help=help); - - echo(str(" ½ Zoll Gewinde ")); -} - -else if(preset==2){// ¾ Zoll Gewinde - if($children) GewindeV2(dn=26.44,w=w,h=h,kern=24.5,winkel=55,p=1.814286,preset=0,fn=1,translate=translate,rotate=rotate)children(); - if(!$children) GewindeV2(dn=26.44,w=w,h=h,winkel=55,p=1.814286,preset=0,fn=1,translate=translate,rotate=rotate); - - echo(str(" ¾ Zoll Gewinde ")); -} - -else if(preset=="M3"){// M3 Gewinde - if($children) GewindeV2(dn=3,w=w,h=h,p=.5,preset=0,fn=1,translate=translate,rotate=rotate)children(); - if(!$children) GewindeV2(dn=3,w=w,h=h,p=.5,preset=0,fn=1,translate=translate,rotate=rotate); - - echo(str(" M3 Gewinde ")); -} -else if(preset=="M6"){// M6 Gewinde - if($children) GewindeV2(dn=6,w=w,h=h,p=1,preset=0,fn=1,translate=translate,rotate=rotate)children(); - if(!$children) GewindeV2(dn=6,w=w,h=h,p=1,preset=0,fn=1,translate=translate,rotate=rotate); - - echo(str(" M6 Gewinde ")); -} - -} - - -module Rand(rand=n(1),center=false,fn=fn,delta=false,chamfer=false,help){ - -if(!center){ - if(rand>0)difference(){ - offset(r=delta?undef:rand,delta=rand,$fn=fn,chamfer=chamfer?true:false)children(); - union(){ - $helpM=0; - $info=0; - children(); - } - } - if(rand<0)difference(){ - children(); - union(){ - $helpM=0; - $info=0; - offset(r=delta?undef:rand,delta=rand,$fn=fn,chamfer=chamfer?true:false)children(); - } - } - } - -if(center) - difference(){ - offset(r=delta?undef:abs(rand),$fn=fn,delta=abs(rand),chamfer=chamfer?true:false)offset(r=delta?undef:-abs(rand/2),$fn=fn,delta=-abs(rand/2),chamfer=chamfer?true:false)children(); - union(){ - $helpM=0; - $info=0; - offset(r=delta?undef:-abs(rand),$fn=fn,delta=-abs(rand),chamfer=chamfer?true:false) offset(r=delta?undef:abs(rand/2),$fn=fn,delta=abs(rand/2),chamfer=chamfer?true:false)children(); - } - } - - MO(!$children); - - HelpTxt("Rand",["rand",rand,"center",center,"fn",fn,"delta",delta,"chamfer",chamfer],help); -} - - - - - - -module Laser3D(h=4,layer=10,var=0.002,name,on=-1){ - - if(on==1)for (i=[0:h/layer:h]){ - c=i/h; - T(z=i/h*var) color([c,c,c]) projection(cut=true)T(z=-i)children(); - } - - if(on==-1) for(i=[+0.0:h/layer:h]){ - - color([i/h,i/h,i/h])T(z=i*+0.01) intersection(){ - T(-500,-500,i) cube([1000,1000,layer]); - T(z=-i*0.000) children(); - } - } - - if(on==0) children(); - - T(z=-.48)color([0,0,0])cube([1000,1000,1],true); - - MO(!$children); - InfoTxt("Laser3D",["color resolution=",str(h/layer,"mm")],name); - -} - - -module Ellipse(x=2,y=2,z=0,fn=36,help){ - - //ToDo z rot; - //function rota(i)=-atan2(sin(i)*y,cos(i)*x)+90; - function rot(i)=atan2(cos(i)*x,sin(i)*y); - for (n=[0:fn-1]){ - $idx=n; - i=360/fn*n; - j=i+360/fn; - - if($children) Color(1/fn*n)hull(){ - T(sin(i)*x,cos(i)*y,cos(i)*z)rotate(rot(i))children(); - union(){ - $idx=$idx+1; - T(sin(j)*x,cos(j)*y,cos(j)*z)rotate(rot(j))children(); - } - } - if(!$children)hull(){ - T(sin(i)*x,cos(i)*y,cos(i)*z)rotate(rot(i))circle($fn=36); - T(sin(j)*x,cos(j)*y,cos(j)*z)rotate(rot(j))circle($fn=36); - } - - } - MO(!$children); - HelpTxt("Ellipse",["x",x,"y",y,"z",z,"fn",fn],help); -} - - - -module WStrebe(grad=45,grad2,h=20,d=2,d2=0,rad=3,rad2=0,sc=0,angle=360,spiel=spiel,fn=fn,2D=false,center=true,rot=0,help){ - - rad2=rad2?rad2:rad; - d2=d2?d2:d; - grad2=is_undef(grad2)?grad:grad2; - - if(!2D)R(0,center?0:grad)Tz(center?0:h/2){ - - rotate(rot)R(180)Halb(1)Tz(-h/2)R(0,-grad2) Strebe(rad=rad2,rad2=rad,d=d2,d2=d,h=h,grad=grad2,single=false,name=0,help=0,2D=0,sc=sc,angle=angle,spiel=spiel,fn=fn); //oben - Tz(.1)Halb(1)Tz(-h/2-.1)R(0,-grad) Strebe(rad=rad,rad2=rad2,d=d,d2=d2,h=h,grad=grad,single=false,name=0,help=0,2D=0,sc=sc,angle=angle,spiel=spiel,fn=fn);//unten - } - - - - if(2D)R(0,0,center?0:-grad)T(0,center?0:h/2){ - mirror([0,1,0])Halb(1,y=1,2D=true)T(0,-h/2)R(0,0,grad2) Strebe(rad=rad2,d=d2,d2=d,h=h,grad=grad2,single=false,n=0,help=0,2D=2D,sc=sc,angle=angle,spiel=spiel,fn=fn); - Halb(1,y=1,2D=true)T(0,-h/2)R(0,0,grad) Strebe(rad=rad,d=d,d2=d2,h=h,grad=grad,single=false,n=0,help=0,2D=2D,sc=sc,angle=angle,spiel=spiel,fn=fn);//unten - } -HelpTxt("WStrebe",["grad",grad,"grad2",grad2,"h",h,"d",d,"d2",d2,"rad",rad,"rad2",rad2,"sc",sc,"angle",angle,"spiel",spiel,"fn",fn,"2D",2D,"center",center,"rot",rot],help); - -} - - - -module Strebe(h=20,d=5,d2,rad=4,rad2,sc=0,grad=0,skew=0,single=false,angle=360,spiel=spiel,fn=fn,fn2=fn/4,center=false,name,2D=false,help){ - - rad2=is_undef(rad2)?is_list(rad)?rad[1]: - rad: - rad2; - rad=is_list(rad)?rad[0]:rad; - d2=is_undef(d2)?d:d2; - skew=skew?skew:tan(grad); - grad=atan(skew); - sc=sc?sc:d/(d*cos(grad)); - winkel=h==rad+rad2?90: - atan((single?(h-rad): - (h-rad-rad2))/(d2/2-d/2)); - - grad1=winkel>0?180-winkel:abs(winkel);//90;//VerbindugsWinkel unten - grad2=180-grad1;//VerbindugsWinkel oben - //assert(h>=(rad+rad2),str("Strebe too short h=",h,"<",rad,"+",rad2," for rad")); - - - if (!2D && !is_parent(needs2D))//search(["Rundrum"], parentList())[0] ) - M(skewzx=skew) Tz(center ? -h/2 : 0) scale([sc, 1, 1]) - rotate(-angle/2) rotate_extrude(angle=angle, convexity=5, $fn=fn) - Strebe(skew=0, h=h, d=d, d2=d2, rad=rad, rad2=rad2, sc=1, grad=0, single=single, spiel=spiel, fn2=fn2, name=0, 2D=2, help=false); - - - InfoTxt("Strebe",[ - "Neigungs ∡",str(atan(skew),"°"), - "center ∡",str(single||rad!=rad2?"~":"=",winkel,"°"), - "Scale",sc, - " dSkew",str(d,"/",d*sc*cos(grad),"-",d2,"/",d2*sc*cos(grad),"mm"), - "Parent",parentList() - ],name); - - -if (2D || is_parent(needs2D))//search(["Rundrum"], parentList())[0] ) - M(skewyx=skew)T(0,center?-h/2:0){ - if(grad1>90) Echo(str("Strebe ∅",d,"mm is d=",(d/2-rad+sin(grad1)*rad)*2),color="warning"); - if(grad2>90) Echo(str("Strebe ∅",d2,"mm is d2=",(d2/2-rad2+sin(grad2)*rad2)*2),color="warning"); - Echo(str("Strebe too short h=",h,"<",rad,"+",rad2," for rad"),color="warning",condition=h<(rad+rad2)); - points= concat( - 2D==2?[[0,h+spiel]]:single?[[-d2/2,h]]:Kreis(fn=fn2,rand=0,r=rad2,grad=-grad2,rot=+grad2,center=false,sek=true,t=[-d2/2-abs(sin(winkel))*rad2,h-rad2]), - - 2D==2?[[+0,h+spiel]]:[[single?-d2/2:-d2/2-rad2,h+spiel]], - - [[single?d2/2:d2/2+rad2,h+spiel]], - - single?[[d2/2,h]]:Kreis(fn=fn2,rand=0,r=rad2,grad=-grad2,rot=0,center=false,sek=true,t=[d2/2+abs(sin(winkel))*rad2,h-rad2]), - - kreis(fn=fn2,rand=0,r=rad,grad=-grad1,rot=grad1-180,center=false,sek=true,t=[d/2+abs(sin(winkel))*rad,rad]), - - [[d/2+rad,0-spiel]], - - 2D==2?[[0,-spiel]]:[[-d/2-rad,0-spiel]], - - 2D==2?[[+0,0]]:Kreis(fn=fn2,rand=0,r=rad,grad=-grad1,rot=180,center=false,sek=true,t=[-d/2-abs(sin(winkel))*rad,rad])); - - scale([sc,1])polygon(points,convexity=5); - -} - -HelpTxt("Strebe",["h",h,"d",d,"d2",d2,"rad",rad,"rad2",rad2,"sc",sc,"grad",grad,"skew",skew,"single",single,"angle",angle,"spiel",spiel,"fn",fn,"fn2",fn2,"name",name,"2D",str(2D,"/*2 for halb*/")],help); - -} - - - -module Bezier( -p0=[+0,+10,0], -p1=[15,-10,0], -p2, -p3=[0,-10,0], -w=1,//weighting -max=1.0, -min=+0.0, -fn=50, -fn2=fn, -ex,//extrude X -pabs=false, //p1/p2 absolut/relativ p0/p3 -messpunkt=true, -mpRot, -twist=0, -scale=1, -hull=true, -points, -d, -name, -help - -){ - mpRot=is_undef(mpRot)?search(["RotEx"],parentList())[0]?true: - mpRot: - mpRot; - //echo(search(["RotEx"],parentList())[0],parentList()); - - messpunkt=is_bool(messpunkt)?messpunkt?pivotSize:0:messpunkt;//$info?messpunkt:0; - 3D=is_list(points)||d&&!$children?true:false; - p0=v3(p0); - p3=v3(p3); - p1=v3(pabs?p1*w:v3(p1)*w+p0); - p2=is_undef(p2)?p1:v3(pabs?p2*w:v3(p2)*w+p3); - - $fn=hull?fn:$fn; - $fa=fa; - $fs=fs; - - - if($children){ - twist=v3(twist); - $helpM=0; - $info=is_undef(name)?is_undef($info)?false:$info:name; - step=((max-min)/fn); - for (t=[min:step:max-step]){ - - $rot=vektorWinkel(Bezier(t,p0,p1,p2,p3),Bezier(t+step,p0,p1,p2,p3))+twist/(max-step)*t; - $tab=true; - $idx=t; - if (hull) Color(1/(max-step)*t,$idxON=false)hull(){ - translate(Bezier(t,p0,p1,p2,p3))rotate($rot)scale(1-(1-scale)/(max-step)*t)children(); - union(){ - $idx=t+step; - $rot=t>=max-step?vektorWinkel(p2,p3)+twist: // last segment - vektorWinkel(Bezier(t+step,p0,p1,p2,p3),Bezier(t+step*2,p0,p1,p2,p3))+twist/(max-step)*(t+step); - translate(Bezier(t+step,p0,p1,p2,p3))rotate($rot)scale(1-(1-scale)/(max-step)*(t+step))children(); - } - } - else Color(1/(max-step)*t,$idxON=false) - translate(Bezier(t,p0,p1,p2,p3))rotate($rot)scale(1-(1-scale)/(max-step)*t)children(); - - } - -} - if(!$children&&3D==false){ - if (is_undef(ex)) polygon([for (t=[min:((max-min)/fn):(max+(max-min)/fn)-((max-min)/fn)])Bezier(t, - [p0[0],p0[1]], - [p1[0],p1[1]], - [p2[0],p2[1]], - [p3[0],p3[1]] - )]); - - else polygon(concat( - [[0,p0[1]]], - [for (t=[min:((max-min)/fn):(max+(max-min)/fn)-((max-min)/fn)])Bezier(t, - [p0[0]+ex,p0[1]], - [p1[0]+ex,p1[1]], - [p2[0]+ex,p2[1]], - [p3[0]+ex,p3[1]] )], - [[0,p3[1]]] - )); - - - } - - if(3D){ - points=is_undef(points)?kreis(d=d,rand=0,fn=fn2):points; - loop=len(points); - path=[for (t=[min:((max-min)/fn):(max+(max-min)/fn)-((max-min)/fn)])Bezier(t, - [p0[0],p0[1]], - [p1[0],p1[1]], - [p2[0],p2[1]], - [p3[0],p3[1]] - )]; - PolyH(pathPoints(points=points,path=path,scale=scale,twist=twist),loop=loop); - - - } - - - - if(messpunkt){ - ex=is_undef(ex)?0:ex; - vpr=mpRot?[90,0,0]:$vpr; - Pivot(mpRot?[p0[0]+ex,0,p0[1]]:p0+[ex,0,0],messpunkt,txt="p0",vpr=vpr); - Pivot(mpRot?[p1[0]+ex,0,p1[1]]:p1+[ex,0,0],messpunkt/2,txt=str("p1",p1==p2?" ":""),vpr=vpr); - Pivot(mpRot?[p2[0]+ex,0,p2[1]]:p2+[ex,0,0],messpunkt/2,txt="p2",vpr=vpr); - Pivot(mpRot?[p3[0]+ex,0,p3[1]]:p3+[ex,0,0],messpunkt,txt="p3",vpr=vpr); - d=b(messpunkt,false)/20; - %Line(mpRot?[p0[0]+ex,0,p0[1]]:p0+[ex,0,0],mpRot?[p1[0]+ex,0,p1[1]]:p1+[ex,0,0],d=d,center=true); - %Line(mpRot?[p3[0]+ex,0,p3[1]]:p3+[ex,0,0],mpRot?[p2[0]+ex,0,p2[1]]:p2+[ex,0,0],d=d,center=true); - - } - - if(name&&!$children)Echo("No Bezier object using polygon!",color="green"); - -HelpTxt("Bezier",[ - "p0",p0, - "p1",p1, - "p2",p2, - "p3",p3, - "w/*weighting*/",w, - "max",max, - "min",min, - "fn",fn, - "fn2",fn2, - "ex/*extrude X*/",ex, - "pabs/*p1/p2 absolut/relativ */",pabs, - "messpunkt",messpunkt, - "mpRot",mpRot, - "twist",twist, - "hull",hull, - "points",points?"points":undef, - "d/*for 3D*/",d, - "name",name] - ,help); -} - - - -module Line(p0=[0,0,0],p1=[10,10,0],d=.5,center=false,2D=false,text=false,fn=8,help=false){ - p0=p0[2]==undef?concat(p0,[0]):p0; - p1=p1[2]==undef?concat(p1,[0]):p1; -p1t=p1-p0; - -x= p1t[0]; y = p1t[1]; z = p1t[2]; // point coordinates of end of cylinder - -length = norm([x,y,z]); // radial distance -b = length?acos(z/length):0; // inclination angle -c = atan2(y,x); // azimuthal angle - -points=center?[-p1t+p0,p0,p1]:[p0,p1t/2+p0,p1]; // for d=0 1d polyhedron - -if(d) - if(2D)translate(p0)rotate([0,b-90,c])translate([0,center?0:-d/2,0]) square([center?length*2:length,d],center=center?true:false); - else translate(p0)rotate([0, b, c]) - cylinder(h=center?length*2:length,d=d,$fn=fn,center=center?true:false); -else polyhedron(points,[[0,1,2]]); -//Points(points); - - if (text&&$preview) - %color("slategrey")translate(center?p0:p0+p1t/2)rotate($vpr) - text(str(runden(center?length*2:length,3),"mm"),size=b(text,false)); - -HelpTxt("Line",[ - "p0",p0, - "p1",p1, - "d",d, - "center",center, - "2D",2D, - "text",text, - "fn",fn - ],help); - -} - -module LineORG(p0=[0,0,0], p1=[10,10,0], d=.5,center=true) { //from https://en.wikibooks.org/wiki/OpenSCAD_User_Manual/Tips_and_Tricks - - p0=p0[2]==undef?concat(p0,[0]):p0; - p1=p1[2]==undef?concat(p1,[0]):p1; - - // Find the unitary vector with direction v. Fails if v=[0,0,0]. -function unit(v) = norm(v)>0 ? v/norm(v) : undef; -// Find the transpose of a rectangular matrix -function transpose(m) = // m is any rectangular matrix of objects - [ for(j=[0:len(m[0])-1]) [ for(i=[0:len(m)-1]) m[i][j] ] ]; -// The identity matrix with dimension n -function identity(n) = [for(i=[0:n-1]) [for(j=[0:n-1]) i==j ? 1 : 0] ]; - -// computes the rotation with minimum angle that brings a to b -// the code fails if a and b are opposed to each other -function rotate_from_to(a,b) = - let( axis = unit(cross(a,b)) ) - axis*axis >= 0.99 ? - transpose([unit(b), axis, cross(axis, unit(b))]) * - [unit(a), axis, cross(axis, unit(a))] : - identity(3); - - v = p1-p0; - translate(p0) - // rotate the cylinder so its z axis is brought to direction v - multmatrix(rotate_from_to([0,0,1],v)) - cylinder(d=d, h=center?norm(v)*2:norm(v), $fn=12,center=center); -} - - -module Pivot(p0=[0,0,0],size,active=[1,1,1,1,1,1],messpunkt,txt,rot=0,vpr=$vpr,help=false){ - messpunkt=is_undef(messpunkt)?is_undef($messpunkt)?true:$messpunkt:messpunkt; - p0=is_num(p0)?[p0,0]:p0; - size=is_undef(size)?is_bool(messpunkt)?pivotSize:messpunkt:size; - - size2=size/+5; -if(messpunkt&&$preview)translate(p0)%union(){ - - if(active[3])rotate(rot) color("blue")cylinder(size,d1=.5*size2,d2=0,center=false,$fn=4); - if(active[2])rotate(rot) color("green")rotate([-90,0,0])cylinder(size,d1=.5*size2,d2=0,center=false,$fn=4); - if(active[1])rotate(rot) color("red")rotate([0,90,0])cylinder(size,d1=.5*size2,d2=0,center=false,$fn=4); - if(active[0]) color("yellow")sphere(d=size2*.6,$fn=12); - //Text - if(active[4]) %color("grey")rotate(vpr) - //linear_extrude(.1,$fn=1) - text(text=str(norm(p0)?p0:""," ",rot?str(rot,"°"):""," "),size=size2,halign="right",valign="top",font="Bahnschrift:style=light",$fn=1); - - if(txt&&active[5])%color("lightgrey")rotate(vpr)translate([0,size/15])//linear_extrude(.1,$fn=1) - Tz(0.1) text(text=str(txt," "),size=size2,font="Bahnschrift:style=light",halign="right",valign="bottom",$fn=1); - - HelpTxt("Pivot",[ - "p0",p0, - "size",size, - "active",active, - "messpunkt",messpunkt, - "txt",txt, - "rot",rot, - "vpr",vpr] - ,help); - } -} - - - - module Achsenklammer(abst=10,achse=3.5,einschnitt=1,h=3,rand=n(2),achsenh=0,fn=fn,help){ achse=is_list(achse)?achse:[achse,achse]; achsenh=is_list(achsenh)?achsenh:[achsenh,achsenh]; - if (achsenh[0])linear_extrude(achsenh[0]+h,convexity=5)T(-abst/2)circle(d=achse[0]+(achsenh[0]<0?.1:0),$fn=fn); - if (achsenh[1])linear_extrude(achsenh[1]+h,convexity=5)T(abst/2)circle(d=achse[1]+(achsenh[1]<0?0.1:0),$fn=fn); + if (achsenh[0]&&h)T(-abst/2)LinEx(achsenh[0]+h,[0,achsenh[0]>+.5?.5:0],grad=45,$d=achse[0])circle(d=$d+(achsenh[0]<0?.1:0),$fn=fn); + if (achsenh[1]&&h)T(abst/2)LinEx(achsenh[1]+h,[0,achsenh[1]>+.5?.5:0],grad=45,$d=achse[1])circle(d=$d+(achsenh[1]<0?0.1:0),$fn=fn); - linear_extrude(h,convexity=5) + if(h)linear_extrude(h,convexity=5) difference(){ union(){ //if(achse[0]==achse[1])T((achse[1]-achse[0])/4)Halb(2D=1,y=1)Ring(0,(achse[0]+achse[1])/2+rand*2,abst,cd=0,2D=1,name=0,fn=fn,help=0); else @@ -6353,114 +13084,24 @@ module Achsenklammer(abst=10,achse=3.5,einschnitt=1,h=3,rand=n(2),achsenh=0,fn=f if(achsenh[0]<=0) T(-abst/2)circle(d=achse[0],$fn=fn); if(achsenh[1]<=0) T( abst/2)circle(d=achse[1],$fn=fn); } + else difference(){ + union(){ + //if(achse[0]==achse[1])T((achse[1]-achse[0])/4)Halb(2D=1,y=1)Ring(0,(achse[0]+achse[1])/2+rand*2,abst,cd=0,2D=1,name=0,fn=fn,help=0); else + T((achse[1]-achse[0])/4)Kreis(d=(achse[0]+achse[1])/2+rand*2+abst,grad=180,rand=0,help=0,name=0,rot=-90); + T(abst/2)circle(d=achse[1]+rand*2,$fn=fn); + T(-abst/2)circle(d=achse[0]+rand*2,$fn=fn); + } + T(-(achse[1]-achse[0])/4)hull(){ + T(y=-einschnitt*(achse[0]+achse[1])/2)circle(d=abst-((achse[0]+achse[1])/2+rand*2),$fn=fn); + T(y=einschnitt*(achse[0]+achse[1])/2)circle(d=abst-((achse[0]+achse[1])/2+rand*2),$fn=fn); + } + if(achsenh[0]<=0) T(-abst/2)circle(d=achse[0],$fn=fn); + if(achsenh[1]<=0) T( abst/2)circle(d=achse[1],$fn=fn); + } + HelpTxt("Achsenklammer",["abst",abst,"achse",achse,"einschnitt",einschnitt,"h",h,"rand",rand,"achsenh",achsenh,"fn",fn],help); } -module Rund(or=+0,ir,chamfer=false,fn=fn) { - ir=is_undef(ir)?is_list(or)?or[1]:or:ir; - or=is_list(or)?or[0]:or; - chamfer=chamfer?true:false; - if(!chamfer)offset(r = or,$fn=fn)offset(r = -or,$fn=fn) - offset(r = -ir,$fn=fn)offset(r = ir,$fn=fn) - children(); - - - if(chamfer)offset(delta = or,chamfer=chamfer)offset(delta = -or,chamfer=chamfer) - offset(delta = -ir,chamfer=chamfer)offset(delta = ir,chamfer=chamfer) - children(); -MO(!$children); -} - - - - -module Ttorus(r=20,twist=360,angle=360,pitch=0,scale=1,r2,fn=fn,help){ - - scale=is_list(scale)?scale:[scale,scale,scale]; - r2=is_undef(r2)?r:r2; - diff=r2-r; - - for (i=[0:fn-1]){//(i=[0:360/fn:angle-.005]){ - step=angle/fn; - rdiff=diff/fn; - j=i+1;//j=i+360/fn; - //$info=i?0:$info; - //$helpM=i?0:$helpM; - $idx=i; - Color(i/fn,$idxON=false) hull(){ - rotate(i*step)translate([r+rdiff*i,0,i*pitch/360*abs(step)]) rotate([0,i*twist/360*step,0])scale([1,1,1]+(scale-[1,1,1])/fn*(i))children(); - rotate(j*step)translate([r+rdiff*j,0,j*pitch/360*abs(step)]) rotate([0,j*twist/360*step,0])union(){ - $info=false; - $helpM=false; - $idx=j; - scale([1,1,1]+(scale-[1,1,1])/fn*(j))children(); - } - } - } - -MO(!$children); - -HelpTxt("Ttorus",[ - "r",r, - "twist",twist, - "angle",angle, - "pitch",pitch, - "scale",scale, - "r2",r2, - "fn=",fn],help); -} - - - -module Kontaktwinkel(winkel=50,d,baseD,r,center=true,2D=0,inv=false,centerBase=0,name,help){ -grad=-winkel+90; -d=is_num(baseD)?(baseD/2)/sin(winkel)*2:is_undef(r)?is_undef(d)?0:d:2*r; - -h=sin(grad)*d/2; -b=sqrt(pow(d/2,2)-pow(h,2)); -viewportSize=is_undef(viewportSize)?1000:max(d*2,viewportSize); - - -centerBase=b(centerBase,false); -$d=d; -$r=d/2; - if(!2D){ - if(!inv) Tz(centerBase==1?h: - centerBase==-1?-h: - 0)intersection(){ - children(); - T(z=center?0:-h)cylinder(center?h*2:viewportSize,d=viewportSize,center=b(center,true),$fn=6); - } - if(inv)Tz(centerBase==1?-h:centerBase==-1?h:0) intersection(){ - children(); - difference(){ - cube(viewportSize,center=true); - T(z=center?0:h-viewportSize)cylinder(center?h*2:viewportSize,d=viewportSize,center=b(center,true),$fn=6); - } - } - } - if(2D){ - if(!inv)T(y=centerBase==1?h:centerBase==-1?-h:0)intersection(){ - children(); - T(center?0:-viewportSize/2,center?0:-h)square([viewportSize,center?h*2:viewportSize],center=b(center,true)); - } - if(inv)T(y=centerBase==1?-h:centerBase==-1?h:0) intersection(){ - children(); - difference(){ - square(viewportSize,center=true); - T(center?0:-viewportSize/2,center?0:h-viewportSize)square([viewportSize,center?h*2:viewportSize],center=b(center,true)); - } - } - - } - -MO(!$children); -InfoTxt("Kontaktwinkel",["∅",d,"radius",r,"winkel",str(winkel,"°"),"Höhe",h,"Kontakt Radius",b,"2×",b*2],name); -HelpTxt("Kontaktwinkel",["winkel",winkel,"d",d,"baseD",baseD,"r",r,"center",center,"2D",2D,"inv",inv,"centerBase",centerBase,"name",name],help); -} - - - module Tring(spiel=+0,angle=153,r=5.0,xd=+0.0,h=1.75,top=n(2.5),base=n(4),name=0,help){ HelpTxt("Tring",["spiel",spiel,"angle",angle,"r",r,"xd",xd,"h",h,"top",top,"base",base,"name",name],help); @@ -6471,335 +13112,34 @@ module Tring(spiel=+0,angle=153,r=5.0,xd=+0.0,h=1.75,top=n(2.5),base=n(4),name=0 } } - - -module Trapez (h=2.5,x1=6,x2=3.0,d=1,x2d=0,fn=36,rad,name,help){ - d=is_undef(rad)?d:rad*2; - - punkte=[ - [-x2/2+d/2+x2d,h-d/2], - [x2/2-d/2+x2d,h-d/2], - [x1/2-d/2,d/2], - [-x1/2+d/2,d/2], - ]; - if(d) minkowski(){ - polygon(punkte); - circle(d=d,$fn=fn); - } - if(!d)polygon(punkte); - //v=((x1+d)-(x2-d))/2/h; - v=((x1+d)-(x2+d))/2/(h-d); - if(name)echo(str(name," Trapez Steigung= ",v*100,"%-",atan(v),"°")); - HelpTxt("Trapez",["h",h,"x1",x1,"x2",x2,"d",d,"x2d",x2d,"fn",fn,"rad",rad],help); -} - - -module OctaH(r=1,n=0,d,help){ - -HelpTxt("OctaH",["r",r,"n",n,"d",d],help); - - scaling=is_list(r)||is_list(d)?true:false; // if subdiv needs sep scaling - r=is_list(r)?[for(i=[0:5]) i%2? -abs(r[i]): // neg quadrant - abs(r[i])]: //pos quadrants - is_undef(d)?[r, -r, r, -r, r, -r]: - is_list(d)? [d.x /2, -d.x /2, - d.y /2, -d.y /2, - d.z /2, -d.z /2]: - [d /2, -d /2, d /2, -d /2, d /2, -d /2]; - - faces=[ - [0,2,4], - [2,1,4], - [1,3,4], - [3,0,4], - [2,0,5], - [1,2,5], - [3,1,5], - [0,3,5], - - ]; - if(n==0)polyhedron(octa(r),faces); - - else OctaSphere(r,n,d); - module OctaSphere(r=10,n=10,d){ - // based on Hans Loeblich alternative spheres - // https://github.com/thehans/FunctionalOpenSCAD - // MIT license - - - data=sphere_subdiv(divs=max(1,floor(n/4)), poly=OCTAHEDRON(1)); - polyhedron(data[0],data[1]); - - - // sum a vector of vectors. vsum([]) == undef - function vsum(v,i=0) = len(v)-1 > i ? v[i] + vsum(v, i+1) : v[i]; - // angle between two vectors (2D or 3D) - function anglev(v1,v2) = acos( (v1*v2) / (norm(v1)*norm(v2) ) ); - function flatten(l) = [ for (a = l) for (b = a) b ]; - //function unit(v) = v / norm(v); // convert vector to unit vector - // spherical linear interpolation - function slerp(p0,p1,t) = let(a = anglev(p0,p1)) (sin((1-t)*a)*p0 + sin(t*a)*p1) / sin(a); - - function OCTAHEDRON(r) = [octa(r),faces]; - - -// [ [[0,0,r[5]],[r[0],0,0],[0,r[2],0],[r[1],0,0],[0,r[3],0],[0,0,r[4]]], -// [ [0,3,4],[0,1,2],[0,2,3],[0,4,1], -// [5,2,1],[5,3,2],[5,4,3],[5,1,4] ] ]; - - - // subdivide faces, splitting edges into integer number of divisions - // input faces must be triangles with vertices on the unit sphere - function sphere_subdiv(divs=1, poly) = - let( - R = r[0],//d == undef ? r : d/2, // optional radius or diameter - d = divs, // shorthand - pv = poly[0], // points vector - tv = poly[1], // triangle index vector - newpoints = [for (t = tv) let(p = [pv[t[0]], pv[t[1]], pv[t[2]]]) - for (i=[0:1:d], j=[0:1:d-i]) if (i+j!=0 && i!=d && j!=d) // skip original corner points - let(subv=[for (vi=[0:2]) let(k=d-i-j, ii=[i,j,k], - j1=ii[(vi+1)%3], n=ii[vi]+j1, - p0=p[vi], p1=p[(vi+1)%3], p2=p[(vi+2)%3], - p_i=slerp(p0,p1,n/d), p_j=slerp(p0,p2,n/d) - ) slerp(p_i,p_j,j1/n) - ]) - vsum(subv) - ], - Tn = function(n) n*(n+1)/2, // triangular numbers - Td = Tn(d+1), // total points for subdivided face - np = Td - 3, // new points per original face - lp = len(pv), - allpoints = concat(pv, newpoints/3), - // Given original triangle point indices t, - // and indices i,j for subdivided basis vectors, { i => (tri[0],tri[1]), j => (tri[0],tri[2]) } - // convert to absolute point index of resulting full point set. - pij = function(n,t,i,j) i+j==0 ? t[0] : i==d ? t[1] : j==d ? t[2] : - lp + n*np + Td - Tn(d+1-i) + j - (i==0 ? 1 : 2), - faces = flatten([for (n = [0:1:len(tv)-1]) let(t = tv[n]) [ - for (i=[0:1:d-1], j=[0:1:d-1-i]) [ pij(n,t,i,j), pij(n,t,i+1,j), pij(n,t,i ,j+1) ], - for (i=[1:1:d-1], j=[0:1:d-1-i]) [ pij(n,t,i,j), pij(n,t,i,j+1), pij(n,t,i-1,j+1) ] - ] ]) - )[scaling?[for(i=[0:len(allpoints)-1])[ - allpoints[i].x>0?allpoints[i].x*r[0]:allpoints[i].x*-r[1], - allpoints[i].y>0?allpoints[i].y*r[2]:allpoints[i].y*-r[3], - allpoints[i].z>0?allpoints[i].z*r[4]:allpoints[i].z*-r[5], - ]] - :R*allpoints - , faces]; - } -} - - - -module Prisma(x1=12,y1,z=6,c1=5,s=1,x2,y2,x2d=0,y2d=0,c2=0,vC=[0,0,1],cRot=0,fnC=fn,fnS=36,center=false,name,help){ - s=abs(s); - helpX1=x1; - helpY1=y1; - helpX2=x2; - helpY2=y2; - helpZ=z; - - - x=is_list(x1)?x1[0]:x1; - y=is_list(x1)?x1[1]:is_undef(y1)?x1:y1; - hErr=s/2-cos(90/ceil(fnS/2))*s/2+.00001; // missing sphere piece - z=is_undef(x1[2])?z+hErr*2:x1[2]+hErr*2; - c1=min(c1,x,y); - - cylinderh=c1?minVal:0; - - x1=c1-s>0?vC[1]?max(x-cylinderh-s,minVal):max(x-c1,minVal):max(x-s,minVal); - y1=c1-s>0?vC[0]?max(y-cylinderh-s,minVal):max(y-c1,minVal):max(y-s,minVal); - - h=vC[0]||vC[1]?c1?max(z-c1,minVal):max(z-s,minVal):c2?minVal:z-s-cylinderh; - //h=z-s-cylinderh; - - cylinderd2=c2?c2:c1; - - y2=is_list(x2)?c1-s>0?vC[0]?max(x2[1]-cylinderh-s,minVal):max(x2[1]-c1,minVal):max(x2[1]-s,minVal) - :is_undef(y2)?y1:c1-s>0?vC[0]?max(y2-cylinderh-s,minVal):max(y2-c1,minVal):max(y2-s,minVal); - x2=is_undef(x2)?x1 - :is_list(x2)?c1-s>0?vC[1]?max(x2[0]-cylinderh-s,minVal):max(x2[0]-c1,minVal):max(x2[0]-s,minVal):c1-s>0?vC[1]?max(x2-cylinderh-s,minVal):max(x2-c1,minVal):max(x2-s,minVal); - - -CubePoints = [ - [-x1/2,-y1/2, 0 ], //0 - [ x1/2,-y1/2, 0 ], //1 - [ x1/2, y1/2, 0 ], //2 - [-x1/2, y1/2, 0 ], //3 - [-x2/2+x2d,-y2/2+y2d, h ], //4 - [ x2/2+x2d,-y2/2+y2d, h ], //5 - [ x2/2+x2d, y2/2+y2d, h ], //6 - [-x2/2+x2d, y2/2+y2d, h ]]; //7 - -CubeFaces = [ - [0,1,2,3], // bottom - [4,5,1,0], // front - [7,6,5,4], // top - [5,6,2,1], // right - [6,7,3,2], // back - [7,4,0,3]]; // left - - translate([0,0,vC[0]||vC[1]?c1?c1/2:s/2:s/2+minVal/2-(center?z/2:hErr)])minkowski(){ - polyhedron( CubePoints, CubeFaces,convexity=5 ); - rotate(a=90,v=vC)rotate(cRot)cylinder(c2?max(z-s-minVal,minVal):minVal,d1=c1-s,d2=cylinderd2-s,center=c2?false:true,$fn=fnC); - sphere(d=s,$fn=fnS);//OctaH(d=s,n=fnS);// - } - vx=((x1+s)-(x2+s))/2/(z-s); - vy=((y1+s)-(y2+s))/2/(z-s); - InfoTxt("Prisma",["SteigungX/Y",str(vx*100,"/",vy*100,"%"),"grad",str(atan(vx),"/",atan(vy),"°")],name); - if(s>z)Echo(str(" »»» ",name," Prisma s>z!«««"),color="red"); - - if(s>c1&&c1)Echo(str("»»» ",name," Prisma s>c1! ⇒ C-Rundung = s ««« "),color="warning"); - -HelpTxt("Prisma",["x1",helpX1,",y1",helpY1,",z",z,"c1",c1,"s",s,"x2",helpX2,"y2",helpY2,"x2d",x2d,"y2d",y2d,"c2",c2,"vC",vC,"cRot",cRot,"fnC",fnC,",fnS",fnS,"center",center,"name",name],help); -} - -module Sichel(h=1,start=55,max=270,dia=33,radius=30,delta=-1,step=5,2D=false,fn=36,help){ - if(!2D&&h) for (i=[start:step:max]){ - j=i+step; - Color(i/max)hull(){ - rotate(i) T(radius+delta*i/max*dia/2)cylinder(h,d=i/max*dia,$fn=fn); - rotate(j) T(radius+delta*j/max*dia/2)cylinder(h,d=j/max*dia,$fn=fn); - } - } - if(2D||!h) for (i=[start:step:max]){ - j=i+step; - Color(i/max)hull(){ - rotate(i) T(radius+delta*i/max*dia/2)circle(d=i/max*dia,$fn=fn); - rotate(j) T(radius+delta*j/max*dia/2)circle(d=j/max*dia,$fn=fn); - } - } - - HelpTxt("Sichel",[ -"h",h, -"start",start, -"max",max, -"dia",dia, -"radius",radius, -"delta",delta, -"step",step, -"2D",2D, -"fn",fn], help); - -} - +//Balg(); module Balg(sizex=16,sizey=16,z=10.0,kerb=6.9,rand=-0.5,help){ - + minVal=0.001; + sizey=is_list(sizex)?sizex.y:sizey; + sizex=is_list(sizex)?sizex.x:sizex; HelpTxt("Balg",["sizex",sizex,"sizey",sizey,"z",z,"kerb",kerb,"rand",rand],help); //Y Falz T(z=z+z/2)difference(){ cube([sizex,sizey,z],true); - Klon(tx=50-kerb/2+sizex/2)rotate(45) Mklon(tz=-minVal)Kegel(fn=4,d1=Hypotenuse(100,100),d2=Hypotenuse(100-kerb,100-kerb),name=0); - Mklon(ty=sizey/2+50-kerb/2,mz=0)difference(){ - rotate(45)Mklon(tz=-minVal)Kegel(fn=4,d1=Hypotenuse(100,100),d2=Hypotenuse(100-kerb,100-kerb),name=0); - Mklon(tx=sizex/2+59.0+rand,mz=0)T(0,-54.4) Mklon(tz=-minVal,rz=+0)rotate(+0)Kegel(fn=4,d1=Hypotenuse(100,100),d2=Hypotenuse(100-kerb,100-kerb),v=1.4,name=0); + Klon(tx=(50-kerb/2+sizex/2))rotate(45)MKlon(tz=-minVal)Kegel(fn=4,d1=hypotenuse(100,100),d2=hypotenuse(100-kerb,100-kerb),name=0); + MKlon(ty=sizey/2+50-kerb/2,mz=0)difference(){ + rotate(45)MKlon(tz=-minVal)Kegel(fn=4,d1=hypotenuse(100,100),d2=hypotenuse(100-kerb,100-kerb),name=0); + MKlon(tx=sizex/2+59.0+rand,mz=0)T(0,-54.4) MKlon(tz=-minVal,rz=+0)rotate(+0)Kegel(fn=4,d1=hypotenuse(100,100),d2=hypotenuse(100-kerb,100-kerb),v=1.4,name=0); } } //X falz T(z=z/2)difference(){ cube([sizex,sizey,z],true); - Mklon(ty=sizey/2+50-kerb/2,mz=0)rotate(45)Mklon(tz=-minVal)Kegel(fn=4,d1=Hypotenuse(100,100),d2=Hypotenuse(100-kerb,100-kerb),name=0); - Mklon(tx=50-kerb/2+sizex/2,mz=0) difference(){ - rotate(45) Mklon(tz=-minVal)Kegel(fn=4,d1=Hypotenuse(100,100),d2=Hypotenuse(100-kerb,100-kerb),name=0); - Mklon(ty=(sizey/2+59+rand)/1+0,mz=0) T(-54.4) Mklon(tz=-minVal,rz=+0)rotate(+0)Kegel(fn=4,d1=Hypotenuse(100,100),d2=Hypotenuse(100-kerb,100-kerb),v=1.4,name=0); + MKlon(ty=sizey/2+50-kerb/2,mz=0)rotate(45)Mklon(tz=-minVal)Kegel(fn=4,d1=hypotenuse(100,100),d2=hypotenuse(100-kerb,100-kerb),name=0); + MKlon(tx=50-kerb/2+sizex/2,mz=0) difference(){ + rotate(45) MKlon(tz=-minVal)Kegel(fn=4,d1=hypotenuse(100,100),d2=hypotenuse(100-kerb,100-kerb),name=0); + MKlon(ty=(sizey/2+59+rand)/1+0,mz=0) T(-54.4) MKlon(tz=-minVal,rz=+0)rotate(+0)Kegel(fn=4,d1=hypotenuse(100,100),d2=hypotenuse(100-kerb,100-kerb),v=1.4,name=0); } } } -module Area(a=10,aInnen=0,rInnen=0,h=0,name,help){ - - //a=PI*pow(r,2); - rInnen=aInnen?sqrt(aInnen/PI):rInnen; - aInnen=aInnen?aInnen:PI*pow(rInnen,2); - rAussen=sqrt((aInnen+a)/PI); - - if(!h) difference(){ - circle(rAussen); - circle(rInnen); - } - if(h) linear_extrude (h,convexity=5)difference(){ - circle(rAussen); - circle(rInnen); - } - - - InfoTxt("Area",["Durchmesseraussen",2*rAussen,"Innen",rInnen*2,"Fläche",a,"Innen",aInnen],name); - HelpTxt("Area",["a",a,"aInnen",aInnen,"rInnen",rInnen,"h",h,"name",name],help); - -} - - -module Spirale(grad=400*1,diff=2,radius=10,rand=n(2),$d,detail,fn=fn,exp=1,center=false,hull=true,end=2,old=false,name,help){ - detail=fn;//compatibility - advance=grad/detail; - rand=is_undef($d)?rand:$d; - $d=rand; - - -points=!$children?center?[ - for(i=[0:fn])RotLang(i*-grad/fn,diff/2/360*grad+radius-rand/2-pow(i*(diff/360*grad)/(fn),exp)), - for(i=[fn:-1:0])RotLang(i*-grad/fn,diff/2/360*grad+radius+rand/2-pow(i*(diff/360*grad)/(fn),exp))] - :[// center=false -for(i=[0:fn])RotLang(i*-grad/fn,radius-rand/2-pow(i*(diff/360*grad)/(fn),exp)), -for(i=[fn:-1:0])RotLang(i*-grad/fn,radius+rand/2-pow(i*(diff/360*grad)/(fn),exp))] - :[0];// $children=true ⇒ deactivate point calculation - - -if(!$children&&!old)rotate(center?-grad/2:0)union(){ - rotate(-90) polygon(points); - if(end>0) rotate(0)T((center?diff/2/360*grad:0)+radius-pow(0*diff,exp))circle(d=rand,$fn=36); - if(end<0||end==2) rotate(grad)T((center?diff/2/360*grad:0)+radius-pow(grad/360*diff,exp))circle(d=rand,$fn=36); - -} - -if(!$children&&old)// compatibility old version - for(i=[center?-grad/2:0:advance:(center?grad/2:grad)-minVal]){ - j=i+advance; - Color(i/((center?grad/2:grad)-minVal))hull(){ - rotate(i)T(radius-pow(i/360*diff,exp))circle(d=rand,$fn=36); - rotate(j)T(radius-pow(j/360*diff,exp))circle(d=rand,$fn=36); - } - } - -if ($children) for(i=[center?-grad/2:0:advance:(center?grad/2:grad)-minVal]){ - j=i+advance; - $idx=i; - if(hull) Color(i/((center?grad/2:grad)-minVal),$idxON=false) hull(){ - - rotate(i)T(radius-pow(i/360*diff,exp))children(); - rotate(j)T(radius-pow(j/360*diff,exp))union(){$idx=j;children();} - } - else rotate(i)T(radius-pow(i/360*diff,exp))children(); - - - } - - lang=(radius*PI+((radius-diff)*PI))/360*grad; - InfoTxt("Spirale",["Länge ca.",lang],name); - - HelpTxt("Spirale",[ - "grad",grad, - "diff",diff, - "radius",radius, - "rand",rand, - "$d",$d, - //detail=",detail," - "fn",fn, - "exp",exp, - "center",center, - "hull",hull, - "end",end, - "old",old, - "name",name], - help); -} - - - module ReuleauxIntersect(h=2,rU=5,2D=false,help){ HelpTxt("ReuleauxIntersect",["h",h,"rU",rU,"2D",2D],help); @@ -6835,58 +13175,6 @@ if(!2D)linear_extrude(height=h,convexity=10,center=true){ } - -module Box(x=8,y,z=5,d2,c=3.5,s=1.5,eck=4,outer=true,fnC=36,fnS=24,help){ - red=c>s?c:s; - - x=is_num(y)||outer?x: - Umkreis(eck,x-red)+red; - d2=is_undef(d2)?x: - outer?d2: - Umkreis(eck,d2-red)+red; - - hErr=s/2-cos(90/ceil(fnS/2))*s/2+.00001; // missing sphere piece - z=z+hErr*2; - - T(z=z/2-hErr) minkowski(){ - if(is_num(y))cube([x -red, y -red, z-s-minVal],center=true); - else cylinder(h=z -s -minVal, d1=x -red, d2=d2 -red, $fn=eck, center=true); - if(c>s)cylinder(minVal,d=c-s,center=true,$fn=fnC); - //OctaH(d=s,n=fnS); - sphere(d=s,$fn=fnS); - } - -HelpTxt("Box",["x",x,"y",y,"z",z,"d2",d2,"c",c,"s",s,"eck",eck,"outer",outer,"fnC",fnC,"fnS",fnS],help); -} - - -module Bogendreieck(rU=5,vari=-1,fn=fn,name){//-1 vari minus mehr bauch weniger ecken - rU=rU; -teilradius=rU/(sqrt(3)/3); -rI=teilradius-rU; -segment=sqrt(pow(rU,2)-pow(rU/2,2)); -hoheh= sqrt(pow(teilradius+vari,2)-pow(segment,2)); -verschieb= hoheh-rU/2; - -if(name)echo(str(name," Bogendreieck Teilradius Abweichung von Reuleauxoptimum= ",vari)); - - intersection_for(i = [0,120,240]){ - rotate(i)T(verschieb)circle (r=teilradius+vari,$fn=fn); - } -} - - -module Reuleaux(rU=5,name,fn=fn){ - r=rU/(sqrt(3)/3); - intersection_for (i=[0,120,240]) - { - rotate(i)T(rU) circle(r=r,$fn=fn); - - } - if(name)echo(str(name," Reuleaux rU=",rU," r=",r)); -} - - module Tugel( dia=40, loch=+24.72, @@ -6911,14 +13199,16 @@ help } +/// Vorterantrotor creates a rotor for the Vorterant pump +//Polar(6,10*tan(60),mitte=true,rotE=t0,rot=-t0,dr=-360)Vorterantrotor(caps=1,rund=+1); -module Vorterantrotor(h=40,twist=360,scale=1,zahn=0,rU=10,achsloch=4,ripple=0,caps=2,caps2=0,capdia=6.5,capdia2=0,screw=1.40,screw2=0,screwrot=60,name,help) +module Vorterantrotor(h=40,twist=360,scale=1,zahn=0,rU=10,achsloch=4,ripple=0,caps=2,caps2=0,capdia=6.5,capdia2=0,screw=1.40,screw2=0,screwrot=60,rund=0.5,name,help) { - + $fn=0; capdia2=capdia2?capdia2:capdia; caps2=caps2?caps2:caps; - + rU=rU-rund;//*sqrt(3)/1.5; r=rU/(sqrt(3)/3); s= h/(rU*PI*2*(twist/360)); rI=r-rU; @@ -6927,208 +13217,85 @@ s= h/(rU*PI*2*(twist/360)); if(zahn) { - - Col(3)T(z=h+2*caps)stirnrad(modul=1.5, zahnzahl=zahn, hoehe=1.5, bohrung=achsloch, eingriffswinkel = 20, schraegungswinkel = 0); } difference() { T(z=caps)union() { - if (caps)T(z=h)rotate(-twist) hull()//Endcap oben + if (caps){T(z=h)rotate(-twist) hull()//Endcap oben { - intersection_for (i=[0,120,240]) + linear_extrude(.001)offset(rund)intersection_for (i=[0,120,240]) { - rotate(i)T(rU) cylinder(0.01,r=r); + rotate(i)T(rU) circle(r=r); } T(z=caps2){ - if(!screw2)cylinder(0.01,d=capdia2); - if(screw2)rotate(screwrot)intersection_for (i=[0,120,240]) + if(!screw2)cylinder(0.001,d=capdia2); + if(screw2)rotate(screwrot)linear_extrude(.001)offset(rund)intersection_for (i=[0,120,240]) { - rotate(i)T(rU*screw2) cylinder(0.01,r=r); + rotate(i)T(rU*screw2) circle(r=r); }} } T(z=0) hull()//Endcap unten { - T(z=-0.01) intersection_for (i=[0,120,240]) - { - rotate(i)T(rU) cylinder(0.01,r=r); - - } - T(z=-caps){ - if(!screw)cylinder(0.01,d=capdia); - if(screw)rotate(screwrot)intersection_for (i=[0,120,240]) - { - rotate(i)T(rU*screw) cylinder(0.01,r=r); - - }} - } - - - - linear_extrude(h,twist=twist,scale=scale,convexity=5)//Läufer - difference() - { - intersection_for (i=[0,120,240]) + T(z=-0.01)linear_extrude(.001)offset(rund)intersection_for (i=[0,120,240]) + { + rotate(i)T(rU) circle(r=r); + + } + T(z=-caps){ + if(!screw)cylinder(0.01,d=capdia); + if(screw)rotate(screwrot)linear_extrude(.001)offset(rund)intersection_for (i=[0,120,240]) + { + rotate(i)T(rU*screw) circle(r=r); + + }} + } + } + + + linear_extrude(h,twist=twist,scale=scale,convexity=5)//Läufer + offset(rund)intersection_for (i=[0,120,240]) { rotate(i)T(rU) circle(r=r); } - circle(d=achsloch);//centerloch - } } - if(ripple)cylinder(200,d=6,center=true);//center - if(ripple) Linear(e=50,s=73,x=0,z=1)Torus(+2,2.8,fn2=6,n=0,fn=50);//center ripple - cylinder(200,d=achsloch,center=true);//center + if(ripple)cylinder(200,d=6,center=true);//center + if(ripple) Linear(e=50,s=73,x=0,z=1)Torus(+2,2.8,fn2=6,fn=50);//center ripple + cylinder(200,d=achsloch,center=true);//center } } +/** \name Gardena +\page Products +Gardena() creates a Gardena hose coupling +\param l base height +\param r base hole radius +\param ir top hole +\param or base outside radius +\center -1,0,1 +\param help help +*/ +//Cut(z=-10)Gardena(l=+5); -module Kassette(r1=2,r2,size=20,h=0,gon=3,fn=fn,fn2=36,r=+0,grad=90,grad2=90,spiel=0.003,mitte=true,sizey=0,basis=1,2D=false,name,help) +module Gardena(l=+10,r=8.5,ir=4.5,or=15,center=0,help) { - r2=is_undef(r2)?r1:r2; -HelpTxt("Kassette",["r1",r1,"r2",r2,"size",size,"h",h,"gon",gon,"fn",fn,",fn2=",fn2,"r",r,"grad",grad,"grad2",grad2,"spiel",spiel,"mitte",mitte,"sizey",sizey,"basis",basis,"2D",2D,"name",name],help); - if(help){ - echo("r1 r2 size — radius unten, oben und durchmesser"); - echo("h gon fn fn2 r — höhenzusatz, ecken, fn, fn2 des profils und eckradius"); - echo(" spiel mitten sizey name— , spielüberlappung Innenpolygon, mitten loch bei gon=2 und y-weite bei gon=4, name=name für Info"); - } - -sizey=sizey?sizey:is_list(size)?size.y:size; -size=is_list(size)?size.x:size; - - r1I=min(r1,size/2-2*r2);//unten innen radius when mitte=1 - points=concat( - kreis(r=r1,grad=-90,fn=fn2/4,rand=0,rot=-90,center=false,t=[size/2+r1,r1]), //r1 unten - [[r1+size/2,-basis]], //unten aussen - [[0,-basis]],//unten mitte - [mitte?[0,r1+r2+h]:[0,0]], //oben mitte - mitte?[[size/2-r2,r1+r2+h]]:Kreis(r=r1I,grad=-90,fn=fn2/4,rand=0,rot=+180,center=false,t=[size/2-r2*2-r1I,r1I]), - kreis(r=r2,rot=mitte?0:-90,grad=mitte?90:180,fn=mitte?fn2/4:fn2/2,rand=0,center=false,t=[size/2-r2,h+r1])// r2 oben - ); - - - if(2D)polygon(points,convexity=5); - else{ - - if(gon>2) - Rundrum(eck=gon,r=r,x=(size-r2*2)/(gon==4?1:2),y=(sizey-r2*2),fn=fn,grad=grad,grad2=grad2,help=0,name=name)intersection(){ - T(-size/2+r2)polygon(points,convexity=5); - if(mitte) translate([-r,-250])square(500); - } - - if(gon<3)RotEx(help=0,fn=fn)polygon(points,convexity=5); - - if(mitte&&gon>2){ - if(gon!=4)translate([0,0,-basis])rotate(gon==4?45:0)linear_extrude(basis+h+r2+r1,convexity=5) - Rund(r,fn=fn)circle(r=Umkreis(gon,(size-r2*2))/2+spiel,$fn=gon); - if(gon==4)translate([0,0,-basis])linear_extrude(basis+h+r2+r1,convexity=5)offset(spiel)Quad(x=size-r2*2,y=sizey-r2*2,grad=grad,grad2=grad2,r=r,help=0,name=0,fn=fn); - } - } -if(name)echo(str(is_bool(name)?"":"

    ",name," Kassette - Höhe=",h+r1+r2,"mm (+",basis," basis)")); - if(h<0)echo(str("

    ",name," Kassette h=",h,"mm ⇒ NEGATIV!")); - -} - - -module Drehpunkt(x=0,rz=0,rx=0,ry=0,y=0,z=0,messpunkt=messpunkt,help) -{ - y=is_list(x)?x[1]:y; - z=is_undef(x[2])?z:x[2]; - x=is_list(x)?x[0]:x; - - translate([x,y,z])rotate([rx,ry,rz])translate([-x,-y,-z])children(); - if(messpunkt) - { - if(rz)%color("blue")translate([x,y,z])cylinder(20,d=.5,center=true,$fn=12); - if(ry)%color("green")translate([x,y,z])rotate([0,0,rz])rotate([90,0,0])cylinder(20,d=.5,center=true,$fn=12); - if(rx)%color("red")translate([x,y,z])rotate([rx,ry,rz])rotate([0,90,0])cylinder(20,d=.5,center=true,$fn=12); - %color("yellow")translate([x,y,z])sphere(d=1,$fn=12); - } - MO(!$children); - - HelpTxt("Drehpunkt",[ - "x",x, - "rz",rz, - "rx",rx, - "ry",ry, - "y",y, - "z",z, - "messpunkt",messpunkt], - help); - -} - - -module Rohr(grad=90,rad=5,d=8,l,l1=10,l2=12,fn=fn,fn2=fn,rand=n(2),name,center=true,messpunkt=messpunkt,spiel=-minVal,help) -{ - Bogen(grad=grad,rad=rad,l=l,l1=l1,l2=l2,fn=fn,name=name,help=0,center=center,messpunkt=messpunkt,spiel=spiel)polygon( kreis(r=d/2,rand=rand,fn=fn2)); - - HelpTxt(titel="Rohr",string=["grad",grad,"rad",rad,"d",d,"l",l,"l1",l1,"l2",l2,"fn",fn,"fn2",fn2,"rand",rand,"name",name,"center",center,"messpunkt",messpunkt,"spiel",spiel],help=help); - InfoTxt(name="Rohr",string=concat(rand>0?["ID",d-rand*2]:["OD",d-rand*2],["d",d]),info=name); - -} - - - -module Kugelmantel(d=20,rand=n(2),fn=fn,help) -{ - difference() - { - sphere(d=d,$fn=fn); - sphere(d=d-2*rand,$fn=fn); - - } - -HelpTxt("Kugelmantel",["d",d, - "rand",rand, - "fn",fn, -],help); -} - - -module Kegelmantel(d=10,d2=5,v=1,rand=n(2),loch=4.5,grad=0,h=0,center=false,fn=fn,name,help) -{ - v=grad?tan(grad):v; - translate([0,0,center?d>d2?(d2-d)/4*v:(d-d2)/4*v:0]) difference() - { - Kegel(d1=d,d2=d2,v=v,h=h,name=name,fn=fn); - //T(z=-.001) Kegel(d1=d-2*rand,d2=0,v=v,n=0); - if(d21)T(x=rad,y=rad)Tz(center?l/2:l)R(180)Kegel(d2=0,d1=Hypotenuse(rad+spiel[0],rad+spiel[1])*2,fn=fn2); + T(r)square([9.9-r,5]);//20mmRand + if(r0)polygon([ + [r,0],[or,0],[or,-l+tan(60)*2],[or-2,-l], + [r+1,-l],[r,-l+1] + ]); } - if(is_num(fillet[1]))intersection(){ - Tz(center?l/2:l)R(-45,-90)T(0,-fillet[1])RotEx(90,cut=true,fn=fn/360*90)T(fillet[1])rotate(-45)Kehle(2D=true,a=a,ax=ax,fn2=fn2,rad=rad,spiel=spiel); - T(-spiel[0],-spiel[1],l-100)cube([rad+spiel[0],rad+spiel[1],600]); - } - - - - - if(end==2)R(x=-90)T(y=center?0:-l/2) MKlon(ty=l/2)RotEx(grad=90,cut=1,fn=fn)Kehle(a=a,ax=ax,rad=rad,spiel=spiel,2D=true,fn2=fn2,help=false); - if(end==-2)R(x=-90)T(y=center?0:-l/2) MKlon(ty=l/2)R(90,0,90)RotEx(grad=90,cut=1,fn=fn)Kehle(a=ax,ax=a,rad=rad,spiel=spiel,2D=true,fn2=fn2); - if(end==1)Tz(center?-l/2:0)R(-90)RotEx(grad=90,cut=1,fn=fn)Kehle(a=a,ax=ax,rad=rad,spiel=spiel,2D=true,fn2=fn2); - } - - if(2D)difference(){ - translate([-spiel[0],-spiel[1]]) square([sin(-90+ax)*rad+rad+spiel[0],sin(a-90)*rad+rad+spiel[1]]); - T(rad,rad)rotate(r2)circle(rad,$fn=fn2); - } -// dia - if(!is_undef(dia)&&!2D){rotate(center?-180-angle/2:0)difference(){ - rotate(fase&&$preview?.05:0)rotate_extrude(angle=angle-(fase&&$preview?.1:0),$fn=fn,convexity=5) - difference() - { - T(dia/2)translate([-spiel[0],-spiel[1]])square([sin(-90+ax)*rad+rad+spiel[0],sin(a-90)*rad+rad+spiel[1]]); - T(dia/2)T(rad,rad)rotate(r2)circle(rad,$fn=fn2); - if(dia>-rad*2)T(-200,-100)square(200); - } - if(fase&&angle)T(dia/2+rad,z=rad)R(-90*sign(dia))Kegel(d2=0,d1=Hypotenuse(rad+spiel[0],rad+spiel[1])*2,fn=fn2); - if(fase>1&&angle)rotate(angle)T(dia/2+rad,z=rad)R(90*sign(dia))Kegel(d2=0,d1=Hypotenuse(rad+spiel[0],rad+spiel[1])*2,fn=fn2); - } - - - - if(angle)rotate(center?-180-angle/2:0){ - if(is_num(fillet[0]))intersection(){// fillet[0] - T(dia/2,minVal*sign(dia))R(45,0,-90)T(0,-fillet[0])rotate(dia<0?[0,0,90]:[0])RotEx(90,cut=true,fn=fn/360*90)T(fillet[0])rotate(-45)Kehle(2D=true,a=a,ax=ax,fn2=fn2,rad=rad,spiel=spiel); - RotEx()T(dia/2)translate([-spiel[0],-spiel[1]])square([rad+spiel[0],rad+spiel[1]]); - } - if(is_num(fillet[1]))intersection(){// fillet[1] - rotate(angle)T(dia/2,-minVal*sign(dia))rotate([135,0,90])T(0,-fillet[1])R(z=dia<0?90:0)RotEx(90,cut=true,fn=fn/360*90)T(fillet[1])rotate(-45)Kehle(2D=true,a=ax,ax=a,fn2=fn2,rad=rad,spiel=spiel); - RotEx()T(dia/2)translate([-spiel[0],-spiel[1]])square([rad+spiel[0],rad+spiel[1]]); - } - - if(end>0) T(dia/2,+minVal*sign(dia)) rotate(dia<0?0:-90) RotEx(grad=90,cut=1,fn=fn)Kehle(a=a,ax=ax,rad=rad,spiel=spiel,2D=true,fn2=fn2); - if(end==2) rotate(angle)T(dia/2,-minVal*sign(dia))rotate(dia<0?-90:0) RotEx(grad=90,cut=1,fn=fn)Kehle(a=a,ax=ax,rad=rad,spiel=spiel,2D=true,fn2=fn2); - if(end<0) T(dia/2,minVal*sign(dia)) rotate(-90) R(-90,dia<0?-180:-90)RotEx(grad=90,cut=1,fn=fn)Kehle(a=ax,ax=a,rad=rad,spiel=[spiel.y,spiel.x],2D=true,fn2=fn2); - if(end==-2) rotate(angle)T(dia/2,-minVal*sign(dia))R(dia<0?-180:90)R(y=90) RotEx(grad=90,cut=1,fn=fn)Kehle(a=ax,ax=a,rad=rad,spiel=[spiel.y,spiel.x],2D=true,fn2=fn2); - - - } - } -HelpTxt("Kehle",["rad",rad,"dia",dia,"l",l,"angle",angle,"grad",grad,"a",a,",ax=",ax,"fn",fn,"fn2",fn2,"r2",r2,"spiel",spiel,"center",center, "2D",2D,"end",end,"fase",fase,"fillet",fillet],help); - + } } -module Sinuskoerper -( -h=10, -d=33, -rand=2, -randamp=1, -amp=1.5, -w=4, -randw=4, -detail=3, -vers=0, -fill=0, -2D=0, -twist=0, -scale=1 -) -{ - if(!2D)linear_extrude(h,convexity=5,twist=twist,scale=scale)for (i=[0:detail:359.9]) - - { - j=i+detail; - hull() - { - rotate(i) T(d/2+amp*sin(i*w))circle(d=rand+randamp*sin((i+vers)*randw),$fn=36); - rotate(j) T(d/2+amp*sin(j*w))circle(d=rand+randamp*sin((j+vers)*randw),$fn=36); - if(fill)circle(d=d/2,$fn=36); - - } - - } - if(2D)for (i=[0:detail:359.9]) - - { - j=i+detail; - hull() - { - rotate(i) T(d/2+amp*sin(i*w))circle(d=rand+randamp*sin((i+vers)*randw),$fn=36); - rotate(j) T(d/2+amp*sin(j*w))circle(d=rand+randamp*sin((j+vers)*randw),$fn=36); - if(fill)circle(d=d/2,$fn=36); - } - - } -} - - - - module Achshalter ( laenge=30, @@ -7332,124 +13368,6 @@ difference() } } -module Dreieck(h=10,ha=10,ha2=0,s=1,name,c=0,2D=0,grad=0) -{ - s=grad?tan(grad/2)*2*(sqrt(3)/2):s; - //echo(*2);atan(((ha/(sqrt(3)/2)*s)/2)/ha) - - - r=(sqrt(3)/3)*ha/(sqrt(3)/2); - r2=(sqrt(3)/3)*(ha2?ha2:ha)/(sqrt(3)/2); - if(!2D)T(c?h/2:0,z=c?ha/2-r:ha-r) R(0,-90) scale([1,s,1])cylinder(h=h,r1=r,r2=r2,$fn=3); - if(2D)T(x=c?ha/2-r:ha-r) R(0,0) scale([1,s,1])circle(r=r,$fn=3); - - - if(name)echo(str("»»» »»» ",name," Dreieck Höhe= ", ha," Breite= ",ha/(sqrt(3)/2)*s," Winkel= ",2*atan(s/2/(sqrt(3)/2)) )); -} - - - - -module GewindeV1(d=20,s=1.5,w=5,g=1,fn=3,r=0,gd=1.75,detail=5,tz=0,name)//depreciated -{ - - - difference() - { - children(); - color("orange")translate([0,0,tz])for (i=[0:detail:w*360]) - { - j=i+detail; - hull() - { - R(z=i)Polar(g,(d-gd)/2,n=0)T(z=i/(360/s))R(90)R(z=r)cylinder(.1,d=gd,$fn=fn); - R(z=j)Polar(g,(d-gd)/2,n=0)T(z=j/(360/s))R(90)R(z=r)cylinder(.1,d=gd,$fn=fn); - } - - } - } - - if(name)echo(str("»»» »»» ",name," Gewinde aussen∅= ",d,"mm — Center∅= ",d-gd,"mm")); - if(r||(fn!=3&&fn!=6)) echo (" !!! Check Aussendurchmesser !!! "); - -} - - -module Bogen(grad=90,rad=5,l,l1=10,l2=12,fn=fn,center=true,tcenter=false,name,d=3,fn2=fn,ueberlapp,spiel=-minVal,help,messpunkt=messpunkt,2D=false) -{ - $fn=fn; - $fs=fs; - $fa=fa; - $helpM=0; - $info=0; - $idxON=false; - ueberlapp=is_undef(ueberlapp)?spiel:ueberlapp; - l1=is_undef(l)?l1-ueberlapp:is_list(l)?l[0]-ueberlapp:l-ueberlapp; - l2=is_undef(l)?l2-ueberlapp:is_list(l)?l[1]-ueberlapp:l-ueberlapp; - 2D=is_parent(needs2D)&&!$children?2D?b(2D,false): - 1: - b(2D,false); - - c=sin(abs(grad)/2)*rad*2;// Sekante - w1=abs(grad)/2; // Schenkelwinkel - w3=180-abs(grad); // Scheitelwinkel - a=(c/sin(w3/2))/2; - hc=grad!=180?Kathete(a,c/2):0; // Sekante tangenten center - hSek=Kathete(rad,c/2); //center Sekante - bl=PI*rad/180*grad;//Bogenlänge - - mirror([grad<0?1:0,0,0])rotate(center?0:tcenter?-abs(grad)/2:+0)T(tcenter?grad>180?hSek+hc:-hSek-hc:0)rotate(tcenter?abs(grad)/2:0) T(center?0:tcenter?0:-rad){ - if(!2D) T(rad)R(+90,+0)Tz(-l1-ueberlapp){ - $idx=0; - $tab=is_undef($tab)?1:b($tab,false)+1; - color("green") linear_extrude(l1,convexity=5) - if ($children)mirror([grad<0?1:0,0,0])children(); - else circle(d=d,$fn=fn2); - //color("lightgreen",.5) T(0,0,l1)if(messpunkt&&$preview)R(0,-90,-90)Dreieck(h=l1,ha=pivotSize,grad=5,n=0);//Pivot(active=[1,1,1,0]); - } - else T(rad)R(0,+0)T(0,ueberlapp)color("green")T(-d/2)square([d,l1]); - - if(grad)if(!2D) rotate_extrude(angle=-abs(grad)-0,$fa = abs(grad)/fn, $fs = $fs,$fn=0,convexity=5)intersection(){ - $idx=1; - $fn=fn; - $fa=fa; - T(rad) - if ($children)mirror([grad<0?1:0,0,0])children(); - else circle(d=d,$fn=fn2); - translate([0,-500])square(1000); - } - else Kreis(rand=d,grad=abs(grad),center=false,r=rad+d/2,fn=fn,name=0,help=0); - - if (!2D)R(z=-abs(grad)-180) T(-rad,ueberlapp)R(-90,180,0){ - $idx=2; - color("darkorange")linear_extrude(l2,convexity=5) - if ($children)mirror([grad<0?1:0,0,0])children(); - else circle(d=d,$fn=fn2); - - //color("orange",0.5)if(messpunkt&&$preview)T(0,0,l2)R(0,-90,-90)Dreieck(h=l2,ha=pivotSize,grad=5,n=0);//Pivot(active=[1,1,1,0]); - } - else R(z=-abs(grad)-180) T(-rad,ueberlapp) color("darkorange")T(-d/2)square([d,l2]); - - union(){//messpunkt - color("yellow") Pivot(active=[1,0,0,1],messpunkt=messpunkt); - if(grad!=180)color("blue")mirror([0,grad<0?1:0,0]) translate(RotLang(90+grad/2,hc+hSek))Pivot(active=[1,0,0,1],messpunkt=messpunkt); - if(grad>180)color("lightblue")mirror([0,grad<0?1:0,0]) translate(RotLang(90+grad/2,-hc-hSek))Pivot(active=[1,0,0,1],messpunkt=messpunkt); - } - } - - - if(name&&!$children)echo(str("»»» »»» ",name," Bogen ",grad,"° Durchmesser= ",d,"mm — Innenmaß= ",2*max(rad,d/2)-d,"mm Außenmaß= ",2*max(rad,d/2)+d)); - - if(name)echo(str(name," Bogen ",grad,"° Radius=",rad,"mm Sekantenradius= ",hSek,"mm — Tangentenschnittpunkt=",hSek+hc,"mm TsSekhöhe=",hc,"mm Kreisstücklänge=",bl," inkl l=",bl+l1+l2,"mm")); - - if(!$children&&name&&!2D)Echo("Bogen missing Object! using circle",color="warning"); - - HelpTxt("Bogen",["grad",grad,"rad",rad,"l",l,"l1",l1,"l2",l2,"fn",fn,"center",center,"tcenter",tcenter,"name",name,"d",d,"fn2",fn2,"spiel",spiel,"messpunkt",messpunkt,"2D",2D],help); - -} - - - module Imprint(txt1=1,radius=20,abstand=7,rotz=-2,h=l(2),rotx=0,roty=0,stauchx=0,stauchy=0,txt0=" ",txt2=" ",size=5,font="Bahnschrift:style=bold",name) { @@ -7473,190 +13391,49 @@ difference(){ } } +/// ¼" Hex Shank +// cylinder(20,d=Umkreis(6,inch(0.25)),$fn=6); +// Bitaufnahme(star=2); -module W5(kurv=15,arms=3,detail=.3,h=50,tz=+0,start=0.7,end=13.7,topdiameter=1,topenddiameter=1,bottomenddiameter=+2,inv=0) -{ - - Polar(e=arms)for (i=[start:detail:end]) - { - - - j=i+detail; - hull() - { - R(z=i*kurv)T(i,0,tz*-2*h/(2*PI*(i)))R(inv*180)cylinder(h/(2*PI*(i)),d1=n(topenddiameter)+i/end*n(bottomenddiameter),d2=n(topdiameter),$fn=fn); - R(z=j*kurv)T(j,0,tz*-2*h/(2*PI*(j)))R(inv*180)cylinder(h/(2*PI*(j)),d1=n(topenddiameter)+j/end*n(bottomenddiameter),d2=n(topdiameter),$fn=fn); - } - } - - -} - -fonts=[ -"Bahnschrift", -"Alef", -"Amiri", -"Arial", -"Caladea", -"Calibri", -"David CLM", -"David libre", -"Deja Vu Sans", -"Ebrima", -"Echolon", -"Forelle", -"Frank Ruehl CLM", -"Frank Ruhl Hofshi", -"Franklin Gothic Medium", -"Gabrielle", -"Gabriola", -"Gadugi", -"Gentium Basic", -"Gentium Book Basic", -"Georgia", -"Impact", -"Ink Free", -"Liberation Mono", -"Liberation Sans", -"Liberation Sans Narrow", -"Liberation Serif", -"Linux Biolinum G", -"Linux Libertine Display G", -"Linux Libertine G", -"Lucida Console", -"Noto Sans", -"OpenSymbol", -"Palatino Linotype", -"Politics Head", -"Reem Kufi", -"Rubik", -"SamsungImagination", -"Segoe Print", -"Segoe Script", -"Segoe UI", -"SimSun", -"Sitka Banner", -"Sitka Display", -"Sitka Heading", -"Sitka Small", -"Sitka Subheading", -"Sitka Subheading", -"Sitka Text", -"Source Code Pro", -"Source Sans Pro", -"Source Serif Pro", -"Tahoma", -"Times New Roman", -"Trebuchet MS", -"Unispace", -"Verdana", -"Yu Gothic", -"Yu Gothic UI", -"cinnamon cake", -"gotische", -"Webdings","Wingdings","EmojiOne Color", -]; - -styles=[ - -"Condensed", -"Condensed Oblique", -"Condensed Bold", -"Condensed Bold Oblique", -"Condensed Bold Italic", -"SemiCondensed", -"SemiLight Condensed", -"SemiLight SemiCondensed", -"SemiBold SemiCondensed", -"SemiBold Condensed", -"Light Condensed", -"Light SemiCondensed", -"SemiLight", -"Light", -"ExtraLight", -"Light Italic", -"Bold", -"Bold SemiCondensed", -"Semibold", -"Semibold Italic", -"Bold Italic", -"Bold Oblique", -"Black", -"Black Italic", -"Book", -"Regular", -"Italic", -"Medium", -"Oblique", -]; - - -module Text(text="»«",size=5,h,cx,cy,cz,center=0,spacing=1,fn=24,radius=0,rot=[0,0,0],font="Bahnschrift:style=bold",style,help,name) -{ - h=is_undef(h)?size:h; - cx=center?is_undef(cx)?1:cx:is_undef(cx)?0:cx; - cy=center?is_undef(cy)?1:cy:is_undef(cy)?0:cy; - cz=center?is_undef(cz)?1:cz:is_undef(cz)?0:cz; - - font=is_num(font)?fonts[font]:font; - style=is_string(style)?style:styles[style]; - fontstr=is_undef(style)?font:str(font,":style=",style); - - if(is_num(text)||text)if(!radius){ - if(h) - rotate(rot)translate([0,0,cz?-abs(h)/2:h<0?h:0]) linear_extrude(abs(h),convexity=10){ - text(str(text),size=size,halign=cx?"center":"left",valign=cy?"center":"baseline",font=fontstr,spacing=spacing,$fn=fn); - } - else rotate(rot)translate([0,0,cz?-h/2:0])text(str(text),size=size,halign=cx?"center":"left",valign=cy?"center":"baseline",spacing=spacing,font=fontstr,$fn=fn); - } -else for(i=[0:len(str(text))-1])rotate(center?gradB((size*spacing)/2*(len(str(text))-1),radius):0)rotate(gradB(size*spacing,radius)*-i) - if(h) - translate([0,radius,0])rotate(rot)Tz(cz?-abs(h)/2:h<0?h:0) linear_extrude(abs(h),convexity=10){ - text(str(text)[i],size=size,halign=true?"center":"left",valign=cy?"center":"baseline",font=fontstr,$fn=fn); - } - else translate([0,radius,cz?-h/2:0])rotate(rot)text(str(text)[i],size=size,halign=true?"center":"left",valign=cy?"center":"baseline",font=fontstr,$fn=fn); - - - if(name)echo(str("",name," Text font=",font," — style=",style)); - - if(help)echo(str("Help Text(", -"text="",text,""", -", size=",size, -", h=",h,"/*0 for 2D*/", -", cx=",cx, -", cy=",cy, -", cz=",cz, -", center=",center, -", spacing=",spacing, -", fn=",fn, -", radius=",radius, -", rot=",rot, -", font="",font,""", - ",style="",style,""", - ",help);")); - -} - - - -module Bitaufnahme(l=10,star=true,help) + +module Bitaufnahme(l=10,star=2,help) { +//¼" Hex Shank = umkreis 7.33235 / inkreis 6.35 if(star){ + LinEx(l+1,h2=[.5,1],scaleCenter=0.97,scale=1.1,scale2=star>1?0.55:0.45){ + if(star==true||star==1)Rund(1,fn=36)Polar(2)circle(4.6,$fn=3); + if(star>1)WStern(6,r=3.63,fn=6*10,help=0,r2=3.1); + } + if(star>1)T(z=l){ + Tz(-0.30)scale([1,1,0.60]) sphere(d=5.8,$fn=36); + *linear_extrude(1.00,scale=0.56,convexity=5)scale(.95)WStern(6,r=3.5,fn=6*10,help=0,r2=3.1); + } + else T(z=l){ + Tz(-0.29)scale([1,1,0.6]) sphere(d=5.3,$fn=36); + *linear_extrude(0.80,scale=0.56,convexity=5)scale(.95)Rund(1,fn=36)Polar(2)circle(4.6,$fn=3); + + + } + } + /* old + %T(6)union(){ linear_extrude(l,scale=.95,convexity=5){ if(star==true||star==1)Rund(1,fn=36)Polar(2)circle(4.6,$fn=3); - if(star==2)WStern(6,r=3.5,fn=6*10,help=0,r2=3.1); + if(star>1)WStern(6,r=3.5,fn=6*10,help=0,r2=3.1); } - if(star==2)T(z=l){ + if(star>1)T(z=l){ Tz(-0.30)scale([1,1,0.60]) sphere(d=5.8,$fn=36); linear_extrude(1.00,scale=0.56,convexity=5)scale(.95)WStern(6,r=3.5,fn=6*10,help=0,r2=3.1); } else T(z=l){ Tz(-0.29)scale([1,1,0.6]) sphere(d=5.3,$fn=36); - linear_extrude(0.80,scale=0.56,convexity=5)scale(.95)Rund(1,fn=36)Polar(2)circle(4.6,$fn=3); + linear_extrude(0.80,scale=0.56,convexity=5)scale(.95)Rund(1,fn=36)Polar(2)circle(4.6,$fn=3); } - } + } + */ + if(!star){hull() { cylinder(l,d1=Umkreis(6,6.3),d2=Umkreis(6,6.1),$fn=6); @@ -7670,31 +13447,31 @@ module Bitaufnahme(l=10,star=true,help) } -module Luer(male=true,lock=true,slip=true,rand=n(2),help) +/// Luer connector +//Luer(male=false); + +module Luer(male=true,lock=true,slip=true,rand=n(2),help,name) { + HelpTxt("Luer",["male",male,"lock",lock,"slip",slip,"rand",rand,"name",name],help); - if(help)echo(str("

    Help Luer (", - "male=",male, - ", lock=",lock, - ", slip=",slip, - ", rand=",rand, - ", help);" - )); - //show=41; 6% nach DIN - //*R(180)T(z=-73.5)color("red")cylinder(100,d1=0,d2=6,$fn=fn);//Eichzylinder 6% - //*T(z=+1.0)color("green")cylinder(5.8,d1=4.35,d2=4.0,$fn=fn);//referenz gemessen + /* show=41; 6% nach DIN + R(180)T(z=-73.5)color("red")cylinder(100,d1=0,d2=6.0,$fn=fn); //Eichzylinder 6% + T(z=+1.0)color("green")cylinder(5.8,d1=4.35,d2=4.0,$fn=fn); //referenz gemessen + // */ d=4.5; + v=33+1/3; + if (male) { if(slip) { translate([0,0,lock?0:-1])difference() { - Kegel(d1=lock?d:d+0.06,d2=4,v=+33.3,name=0); - translate([0,0,-0.01])Kegel(d1=d-rand*2,d2=0,v=+33.3,name=0); - echo(str("»»» »»» Luer uses Kegel(d1=",d,",d2=4,v=+33.3);")); + Kegel(d1=lock?d:d +0.06,d2=4,v=v,name=0); + translate([0,0,-0.01])Kegel(d1=-rand*2+(lock?d:d +0.06),d2=0,v=v,name=0); + echo(str("»»» »»» Luer uses Kegel(d1=",d,",d2=4,v=",v,");")); } intersection() { @@ -7706,9 +13483,9 @@ module Luer(male=true,lock=true,slip=true,rand=n(2),help) if (lock) { - //T(z=6)Gewinde(d=8.85,w=1.4,s=5.5,g=2,gd=Umkreis(4,1.3),fn=5,r=36,tz=-6.4,name=0,new=false)R(180)Ring(6,1.9,10.2,name="Luerlock");// OLD + intersection(){ - Gewinde(tz=-1.75,dn=8,kern=6.75,innen=true,breite=0.5,winkel=75,g=2,p=5.5,wand=0.75,h=10,new=true,center=+0,cyl=1,name=0); + Gewinde(tz=-1.75,dn=8,kern=6.75,innen=true,breite=0.5,winkel=75,g=2,p=5.5,wand=0.75,h=10,new=true,center=+0,cyl=1,name=0,fn=60); cylinder(6,d=20); } difference() @@ -7719,30 +13496,28 @@ module Luer(male=true,lock=true,slip=true,rand=n(2),help) } } - if (!lock&&!slip)color("orange")cylinder(10,d=10.5,$fn=fn); + if (!lock&&!slip)color("magenta")cylinder(10,d=10.5,$fn=fn); if (!male) { - T(z=0)rotate(360/5.5*0.5)difference() - { - union() - { - if(lock)Halb()Gewinde(dn=7.8,p=5.5,g=2,winkel=75,kern=6,grad=200,start=fn/6,name=0,new=true,center=1,tz=+0);// rotate(360/5.5*0.3)Gewinde(d=7.8,w=0.5,s=5.5,g=2,gd=1.2,fn=5,r=36,tz=-0.7,name=0); - if(slip) cylinder(10,d=6);//Ring (10,n(2),6,name=0); - } - translate([0,0,-0.1])Kegel(d1=4.45,d2=2.0,v=+33.3,name=0); + //T(z=0)rotate(360/5.5*0.5) + difference(){ + union(){ + if(lock)Halb()Gewinde(dn=7.8,p=5.5,g=2,winkel=75,kern=6,grad=200,start=fn/6,name=0,new=true,center=1,tz=+0);// + if(slip) cylinder(10,d=6); + } + translate([0,0,-0.01])Kegel(d1=d,d2=2.0,v=v,name=0); //mirror([0,0,1])cylinder(5,d=12); } } - +InfoTxt("Luer",male?["h",v*(d-4)/2]:["h",10,"d",6],name); } - module Knochen(l=+15,d=3,d2=5,b=0,fn=fn,help) { @@ -7760,69 +13535,102 @@ module Knochen(l=+15,d=3,d2=5,b=0,fn=fn,help) } -module DGlied(sym,l=12,l1,l2,la=+0.0,d=3,h=5,spiel=0.4,rand=n(1.5),freiwinkel=20,help){ -if (sym) DGlied1(l=l,l1=l1,l2=l2,la=la,spiel=spiel,d=d,h=h,rand=rand,freiwinkel=freiwinkel); -else DGlied0(l=l,l1=l1,l2=l2,la=la,spiel=spiel,d=d,h=h,rand=rand,freiwinkel=freiwinkel); +/// dual glied -HelpTxt("DGlied",["sym",sym,"l",l,"l1",l1,"l2",l2,"spiel",spiel,"la",la,"fn",fn,"d",d,"h",h,"rand",rand,"freiwinkel",freiwinkel],help); +//DGlied1(shield=true,winkel=150); + +module DGlied(sym,l=12,l1,l2,la=+0.0,d=3,h=5,spiel=0.4,spielZ=nozzle/2,rand=.6,freiwinkel=20,fn=36,cap=false,shield=false,winkel,help){ +if (sym) DGlied1(l=l,l1=l1,l2=l2,la=la,spiel=spiel,d=d,h=h,rand=rand,spielZ=spielZ,freiwinkel=freiwinkel,winkel=winkel,shield=shield,cap=cap,fn=fn); +else DGlied0(l=l,l1=l1,l2=l2,la=la,spiel=spiel,d=d,h=h,rand=rand,spielZ=spielZ,freiwinkel=freiwinkel,cap=cap,winkel=winkel,shield=shield,fn=fn); + +HelpTxt("DGlied",["sym",sym,"l",l,"l1",l1,"l2",l2,"spiel",spiel,"spielZ",spielZ,"la",la,"fn",fn,"d",d,"h",h,"rand",rand,"freiwinkel",freiwinkel,"cap",cap],help); } -module DGlied0(l=12,l1,l2,la=+0.0,d=3,h=5,spiel=0.4,rand=n(1.5),freiwinkel=20) +module DGlied0(l=12,l1,l2,la=+0.0,d=3,h=5,spiel=0.4,spielZ=nozzle/2,rand=.6,freiwinkel=20,winkel,shield=false,cap,fn=36) { +winkel=is_list(winkel)?winkel:[winkel,winkel]; +shield=is_list(shield)?shield:[shield,shield]; l1=is_undef(l1)?is_list(l)?l[0]:l:l1; l2=is_undef(l2)?is_list(l)?l[1]:l:l2; - Glied(l1,la=la,spiel=spiel,d=d,h=h,rand=rand,freiwinkel=freiwinkel); - mirror([0,1,0])Glied(l2,la=la,spiel=spiel,d=d,h=h,rand=rand,freiwinkel=freiwinkel); + Glied(l1,la=la,spiel=spiel,spielZ=spielZ,d=d,h=h,rand=rand,freiwinkel=freiwinkel,cap=cap,winkel=winkel[0],shield=shield[0],fn=fn); + rotate(180)Glied(l2,la=la,spiel=spiel,spielZ=spielZ,d=d,h=h,rand=rand,freiwinkel=freiwinkel,cap=cap,winkel=winkel[1],shield=shield[1],fn=fn); } -module DGlied1(l=12,l1,l2,la=0,d=3,h=5,spiel=0.4,rand=n(1.5),freiwinkel=20) +module DGlied1(l=12,l1,l2,la=0,d=3,h=5,spiel=0.4,spielZ=nozzle/2,rand=.6,freiwinkel=20,cap,winkel,shield=false,fn=fn) { +winkel=is_list(winkel)?winkel:[winkel,winkel]; +shield=is_list(shield)?shield:[shield,shield]; l1=is_undef(l1)?is_list(l)?l[0]:l:l1; l2=is_undef(l2)?is_list(l)?l[1]:l:l2; - mirror([+0,1,0])T(0,-l1)Glied(l1,la=la,spiel=spiel,d=d,h=h,rand=rand,freiwinkel=freiwinkel); - T(0,-l2)Glied(l2,la=la,d=d,h=h,spiel=spiel,rand=rand,freiwinkel=freiwinkel); + mirror([+0,1,0])T(0,-l1)Glied(l1,la=la,spiel=spiel,spielZ=spielZ,d=d,h=h,rand=rand,freiwinkel=freiwinkel,cap=cap,winkel=winkel[0],shield=shield[0],fn=fn); + T(0,-l2)Glied(l2,la=la,d=d,h=h,spiel=spiel,spielZ=spielZ,rand=rand,freiwinkel=freiwinkel,cap=cap,winkel=winkel[1],shield=shield[1],fn=fn); } +/// symetric Glied male or female +// SGlied(sym=+0); -module SGlied(sym=0,l=12,la=-.5,d=3,h=5,spiel=0.4,rand=n(1.5),freiwinkel=30,help){ +module SGlied(sym=0,l=12,la=-.5,d=3,h=5,spiel=0.4,spielZ=nozzle/2,rand=.6,freiwinkel=30,help,messpunkt=messpunkt,fn=36){ -T(0,l/2){ -Halb(!sym,x=1)T(0,-l/2)Glied(l,la=la,spiel=spiel,d=d,h=h,rand=rand,freiwinkel=sym?freiwinkel:90); -Halb(sym,x=1)rotate(180)T(0,-l/2)Glied(l,la=la,spiel=spiel,d=d,h=h,rand=rand,freiwinkel=sym?freiwinkel:90); -} -HelpTxt("SGlied",["sym",sym,"l",l,"spiel",spiel,"la",la,"fn",fn,"d",d,"h",h,"rand",rand,"freiwinkel",freiwinkel],help); + T(0,l/2){ + Halb(sym,y=1)T(0,-l/2)Glied(l,la=la,spiel=spiel,d=d,h=h,rand=rand,fn=fn,freiwinkel=sym?freiwinkel:90,messpunkt=false); + Halb(!sym,y=1)rotate(180)T(0,-l/2)Glied(l,la=la,spiel=spiel,d=d,h=h,rand=rand,fn=fn,messpunkt=false,freiwinkel=sym?freiwinkel:90); + } + HelpTxt("SGlied",["sym",sym,"l",l,"spiel",spiel,"spielZ",spielZ,"la",la,"fn",fn,"d",d,"h",h,"rand",rand,"freiwinkel",freiwinkel],help); + + if (messpunkt) + { + %color (sym?"red":"blue")translate([0,l,0.1])R(z=180/12)cylinder(5, d1=1,d2=1,$fn=12,center=true);//messachse1 + %color(sym?"red":"blue")cylinder(5, d1=1,d2=1,$fn=12,center=true);//messachse2 + } } /* -Schnitt(center=true,z=3){ -Glied(l=31,d=3,la=+0); -rotate(20+180)T(0,-31)Glied(l=31,d=3,la=+0); +Schnitt(0,center=true,z=3){ +Glied(l=31,d=3,la=-1,spielZ=0); +rotate(30+180)T(0,-31)Glied(l=31,d=3,la=-1,spielZ=0); } -*/ +// */ + +/// joint + +//Glied(shield=true,cap=true,freiwinkel=91); - -module Glied(l=12,spiel=0.4,la=-0.5,fn=20,d=3,h=5,rand=n(1.5),freiwinkel=30,name=0,help) +module Glied(l=12,spiel=0.4,spielZ=nozzle/2,la=-0.5,d=3,h=5,rand=.6,freiwinkel=30,fn=36,shield=false,winkel,cap=false,pip,center=false,name=0,help,messpunkt=messpunkt) { - hFreiraum=h/2+nozzle /2; - hSteg=h/2 - nozzle /2; - + spiel=is_undef(pip)?spiel:pip; + winkel=is_undef(winkel)?freiwinkel:is_list(winkel)?winkel:[winkel,winkel]; + freiwinkel= is_num(winkel)?[winkel,winkel]:winkel; + hFreiraum=h/2 + spielZ; + hSteg=h/2 - spielZ; + sphereR=.8; + hErr=sphereR-cos(90/ceil(fn/2))*sphereR+.0001; // sphere fn error minkowski + shield=is_num(shield)?shield:rand/2; $info=false; $helpM=false; + center=is_bool(center)?bool(!center,false):center; + HelpTxt("Glied",[ "l",l, "spiel",spiel, + "spielZ",spielZ, "la",la, "fn",fn, "d",d, "h",h, "rand",rand, - "freiwinkel",freiwinkel, - "name",name],help); + "winkel",winkel, + "shield",shield, + "cap",cap, + "pip",pip, + "center",center, + "name",name,"messpunkt",messpunkt],help); - T(y=l,z=h/2)Pille(l=hSteg,d=d+1,rad=.8,fn=fn);//Torus(1.2,1.7,fn=fn,n=name); + T(0,center*l/2-l/2){ + + T(y=l,z=h/2)Pille(l=hSteg,d=d +1,rad=min(hSteg/2,.8),fn=fn);//Torus(1.2,1.7,fn=fn,n=name); if (messpunkt) { %color ("blue")translate([0,l,0.1])R(z=180/12)cylinder(5, d1=1,d2=1,$fn=12,center=true);//messachse1 @@ -7832,53 +13640,74 @@ module Glied(l=12,spiel=0.4,la=-0.5,fn=20,d=3,h=5,rand=n(1.5),freiwinkel=30,name T(0,l)//kopfstück { - lkopf=l-(d-.5)/tan(freiwinkel)+la -1; + lkopf=l-(d-.5)/tan(min(70,freiwinkel[0],freiwinkel[1]))+la -1; T(0,-lkopf/2,h/2) minkowski() { - cube([d-2*0.8+.25,lkopf-2*0.8,hSteg-2*.8],true); - sphere(0.8,$fn=fn); + cube([d -2*sphereR +0.25,lkopf-2*0.8,max(minVal,hSteg-2*.8)],true); + sphere(sphereR,$fn=fn); } cylinder(h,d=d,$fs=0.2,$fa=5,$fn=0);//Achse! } - difference() +//cap + if(cap)Tz(h-0.001)difference(){ + Pille(1,d=d+rand*2+spiel*2,rad=[0,1],center=false); + Kegel(d+spiel*2,d2=d+spiel*2-1,grad=45,lap=[.5,0]); + } + + T(0,0,h/2)difference() { - T(0,0,h/2)hull()//Ringanker - { - T(0,l/2+la/2-d/2) minkowski() + + hull(){//Ringanker + T(0,l/2+la/2-d/2) minkowski() { - cube([max(d-2*.8-.5,.1),l+la-2*.8-d,h-0.8*2],true); - sphere(0.8,$fn=fn); + cube([max(d -2*sphereR-.5,.1),l+la-2*.8-d,max(minVal,h-sphereR*2 + hErr*2)],true); + sphere(sphereR,$fn=fn); } - T(0,l -d/2 -rand-spiel+la) minkowski()// spitze + T(0,l -d/2 -rand-spiel+la) minkowski()// spitze { - cube([max(d-2*.8-.5,.1),0.1,+0.01],true); - sphere(0.8,$fn=fn); + cube([max(d-2*sphereR-.5,.1),0.1,+0.01],true); + sphere(sphereR,$fn=fn); } - } - translate([0,l])cylinder(h*2,d=d+rand*2+spiel*4,$fn=0,$fs=0.5);// space for ring of other + translate([0,l])cylinder(h*2,d=d+rand*2+spiel*4,$fn=0,$fs=0.5,center=true);// space for ring of other cylinder(h*2,d=d+2*spiel,$fn=fn,center=true); Freiwinkel(); - Tz(h/2)Pille(l=hFreiraum,d=d+1+2*spiel,rad=1,fn=fn); + Pille(l=hFreiraum,d=d+1+2*spiel,rad=min(hFreiraum/2,1),fn=fn); } - T(0,0)union()//B ring + if(shield){ + r=d/2+rand+spiel; + deg=freiwinkel; + deltaW=gradS(s=d-.5+spiel,r=r)/2; + LinEx(h,h/4-spielZ/2,scale=r/(r+shield),center=false){ + if(freiwinkel[0]>90)Kreis(rand=-shield,grad=deg[0]-deltaW*2,r=r-.01,center=false,rot=-deg[0]-90+deltaW*1.5); + if(freiwinkel[1]>90)Kreis(rand=-shield,grad=deg[1]-deltaW*2,r=r-.01,center=false,rot=-90+deltaW*.5); + + } + } + + T(0,0,h/2)union()//B ring { difference() { union() { - Ring(h,rand,d+2*spiel,cd=-1,name=name); +//shield + + linear_extrude(h,center=true,convexity=5)Rund(0,d/2+spiel -.1) + { + Ring(h=0,rand,d+2*spiel,cd=-1,name=name,center=true); + T(0,d/2+spiel)Quad([max(d -0.5,sphereR*2+.1),sphereR*2],r=sphereR*[1,1,0,0],centerX=true); + } //T(0,3.2)R(z=33)cylinder(5,d=3,$fn=3); - } - Tz(h/2)cylinder(hFreiraum,d=d+rand*2+2*spiel,center=true);//Pille(l=hSteg+n(1),d=d+rand*2+2*spiel +1,rad=1,fn=fn); - color("red")Freiwinkel(); + cylinder(hFreiraum,d=d+rand*2+2*spiel,center=true);//Pille(l=hSteg+n(1),d=d+rand*2+2*spiel +1,rad=1,fn=fn); + Freiwinkel(); /* * T(+2.9,-1.40,2.5)R(z=46)minkowski() { cube([5,+5,1.0],true); @@ -7901,94 +13730,32 @@ module Glied(l=12,spiel=0.4,la=-0.5,fn=20,d=3,h=5,rand=n(1.5),freiwinkel=30,name } */ } - - module Freiwinkel(w=freiwinkel+90)//Glied only - T(0,+0.5){ - R(z=+w) T(+0,+25-d/2,h/2)minkowski() + +} + + module Freiwinkel(w=freiwinkel+[90,90])//Glied only + color("red")T(0,+0.5){ + R(z=min(170,w[0])) T(+0,+25-d/2)minkowski() { - cube([200,+50-.8*2,hFreiraum-2*0.8],true); + cube([200,+50-.8*2,max(minVal,hFreiraum-2*0.8)],true); sphere(0.8,$fn=fn); } - R(z=-w) T(+0,+25-d/2,h/2)minkowski() + R(z=-min(170,w[1])) T(+0,+25-d/2)minkowski() { - cube([200,+50-.8*2,hFreiraum-2*0.8],true); + cube([200,+50-.8*2,max(minVal,hFreiraum-2*0.8)],true); sphere(0.8,$fn=fn); } } -} -module Freiwinkel(w=60,h=1) - T(0,+1.0){ - R(z=w/2-90) T(-6,+0,2.0)minkowski() - { - cube([20,5,h],false); - sphere(0.8,$fn=fn); - } - R(z=-w/2+90) T(-14,+0,2.0)minkowski() - { - cube([20,5,h],false); - sphere(0.8,$fn=fn); - } - - } +} // end Glied - -module Torus2(m=5,trx=10,a=1,rq=1,d=5,w=2,name,new=true)//m=feinheit,trx = abstand mitte,rq = sin verschiebung , a=amplitude, w wellen -{ - -//if(new&&w==2)rotate(90/w)WaveEx(grad=360,trx=trx-a/2*1,try=trx+a/2*1,f=w,tf=w,fv=0,tfv=0,r=d/2,ta=a/2,a=-rq/2); -if(new)rotate(-90/w)WaveEx(grad=360,trx=trx,try=trx,f=w,tf=-w,fv=0,tfv=180,r=d/2,ta=a,a=rq/2,fn=360/m); - -if(!new)echo("

    For Torus2 use 'new=true' (WaveEx)"); -if(new)echo("

    Torus2 is using WaveEx"); -if(!new)rotate ([0,0,0])for (i=[0:m:360]) - { - - hull() - { - rotate ([0,0,i])translate([trx+(sin(w*i)*a),0,0])rotate([90,0,0])cylinder(.01,d1=sin(w*i)*rq+d,d2=0,$fn=200/m,center=false); - - rotate ([0,0,i-m])translate([trx+(sin(w*(i-m))*a),0,0])rotate([90,0,0])cylinder(.01,d1=sin(w*(i-m))*rq+d,$fn=200/m,d2=0,center=false); - } - } - - if(name)echo(str("»»» »»» ",name," Torus2 ",w," Wellen")); - -} - -module Kegel(d1=undef,d2=0,v=1,grad=0,h=0,r1,r2,fn=fn,center=false,name,help) -{ -v=grad?tan(grad):v; -d2=h&&(is_num(d1)||is_num(r1))?h/-v*2+(is_num(r1)?2*r1:d1):is_num(r2)?2*r2:d2; -d1=is_undef(d1)&&is_undef(r1)&&h?h/v*2+(is_num(r2)?2*r2:d2):is_num(r1)?r1*2:is_undef(d1)?0:d1; -cylinder (abs((d1-d2)/2*v),d1=d1,d2=d2,$fn=fn,center=center); -//if(d2>d1)cylinder (abs((d2-d1)/2*v),d1=d1,d2=d2,$fn=fn,center=center); -if(d1==d2)cylinder (h?h:10,d1=d1,d2=d2,$fn=fn,center=center); -if(!d1&&!d2&&is_undef(r1))color("magenta")%cylinder(5,5,0,$fn=fn,center=center); - - if(d2<0||d1<0)Echo(str("‼ negativ ∅",name," Kegel d1=",negRed(d1)," d2=",negRed(d2)),color="red"); - InfoTxt("Kegel",["höhe",abs((d1-d2)/2*v),"Steigung",str(v*100,"% ",atan(v),"°"),"Spitzenwinkel",str(2*(90-atan(v)),"°"),"d2",negRed(d2)],name); - - HelpTxt("Kegel",["d1",d1,"d2",d2,"v",v,"grad",grad,"h",h,"r1",r1,"r2",r2,"fn",fn,"center",center,"name=",name],help); -} - -module MK(d1=12,d2=6,v=19.5,fn=fn) -{ -//Basis -// Obererdurchmesser -//kegelverjüngung -cylinder ((d1-d2)/2*v,d1=d1,d2=d2,$fn=fn); - echo(str("»»»››› Konushöhe=",(d1-d2)/2*v)); -} - - module Stabhalter (l=10,d=3.5)// Replaced with Ring(cd=-1,rand(n(1.5)),durchmesser=In6eck(3.1),fn=6) { @@ -8004,8 +13771,20 @@ module Stabhalter (l=10,d=3.5)// Replaced with Ring(cd=-1,rand(n(1.5)),durchmess } +/** \name Halbrund \page Products +Halbrund() removes a flat circle from a children +\param h height (h=0 ↦ 2D polygon) +\param d diameter +\param d2 flat diameter (x can be used instead) +\param x the flat reduction optional to calc ↦ d2 +\param doppel makes it doubble side flat +*/ + +//Halbrund(help=1); + module Halbrund(h=10,d=3+2*spiel,d2,x=1.0-spiel,doppel=false,name,help) { +h=is_parent(needs2D)?0:h; d2=is_undef(d2)?doppel?d-x*2:d-x:d2; x=is_undef(d2)?x:doppel?(d-d2)/2:d-d2; if(h){difference() @@ -8014,12 +13793,12 @@ if(h){difference() if(!doppel)difference() { cylinder(d=d,h=h*2,center=true,$fn=36); - translate([d/2-x, -25, -50])cube([50,50,100],center=false); + translate([d/2-x, -d, -h*2])cube([d*2,d*2,h*4],center=false); } else intersection() { cylinder(d=d,h=h*2,center=true,$fn=36); - cube([d2,d+1,100],center=true); + cube([d2,d+1,h*3],center=true); //translate([-d/2+x-50, -25, -50])cube([50,50,100],center=false); } @@ -8050,23 +13829,6 @@ help); } -module Twins(h=1,d,d11=10,d12,d21=10,d22,l=20,r=0,fn=fn,center=0,sca=+0,2D=false) -{ - d11=d?d:d11; - d12=d?d:is_undef(d12)?d11:d12; - d21=d?d:d21; - d22=d?d:is_undef(d22)?d21:d22; - - if(!2D) rotate([0,0,center?r:0])translate([center?-l/2:0,0,0]){ - rotate([0,-sca,0])cylinder(h,d11*.5,d12*.5,$fn=fn); - rotate([0,0,center?0:r])translate([l,0,0])rotate([0,sca,0])cylinder(h,d21*.5,d22*.5,$fn=fn); } - - if(2D) rotate([0,0,center?r:0])translate([center?-l/2:0,0,0]){ - rotate([0,-sca,0])circle(d=d11,$fn=fn); - rotate([0,0,center?0:r])translate([l,0,0])rotate([0,sca,0])circle(d=d21,$fn=fn); } - - -} @@ -8088,7 +13850,65 @@ module Riemenscheibe(e=40,radius=25,nockendurchmesser1=2,nockendurchmesser2=2,ho -module Servokopf(rot=0,spiel=0,schraube=true,help) +//Schnitt()Servokopf(schraube=1)Pille(5,d=8,center=false,rad=.5); + + +module Servokopf(rot,spiel=0.1,schraube=true,T=21,d=4.9,h=3.25,name,help) +{ + // 21 Zacken! + + tdepth=.25; + r1=d/2+spiel; + r2=d/2-tdepth+spiel; + + preset=[ + ["name","T","d"], + ["A15T",15,3.9],// A1 + ["B25T",25,4.9],// B1 + ["C24T",24,5.6],// C1 + ["H25T",25,5.9],// 3F + ["D15T",15,7.6],// D1 + [" 21T",21,4.9] // this + ]; + + if(help)for(i=[0:len(preset)-1])echo(preset[i]); + %if(is_num(rot))Tz(+0){//direction + Col(5,0.5) rotate(rot+90) scale([1,0.5])circle(3.5,$fn=3); + Col(6,0.7) rotate(90) scale([1,0.5])circle(4,$fn=3); + } + + difference(){ + + if($children)children(); + translate([0,0,-0.01])union(){ + linear_extrude(h,convexity=5,scale=scaleGrad(grad=88,h=h,r=r1))Rund(+0,0.1,fn=12)Star(T,r1,r2,grad=3,grad2=gradS(wall(0.199,.8,even=0),r2),fn=0); + Kegel(d1=d+spiel*2+.2,h=.5,name=false); + } + + if(schraube&&$children){ + cylinder(h+10,d=2,$fn=36); //SchraubenlochNarbe + translate([0,0,h-.011])cylinder(.2,d1=r2*2,d2=2,$fn=36); //Decke + translate([0,0,h])Polar(teiler(T,5),rot=-90,name=false)R(0,-90)cylinder(d/2-tdepth*.8,d=.5,$fn=3); //Decke Support Struktur + + translate([0,0,h + 1.15])cylinder(100,d=4.5,$fn=36); //SchraubenKopflochNarbe + } + translate([0,0,-30.01])cylinder(30,d=50,$fn=36); //Servo + } + + InfoTxt("Servokopf",["T",T,"d",d+spiel*2,"dTop",(d+spiel*2)*scaleGrad(grad=88,h=h,r=d/2+spiel)],name); + HelpTxt("Servokopf",[ + "rot",rot, + "spiel",spiel, + "schraube",schraube, + "T",T, + "d",d, + "h",h, + "name",name + ],help); + +} + +module ServokopfT15(rot=0,spiel=0,schraube=true,help) // .6 nozzle { // 15 Zacken! d2=6+spiel; @@ -8129,7 +13949,7 @@ module Servokopf(rot=0,spiel=0,schraube=true,help) if(!$children) translate([0,0,-0.01])cylinder(.5,d1=d1-0.1,d2=d1-2,$fn=36,center=false);//basekone - HelpTxt("Servokopf",[ + HelpTxt("ServokopfT15",[ "rot",rot, "spiel",spiel, "schraube",schraube], @@ -8233,37 +14053,6 @@ module Gelenk(l=20,w=0,help)//ausschnittlänge, winkel -module Ring(h=5,rand,d=10,r,cd=1,id=6,ir,grad=360,rcenter,center=false,fn=fn,name,2D=0,help){ - - id=is_undef(id)?d-rand*2:id; - r=is_undef(r)?d/2:r; - ir=is_undef(ir)?id/2:ir; - rcenter=is_undef(rcenter)?!abs(cd):rcenter; - rand=is_undef(rand)?r-ir:rand*sign(cd==0?1:cd); - if(2D||!h)Kreis(rand=rand,rcenter=rcenter,r=r,grad=grad,fn=fn,rot=0,center=center,name=0,help=0); - else rotate([h>0?0:180])linear_extrude(abs(h),center=center,convexity=5)Kreis(rand=rand,rcenter=rcenter,r=r,grad=grad,center=center,fn=fn,rot=0,name=0,help=0); - -if(name)echo(str(is_bool(name)?"":"",name," Ring Aussen∅= ",rcenter?d+abs(rand):rand>0?d:d-rand*2,"mm — Mitte∅= ",rcenter?d:d-rand,"mm — Innen∅= ",rcenter?d-abs(rand):rand>0?d-(rand*2):d,"mm groß und ",2D||!h?"2D":str(h," hoch"))); - -HelpTxt("Ring",["h",h, - "rand",rand, - "d",d, - "r",r, - "id",id, - "ir",ir, - "cd",cd, - "rcenter",rcenter, - "center",center, - "fn",fn, - "name",name, - "2D",2D,],help); - -} - - - - - module Servotraeger(SON=1,top=0,help) { HelpTxt("Servotraeger",["SON",SON,"top",top],help); @@ -8303,8 +14092,10 @@ if (top) difference(){ } - -// OLD and Replaced modules +}//fold // Products ΔΔ +{ // OLD and Replaced modules + + module ZylinderOLD(h=10,r=10,fn=150,fnh=150,grad=360,grad2=84,f=10,f2=10,f3=0,a=.5,a3=0,fz=0,az=0,deltaFz=0,deltaF=90,deltaF2=0,deltaF3=0,twist=0,scale=+1,sphere=0,lz,help){ stepRot=grad/fn; @@ -8387,7 +14178,9 @@ module BogenOrg(grad=90,rad=5,d=3,l1=10,l2=12,name,fn=fn,fn2=fn,ueberlapp=-0.001 if(help)echo(str("Help Bogen(grad=90,rad=5,d=3,l1=10,l2=12,name,fn=fn,fn2=fn,ueberlapp=-0.001,help)")); } -/*///////////////////////////////////////////////////////////////////////////////////////////// + +} +/* // Depreciated // // // // // // // // // // // // // Depreciated / for Deletion module Aussenkreis(h=5,d=5.5,eck=6,kreis=0,fn=150,n=1)//misleading depreciated @@ -8491,83 +14284,82 @@ DEL module RingX(layer,rand,durchmesser)//old don't use! -//*/ +// */ - if(version()[0]<2021)echo("

    ---—————————————————————————————————————————————---"); - else echo("\n---————————————————————————————————————————---\n"); + +// echo("\n--------------\n"); // for demo Objects (incomplete) if (show) %color([0.6,+0.0,0.9,0.8]){ -if (show==402)Strebe(); -if (show==400)Pivot(); -if (show==100)Trapez(); -if (show==67)Tring(); -if (show==66)Prisma(); -if (show==65)Sichel(); -if (show==64)Balg(); -if (show==63)Area(); -if (show==62)Spirale(); -if (show==61)Gelenk(); -if (show==60)Glied(); -if (show==59)ReuleauxIntersect(); -if (show==58)Box(); -if (show==57)Tugel(); -if (show==56)Vorterantrotor(); -if (show==55)Kassette(); -if (show==54) Sinuskoerper(); -if (show==504) Achsenklammer(); -if (show==503) Achshalter(); -if (show==52) Freiwinkel(); -if (show==51) Dreieck(); -if (show==50) Rohr(); -if (show==49)Bogen(grad=90,rad=5,d=3,l1=10,l2=12); -if (show==48)Imprint(txt1="››»»Rundherrummmm»»››",abstand=17.8,radius=20,rotz=-27,h=l(2),rotx=0,roty=0,stauchx=0,stauchy=0,txt0=" ",txt2=" "); -if (show==47)W5(kurv=15,arms=3,detail=.3,h=50,tz=+0,start=0.7,end=13.7,topdiameter=1,bottomenddiameter=+2);//Spiralarm -if (show==46)Text(text="»DEMO«",size=5,h=0,cx=0,cy=0,cz=0,center=0,radius=0); -if (show==45)Bitaufnahme(); -if (show==44)Knochen(); -if (show==43)Servotraeger(SON=1); -if (show==42)Gardena(); -if (show==41)Luer(); -if (show==40)DGlied1(); -if (show==39)DGlied0(); -if (show==38)Glied(); -if (show==37)Kehle(); -if (show==36)Twins(); -if (show==35)Pille(); -if (show==34)Torus2(); -if (show==33)Torus(); -if (show==32)Ring(); -if (show==31)MK(); -if (show==301)Kegelmantel(); -if (show==30)Kegel(); -if (show==300)Kugelmantel(); -if (show==202)Halbrund(); -if (show==29)Bezier()sphere(2,$fn=12); -if (show==28)Kontaktwinkel()sphere(d=10); -if (show==27)Gewinde(); -if (show==26)Rundrum()circle(5); -if (show==261)Ttorus()scale([2,1,1])sphere(5,$fn=12); -if (show==25)Drehpunkt(x=15,y=2,z=-8,rx=20,ry=20,rz=20,messpunkt=1)cube(5); -if (show==24)Halb()sphere(20); -if (show==23)Klon(tx=10,rx=+25)cube(10,true); -if (show==22)Polar(x=10,y=10)cube(5); -if (show==21)Linear(es=0.5,s=1.0,e=4,x=90,y=0,z=0,r=0,re=0,center=+1,cx=+0)cube(5); + if (show==402)Strebe(); + if (show==400)Pivot(); + if (show==100)Trapez(); + if (show==67)Tring(); + if (show==66)Prisma(); + if (show==65)Sichel(); + if (show==64)Balg(); + if (show==63)Area(); + if (show==62)Spirale(); + if (show==61)Gelenk(); + if (show==60)Glied(); + if (show==59)ReuleauxIntersect(); + if (show==58)Box(); + if (show==57)Tugel(); + if (show==56)Vorterantrotor(); + if (show==55)Kassette(); + if (show==54) Sinuskoerper(); + if (show==504) Achsenklammer(); + if (show==503) Achshalter(); + if (show==52) Freiwinkel(); + if (show==51) Dreieck(); + if (show==50) Rohr(); + if (show==49)Bogen(grad=90,rad=5,d=3,l1=10,l2=12); + if (show==48)Imprint(txt1="››»»Rundherrummmm»»››",abstand=17.8,radius=20,rotz=-27,h=l(2),rotx=0,roty=0,stauchx=0,stauchy=0,txt0=" ",txt2=" "); + if (show==47)W5(kurv=15,arms=3,detail=.3,h=50,tz=+0,start=0.7,end=13.7,topdiameter=1,bottomenddiameter=+2);//Spiralarm + if (show==46)Text(text="»DEMO«",size=5,h=0,cx=0,cy=0,cz=0,center=0,radius=0); + if (show==45)Bitaufnahme(); + if (show==44)Knochen(); + if (show==43)Servotraeger(SON=1); + if (show==42)Gardena(); + if (show==41)Luer(); + if (show==40)DGlied1(); + if (show==39)DGlied0(); + if (show==38)Glied(); + if (show==37)Kehle(); + if (show==36)Twins(); + if (show==35)Pille(); + if (show==34)Torus2(); + if (show==33)Torus(); + if (show==32)Ring(); + if (show==31)MK(); + if (show==301)Kegelmantel(); + if (show==30)Kegel(); + if (show==300)Kugelmantel(); + if (show==202)Halbrund(); + if (show==29)Bezier()sphere(2,$fn=12); + if (show==28)Kontaktwinkel()sphere(d=10); + if (show==27)Gewinde(); + if (show==26)Rundrum()circle(5); + if (show==261)Ttorus()scale([2,1,1])sphere(5,$fn=12); + if (show==25)Drehpunkt(x=15,y=2,z=-8,rx=20,ry=20,rz=20,messpunkt=1)cube(5); + if (show==24)Halb()sphere(20); + if (show==23)Klon(tx=10,rx=+25)cube(10,true); + if (show==22)Polar(x=10,y=10)cube(5); + if (show==21)Linear(es=0.5,s=1.0,e=4,x=90,y=0,z=0,r=0,re=0,center=+1,cx=+0)cube(5); -if (show==4){cube(50,true);Echo("50mm Cube",color="purple");} -if (show==3){cube(20,true);echo("20mm Cube",color="purple");} -if (show==2){cylinder(10,d=n(1),$fn=36,center=true);echo(str(n(1)," mm ∅ =n(1) cylinder×10mm"),color="purple");} -if (show==1){cube(10,true);echo("10mm Cube",color="purple");} + if (show==4){cube(50,true);Echo("50mm Cube",color="purple");} + if (show==3){cube(20,true);echo("20mm Cube",color="purple");} + if (show==2){cylinder(10,d=n(1),$fn=36,center=true);echo(str(n(1)," mm ∅ =n(1) cylinder×10mm"),color="purple");} + if (show==1){cube(10,true);echo("10mm Cube",color="purple");} } - - - /* •••• Archive •••• +/** \name Archive +## •••• Archive •••• - 140|17 Changelog - beta 4.7 +140|17 Changelog - beta 4.7 140|17 ADD Text - beta 4.7 141|17 ADD show 164|17 ADD Bogen CHG Schnitt rotation default - beta 4.9 @@ -9017,5 +14809,158 @@ v2019.5 363|21 CHG func stern quad bezier kreis CHG Kehle help fix end spiel CHG Buchtung help 364|21 FIX Ring REP Kreis kreis +2022 + +000|22 prepare release CHG VarioFill +001|22 CHG MKlon +002|22 CHG Line +004|22 FIX Gewinde CHG Vollwelle CHG Caliper CHG GewindeV3 +005|22 CHG Gewinde +006|22 CHG Anschluss FIX Zylinder +007|22 FIX Ellipse CHG Points ADD PolyH +008|22 FIX Ttorus CHG PolyH CHG RotLang +009|22 CHG Points add center CHG kreis add z CHG quad add z +011|22 FIX Box Prisma FIX Gewinde +012|22 CHG Rosette Add id od FIX spelling help CHG Anorden (fix for 2021.1) +0121|22 FIX Anordnen FIX SRing FIX Knochen +013|22 CHG Rosette autocalc +015|22 FIX Gewinde +016|22 CHG RingSeg FIX Kassette help CHG Superellipse +019|22 CHG Schnitt size +020|22 CHG KBS CHG Prisma CHG Box CHG Pille +021|22 CHG Pille FIX m chg v3 chg stern CHG Buchtung CHG Schnitt size +022|22 CHG Kassette ADD pathPoints CHG kreis ADD Coil ADD wStern CHG vektorWinkel CHG Halb CHG Superellipse CHG Glied ADD SGlied CHG Prisma ADD Tdrop CHG Bezier +Release +033|22 CHG DRing CHG DBogen CHG Strebe CHG Ttorus CHG Glied CHG Kreis ADD wall CHG n() +036|22 ADD star CHG SpiralCut CHG Gewinde CHG Bevel +037|22 CHG star ADD Star +038|22 CHG star CHG SpiralCut CHG Anordnen FIX DGlied Glied SGLied +040|22 FIX SGLied CHG wall +042|22 FIX CycloidZahn CHG Cycloid CHG Polar FIX star +044|22 CHG Kegel FIX star +045|22 CHG CycloidZahn CHG CyclGetriebe add f CHG Cycloid +046|22 CHG CyclGetriebe CHG CycloidZahn CHG LinEx CHG REcke +047|22 FIX CyclGtriebe +048|22 Add CyclGear FIX Bezier CHG v3 CHG vektorWinkel CHG Points ADD vMult +050|22 CHG vMult CHG Gewinde +052|22 CHG Buchtung CHG SpiralCut Add 2D +054|22 CHG inch CHG Pille ADD Roof +056|22 CHG PolyH CHG kreis CyclGetriebe CHG gradS CHG LinEx CHG Echo +058|22 CHG PolyH +060|22 CHG nametext CHG Egg CHG Stern CHG Star CHG star CHG Roof CHG Linse add fn +062|22 CHG Pfeil +064|22 CHG Pfeil CHG Star add fn2 CHG Roof CHG GT +066|22 ADD naca ADD NACA CHG Roof CHG WStern CHG wall CHG Points +068|22 FIX Polar CHG Umkreis +070|22 FIX star ADD pathLength +072|22 CHG NACA CHG Roof chg LinEx CHG Linse +074|22 CHG Points +076|22 CHG Points FIX Cring CHG Text ADD stringChunk +078|22 CHG Servokopf CHG wall CHG Roof CHG title menue ADD line line() CHG wall chg l() n() +080|22 CHG Star CHG kreis chg Roof +082|22 CHG Seg7 Prisma ADD Cut +084|22 FIX Seg7 fix Cut +086|22 FIX Cut CHG Achsenklammer ADD nut FIX stringChunk +088|22 CHG bezier add p CHG Seg7 CHG wall CHG nut +090|22 ADD Involute involute +092|22 CHG gcode +094|22 ADD riemen, Riemen +096|22 CHG Seg7 +098|22 CHG Coil CHG T +100|22 UPD ZigZag FIX Riemen +101|22 reordered +102|22 CHG Glied CHG Riemen UPD Welle CHG Nut +104|22 CHG Riemen UPD Zylinder CHG Bogen SBogen +106|22 ADD kreisSek CHG Points +108|22 CHG Pivot FIX/UPD kreisSek +110|22 UPD Cut CHG GewindeV4 +112|22 UPD HexGrid UPD Grid FIX vollwelle +114|22 CHG RotEx CHG DGlied0 +116|22 FIX SGlied,DGlied upd Seg7 +118|22 ADD vSum CHG Rund CHG CycloidZahn +120|22 CHG Roof FIX gradS UPD Coil CHG quad chg pPos +130|22 ADD bend ADD sq upd needs2D UPD mPoints UPD m UPD Bezier UPD Coil chg pathPoints +132|22 CHG Spirale UPD pathPoints +134|22 UPD Rundrum UPD Spirale CHG Row +135|22 Doxygen comments +137|22 FIX Spirale +140|22 FIX Caliper +142|22 CHG Quad fn Add DPfeil FIX Text +144|22 ADD scene ADD map +146|22 CHG Disphenoid UPD vSum +148|22 FIX Prisma UPD LinEx UPD map +150|22 CHG Torus UPD Ellipse +152|22 ADD Schlaufe +156|22 CHG Menu FIX Torus help FIX Torus2 help +158|22 CHG Pin CHG RStern CHG Schlaufe +160|22 CHG Schlaufe UPD Ellipse UPD MO +162|22 UPD Involute +164|22 UPD Schlaufe +166|22 FIX Schlaufe +168|22 ADD PrevPos +170|22 FIX Torus FIX Rundrum +172|22 UPD Rund FIX Spirale +174|22 UPD kreis ADD polyRund PolyRund PolyDeg +176|22 CHG stern +178|22 FIX polyRund UPD PolyRund FIX DPfeil +180|22 ADD revP UPD polyRund PolyRund CHG sq +181|22 FIX polyRund +182|22 FIX polyRund FIX PolyRund +184|22 CHG PolyRund +185|22 CHG PolyRund +188|22 UPD map UPD Rand ADD sehne,UPD Roof +190|22 CHG Quad ADD arc Arc UPD LinEx CHG vMult +202|22 UPD tangentenP +204|22 UPD PolyH +206|22 ADD Knurl +208|22 CHG Text add trueSize add cy=-1/2 +210|22 CHG Text Fix Knurl +212|22 upd fold +214|22 ADD parabel +216|22 UPD Tdrop UPD Line UPD Rand +218|22 FIX Schlaufe FIX Knurl +220|22 FIX Kegel ADD designVersion +222|22 FIX LinEx FIX Cut UPD M FIX Rand FIX Knurl FIX Text FIX Roof UPD vSum UPD Quad +230|22 CHG Kreis FIX Cut CHG Pin CHG Roof FIX LinEx FIX Prisma +232|22 UPD Sehne FIX Roof +234|22 FIX Prisma FIX Caliper +236|22 FIX LinEx +240|22 UPD Polar UPD Roof +242|22 FIX Anschluss UPD SQ +250|22 FIX Halb UPD PrevPos +270|22 ADD KnurlTri +272|22 UPD Cring FIX DPfeil CHG radiusS ADD distS UPD Ring CHG Torus UPD Drehpunkt +274|22 FIX LinEx() FIX KnurlTri +276|22 FIX LinEx() UPD Halb() +278|22 CHG Points UPD arc ADD LangL UPD line FIX fs2fn CHG Roof Fix Seg7 +280|22 UPD Seg7 UPD name CHG LangL↦Loch +282|22 UPD Vollwelle UPD Nut +283|22 UPD nut +292|22 UPD Echo UPD BB CHG Loch FIX Gardena UPD Pille FIX fs2fn FIX Halb UPD GewindeV1 +294|22 UPD Prisma FIX Linear +303|22 UPD Roof FIX Loch +306|22 FIX Pille chg Quad CHG kreis CHG fs +308|22 UPD Welle CHG PrevPos FIX Prisma CHG RotEx +310|22 ADD string2num +312|22 UPD Prisma FIX Roof +316|22 UPD LinEx2 UPD Text FIX DPfeil FIX LinEx FIX Roof FIX radiusS +322|22 FIX Kreis FIX map FIX Line UPD Ring UPD kreis FIX Prisma +333|22 UPD GT2Pulley UPD GT UPD Ring UPD Grid CHG Loch +336|22 UPD Coil FIX LinEx ADD SWelle +338|22 Fix Roof UPD InfoTxt Fix LinEx UPD Ring UPD Bezier UPD Arc CHG SWelle +340|22 CHG VarioFill UPD fs2fn +342|22 ADD layerProfile FIX Linear FIX Kegelmantel +344|22 CHG Luer UPD Kegel FIX VarioFill ADD Filter +352|22 CHG Filter UPD star FIX VarioFill CHG Kegel +354|22 CHG Anschluss UPD Coil UPD Pin UPD vpr +356|22 CHG SBogen CHG Anschluss +358|22 UPD Torus UPD Coil CHG kreis +360|22 FIX Rund UPD fs2fn UPD Luer +362|22 FIX fs2fn UPD BB CHG Torus +364|22 UPD Rand UPD Loch UPD CyclGetriebe + + */ + +// */ diff --git a/models/candle/candle.scad b/models/candle/candle.scad index 834909a..969c7ff 100644 --- a/models/candle/candle.scad +++ b/models/candle/candle.scad @@ -1,4 +1,155 @@ -include<../lib/ub.scad> +include <../../lib/ub.scad>; + +/*[Hidden]*/ +designVersion="1.0"; +designer="Andey Belvedersky"; + +useVersion=24.260; +assert(Version>=useVersion,str("lib version ",Version," detected, install ",useVersion," ub.scad library‼ ⇒http://v.gd/ubaer")); + +license="CC0"; +/*[Basics]*/ +nozzle=.2; +bed=true; +pPos=[0,0]; +info=true; +name=undef; + +// Parameters for the snake-like candle + snake_length = 50; // Length of the candle + snake_radius = 20; // Base radius of the candle + twist_amount = 20; // Amount of twist in the snake shape + height_variation = 6; // Variation in height to create a snake-like effect + +// +WaveEx( + grad=0, + h=snake_length, + r=snake_radius, + ry=twist_amount, + f=3, + fy=height_variation, // 😃 + a=0, + ay=1.3, // + fv=1.4, + fvy=4, + tf=5, + trx=0, + try=0, + tfy=3.2, + tfv=6, + tfvy=10, + ta=1.5, + tay=1.7, + fn=150, + fn2=150, + rot=0, + scale=1, + scaley=1, + close=false, + p=4, + name=undef, + help=1 +); + + + +hull() { + + +hull() { + + + +hull() { + sphere(d=20); + +translate([0,0,50]){ +minkowski() { + sphere(r = 20, d=20, $fn=5); + cylinder(r=2,h=1, center=true); +} +} +} + +translate([10,10,25]){ + +rotate([10,80,40]) +minkowski() { + sphere(d=20, $fn=5); + cylinder(r=2,h=1, center=true); +} +} +} + +translate([-10,-10,25]){ + rotate([10,30,40]) + +minkowski() { + +OctaH(help=true, d=20); + cylinder(r=2,h=1, $fn=50); + +} +} +} + +// Spirale(help=1, grad=10, radius=0, exp=1, fn=2)Linse( messpunkt=false); +// Rundrum(fn=40, grad=40, r=3, twist=1, x=25, y=10, r=195)Linse(help=1, dia=12, r=6.5, messpunkt=false); +// Spirale(help=1, grad=200, radius=0, exp=1, fn=170); + + +// // Parameters for the snake scales +// scale_length = 10; // Base length of each scale +// scale_width = 6; // Base width of each scale +// scale_height = 2; // Base height of each scale +// scale_spacing = 0.2; // Base spacing between scales +// scale_rows = 3; // Number of rows of scales +// scale_columns = 6; // Number of columns of scales + +// // Function to create a single scale with limited randomness +// module scale() { +// // Randomize scale dimensions and rotation with less variation +// l = scale_length + rands(-1, 1, 1)[0]; // Limited random length variation +// w = scale_width + rands(-0.5, 0.5, 1)[0]; // Limited random width variation +// h = scale_height + rands(-0.2, 0.2, 1)[0]; // Limited random height variation +// rot = rands(-10, 10, -10)[0]; // Limited random rotation + +// color("darkgreen") { +// // Create a scale shape using a rounded rectangle +// linear_extrude(height=h) { +// rotate(rot) { +// Linse(help=1, dia=12, r=6.5, messpunkt=false); +// } +// } +// } +// } + +// // Function to create a row of scales with limited randomness +// module scale_row(y_offset) { +// for (i = [0:scale_columns - 1]) { +// // Randomize the position of each scale with limited variation +// x_offset = i * (scale_length - scale_width + scale_spacing) + rands(-0.5, 0.5, 1)[0]; +// translate([x_offset, y_offset, 0]) { +// scale(); +// } +// } +// } + +// // Function to create the snake scale pattern with limited randomness +// module snake_scale_pattern() { +// for (j = [0:scale_rows - 1]) { +// // Randomize the vertical position of each row with limited variation +// y_offset = j * (scale_width + scale_spacing); +// translate([0, y_offset, 0]) { +// scale_row(j * (scale_width + scale_spacing)); +// } +// } +// } + +// // Create the snake scale pattern +// snake_scale_pattern(); +render(); \ No newline at end of file diff --git a/models/cup/cup.scad b/models/cup/cup.scad index 3098a75..2023c43 100644 --- a/models/cup/cup.scad +++ b/models/cup/cup.scad @@ -1,28 +1,30 @@ -module tube(thickness, length1, length2, height, fn=100) { - difference() { - cylinder(h = height, r1 = length1 , r2 = length2, $fn = fn); - cylinder(h = height+0.01, r1 = length1 -thickness * 2,r2 = length2 -thickness * 2, $fn = fn); - } -} +include ; -union(){ -// Поднимаем на 40 мм вверх -translate([0, 0, 40]) { - // Создаем трубу диаметром 140 мм, толщиной стенок 10 мм и высотой 10 мм - tube(thickness = 10, length1 = 70, length2=70, height = 7); -} -// Создаем трубу диаметром 120 мм, толщиной стенок 5 мм и высотой 40 мм -tube(thickness = 5, length1 = 60, length2 = 60, height = 40); +/*[Hidden]*/ +designVersion="1.0"; +designer="Andey Belvedersky"; -// Опускаем на 40 мм вниз -translate([0, 0, -80]) { +minkowski() { + // Стакан union(){ - // Создаем трубу c начальным диаметром 120 мм, и конечным 80 мм толщиной стенок 5 мм и высотой 80 мм - tube(thickness = 5, length1 = 40, length2 = 60, height = 80); - cylinder(5, 40,40); + // Поднимаем на 40 мм вверх + translate([0, 0, 40]) { + // Создаем трубу диаметром 140 мм, толщиной стенок 10 мм и высотой 10 + tube(thickness = 15, length1 = 70, length2=70, height = 7); + } + // Создаем трубу диаметром 120 мм, толщиной стенок 5 мм и высотой 40 мм + tube(thickness = 5, length1 = 60, length2 = 60, height = 40); + + // Опускаем на 40 мм вниз + translate([0, 0, -80]) { + union(){ + // Создаем трубу c начальным диаметром 120 мм, и конечным 80 мм толщиной + // стенок 5 мм и высотой 80 мм + tube(thickness = 5, length1 = 40, length2 =60, height = 80); + cylinder(5, 40,40); + } + } } + sphere(.5, $fn = 5); } -} - render(); - diff --git a/models/cup/cup.stl b/models/cup/cup.stl deleted file mode 100644 index 1629104b27f2164459b413fcfe3ad0e9b40406b6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 133084 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 z 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 + +/*[Hidden]*/ +designVersion="1.0"; +designer="Andey Belvedersky"; + +// Ручка +color([0.5,0.2,0.2]) { + union() { + // Сама ручка + // Толщина 10мм, радиус 40 мм, высота 15мм, разрешение 150 + minkowski() { + tube(10, 40, 40, 15, 150); + + sphere(.35, $fn = 20); + } + + // Площадка + translate([ 40, 0, 7.5 ]) { + minkowski() { + cube(center = true, size = [ 10, 20, 15 ], $fn = 150); + sphere(.35, $fn = 20); + } + } + // Литник + translate([ 39.7, -5, 0 ]) { + minkowski() { + cube(center = false, size = [ 25, 10, 15 ], $fn = 100); + sphere(.35, $fn = 20); + } + } + } +} +render(); + diff --git a/models/cup/tube.scad b/models/cup/tube.scad new file mode 100644 index 0000000..9413ebc --- /dev/null +++ b/models/cup/tube.scad @@ -0,0 +1,7 @@ +module tube(thickness, length1, length2, height, fn = 100) { + difference() { + cylinder(h = height, r1 = length1, r2 = length2, $fn = fn); + cylinder(h = height + 0.01, r1 = length1 - thickness, + r2 = length2 - thickness, $fn = fn); + } +} \ No newline at end of file