Working along a wire
A wire is more than an outline. You can stand anywhere on it and ask where you are, which way it is heading and how far you have come, and that is how you hang posts on a fence line or thread beads on a string.
Copies that follow a curve
framesAlongWire spreads count frames evenly by length along a wire. Each frame has an origin on the wire and a normal along it, so a part placed on the frames with transforms.placeOnFrames follows the curve. Model the part around the origin with its forward direction along Z, because placeOnFrames carries the world's Z axis onto each frame's normal.
kind chooses how a frame turns about the curve:
rotationMinimizingis carried along from the start without twisting, the way a swept profile rides. It is the safe choice for curves in space.perpendicularstands across the curve and stays level withup.frenetlies in the plane the curve bends in, and has no normal where the curve runs straight.
This chain takes 17 frames and shares them out with lists.getNthItem. The links on the odd frames are turned 90 degrees about Z, so each link threads through its neighbours. They are spaced closely enough to overlap and far enough apart not to touch:
- Rete
- Blockly
- TypeScript
{
"id": "rete-v2-json",
"nodes": {
"points": {
"id": "points",
"name": "bitbybit.json.parse",
"customName": "parse",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"text": "[[0, 0, 0], [8, 2, 3], [16, 0, 0], [24, 3, -3], [32, 0, 0]]"
},
"inputs": {},
"position": [
40,
40
]
},
"path": {
"id": "path",
"name": "bitbybit.occt.shapes.wire.interpolatePoints",
"customName": "interpolate points",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"periodic": false,
"tolerance": 1e-7,
"parametrization": "chordLength"
},
"inputs": {
"points": {
"connections": [
{
"node": "points",
"output": "result",
"data": {}
}
]
}
},
"position": [
460,
40
]
},
"frames": {
"id": "frames",
"name": "bitbybit.occt.shapes.wire.framesAlongWire",
"customName": "frames along wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"count": 17,
"skipEndOnClosed": true,
"kind": "rotationMinimizing",
"up": [
0,
1,
0
]
},
"inputs": {
"shape": {
"connections": [
{
"node": "path",
"output": "result",
"data": {}
}
]
}
},
"position": [
880,
40
]
},
"everyOther": {
"id": "everyOther",
"name": "bitbybit.lists.getNthItem",
"customName": "get nth item",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"nth": 2,
"offset": 0,
"clone": true
},
"inputs": {
"list": {
"connections": [
{
"node": "frames",
"output": "result",
"data": {}
}
]
}
},
"position": [
1300,
40
]
},
"theOthers": {
"id": "theOthers",
"name": "bitbybit.lists.getNthItem",
"customName": "get nth item",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"nth": 2,
"offset": 1,
"clone": true
},
"inputs": {
"list": {
"connections": [
{
"node": "frames",
"output": "result",
"data": {}
}
]
}
},
"position": [
1300,
380
]
},
"ring": {
"id": "ring",
"name": "bitbybit.occt.shapes.wire.createEllipseWire",
"customName": "ellipse wire",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"center": [
0,
0,
0
],
"direction": [
0,
1,
0
],
"radiusMinor": 0.9,
"radiusMajor": 1.6
},
"inputs": {},
"position": [
40,
280
]
},
"link": {
"id": "link",
"name": "bitbybit.occt.operations.pipeWireCylindrical",
"customName": "pipe wire cylindrical",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"radius": 0.22,
"makeSolid": true,
"trihedronEnum": "isConstantNormal",
"forceApproxC1": false,
"bendRadius": 0
},
"inputs": {
"shape": {
"connections": [
{
"node": "ring",
"output": "result",
"data": {}
}
]
}
},
"position": [
460,
518
]
},
"lying": {
"id": "lying",
"name": "bitbybit.occt.transforms.placeOnFrames",
"customName": "place on frames",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shape": {
"connections": [
{
"node": "link",
"output": "result",
"data": {}
}
]
},
"frames": {
"connections": [
{
"node": "everyOther",
"output": "result",
"data": {}
}
]
}
},
"position": [
1720,
40
]
},
"turned": {
"id": "turned",
"name": "bitbybit.occt.transforms.rotate",
"customName": "rotate",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"axis": [
0,
0,
1
],
"angle": 90
},
"inputs": {
"shape": {
"connections": [
{
"node": "link",
"output": "result",
"data": {}
}
]
}
},
"position": [
880,
426
]
},
"standing": {
"id": "standing",
"name": "bitbybit.occt.transforms.placeOnFrames",
"customName": "place on frames",
"async": true,
"drawable": true,
"data": {
"genericNodeData": {
"hide": true,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
}
},
"inputs": {
"shape": {
"connections": [
{
"node": "turned",
"output": "result",
"data": {}
}
]
},
"frames": {
"connections": [
{
"node": "theOthers",
"output": "result",
"data": {}
}
]
}
},
"position": [
1720,
334
]
},
"steel": {
"id": "steel",
"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": "#5f6773",
"faceColour": "#ff0000",
"vertexColour": "#ff00ff",
"edgeWidth": 2,
"edgeWidthBySize": false,
"vertexSize": 0.03,
"drawEdges": false,
"drawFaces": true,
"drawVertices": false,
"precision": 0.01,
"angularDeflection": 0.5,
"relativeDeflection": false,
"precisionShare": 0,
"drawEdgeIndexes": false,
"edgeIndexHeight": 0.06,
"edgeIndexColour": "#ff00ff",
"drawFaceIndexes": false,
"faceIndexHeight": 0.06,
"faceIndexColour": "#0000ff",
"drawTwoSided": false,
"backFaceColour": "#0000ff",
"backFaceOpacity": 1,
"edgeArrowSize": 0,
"edgeArrowAngle": 15,
"keepMeshData": false,
"allowQualityDecrease": true,
"forceFaceDeflection": false,
"drawIsoCurves": false,
"isoCurvesU": 5,
"isoCurvesV": 5,
"isoCurvesColour": "#808080",
"surfaceAnalysis": "none",
"draftDirection": [
0,
1,
0
]
},
"inputs": {
"faceMaterial": {
"connections": [
{
"node": "steelMaterial",
"output": "result",
"data": {}
}
]
}
},
"position": [
460,
950
]
},
"steelMaterial": {
"id": "steelMaterial",
"name": "bitbybit.draw.createPBRMaterial",
"customName": "create pbr material",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"name": "PBRMaterial",
"baseColor": "#eef0f2",
"metallic": 0.7,
"roughness": 0.3,
"alpha": 1,
"emissiveColor": "#000000",
"emissiveIntensity": 1,
"zOffset": 0,
"zOffsetUnits": 0,
"alphaMode": "opaque",
"alphaCutoff": 0.5,
"doubleSided": false,
"wireframe": false,
"unlit": false
},
"inputs": {},
"position": [
40,
620
]
},
"darker": {
"id": "darker",
"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": "#5f6773",
"faceColour": "#ff0000",
"vertexColour": "#ff00ff",
"edgeWidth": 2,
"edgeWidthBySize": false,
"vertexSize": 0.03,
"drawEdges": false,
"drawFaces": true,
"drawVertices": false,
"precision": 0.01,
"angularDeflection": 0.5,
"relativeDeflection": false,
"precisionShare": 0,
"drawEdgeIndexes": false,
"edgeIndexHeight": 0.06,
"edgeIndexColour": "#ff00ff",
"drawFaceIndexes": false,
"faceIndexHeight": 0.06,
"faceIndexColour": "#0000ff",
"drawTwoSided": false,
"backFaceColour": "#0000ff",
"backFaceOpacity": 1,
"edgeArrowSize": 0,
"edgeArrowAngle": 15,
"keepMeshData": false,
"allowQualityDecrease": true,
"forceFaceDeflection": false,
"drawIsoCurves": false,
"isoCurvesU": 5,
"isoCurvesV": 5,
"isoCurvesColour": "#808080",
"surfaceAnalysis": "none",
"draftDirection": [
0,
1,
0
]
},
"inputs": {
"faceMaterial": {
"connections": [
{
"node": "darkerMaterial",
"output": "result",
"data": {}
}
]
}
},
"position": [
460,
2900
]
},
"darkerMaterial": {
"id": "darkerMaterial",
"name": "bitbybit.draw.createPBRMaterial",
"customName": "create pbr material",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"name": "PBRMaterial",
"baseColor": "#9aa4ae",
"metallic": 0.7,
"roughness": 0.3,
"alpha": 1,
"emissiveColor": "#000000",
"emissiveIntensity": 1,
"zOffset": 0,
"zOffsetUnits": 0,
"alphaMode": "opaque",
"alphaCutoff": 0.5,
"doubleSided": false,
"wireframe": false,
"unlit": false
},
"inputs": {},
"position": [
40,
1650
]
},
"drawLying": {
"id": "drawLying",
"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": "lying",
"output": "result",
"data": {}
}
]
},
"options": {
"connections": [
{
"node": "steel",
"output": "result",
"data": {}
}
]
}
},
"position": [
2140,
40
]
},
"drawStanding": {
"id": "drawStanding",
"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": "standing",
"output": "result",
"data": {}
}
]
},
"options": {
"connections": [
{
"node": "darker",
"output": "result",
"data": {}
}
]
}
},
"position": [
2140,
334
]
},
"view": {
"id": "view",
"name": "bitbybit.babylon.scene.adjustActiveArcRotateCamera",
"customName": "adjust active arc rotate camera",
"async": false,
"drawable": false,
"data": {
"genericNodeData": {
"hide": false,
"oneOnOne": false,
"flatten": 0,
"forceExecution": false
},
"position": [
16,
18,
-48
],
"lookAt": [
16,
1,
0
],
"lowerBetaLimit": 1,
"upperBetaLimit": 179,
"angularSensibilityX": 1000,
"angularSensibilityY": 1000,
"maxZ": 1000,
"panningSensibility": 1000,
"wheelPrecision": 3
},
"inputs": {},
"position": [
2140,
628
]
}
},
"modules": {}
}
<xml xmlns="https://developers.google.com/blockly/xml"><variables><variable id="frames">frames</variable><variable id="link">link</variable></variables><block type="variables_set" x="40" y="200"><field name="VAR" id="frames">frames</field><value name="VALUE"><block type="base_time_await_return"><value name="Promise"><block type="bitbybit.occt.shapes.wire.framesAlongWire"><value name="Shape"><block type="bitbybit.occt.shapes.wire.interpolatePoints"><value name="Points"><block type="bitbybit.json.parse"><value name="Text"><block type="text"><field name="TEXT">[[0, 0, 0], [8, 2, 3], [16, 0, 0], [24, 3, -3], [32, 0, 0]]</field></block></value></block></value><value name="Periodic"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="Tolerance"><block type="math_number"><field name="NUM">1e-7</field></block></value><value name="Parametrization"><block type="bitbybit.occt.enums.bSplineParametrizationEnum"><field name="bitbybit.occt.enums.bSplineParametrizationEnum">'chordLength'</field></block></value></block></value><value name="Count"><block type="math_number"><field name="NUM">17</field></block></value><value name="SkipEndOnClosed"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value><value name="Kind"><block type="bitbybit.occt.enums.curveFrameEnum"><field name="bitbybit.occt.enums.curveFrameEnum">'rotationMinimizing'</field></block></value><value name="Up"><block type="bitbybit.vector.vectorXYZ"><value name="X"><block type="math_number"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number"><field name="NUM">0</field></block></value></block></value></block></value></block></value><next><block type="variables_set"><field name="VAR" id="link">link</field><value name="VALUE"><block type="bitbybit.occt.operations.pipeWireCylindrical"><value name="Shape"><block type="bitbybit.occt.shapes.wire.createEllipseWire"><value name="Center"><block type="bitbybit.point.pointXYZ"><value name="X"><block type="math_number"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number"><field name="NUM">0</field></block></value></block></value><value name="Direction"><block type="bitbybit.vector.vectorXYZ"><value name="X"><block type="math_number"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number"><field name="NUM">0</field></block></value></block></value><value name="RadiusMinor"><block type="math_number"><field name="NUM">0.9</field></block></value><value name="RadiusMajor"><block type="math_number"><field name="NUM">1.6</field></block></value></block></value><value name="Radius"><block type="math_number"><field name="NUM">0.22</field></block></value><value name="MakeSolid"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value><value name="TrihedronEnum"><block type="bitbybit.occt.enums.geomFillTrihedronEnum"><field name="bitbybit.occt.enums.geomFillTrihedronEnum">'isConstantNormal'</field></block></value><value name="ForceApproxC1"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="BendRadius"><block type="math_number"><field name="NUM">0</field></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn"><value name="Entity"><block type="bitbybit.occt.transforms.placeOnFrames"><value name="Shape"><block type="variables_get"><field name="VAR" id="link">link</field></block></value><value name="Frames"><block type="bitbybit.lists.getNthItem"><value name="List"><block type="variables_get"><field name="VAR" id="frames">frames</field></block></value><value name="Nth"><block type="math_number"><field name="NUM">2</field></block></value><value name="Offset"><block type="math_number"><field name="NUM">0</field></block></value><value name="Clone"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value></block></value></block></value><value name="Options"><block type="bitbybit.draw.optionsOcctShape"><value name="FaceOpacity"><block type="math_number"><field name="NUM">1</field></block></value><value name="EdgeOpacity"><block type="math_number"><field name="NUM">1</field></block></value><value name="EdgeColour"><block type="colour_picker"><field name="COLOUR">#5f6773</field></block></value><value name="FaceColour"><block type="colour_picker"><field name="COLOUR">#ff0000</field></block></value><value name="VertexColour"><block type="colour_picker"><field name="COLOUR">#ff00ff</field></block></value><value name="FaceMaterial"><block type="bitbybit.draw.createPBRMaterial"><value name="Name"><block type="text"><field name="TEXT">PBRMaterial</field></block></value><value name="BaseColor"><block type="colour_picker"><field name="COLOUR">#eef0f2</field></block></value><value name="Metallic"><block type="math_number"><field name="NUM">0.7</field></block></value><value name="Roughness"><block type="math_number"><field name="NUM">0.3</field></block></value><value name="Alpha"><block type="math_number"><field name="NUM">1</field></block></value><value name="EmissiveColor"><block type="colour_picker"><field name="COLOUR">#000000</field></block></value><value name="EmissiveIntensity"><block type="math_number"><field name="NUM">1</field></block></value><value name="ZOffset"><block type="math_number"><field name="NUM">0</field></block></value><value name="ZOffsetUnits"><block type="math_number"><field name="NUM">0</field></block></value><value name="AlphaMode"><block type="bitbybit.draw.enums.alphaModeEnum"><field name="bitbybit.draw.enums.alphaModeEnum">'opaque'</field></block></value><value name="AlphaCutoff"><block type="math_number"><field name="NUM">0.5</field></block></value><value name="DoubleSided"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="Wireframe"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="Unlit"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value></block></value><value name="EdgeWidth"><block type="math_number"><field name="NUM">2</field></block></value><value name="EdgeWidthBySize"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="VertexSize"><block type="math_number"><field name="NUM">0.03</field></block></value><value name="DrawEdges"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="DrawFaces"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value><value name="DrawVertices"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="Precision"><block type="math_number"><field name="NUM">0.01</field></block></value><value name="AngularDeflection"><block type="math_number"><field name="NUM">0.5</field></block></value><value name="RelativeDeflection"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="PrecisionShare"><block type="math_number"><field name="NUM">0</field></block></value><value name="DrawEdgeIndexes"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="EdgeIndexHeight"><block type="math_number"><field name="NUM">0.06</field></block></value><value name="EdgeIndexColour"><block type="colour_picker"><field name="COLOUR">#ff00ff</field></block></value><value name="DrawFaceIndexes"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="FaceIndexHeight"><block type="math_number"><field name="NUM">0.06</field></block></value><value name="FaceIndexColour"><block type="colour_picker"><field name="COLOUR">#0000ff</field></block></value><value name="DrawTwoSided"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="BackFaceColour"><block type="colour_picker"><field name="COLOUR">#0000ff</field></block></value><value name="BackFaceOpacity"><block type="math_number"><field name="NUM">1</field></block></value><value name="EdgeArrowSize"><block type="math_number"><field name="NUM">0</field></block></value><value name="EdgeArrowAngle"><block type="math_number"><field name="NUM">15</field></block></value><value name="KeepMeshData"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="AllowQualityDecrease"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value><value name="ForceFaceDeflection"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="DrawIsoCurves"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="IsoCurvesU"><block type="math_number"><field name="NUM">5</field></block></value><value name="IsoCurvesV"><block type="math_number"><field name="NUM">5</field></block></value><value name="IsoCurvesColour"><block type="colour_picker"><field name="COLOUR">#808080</field></block></value><value name="SurfaceAnalysis"><block type="bitbybit.occt.enums.surfaceAnalysisEnum"><field name="bitbybit.occt.enums.surfaceAnalysisEnum">'none'</field></block></value><value name="DraftDirection"><block type="bitbybit.vector.vectorXYZ"><value name="X"><block type="math_number"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number"><field name="NUM">0</field></block></value></block></value></block></value><next><block type="bitbybit.draw.drawAnyAsyncNoReturn"><value name="Entity"><block type="bitbybit.occt.transforms.placeOnFrames"><value name="Shape"><block type="bitbybit.occt.transforms.rotate"><value name="Shape"><block type="variables_get"><field name="VAR" id="link">link</field></block></value><value name="Axis"><block type="bitbybit.vector.vectorXYZ"><value name="X"><block type="math_number"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number"><field name="NUM">0</field></block></value><value name="Z"><block type="math_number"><field name="NUM">1</field></block></value></block></value><value name="Angle"><block type="math_number"><field name="NUM">90</field></block></value></block></value><value name="Frames"><block type="bitbybit.lists.getNthItem"><value name="List"><block type="variables_get"><field name="VAR" id="frames">frames</field></block></value><value name="Nth"><block type="math_number"><field name="NUM">2</field></block></value><value name="Offset"><block type="math_number"><field name="NUM">1</field></block></value><value name="Clone"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value></block></value></block></value><value name="Options"><block type="bitbybit.draw.optionsOcctShape"><value name="FaceOpacity"><block type="math_number"><field name="NUM">1</field></block></value><value name="EdgeOpacity"><block type="math_number"><field name="NUM">1</field></block></value><value name="EdgeColour"><block type="colour_picker"><field name="COLOUR">#5f6773</field></block></value><value name="FaceColour"><block type="colour_picker"><field name="COLOUR">#ff0000</field></block></value><value name="VertexColour"><block type="colour_picker"><field name="COLOUR">#ff00ff</field></block></value><value name="FaceMaterial"><block type="bitbybit.draw.createPBRMaterial"><value name="Name"><block type="text"><field name="TEXT">PBRMaterial</field></block></value><value name="BaseColor"><block type="colour_picker"><field name="COLOUR">#9aa4ae</field></block></value><value name="Metallic"><block type="math_number"><field name="NUM">0.7</field></block></value><value name="Roughness"><block type="math_number"><field name="NUM">0.3</field></block></value><value name="Alpha"><block type="math_number"><field name="NUM">1</field></block></value><value name="EmissiveColor"><block type="colour_picker"><field name="COLOUR">#000000</field></block></value><value name="EmissiveIntensity"><block type="math_number"><field name="NUM">1</field></block></value><value name="ZOffset"><block type="math_number"><field name="NUM">0</field></block></value><value name="ZOffsetUnits"><block type="math_number"><field name="NUM">0</field></block></value><value name="AlphaMode"><block type="bitbybit.draw.enums.alphaModeEnum"><field name="bitbybit.draw.enums.alphaModeEnum">'opaque'</field></block></value><value name="AlphaCutoff"><block type="math_number"><field name="NUM">0.5</field></block></value><value name="DoubleSided"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="Wireframe"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="Unlit"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value></block></value><value name="EdgeWidth"><block type="math_number"><field name="NUM">2</field></block></value><value name="EdgeWidthBySize"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="VertexSize"><block type="math_number"><field name="NUM">0.03</field></block></value><value name="DrawEdges"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="DrawFaces"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value><value name="DrawVertices"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="Precision"><block type="math_number"><field name="NUM">0.01</field></block></value><value name="AngularDeflection"><block type="math_number"><field name="NUM">0.5</field></block></value><value name="RelativeDeflection"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="PrecisionShare"><block type="math_number"><field name="NUM">0</field></block></value><value name="DrawEdgeIndexes"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="EdgeIndexHeight"><block type="math_number"><field name="NUM">0.06</field></block></value><value name="EdgeIndexColour"><block type="colour_picker"><field name="COLOUR">#ff00ff</field></block></value><value name="DrawFaceIndexes"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="FaceIndexHeight"><block type="math_number"><field name="NUM">0.06</field></block></value><value name="FaceIndexColour"><block type="colour_picker"><field name="COLOUR">#0000ff</field></block></value><value name="DrawTwoSided"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="BackFaceColour"><block type="colour_picker"><field name="COLOUR">#0000ff</field></block></value><value name="BackFaceOpacity"><block type="math_number"><field name="NUM">1</field></block></value><value name="EdgeArrowSize"><block type="math_number"><field name="NUM">0</field></block></value><value name="EdgeArrowAngle"><block type="math_number"><field name="NUM">15</field></block></value><value name="KeepMeshData"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="AllowQualityDecrease"><block type="logic_boolean"><field name="BOOL">TRUE</field></block></value><value name="ForceFaceDeflection"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="DrawIsoCurves"><block type="logic_boolean"><field name="BOOL">FALSE</field></block></value><value name="IsoCurvesU"><block type="math_number"><field name="NUM">5</field></block></value><value name="IsoCurvesV"><block type="math_number"><field name="NUM">5</field></block></value><value name="IsoCurvesColour"><block type="colour_picker"><field name="COLOUR">#808080</field></block></value><value name="SurfaceAnalysis"><block type="bitbybit.occt.enums.surfaceAnalysisEnum"><field name="bitbybit.occt.enums.surfaceAnalysisEnum">'none'</field></block></value><value name="DraftDirection"><block type="bitbybit.vector.vectorXYZ"><value name="X"><block type="math_number"><field name="NUM">0</field></block></value><value name="Y"><block type="math_number"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number"><field name="NUM">0</field></block></value></block></value></block></value><next><block type="bitbybit.babylon.scene.adjustActiveArcRotateCamera"><value name="Position"><block type="bitbybit.point.pointXYZ"><value name="X"><block type="math_number"><field name="NUM">16</field></block></value><value name="Y"><block type="math_number"><field name="NUM">18</field></block></value><value name="Z"><block type="math_number"><field name="NUM">-48</field></block></value></block></value><value name="LookAt"><block type="bitbybit.point.pointXYZ"><value name="X"><block type="math_number"><field name="NUM">16</field></block></value><value name="Y"><block type="math_number"><field name="NUM">1</field></block></value><value name="Z"><block type="math_number"><field name="NUM">0</field></block></value></block></value><value name="LowerBetaLimit"><block type="math_number"><field name="NUM">1</field></block></value><value name="UpperBetaLimit"><block type="math_number"><field name="NUM">179</field></block></value><value name="AngularSensibilityX"><block type="math_number"><field name="NUM">1000</field></block></value><value name="AngularSensibilityY"><block type="math_number"><field name="NUM">1000</field></block></value><value name="MaxZ"><block type="math_number"><field name="NUM">1000</field></block></value><value name="PanningSensibility"><block type="math_number"><field name="NUM">1000</field></block></value><value name="WheelPrecision"><block type="math_number"><field name="NUM">3</field></block></value></block></next></block></next></block></next></block></next></block></xml>
const path = await bitbybit.occt.shapes.wire.interpolatePoints({ points: [[0, 0, 0], [8, 2, 3], [16, 0, 0], [24, 3, -3], [32, 0, 0]], periodic: false, tolerance: 1e-7 });
const frames = await bitbybit.occt.shapes.wire.framesAlongWire({ shape: path, count: 17, skipEndOnClosed: true, kind: Bit.Inputs.OCCT.curveFrameEnum.rotationMinimizing, up: [0, 1, 0] });
const everyOther = bitbybit.lists.getNthItem({ list: frames, nth: 2, offset: 0, clone: true });
const theOthers = bitbybit.lists.getNthItem({ list: frames, nth: 2, offset: 1, clone: true });
const ring = await bitbybit.occt.shapes.wire.createEllipseWire({ radiusMajor: 1.6, radiusMinor: 0.9, center: [0, 0, 0], direction: [0, 1, 0] });
const link = await bitbybit.occt.operations.pipeWireCylindrical({ shape: ring, radius: 0.22, makeSolid: true });
const lying = await bitbybit.occt.transforms.placeOnFrames({ shape: link, frames: everyOther });
const turned = await bitbybit.occt.transforms.rotate({ shape: link, axis: [0, 0, 1], angle: 90 });
const standing = await bitbybit.occt.transforms.placeOnFrames({ shape: turned, frames: theOthers });
const steel = new Bit.Inputs.Draw.DrawOcctShapeOptions();
steel.faceMaterial = bitbybit.draw.createPBRMaterial({ baseColor: "#eef0f2", metallic: 0.7, roughness: 0.3 });
steel.edgeColour = "#5f6773";
steel.drawTwoSided = false;
steel.drawEdges = false;
const darker = new Bit.Inputs.Draw.DrawOcctShapeOptions();
darker.faceMaterial = bitbybit.draw.createPBRMaterial({ baseColor: "#9aa4ae", metallic: 0.7, roughness: 0.3 });
darker.edgeColour = "#5f6773";
darker.drawTwoSided = false;
darker.drawEdges = false;
await bitbybit.draw.drawAnyAsync({ entity: lying, options: steel });
await bitbybit.draw.drawAnyAsync({ entity: standing, options: darker });
bitbybit.babylon.scene.adjustActiveArcRotateCamera({ position: [16, 18, -48], lookAt: [16, 1, 0] });
Points, directions and pieces
The same questions come in two forms. ...AtLength takes a distance along the wire in model units. ...AtParam takes a place from 0 at the start to 1 at the end of the curve's own parameter, which is close to but not the same as that share of its length. When even spacing matters, use lengths.
| To get | Use |
|---|---|
| The length of a wire | getWireLength |
| A point at a place | pointOnWireAtLength, pointOnWireAtParam |
| Points at regular steps | pointsOnWireAtEqualLength, divideWireByEqualDistanceToPoints |
| Points at a repeating rhythm | pointsOnWireAtPatternOfLengths |
| The heading at a place | tangentOnWireAtLength, tangentOnWireAtParam |
| A frame at a place | frameOnWireAtLength, frameOnWireAtParam |
| Pieces of the wire | splitWireAtLengths, splitWireAtParams, splitOnPoints |
shapes.edge has the matching functions for a single edge, with Edge in the name.



