Skip to main content

OCCT Fillets: Applying to 3D Wires (Non-Planar)

OCCT category icon with a stylized logo representation

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.

A 3D wire (e.g., a star shape extruded slightly and then its top edges filleted) showing rounded corners in three-dimensional space. 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:

  1. A temporary shell is constructed by extruding the input 3D wire along the provided direction vector.
  2. 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.
  3. 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

Bitbybit Platform

Fillet 3D Wire Specific Corners

typescript logoTypescript
Script Source (typescript)
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

Bitbybit Platform

Fillet 3D Wire Specific Corners

blockly logoBlockly
Script Source (blockly)
<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

Bitbybit Platform

Fillet 3D Wire Specific Corners

rete logoRete
Script Source (rete)
{
"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 editor showing the 3D star wire with filleted corners. TypeScript code in the live editor with finished geometries

Blockly editor showing the 3D star wire with filleted corners. Blockly code in the live editor with finished geometries

Rete editor showing the 3D star wire with filleted corners. 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:
    1. Getting all corner points of the wire using a command like bitbybit.occt.shapes.wire.getCornerPoints (or its equivalent, which might be bitbybit.occt.shapes.edge.getCornerPointsOfEdgesForShape if you first get the edges of the wire).
    2. 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).
    3. 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.

This technique allows for precise targeting of corners when applying variable radius fillets to 3D wires.