OCCT Fillets: Applying to 3D Wires (Non-Planar)
Introduction to Filleting 3D Wires
Applying fillets to 3D wires (wires whose constituent edges do not all lie on a single plane) is a process that creates smooth, rounded transitions at the corners where two or more edges meet. Similar to 2D wires, fillets on 3D wires can be applied:
- Globally: With a uniform radius to all eligible corners of the wire.
- Specifically: With potentially different radii to selected corners.
Fillets on a 3D wire.
How Fillets are Applied to a 3D Wire
In Bitbybit, you will typically use a command like bitbybit.occt.fillets.fillet3DWire (or its equivalent in visual editors) to perform this operation. This command generally takes the following inputs:
- Shape (Wire): The 3D wire to be filleted.
- Radius or Radius List:
- A single radius value to apply uniformly to all corners.
- A list of radii if you intend to apply different fillet sizes to specific corners.
- Corner Indexes (Optional): A list of indexes specifying which corners to fillet. This is used in conjunction with a radius list. If applying a uniform radius to all corners, this might be left empty.
- Direction: A vector indicating a direction along which an internal extrusion operation is performed (see "Inner Workings" below).
If you provide a list of radii, you must also provide a corresponding list of corner indexes. If you use a single radius value and leave the radius list and indexes empty, that single radius will be applied to all eligible corners of the 3D wire.
Inner Workings of the 3D Wire Fillet Algorithm
The filleting of a 3D wire in OCCT, as implemented in Bitbybit, often involves a clever behind-the-scenes process:
- A temporary shell is constructed by extruding the input 3D wire along the provided
directionvector. - Standard 3D filleting operations are then performed on specific edges of this temporary shell. These edges correspond to the corners of the original 3D wire that were targeted for filleting.
- After the filleting on the shell is complete, the newly filleted edges (which now form rounded paths) are extracted and reconstructed back into a new 3D wire.
This is why the direction parameter is crucial for the fillet3DWire algorithm to function correctly. The length of this direction vector can also influence the intermediate extrusion and thus, sometimes, the success or quality of the 3D fillet.
Filleting Specific Corners on a 3D Wire with Variable Radii
The following examples demonstrate how to fillet a 3D wire by targeting specific corner indexes and applying a list of corresponding radii. The two lists (corner indexes and radii) must be of the same length. It's not necessary to round all corners; you can select specific ones.
In these examples, we first construct a 3D star-shaped wire. Then, we apply different fillet radii to its inner and outer corners, showcasing the ability to create complex filleting patterns.
TypeScript Example: Fillet Specific Corners of a 3D Wire
const nrRays = 7;
const outerStarRadius = 10;
const innerStarRadius = 4;
const outerFillet = 0.6;
const innerFillet = 1.7;
const start = async () => {
const repeatOpt = new Bit.Inputs.Lists.MultiplyItemDto<number[]>([innerFillet, outerFillet], nrRays);
const radiusList = bitbybit.lists.repeat(repeatOpt).flat();
const spanOptions = new Bit.Inputs.Vector.SpanDto(1, 1, nrRays * 2);
const indexes = bitbybit.vector.span(spanOptions);
const starOptions = new Bit.Inputs.OCCT.StarDto(outerStarRadius, innerStarRadius, nrRays, [0, 0, 0], [0, 1, 0], 4, false);
const star = await bitbybit.occt.shapes.wire.createStarWire(starOptions);
const filletOptions = new Bit.Inputs.OCCT.Fillet3DWireDto<Bit.Inputs.OCCT.TopoDSShapePointer>(star, undefined, [0, 1, 0], radiusList, indexes);
const starFillet = await bitbybit.occt.fillets.fillet3DWire(filletOptions);
const startFilletTranslated1 = await bitbybit.occt.transforms.translate({ shape: starFillet, translation: [0, 5, 0] })
const startFilletTranslated2 = await bitbybit.occt.transforms.translate({ shape: starFillet, translation: [0, 10, 0] })
const starFace = await bitbybit.occt.shapes.face.createFaceFromWire({ shape: startFilletTranslated2, planar: false });
const starThick = await bitbybit.occt.operations.makeThickSolidSimple({ shape: starFace, offset: -1 });
const starThickFillet = await bitbybit.occt.fillets.filletEdges({ shape: starThick, radius: 0.3 });
const drawOptions = new Bit.Inputs.Draw.DrawOcctShapeOptions();
drawOptions.edgeWidth = 15;
bitbybit.draw.drawAnyAsync({ entity: star, options: drawOptions });
bitbybit.draw.drawAnyAsync({ entity: startFilletTranslated1, options: drawOptions });
drawOptions.faceColour = "#5555ff";
drawOptions.edgeColour = "#000000";
drawOptions.edgeWidth = 2;
drawOptions.precision = 0.005;
bitbybit.draw.drawAnyAsync({ entity: starThickFillet, options: drawOptions });
const gridOptions = new Bit.Inputs.Draw.SceneDrawGridMeshDto();
bitbybit.draw.drawGridMesh(gridOptions);
const skyboxOptions = new Bit.Inputs.BabylonScene.SkyboxDto();
skyboxOptions.skybox = Bit.Inputs.Base.skyboxEnum.clearSky;
bitbybit.babylon.scene.enableSkybox(skyboxOptions);
}
start();
Blockly Example: Fillet Specific Corners of a 3D Wire
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable id="rIY|Dn)1QdvLLNjzZ-*s">nrRays</variable><variable id="p9/Ol0L/L#bE:JI(5Uh(">innerFilletRadius</variable><variable id=",/et5C|cK+]3NY:%_j!s">outerRadiusFillet</variable><variable id="RwvX0OzX1if7fO7ld$02">filletIndexes</variable><variable id="a(lnwdi|27GhEdWcHW6A">radiusList</variable><variable id="!-qq?Skeyp+lFbio.xAj">i</variable><variable id="+Hd9l5uqZXm),-4GGz(8">starPromise</variable><variable id="/x:G{;(Y971beTaQkJiK">starFilletPromise</variable></variables><block type="base_time_async_context" id="YxFZMoXnK{qof?[PEd06" x="-1135" y="-1545"><statement name="Then"><block type="variables_set" id="mIW!g|4wdO#^;u5Zq,Bg"><field name="VAR" id="rIY|Dn)1QdvLLNjzZ-*s">nrRays</field><value name="VALUE"><block type="math_number" id="|D^1y9]r/p$4Q@IjC*]C"><field name="NUM">7</field></block></value><next><block type="variables_set" id="M^46F(Y,V@J?#KLj}]`l"><field name="VAR" id="p9/Ol0L/L#bE:JI(5Uh(">innerFilletRadius</field><value name="VALUE"><block type="math_number" id="UlK9he,QWWTw.Cs-3Y;6"><field name="NUM">1.7</field></block></value><next><block type="variables_set" id=",H5{}h^dRSW-jk}00xZ:"><field name="VAR" id=",/et5C|cK+]3NY:%_j!s">outerRadiusFillet</field><value name="VALUE"><block type="math_number" id="L/BRmy2AWWM!%=^nUh]R"><field name="NUM">0.6</field></block></value><next><block type="variables_set" id="MsJpG.,g|.CUlJD)]Y/o"><field name="VAR" id="RwvX0OzX1if7fO7ld$02">filletIndexes</field><value name="VALUE"><block type="bitbybit.vector.span" id="h2O.6?rtu$uPr.kS3P~!"><value name="Step"><block type="math_number" id="pgR`2W?heVbsRDNJU6d1"><field name="NUM">1</field></block></value><value name="Min"><block type="math_number" id="{Ht{4jCLw%z`EnN_k9+%"><field name="NUM">1</field></block></value><value name="Max"><block type="math_arithmetic" id="#Jf6RK@NFpYxoB$X1slN"><field name="OP">MULTIPLY</field><value name="A"><block type="variables_get" id="*`%CG*n?{8Q|?cqJV{0,"><field name="VAR" id="rIY|Dn)1QdvLLNjzZ-*s">nrRays</field></block></value><value name="B"><block type="math_number" id="jepAN[_k+sdevh!gg!6:"><field name="NUM">2</field></block></value></block></value></block></value><next><block type="bitbybit.babylon.scene.enableSkybox" id="O[b)*aCH_$R[mO5_mX;f"><value name="Skybox"><block type="bitbybit.babylon.enums.skyboxEnum" id="{?7Tk*UMbl#e74%m?PzJ"><field name="bitbybit.babylon.enums.skyboxEnum">'clearSky'</field></block></value><value name="Size"><block type="math_number" id="CJ4(F7s0NZY/bR4tNW?."><field name="NUM">1000</field></block></value><value name="Blur"><block type="math_number" id="1$Gd/YcAr`;Kkj+tx8eY"><field name="NUM">0.1</field></block></value><value name="EnvironmentIntensity"><block type="math_number" id="Uhab4WuGZpb$z1QRp-hv"><field name="NUM">0.7</field></block></value><next><block type="variables_set" id="{ijEYxx=TWzZfW)XpObP"><field name="VAR" id="a(lnwdi|27GhEdWcHW6A">radiusList</field><value name="VALUE"><block type="lists_create_with" id="_qTuf/-.]Z|Csmx7EUkm"><mutation items="0"></mutation></block></value><next><block type="controls_for" id="Q8NjENy0~J;vHkMFSvhS"><field name="VAR" id="!-qq?Skeyp+lFbio.xAj">i</field><value name="FROM"><block type="math_number" id="ui9!X1P4UM3Q%$e%{Wsj"><field name="NUM">1</field></block></value><value name="TO"><block type="math_arithmetic" id="UA+zau%=ZdIvjS|Qe0SO"><field name="OP">MULTIPLY</field><value name="A"><block type="variables_get" id="Ss1dTGfVeQ8S^h(I8J;x"><field name="VAR" id="rIY|Dn)1QdvLLNjzZ-*s">nrRays</field></block></value><value name="B"><block type="math_number" id="9eUyo=dJGSA8lSj8uI2T"><field name="NUM">2</field></block></value></block></value><value name="BY"><block type="math_number" id="}QE#e*_[jLFgJUZjDrpd"><field name="NUM">1</field></block></value><statement name="DO"><block type="controls_if" id="34#(2r9o+-YDJIo[HoeH"><mutation else="1"></mutation><value name="IF0"><block type="logic_compare" id="Sg5Ty54Pk==$IKp.@r#%"><field name="OP">EQ</field><value name="A"><block type="bitbybit.math.modulus" id="O3vJa+IuVxKe[VO]T#o6"><value name="Number"><block type="variables_get" id="IKG:jr%S;`i)m{Ah{B3e"><field name="VAR" id="!-qq?Skeyp+lFbio.xAj">i</field></block></value><value name="Modulus"><block type="math_number" id="xT4ZG(2MQiJ{Cp+;EXhP"><field name="NUM">2</field></block></value></block></value><value name="B"><block type="math_number" id="Imt|B7}Gs9~likazG2Oi"><field name="NUM">0</field></block></value></block></value><statement name="DO0"><block type="lists_setIndex" id="x7imOL2S2,9seB6y}{Ld"><mutation at="false"></mutation><field name="MODE">INSERT</field><field name="WHERE">LAST</field><value name="LIST"><block type="variables_get" id="ki]/zxp0Qk-F_Yy*p9B%"><field name="VAR" id="a(lnwdi|27GhEdWcHW6A">radiusList</field></block></value><value name="TO"><block type="variables_get" id="#d[m.4:5@J$EbW{a~h^{"><field name="VAR" id=",/et5C|cK+]3NY:%_j!s">outerRadiusFillet</field></block></value></block></statement><statement name="ELSE"><block type="lists_setIndex" id="dn5}(iOiYE015pThzI4U"><mutation at="false"></mutation><field name="MODE">INSERT</field><field name="WHERE">LAST</field><value name="LIST"><block type="variables_get" id="wwAR~H6MvEPe;`bLwb3D"><field name="VAR" id="a(lnwdi|27GhEdWcHW6A">radiusList</field></block></value><value name="TO"><block type="variables_get" id="uILL+)o%k2#goBe_a-q!"><field name="VAR" id="p9/Ol0L/L#bE:JI(5Uh(">innerFilletRadius</field></block></value></block></statement></block></statement><next><block type="variables_set" id="w$A#9;ZuJs$@@5-u]Nu8"><field name="VAR" id="+Hd9l5uqZXm),-4GGz(8">starPromise</field><value name="VALUE"><block type="bitbybit.occt.shapes.wire.createStarWire" id="Ebv[zzO7~kL18Mc[%NMf"><value name="Center"><block type="bitbybit.point.pointXYZ" id=";5+zQQaM]k]P~2+}=dQd"><value name="X"><block type="math_number" id="U)IQ;dG)PY#d;F}Jlb]8"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="=^VM;4V/W8$kbQ{GO+{_"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number" id="b(AyGHBm.72y#@ZwKr%j"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="@v;xLVTxvQs7Hw.C0rBj"><value name="X"><block type="math_number" id="-Gk9C29KzXPCuG4%I7iC"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="oI4cOrd#bR[G!)0XN4wm"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id="@U8UBf.~_!cbuuy5pg0d"><field name="NUM">0</field></block></value></block></value><value name="NumRays"><block type="variables_get" id="1]d!Vhld]f^t]!f$k`LP"><field name="VAR" id="rIY|Dn)1QdvLLNjzZ-*s">nrRays</field></block></value><value name="OuterRadius"><block type="math_number" id=";]s@N~EDaP?X[FxiN,K^"><field name="NUM">10</field></block></value><value name="InnerRadius"><block type="math_number" id="*5`?bJ4LjQ|8:/9g)eMw"><field name="NUM">4</field></block></value><value name="OffsetOuterEdges"><block type="math_number" id="5^w5q4%6~9CHp`{;oEcL"><field name="NUM">4</field></block></value><value name="Half"><block type="logic_boolean" id=",QSI$H0HP-(i`C!t/ry]"><field name="BOOL">FALSE</field></block></value></block></value><next><block type="variables_set" id="mWi4F%Q_|iM2zR}(A?{3"><field name="VAR" id="/x:G{;(Y971beTaQkJiK">starFilletPromise</field><value name="VALUE"><block type="bitbybit.occt.fillets.fillet3DWire" id="d8#IZ;nS+{;j$::lcV7P"><value name="Shape"><block type="variables_get" id="2=Wi@:n!Xmi$rpL~PFD0"><field name="VAR" id="+Hd9l5uqZXm),-4GGz(8">starPromise</field></block></value><value name="RadiusList"><block type="variables_get" id="vp]jdUZOp;o}%S=qE@:4"><field name="VAR" id="a(lnwdi|27GhEdWcHW6A">radiusList</field></block></value><value name="Indexes"><block type="variables_get" id="?%7XP$Hkn|qjMs#*zj7$"><field name="VAR" id="RwvX0OzX1if7fO7ld$02">filletIndexes</field></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ" id="91JU{LIl`!(5wh]qm{GZ"><value name="X"><block type="math_number" id="Y#`eE{go~]%[~K)%=6#c"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="U?IET*#GY/k9yV{|26P:"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number" id=".!zd5ec((7yx(@Q7iD5a"><field name="NUM">0</field></block></value></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="$i3o*mQXU%/_sO@xl}]g"><value name="Entity"><block type="variables_get" id="k:~5Cg[R94gN{E{GD*Am"><field name="VAR" id="+Hd9l5uqZXm),-4GGz(8">starPromise</field></block></value><value name="Options"><block type="bitbybit.draw.optionsOcctShapeSimple" id="NJ9Zwbbp5E@d+FCsUJ3%"><value name="Precision"><block type="math_number" id="gAbQ2A`}Tl-+YK9m)~ht"><field name="NUM">0.01</field></block></value><value name="DrawFaces"><block type="logic_boolean" id="E;5cCx:9K`_`g,)bO5!("><field name="BOOL">FALSE</field></block></value><value name="FaceColour"><block type="colour_picker" id="Tss?4[%4!]EK[hw_brt9"><field name="COLOUR">#ff0000</field></block></value><value name="DrawEdges"><block type="logic_boolean" id="h_n=Pv918Q:P:5la+DV."><field name="BOOL">TRUE</field></block></value><value name="EdgeColour"><block type="colour_picker" id="BU-xP%@7wo;gi/yeLQ}V"><field name="COLOUR">#ffffff</field></block></value><value name="EdgeWidth"><block type="math_number" id="{`Wm:.sX3l6X+0*JC7r$"><field name="NUM">15</field></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id="hMYIY{dn1|e095?ZFIse"><value name="Entity"><block type="bitbybit.occt.transforms.translate" id="RmhL@P6gQ_;kg).V1?$4"><value name="Shape"><block type="variables_get" id="=^@vD6[hAtimj$awb,0M"><field name="VAR" id="/x:G{;(Y971beTaQkJiK">starFilletPromise</field></block></value><value name="Translation"><block type="bitbybit.vector.vectorXYZ" id="sf^;7*(S-^LY95fF0##q"><value name="X"><block type="math_number" id="=`*Xz/PGy4x%O^)5P.up"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="|JN+SPG}tYi8qdY2Zp!e"><field name="NUM">5</field></block></value><value name="Z"><block type="math_number" id="mfw(QoT!JfaPbgPPGQM^"><field name="NUM">0</field></block></value></block></value></block></value><value name="Options"><block type="bitbybit.draw.optionsOcctShapeSimple" id="s~Rg[1?%c3Q7=B%y+q%p"><value name="Precision"><block type="math_number" id="y|uw;5ds=^_Ik3A,?vsz"><field name="NUM">0.01</field></block></value><value name="DrawFaces"><block type="logic_boolean" id="=Mi)gm/)m0R;G;/a4VOb"><field name="BOOL">FALSE</field></block></value><value name="FaceColour"><block type="colour_picker" id="}!l~fdJqR87$[vR7ku^$"><field name="COLOUR">#ff0000</field></block></value><value name="DrawEdges"><block type="logic_boolean" id="u5bpZ;**L{-7L1F2nU9L"><field name="BOOL">TRUE</field></block></value><value name="EdgeColour"><block type="colour_picker" id="%6n{;A_R~ENS]tup`kNF"><field name="COLOUR">#ffffff</field></block></value><value name="EdgeWidth"><block type="math_number" id=";[`bQ0X=n$(|ECXV}bV("><field name="NUM">15</field></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn" id=":LORr]JWID{]nh.@d(,o"><value name="Entity"><block type="bitbybit.occt.fillets.filletEdges" id="a[/9-iB:/ER^nZ1rZ0L~"><value name="Shape"><block type="bitbybit.occt.operations.makeThickSolidSimple" id="[-;z]vFLEOM{Sc|@$0#g"><value name="Shape"><block type="bitbybit.occt.shapes.face.createFaceFromWire" id="b%z{#XU;:/f#G2wl;3Bo"><value name="Shape"><block type="bitbybit.occt.transforms.translate" id="(Z|o@u|1%obSX#$M3-22"><value name="Shape"><block type="variables_get" id=",$7fiU1MnXzG*:b2[N^%"><field name="VAR" id="/x:G{;(Y971beTaQkJiK">starFilletPromise</field></block></value><value name="Translation"><block type="bitbybit.vector.vectorXYZ" id="Wj*!tEsvN_}0ydA+DNVE"><value name="X"><block type="math_number" id="b*XdDPBj@ilcfbV,T,O("><field name="NUM">0</field></block></value><value name="Y"><block type="math_number" id="sGf_ba{bOU^Z70*ch9fM"><field name="NUM">10</field></block></value><value name="Z"><block type="math_number" id="OF@-M}~,sEvgiPaqU|!~"><field name="NUM">0</field></block></value></block></value></block></value><value name="Planar"><block type="logic_boolean" id="[@.?a~Iq5FnB51bQhRK$"><field name="BOOL">FALSE</field></block></value></block></value><value name="Offset"><block type="math_number" id="zyfsf%)@;)S*G:B3$1ly"><field name="NUM">-1</field></block></value></block></value><value name="Radius"><block type="math_number" id="?blPv*38`9tpU16vQ7*)"><field name="NUM">0.3</field></block></value></block></value><value name="Options"><block type="bitbybit.draw.optionsOcctShapeSimple" id="!#5Oh,X[g?|D;fAQr,I~"><value name="Precision"><block type="math_number" id="PJF%x5dJ[EWT1!l+ub^t"><field name="NUM">0.005</field></block></value><value name="DrawFaces"><block type="logic_boolean" id="KOB19PY9BdKNRW,[:y(u"><field name="BOOL">TRUE</field></block></value><value name="FaceColour"><block type="colour_picker" id="1bkOh~Z![kQfnc7.NbZ|"><field name="COLOUR">#3333ff</field></block></value><value name="DrawEdges"><block type="logic_boolean" id="/Q+RreGEh,_J06*ei^Y1"><field name="BOOL">TRUE</field></block></value><value name="EdgeColour"><block type="colour_picker" id="StzHgk@*RS.(#(HC#Wz+"><field name="COLOUR">#000000</field></block></value><value name="EdgeWidth"><block type="math_number" id="=pk:t:.)*Q0^xr!Rz-L!"><field name="NUM">2</field></block></value></block></value><next><block type="bitbybit.draw.drawGridMeshNoReturn" id="{HVY~,_B0[W)P(-qB-_+"><value name="Width"><block type="math_number" id="xt~XJ$W;kaMy;54RWS!n"><field name="NUM">400</field></block></value><value name="Height"><block type="math_number" id="S~m]^!m0Az~:v6Fx$~~x"><field name="NUM">400</field></block></value><value name="Subdivisions"><block type="math_number" id="08d*gPz@%fzqJ0=l)=M`"><field name="NUM">10</field></block></value><value name="MajorUnitFrequency"><block type="math_number" id="at)keE8=K.+hXDF_[]eD"><field name="NUM">10</field></block></value><value name="MinorUnitVisibility"><block type="math_number" id="{!BWdg)-ML.JG4W4SsK7"><field name="NUM">0.45</field></block></value><value name="GridRatio"><block type="math_number" id="3+2x$n,%:n5W-dW3^EV!"><field name="NUM">0.5</field></block></value><value name="Opacity"><block type="math_number" id="F^/POR!mOH]P!Xqyw;8E"><field name="NUM">0.5</field></block></value><value name="BackFaceCulling"><block type="logic_boolean" id="?)UzlLqsI1gf6kA!?)qx"><field name="BOOL">FALSE</field></block></value><value name="MainColor"><block type="colour_picker" id="]HWZ?VH{)=iqMuHwI]yi"><field name="COLOUR">#ffffff</field></block></value><value name="SecondaryColor"><block type="colour_picker" id="I_dxNk=+2*LGoG;2tJ]1"><field name="COLOUR">#ffffff</field></block></value></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></next></block></statement></block></xml>
Rete Example: Fillet Specific Corners of a 3D Wire
{
"id": "rete-v2-json",
"nodes": {
"236000e6be6ccf2b": {
"id": "236000e6be6ccf2b",
"name": "bitbybit.occt.shapes.wire.createStarWire",
"customName": "star wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
],
"numRays": 7,
"outerRadius": 10,
"innerRadius": 4,
"offsetOuterEdges": 4,
"half": false
},
"inputs": {
"numRays": {
"connections": [
{
"node": "f3b639af0a8a6f50",
"output": "result",
"data": {}
}
]
}
},
"position": [
-11.315676390459487,
280.7958914765325
]
},
"7287627509e8630e": {
"id": "7287627509e8630e",
"name": "bitbybit.occt.fillets.fillet3DWire",
"customName": "fillet 3d wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 0.1,
"direction": [
0,
1,
0
]
},
"inputs": {
"shape": {
"connections": [
{
"node": "236000e6be6ccf2b",
"output": "result",
"data": {}
}
]
},
"radiusList": {
"connections": [
{
"node": "a7e05f6656a0212f",
"output": "list",
"data": {}
}
]
},
"indexes": {
"connections": [
{
"node": "70cc1486aae9f9d9",
"output": "result",
"data": {}
}
]
}
},
"position": [
1577.5711831165675,
296.1831250873849
]
},
"f3b639af0a8a6f50": {
"id": "f3b639af0a8a6f50",
"name": "bitbybit.math.numberSlider",
"customName": "number slider",
"data": {
"options": {
"min": 5,
"max": 10,
"step": 1,
"width": 350
},
"number": 7
},
"inputs": {},
"position": [
-1052.3470210619662,
333.63761446923337
]
},
"70cc1486aae9f9d9": {
"id": "70cc1486aae9f9d9",
"name": "bitbybit.vector.span",
"customName": "span",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"step": 1,
"min": 1,
"max": 1
},
"inputs": {
"max": {
"connections": [
{
"node": "c1feeb47a95c86e6",
"output": "result",
"data": {}
}
]
}
},
"position": [
830.5434465316521,
586.020483457695
]
},
"c1feeb47a95c86e6": {
"id": "c1feeb47a95c86e6",
"name": "bitbybit.math.twoNrOperation",
"customName": "two nr operation",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"first": 1,
"second": 2,
"operation": "multiply"
},
"inputs": {
"first": {
"connections": [
{
"node": "f3b639af0a8a6f50",
"output": "result",
"data": {}
}
]
}
},
"position": [
-18.310614644244822,
866.0500018140378
]
},
"9f48e3e48cfbde1b": {
"id": "9f48e3e48cfbde1b",
"name": "bitbybit.math.numberSlider",
"customName": "number slider",
"data": {
"options": {
"min": 0.5,
"max": 2,
"step": 0.1,
"width": 350
},
"number": 1.7
},
"inputs": {},
"position": [
-1050.1077294976728,
-16.32890598511689
]
},
"b349fa782bf4a508": {
"id": "b349fa782bf4a508",
"name": "bitbybit.math.numberSlider",
"customName": "number slider",
"data": {
"options": {
"min": 0.5,
"max": 1,
"step": 0.1,
"width": 350
},
"number": 0.6
},
"inputs": {},
"position": [
-1054.0906529622296,
152.4521832719633
]
},
"ada8a94e9ae868d1": {
"id": "ada8a94e9ae868d1",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "9f48e3e48cfbde1b",
"output": "result",
"data": {}
},
{
"node": "b349fa782bf4a508",
"output": "result",
"data": {}
}
]
}
},
"position": [
-113.72439356073457,
-167.01602134486205
]
},
"5ef5af7f0aafbcff": {
"id": "5ef5af7f0aafbcff",
"name": "bitbybit.lists.repeat",
"customName": "repeat",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"times": 10
},
"inputs": {
"item": {
"connections": [
{
"node": "ada8a94e9ae868d1",
"output": "list",
"data": {}
}
]
},
"times": {
"connections": [
{
"node": "f3b639af0a8a6f50",
"output": "result",
"data": {}
}
]
}
},
"position": [
307.58835103278113,
-101.21360658941975
]
},
"6401897a43288e43": {
"id": "6401897a43288e43",
"name": "bitbybit.lists.flatten",
"customName": "flatten",
"data": {
"nrLevels": 2
},
"inputs": {
"list": {
"connections": [
{
"node": "5ef5af7f0aafbcff",
"output": "result",
"data": {}
}
]
}
},
"position": [
718.7790781989961,
-125.32777378822661
]
},
"a7e05f6656a0212f": {
"id": "a7e05f6656a0212f",
"name": "bitbybit.lists.createList",
"customName": "create list",
"data": {},
"inputs": {
"listElements": {
"connections": [
{
"node": "6401897a43288e43",
"output": "result",
"data": {}
}
]
}
},
"position": [
1119.8671943851466,
-119.98346408038245
]
},
"e916c48b1203c51f": {
"id": "e916c48b1203c51f",
"name": "bitbybit.occt.transforms.translate",
"customName": "translate",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"translation": [
0,
0,
0
]
},
"inputs": {
"shape": {
"connections": [
{
"node": "7287627509e8630e",
"output": "result",
"data": {}
}
]
},
"translation": {
"connections": [
{
"node": "a4789489fb26b903",
"output": "result",
"data": {}
}
]
}
},
"position": [
2055.461339742562,
439.8635001386789
]
},
"a4789489fb26b903": {
"id": "a4789489fb26b903",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 5,
"z": 0
},
"inputs": {},
"position": [
1573.6676810146807,
817.2653192641134
]
},
"50186ce95b274d19": {
"id": "50186ce95b274d19",
"name": "bitbybit.vector.vectorXYZ",
"customName": "vector xyz",
"async": false,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"x": 0,
"y": 6,
"z": 0
},
"inputs": {},
"position": [
2052.6444596081433,
723.0890796115883
]
},
"724598de3a71b4fd": {
"id": "724598de3a71b4fd",
"name": "bitbybit.occt.transforms.translate",
"customName": "translate",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"translation": [
0,
0,
0
]
},
"inputs": {
"shape": {
"connections": [
{
"node": "e916c48b1203c51f",
"output": "result",
"data": {}
}
]
},
"translation": {
"connections": [
{
"node": "50186ce95b274d19",
"output": "result",
"data": {}
}
]
}
},
"position": [
2652.08911051333,
582.1960376964696
]
},
"bf2f337edb238436": {
"id": "bf2f337edb238436",
"name": "bitbybit.occt.shapes.face.createFaceFromWire",
"customName": "face from wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"planar": false
},
"inputs": {
"shape": {
"connections": [
{
"node": "724598de3a71b4fd",
"output": "result",
"data": {}
}
]
}
},
"position": [
3139.2415194215505,
503.6284458343018
]
},
"cee96b09ceb73b4b": {
"id": "cee96b09ceb73b4b",
"name": "bitbybit.occt.operations.makeThickSolidSimple",
"customName": "make thick solid simple",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"offset": -1
},
"inputs": {
"shape": {
"connections": [
{
"node": "bf2f337edb238436",
"output": "result",
"data": {}
}
]
}
},
"position": [
3528.153271640637,
503.28011127738876
]
},
"b2b7ec3b80b0df50": {
"id": "b2b7ec3b80b0df50",
"name": "bitbybit.occt.fillets.filletEdges",
"customName": "fillet edges",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 0.3
},
"inputs": {
"shape": {
"connections": [
{
"node": "cee96b09ceb73b4b",
"output": "result",
"data": {}
}
]
}
},
"position": [
3937.7873364263783,
500.45923439202704
]
},
"8bd8ed9fd890e5cb": {
"id": "8bd8ed9fd890e5cb",
"name": "bitbybit.babylon.scene.enableSkybox",
"customName": "enable skybox",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"skybox": "clearSky",
"size": 1000,
"blur": 0.1,
"environmentIntensity": 0.7
},
"inputs": {},
"position": [
-872.9310695464733,
1325.8217652474093
]
},
"60bc0d7e14b90dec": {
"id": "60bc0d7e14b90dec",
"name": "bitbybit.draw.drawAnyAsync",
"customName": "draw any async",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"entity": {
"connections": [
{
"node": "b2b7ec3b80b0df50",
"output": "result",
"data": {}
}
]
},
"options": {
"connections": [
{
"node": "9ddd3ef16739bcaa",
"output": "result",
"data": {}
}
]
}
},
"position": [
4590.697492451062,
813.5693461000375
]
},
"9ddd3ef16739bcaa": {
"id": "9ddd3ef16739bcaa",
"name": "bitbybit.draw.optionsOcctShape",
"customName": "options occt shape",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"faceOpacity": 1,
"edgeOpacity": 1,
"edgeColour": "#000000",
"faceColour": "#0040ff",
"vertexColour": "#ff00ff",
"edgeWidth": 2,
"vertexSize": 0.03,
"drawEdges": true,
"drawFaces": true,
"drawVertices": false,
"precision": 0.005,
"drawEdgeIndexes": false,
"edgeIndexHeight": 0.06,
"edgeIndexColour": "#ff00ff",
"drawFaceIndexes": false,
"faceIndexHeight": 0.06,
"faceIndexColour": "#0000ff"
},
"inputs": {},
"position": [
3983.486163294121,
1202.4958710764429
]
},
"9be05dbe14e2af43": {
"id": "9be05dbe14e2af43",
"name": "bitbybit.draw.drawGridMesh",
"customName": "draw grid mesh",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"width": 400,
"height": 400,
"subdivisions": 10,
"majorUnitFrequency": 10,
"minorUnitVisibility": 0.45,
"gridRatio": 0.5,
"opacity": 0.5,
"backFaceCulling": false,
"mainColor": "#ffffff",
"secondaryColor": "#ffffff"
},
"inputs": {},
"position": [
-862.2779510804795,
1721.8456582103267
]
},
"d63192372194865c": {
"id": "d63192372194865c",
"name": "bitbybit.draw.drawAnyAsync",
"customName": "draw any async",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"entity": {
"connections": [
{
"node": "236000e6be6ccf2b",
"output": "result",
"data": {}
},
{
"node": "e916c48b1203c51f",
"output": "result",
"data": {}
}
]
},
"options": {
"connections": [
{
"node": "7458f3c6c195b724",
"output": "result",
"data": {}
}
]
}
},
"position": [
4093.3009234789824,
-419.951086411402
]
},
"7458f3c6c195b724": {
"id": "7458f3c6c195b724",
"name": "bitbybit.draw.optionsOcctShapeSimple",
"customName": "options occt shape simple",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"precision": 0.01,
"drawFaces": false,
"faceColour": "#ff0000",
"drawEdges": true,
"edgeColour": "#ffffff",
"edgeWidth": 15
},
"inputs": {},
"position": [
3603.530645172864,
-11.344274431578413
]
}
}
}
Visual Results: The images below show the filleted 3D star wire as rendered in the respective editors after running the scripts:
TypeScript code in the live editor with finished geometries
Blockly code in the live editor with finished geometries
Rete code in the live editor with finished geometries
How to Know Which Index Applies to Which Corner?
- 1-Based Indexing: Similar to edge indexing, corner indexes for wires (which correspond to the vertices of the wire) typically start from 1 due to legacy reasons. So, the first corner/vertex of the wire will have an index of 1, the second will be 2, and so on.
- Visualizing Corner Points: While there isn't a direct "draw corner indexes" option at this moment, you can identify corners by:
- Getting all corner points of the wire using a command like
bitbybit.occt.shapes.wire.getCornerPoints(or its equivalent, which might bebitbybit.occt.shapes.edge.getCornerPointsOfEdgesForShapeif you first get the edges of the wire). - This will return a list of points. You can then select a specific point from this list by its index (using a list item retrieval command like
bitbybit.lists.getItem, remembering that list indexes are usually 0-based here). - Draw this selected point (e.g., as a small sphere or a 3D text label with its index) to visually confirm its location on the wire.
- Getting all corner points of the wire using a command like
This technique allows for precise targeting of corners when applying variable radius fillets to 3D wires.



