From ce3887d87d9d95b7eb8536567f97dd6ea08d9203 Mon Sep 17 00:00:00 2001 From: Matas Ubarevicius Date: Sun, 5 Oct 2025 12:51:49 +0300 Subject: [PATCH 01/11] update authors image --- docs/blog/authors.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/blog/authors.yml b/docs/blog/authors.yml index d27d4110..c6a6e87b 100644 --- a/docs/blog/authors.yml +++ b/docs/blog/authors.yml @@ -2,7 +2,7 @@ ubarevicius: name: Matas Ubarevičius title: Founder url: https://www.linkedin.com/in/matas-ubarevicius/ - image_url: https://media.licdn.com/dms/image/v2/C4E03AQHk-J4Sg5zXcw/profile-displayphoto-shrink_400_400/profile-displayphoto-shrink_400_400/0/1606831113149?e=1753315200&v=beta&t=JqFMDsxNLpq0Jkgj9jtnfEsqH2swc3vYOqxYPVbqsm0 + image_url: https://media.licdn.com/dms/image/v2/D4D03AQG-ryTDnp5Gmg/profile-displayphoto-scale_200_200/B4DZj7zQkTGkAY-/0/1756571175899?e=1762387200&v=beta&t=r2guT1tJv3FiumJwYF0-bmiTsKTun5Aw0JCzDM2lY_I page: # customize the url of the author page at /blog/authors/ permalink: '/all-matas-ubarevicius-articles' From 5f90abcfab6214f18bcbed69f0b5db7b894b5c42 Mon Sep 17 00:00:00 2001 From: Matas Ubarevicius Date: Tue, 7 Oct 2025 13:59:13 +0300 Subject: [PATCH 02/11] two tutorial pages for compounds --- .../occt/shapes/compound/_category_.json | 10 ++ .../compound/compounds-for-rendering.md | 135 +++++++++++++++++ .../code/common/occt/shapes/compound/intro.md | 140 ++++++++++++++++++ 3 files changed, 285 insertions(+) create mode 100644 docs/learn/code/common/occt/shapes/compound/_category_.json create mode 100644 docs/learn/code/common/occt/shapes/compound/compounds-for-rendering.md create mode 100644 docs/learn/code/common/occt/shapes/compound/intro.md diff --git a/docs/learn/code/common/occt/shapes/compound/_category_.json b/docs/learn/code/common/occt/shapes/compound/_category_.json new file mode 100644 index 00000000..3d8d41c8 --- /dev/null +++ b/docs/learn/code/common/occt/shapes/compound/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Compound", + "position": 4, + "link": { + "type": "generated-index", + "title": "Compound Shapes", + "description": "Compound shapes are formed by combining multiple basic shapes. These tutorials will help you understand how to create and manipulate compound shapes in your 3D models.", + "slug": "/code/common/occt/shapes/compound" + } +} \ No newline at end of file diff --git a/docs/learn/code/common/occt/shapes/compound/compounds-for-rendering.md b/docs/learn/code/common/occt/shapes/compound/compounds-for-rendering.md new file mode 100644 index 00000000..83f172d6 --- /dev/null +++ b/docs/learn/code/common/occt/shapes/compound/compounds-for-rendering.md @@ -0,0 +1,135 @@ +--- +sidebar_position: 2 +title: Compounded Drawing +sidebar_label: Compounded Drawing +description: Learn how to use compounds for efficient rendering of complex geometric patterns and assemblies +tags: [code, occt, rete, blockly, typescript] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +OCCT category icon with a stylized logo representation + +Building on the fundamental concepts from the compound shapes introduction, this tutorial demonstrates how to apply compound techniques to complex, real-world scenarios. We'll explore a sophisticated example that creates a parametric hexagonal pattern on a curved surface, showing how compounds dramatically improve rendering performance while enabling organized management of complex geometries. + +## The Challenge: Complex Parametric Patterns + +When working with parametric designs that generate hundreds or thousands of individual geometric elements, performance becomes critical. Consider a scenario where you need to create a hexagonal frame pattern across a curved surface - each hexagon consists of multiple faces, wires, and edges that would normally require individual rendering calls. + +Without compounds, such patterns would overwhelm the graphics pipeline with separate draw calls for each element. The solution lies in strategically grouping related elements into compounds before rendering, transforming what could be thousands of individual operations into just a few efficient compound draws. + +## Advanced Compound Application: Hexagonal Surface Pattern + +The example below demonstrates this principle through a complex workflow that creates a parametric hexagonal pattern on a lofted surface. This real-world scenario showcases several advanced compound techniques: + +**Surface Creation**: First, we generate a complex curved surface by lofting between three interpolated wire curves with different point configurations. + +**Pattern Generation**: The surface is subdivided into hexagonal patterns using two different scaling approaches - one regular and one scaled - creating complementary geometric sets. + +**Strategic Grouping**: Rather than rendering each hexagonal frame individually, we use pattern filtering to group frames into logical sets, then create separate compounds for each group. + +**Efficient Rendering**: Finally, we render only two compound entities instead of potentially hundreds of individual faces, with different materials applied to each compound group. + + + + + + + bottomPointsmiddlePointstopPointsbottomWiremiddleWiretopWirewiresListloftedSurfacemainFacenrHexagonsUnrHexagonsVscalePatternhexWires1hexWires2reversedWiresiframesfirstFramesCompoundsecondFramesCompoundmaterial1material2bottomPoints[[-30, 0, -20], [-10, 0, 0], [0, 0, 10], [10, 0, 0],[30, 0, -20]]middlePoints[[-20, 20, -10], [-5, 20, 15], [0, 20, 20], [5, 20, 15],[20, 20, -10]]topPoints[[-15, 30, 0], [-5, 30, 5], [0, 30, 10], [5, 30, 5],[15, 30, 0]]bottomWirebottomPointsFALSE0.1middleWiremiddlePointsFALSE0.1topWiretopPointsFALSE0.1wiresListbottomWiremiddleWiretopWireloftedSurfacewiresListFALSEmainFaceloftedSurface0nrHexagonsU28nrHexagonsV10scalePattern0.7hexWires1mainFacenrHexagonsUnrHexagonsVFALSE00FALSEFALSEFALSEFALSEhexWires2mainFacenrHexagonsUnrHexagonsVFALSEscalePatternscalePattern00FALSEFALSEFALSEFALSEreversedWiresi1hexWires21INSERTLASTreversedWiresGETFROM_STARThexWires2iframesi1hexWires11INSERTLASTframesGETFROM_STARThexWires1iGETFROM_STARTreversedWiresiFALSEfirstFramesCompoundframes[true, true, false]secondFramesCompoundframes[false,false,true]material1First#9155ff#0000000.150.91FALSE3material2Second#000000#0000000.90.151FALSE3firstFramesCompound0.01material1TRUE#00000010secondFramesCompound0.01material2TRUE#00000010-100-100-1003#ffffff#ffffff1024TRUE0TRUE0.20.00010.00210000'default'10000.10.7TRUE442244015011791000100010001000340040010100.450.50.5FALSE#ffffff#ffffff#050506#627a9d'to top'0100","version":"0.20.7","type":"blockly"}} + title="Compounding hex frames into single entity will render faster" + /> + + + {\n // Define point sets for three different wire levels\n const bottomPoints: Point3[] = [\n [-30, 0, -20],\n [-10, 0, 0],\n [0, 0, 10],\n [10, 0, 0],\n [30, 0, -20]\n ];\n\n const middlePoints: Point3[] = [\n [-20, 20, -10],\n [-5, 20, 15],\n [0, 20, 20],\n [5, 20, 15],\n [20, 20, -10]\n ];\n\n const topPoints: Point3[] = [\n [-15, 30, 0],\n [-5, 30, 5],\n [0, 30, 10],\n [5, 30, 5],\n [15, 30, 0]\n ];\n\n // Create wires by interpolating points\n const bottomWireOptions = new InterpolationDto();\n bottomWireOptions.points = bottomPoints;\n bottomWireOptions.periodic = false;\n bottomWireOptions.tolerance = 0.1;\n const bottomWire = await wire.interpolatePoints(bottomWireOptions);\n\n const middleWireOptions = new InterpolationDto();\n middleWireOptions.points = middlePoints;\n middleWireOptions.periodic = false;\n middleWireOptions.tolerance = 0.1;\n const middleWire = await wire.interpolatePoints(middleWireOptions);\n\n const topWireOptions = new InterpolationDto();\n topWireOptions.points = topPoints;\n topWireOptions.periodic = false;\n topWireOptions.tolerance = 0.1;\n const topWire = await wire.interpolatePoints(topWireOptions);\n\n // Create list of wires for lofting\n const wiresList = [bottomWire, middleWire, topWire];\n\n // Loft the wires to create a surface\n const loftOptions = new LoftDto();\n loftOptions.shapes = wiresList;\n loftOptions.makeSolid = false;\n const loftedSurface = await operations.loft(loftOptions);\n\n // Get the face from the lofted surface\n const getFaceOptions = new ShapeIndexDto();\n getFaceOptions.shape = loftedSurface;\n getFaceOptions.index = 0;\n const mainFace = await face.getFace(getFaceOptions);\n\n // Subdivision parameters\n const nrHexagonsU = 28;\n const nrHexagonsV = 10;\n const scalePattern = [0.7];\n\n // Create first hexagon subdivision (regular pattern)\n const hexSubdivision1Options = new FaceSubdivideToHexagonWiresDto();\n hexSubdivision1Options.shape = mainFace;\n hexSubdivision1Options.nrHexagonsU = nrHexagonsU;\n hexSubdivision1Options.nrHexagonsV = nrHexagonsV;\n const hexWires1 = await face.subdivideToHexagonWires(hexSubdivision1Options);\n\n // Create second hexagon subdivision (scaled pattern)\n const hexSubdivision2Options = new FaceSubdivideToHexagonWiresDto();\n hexSubdivision2Options.shape = mainFace;\n hexSubdivision2Options.nrHexagonsU = nrHexagonsU;\n hexSubdivision2Options.nrHexagonsV = nrHexagonsV;\n hexSubdivision2Options.scalePatternU = scalePattern;\n hexSubdivision2Options.scalePatternV = scalePattern;\n const hexWires2 = await face.subdivideToHexagonWires(hexSubdivision2Options);\n\n // Reverse the wires from the second subdivision using for loop\n const reversedWiresPromises: Promise[] = [];\n for (const hexWire of hexWires2) {\n const reversedWire = wire.reversedWire({ shape: hexWire });\n reversedWiresPromises.push(reversedWire);\n }\n\n const reversedWires = await Promise.all(reversedWiresPromises);\n\n // Combine both wire sets - equivalent to flip lists operation in Rete\n const frameWiresGrouped = hexWires1.map((h, i) => [h, reversedWires[i]]);\n\n // Create frames\n const framePromises = frameWiresGrouped.map(f => {\n const faceFromWires2Options = new FaceFromWiresDto();\n faceFromWires2Options.shapes = f;\n faceFromWires2Options.planar = false;\n return face.createFaceFromWires(faceFromWires2Options);\n });\n\n const frames = await Promise.all(framePromises);\n\n const firstFrames = await bitbybit.lists.getByPattern({\n list: frames,\n pattern: [true, true, false]\n });\n\n const secondFrames = await bitbybit.lists.getByPattern({\n list: frames,\n pattern: [false, false, true]\n })\n\n // Create first compound from the first pattern of hexagon faces\n const compoundOptions = new CompoundShapesDto();\n compoundOptions.shapes = firstFrames;\n const firstCompound = await compound.makeCompound(compoundOptions);\n\n // Create second compound from the first pattern of hexagon faces\n compoundOptions.shapes = secondFrames;\n const secondCompound = await compound.makeCompound(compoundOptions);\n\n // Create materials for rendering\n const firstMaterial = new PBRMetallicRoughnessDto();\n firstMaterial.name = \"Blue Material\";\n firstMaterial.baseColor = \"#9155ff\";\n firstMaterial.metallic = 0.1;\n firstMaterial.roughness = 0.9;\n firstMaterial.backFaceCulling = false;\n firstMaterial.zOffset = 3;\n const blueMatResult = material.pbrMetallicRoughness.create(firstMaterial);\n\n // Create drawing options for the first frames\n const firstDrawOptions = new DrawOcctShapeOptions();\n firstDrawOptions.drawEdges = true;\n firstDrawOptions.edgeColour = \"#000000\";\n firstDrawOptions.edgeWidth = 10;\n firstDrawOptions.faceMaterial = blueMatResult;\n\n bitbybit.draw.drawAnyAsync({\n entity: firstCompound,\n options: firstDrawOptions\n });\n\n // Create materials for rendering\n const secondMaterial = new PBRMetallicRoughnessDto();\n secondMaterial.name = \"Black Material\";\n secondMaterial.baseColor = \"#000000\";\n secondMaterial.metallic = 0.9;\n secondMaterial.roughness = 0.23;\n secondMaterial.backFaceCulling = false;\n secondMaterial.zOffset = 3;\n const secondMatResult = material.pbrMetallicRoughness.create(secondMaterial);\n\n // Create drawing options for the first frames\n const secondDrawOptions = new DrawOcctShapeOptions();\n secondDrawOptions.drawEdges = true;\n secondDrawOptions.edgeColour = \"#000000\";\n secondDrawOptions.edgeWidth = 10;\n secondDrawOptions.faceMaterial = secondMatResult;\n\n bitbybit.draw.drawAnyAsync({\n entity: secondCompound,\n options: secondDrawOptions\n });\n\n // Set up scene lighting and camera\n const skyboxOptions = new SkyboxDto();\n skyboxOptions.skybox = skyboxEnum.city;\n skyboxOptions.hideSkybox = true;\n scene.enableSkybox(skyboxOptions);\n\n const dirLightOptions = new DirectionalLightDto();\n dirLightOptions.intensity = 3;\n scene.drawDirectionalLight(dirLightOptions);\n\n const gradientBackgroundOptions = new SceneTwoColorLinearGradientDto();\n gradientBackgroundOptions.colorFrom = \"#050506\";\n gradientBackgroundOptions.colorTo = \"#627a9d\";\n gradientBackgroundOptions.direction = gradientDirectionEnum.toTop;\n scene.twoColorLinearGradient(gradientBackgroundOptions);\n\n const cameraConfigurationOptions = new CameraConfigurationDto();\n cameraConfigurationOptions.position = [44, 30, 44];\n cameraConfigurationOptions.lookAt = [0, 15, 0];\n scene.adjustActiveArcRotateCamera(cameraConfigurationOptions);\n\n const gridOptions = new SceneDrawGridMeshDto();\n bitbybit.draw.drawGridMesh(gridOptions);\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Compounding hex frames into single entity will render faster" + /> + + + +## Understanding the Workflow: Step-by-Step Breakdown + +Let's examine how this complex example demonstrates advanced compound usage by breaking down the key phases: + +### Phase 1: Surface Creation Through Lofting + +The workflow begins by creating a complex curved surface that will serve as the foundation for our hexagonal pattern. This involves several steps: + +1. **Point Definition**: Three distinct sets of 3D points define the profile curves at different heights - bottom, middle, and top levels with varying shapes and positions. + +2. **Wire Interpolation**: Each point set is converted into smooth interpolated wires using `interpolatePoints()`, creating the skeletal framework for the surface. + +3. **Surface Lofting**: The three wires are lofted together using `operations.loft()` to create a complex curved surface that transitions smoothly between the different profile shapes. + +This foundational surface provides the 3D canvas on which our hexagonal pattern will be projected. + +### Phase 2: Dual Pattern Generation + +The core innovation of this example lies in creating two complementary hexagonal patterns on the same surface: + +1. **Primary Pattern**: The surface is subdivided using `face.subdivideToHexagonWires()` with standard parameters, creating an array of hexagonal wire outlines. + +2. **Secondary Pattern**: A second subdivision is created using the same parameters but with added scaling factors (`scalePatternU` and `scalePatternV` set to 0.7), producing smaller hexagons that nest within the primary pattern. + +3. **Wire Direction Management**: The wires from the secondary pattern are reversed using `wire.reversedWire()` to ensure proper face creation when combined with the primary pattern wires. + +### Phase 3: Frame Construction and Strategic Grouping + +The two wire sets are combined to create individual hexagonal frames: + +1. **Frame Assembly**: Each hexagon frame is created by pairing a wire from the primary pattern with the corresponding reversed wire from the secondary pattern, then using `face.createFaceFromWires()` to create the actual geometric face. + +2. **Pattern-Based Filtering**: Using `bitbybit.lists.getByPattern()`, the frames are separated into logical groups. The patterns `[true, true, false]` and `[false, false, true]` create alternating groupings that distribute the frames across different visual layers. + +3. **Compound Creation**: Each filtered group is consolidated into a separate compound using `compound.makeCompound()`, transforming hundreds of individual faces into just two cohesive entities. + +### Phase 4: Optimized Rendering with Material Differentiation + +The final phase demonstrates the rendering advantages of compounds: + +1. **Material Assignment**: Different materials are created for each compound group - a purple metallic material for the first compound and a black metallic material for the second. + +2. **Single Draw Calls**: Instead of rendering each hexagonal frame individually (which could be hundreds of draw calls), only two `bitbybit.draw.drawAnyAsync()` calls are made - one for each compound. + +3. **Unified Processing**: The graphics pipeline processes each compound as a single mesh, dramatically reducing computational overhead while maintaining the visual complexity of the pattern. + +## Performance Impact Analysis + +This example demonstrates several critical performance optimizations that compounds enable: + +**GPU Efficiency**: Without compounds, a pattern with 280 hexagonal frames would require 280 separate GPU draw calls. With compounds, this reduces to just 2 draw calls - a 99% reduction in rendering overhead. + +**Memory Consolidation**: Individual geometries each require separate memory allocation and management. Compounds consolidate this into unified memory blocks, reducing fragmentation and improving cache efficiency. + +**Transformation Performance**: If you needed to rotate or translate this entire pattern, compounds allow you to transform both groups with just two operations instead of potentially hundreds of individual transformations. + +**Material Management**: Rather than managing materials for hundreds of individual objects, you only need to manage materials for the compound groups, simplifying state changes and reducing GPU state switching overhead. + +## Best Practices for Complex Patterns + +This example illustrates several important patterns for effective compound usage: + +1. **Logical Grouping**: Group geometries that share similar properties (materials, transformation behavior, visibility states) into the same compound. + +2. **Pattern-Based Organization**: Use systematic filtering (like the pattern-based selection shown) to create logical hierarchies rather than arbitrary groupings. + +3. **Strategic Timing**: Create compounds after all individual geometry generation is complete but before rendering operations begin. + +4. **Balance Complexity**: While compounds improve performance, extremely large compounds can become unwieldy. Consider breaking very large patterns into multiple logical compound groups. + +5. **Material Strategy**: Design your material workflow around compound groupings rather than individual geometries to maximize the rendering efficiency gains. + +This advanced example demonstrates how compounds scale from simple grouping mechanisms to sophisticated performance optimization tools in complex parametric design workflows. diff --git a/docs/learn/code/common/occt/shapes/compound/intro.md b/docs/learn/code/common/occt/shapes/compound/intro.md new file mode 100644 index 00000000..f451fcef --- /dev/null +++ b/docs/learn/code/common/occt/shapes/compound/intro.md @@ -0,0 +1,140 @@ +--- +sidebar_position: 1 +title: Compound Shapes +sidebar_label: Intro Compounds +description: Learn how to create compound shapes for better performance and grouped transformations in OCCT +tags: [code, occt, rete, blockly, typescript] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +OCCT category icon with a stylized logo representation + +Compound shapes are one of the most powerful features in OCCT that allow you to group multiple geometric entities into a single cohesive unit. They serve as containers that can hold any combination of OCCT shape types - wires, edges, faces, shells, and solids - treating them as one unified entity. + +## What Are Compound Shapes? + +A compound is essentially a collection of shapes that behave as a single OCCT shape object. Think of it as a group in a drawing application, but with much more sophisticated geometric capabilities. When you create a compound, you're not merging the geometries like with boolean operations - instead, you're creating a hierarchical structure that maintains individual shape identities while enabling collective operations. + +This grouping mechanism is particularly valuable when working with complex assemblies, repetitive patterns, or when you need to apply transformations to multiple objects simultaneously. Compounds preserve the original topology of each constituent shape while providing the convenience of single-entity manipulation. + +## Key Benefits of Using Compounds + +**Performance Optimization**: One of the most significant advantages of compounds is their impact on rendering performance. When you have many individual shapes, each one requires its own mesh generation and GPU draw call. Compounds in Bitbybit consolidate these into a single mesh, dramatically reducing the computational overhead and improving frame rates. + +**Unified Transformations**: Compounds allow you to treat multiple shapes as a single entity for transformations. Whether you're rotating, translating, scaling, or applying complex transformations, all constituent shapes move together as one cohesive unit. This eliminates the need to individually transform each shape and ensures perfect synchronization. + +**Simplified Organization**: In complex models with hundreds or thousands of individual elements, compounds provide a natural organizational structure. You can group related shapes logically, making your code more maintainable and your geometric operations more intuitive. + +**Memory Efficiency**: By grouping shapes into compounds, you reduce the overhead associated with managing individual shape references, leading to more efficient memory usage in large-scale applications. + +## Performance Problem: Individual Shape Creation + +When creating multiple similar shapes individually, you encounter significant performance bottlenecks. Each shape requires separate mesh generation, individual GPU draw calls, and independent memory allocation. This becomes particularly problematic when working with patterns or arrays of objects. + +The example below demonstrates this performance issue by creating individual spheres in a 3D grid pattern. Notice how each sphere is created and rendered separately, leading to reduced performance and slower frame rates as the number of objects increases. + +:::important Performance Testing +If you're not experiencing noticeable performance issues in the first example, try increasing the grid size substantially (to 8 or 10) to see the difference. The performance impact becomes much more apparent with larger numbers of objects. +::: + + + + + + + gridSizesphereRadiusspacinghalfGridxPositionsyPositionszPositionsxyzgridSize3sphereRadius1spacing2.5halfGridDIVIDEMULTIPLYgridSizespacing2xPositionsspacingNEGhalfGridhalfGridyPositionsspacingNEGhalfGridhalfGridzPositionsspacingNEGhalfGridhalfGridx1xPositions1y1yPositions1z1zPositions1GETFROM_STARTxPositionsxGETFROM_STARTyPositionsyGETFROM_STARTzPositionsz","version":"0.20.7","type":"blockly"}} + title="Creating individual spheres leads to performance issues" + /> + + + {\n // Grid parameters\n const gridSize = 3; // Number of spheres per side\n const sphereRadius = 1; // Radius of each sphere\n const spacing = 2.5; // Distance between sphere centers\n \n // Calculate grid boundaries\n const halfGrid = (gridSize * spacing) / 2;\n \n // Generate grid positions using span functions for 3D grid\n const xPositions = vector.span({\n min: -halfGrid,\n max: halfGrid,\n step: spacing\n });\n \n const yPositions = vector.span({\n min: -halfGrid,\n max: halfGrid,\n step: spacing\n });\n \n const zPositions = vector.span({\n min: -halfGrid,\n max: halfGrid,\n step: spacing\n });\n \n // Create individual spheres using nested loops for 3D grid\n // This approach creates each sphere separately, leading to performance issues\n for (const xPos of xPositions) {\n for (const yPos of yPositions) {\n for (const zPos of zPositions) {\n // Define sphere creation options\n const sphereOptions = new SphereDto();\n sphereOptions.radius = sphereRadius;\n sphereOptions.center = [xPos, yPos, zPos];\n \n // Create and immediately draw each sphere individually\n // This is inefficient as each sphere requires its own mesh and draw call\n const sphere = await solid.createSphere(sphereOptions);\n \n // Each draw call is separate, creating performance overhead\n bitbybit.draw.drawAnyAsync({\n entity: sphere\n });\n }\n }\n }\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating individual spheres leads to performance issues" + /> + + + +## Solution: Creating Compounds for Better Performance + +The solution to this performance problem is to use compounds. Instead of creating individual shapes that are rendered separately, you create all the shapes first and then combine them into a single compound. This compound is then treated as one entity for rendering purposes, dramatically improving performance. + + + + + + + gridSizesphereRadiusspacinghalfGridxPositionsyPositionszPositionsspheresxycompoundzgridSize3sphereRadius1spacing2.5halfGridDIVIDEMULTIPLYgridSizespacing2xPositionsspacingNEGhalfGridhalfGridyPositionsspacingNEGhalfGridhalfGridzPositionsspacingNEGhalfGridhalfGridspheresx1xPositions1y1yPositions1z1zPositions1INSERTLASTspheressphereRadiusGETFROM_STARTxPositionsxGETFROM_STARTyPositionsyGETFROM_STARTzPositionszcompoundspherescompound","version":"0.20.7","type":"blockly"}} + title="Compounded spheres provide significantly better performance" + /> + + + {\n // Grid parameters\n const gridSize = 5; // Number of spheres per side\n const sphereRadius = 1; // Radius of each sphere\n const spacing = 2.5; // Distance between sphere centers\n\n // Calculate grid boundaries\n const halfGrid = (gridSize * spacing) / 2;\n\n // Generate grid positions using span functions\n const xPositions = vector.span({\n min: -halfGrid,\n max: halfGrid,\n step: spacing\n });\n\n const yPositions = vector.span({\n min: -halfGrid,\n max: halfGrid,\n step: spacing\n });\n\n const zPositions = vector.span({\n min: -halfGrid,\n max: halfGrid,\n step: spacing\n });\n\n // Create array to store all spheres before compounding\n const spheres: TopoDSSolidPointer[] = [];\n\n // Create all spheres first and store them in the array\n for (const xPos of xPositions) {\n for (const yPos of yPositions) {\n for (const zPos of zPositions) {\n // Define sphere creation options\n const sphereOptions = new SphereDto();\n sphereOptions.radius = sphereRadius;\n sphereOptions.center = [xPos, yPos, zPos];\n\n // Create sphere and add to array\n const sphere = await solid.createSphere(sphereOptions);\n spheres.push(sphere);\n }\n }\n }\n\n // Create compound from all spheres\n const compoundOptions = new CompoundShapesDto();\n compoundOptions.shapes = spheres;\n const sphereCompound = await compound.makeCompound(compoundOptions);\n\n // Draw compound\n bitbybit.draw.drawAnyAsync({\n entity: sphereCompound\n });\n\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Compounded spheres provide significantly better performance" + /> + + + +## Unified Transformations: Moving Compounds as Single Entities + +Another major advantage of compounds is the ability to transform the entire group as a single entity. When you rotate a compound, all constituent shapes move together in perfect synchronization. This eliminates the complexity of managing individual transformations for each shape and demonstrates how compounds maintain their internal relationships during transformations. + + + + + + + + gridSizesphereRadiusspacinghalfGridxPositionsyPositionszPositionsspheresxycompoundzrotatedCompoundgridSize5sphereRadius1spacing2.5halfGridDIVIDEMULTIPLYgridSizespacing2xPositionsspacingNEGhalfGridhalfGridyPositionsspacingNEGhalfGridhalfGridzPositionsspacingNEGhalfGridhalfGridspheresx1xPositions1y1yPositions1z1zPositions1INSERTLASTspheressphereRadiusGETFROM_STARTxPositionsxGETFROM_STARTyPositionsyGETFROM_STARTzPositionszcompoundspheresrotatedCompoundcompound00145rotatedCompound","version":"0.20.7","type":"blockly"}} + title="Compound can be rotated and translated as a single grouped entity" + /> + + + {\n // Grid parameters\n const gridSize = 5; // Number of spheres per side\n const sphereRadius = 1; // Radius of each sphere\n const spacing = 2.5; // Distance between sphere centers\n\n // Calculate grid boundaries\n const halfGrid = (gridSize * spacing) / 2;\n\n // Generate grid positions using span functions\n const xPositions = vector.span({\n min: -halfGrid,\n max: halfGrid,\n step: spacing\n });\n\n const yPositions = vector.span({\n min: -halfGrid,\n max: halfGrid,\n step: spacing\n });\n\n const zPositions = vector.span({\n min: -halfGrid,\n max: halfGrid,\n step: spacing\n });\n\n // Create array to store all spheres before compounding\n const spheres: TopoDSSolidPointer[] = [];\n\n // Create all spheres first and store them in the array\n for (const xPos of xPositions) {\n for (const yPos of yPositions) {\n for (const zPos of zPositions) {\n // Define sphere creation options\n const sphereOptions = new SphereDto();\n sphereOptions.radius = sphereRadius;\n sphereOptions.center = [xPos, yPos, zPos];\n\n // Create sphere and add to array\n const sphere = await solid.createSphere(sphereOptions);\n spheres.push(sphere);\n }\n }\n }\n\n // Create compound from all spheres\n const compoundOptions = new CompoundShapesDto();\n compoundOptions.shapes = spheres;\n const sphereCompound = await compound.makeCompound(compoundOptions);\n\n // Transform the entire compound as a single entity\n // First, rotate the compound around the Z-axis\n const rotateOptions = new RotateDto();\n rotateOptions.shape = sphereCompound;\n rotateOptions.axis = [0, 0, 1]; // Z-axis rotation\n rotateOptions.angle = 45; // 45 degrees\n const rotatedCompound = await transforms.rotate(rotateOptions);\n\n // Draw the transformed compound\n // All spheres move together as a single unified entity\n bitbybit.draw.drawAnyAsync({\n entity: rotatedCompound\n });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Compound can be rotated and translated as a single grouped entity" + /> + + + +## Applications and Best Practices + +Compounds are particularly valuable in several scenarios: + +**Assembly Management**: When working with mechanical assemblies, architectural models, or any complex structure with multiple components, compounds provide a natural hierarchy for organization and manipulation. + +**Performance Optimization**: For applications requiring real-time interaction with many objects, compounds dramatically reduce the computational overhead of rendering and transforming multiple shapes. + +**Parametric Design**: In parametric workflows where you need to generate multiple variations of pattern-based designs, compounds allow you to treat complex patterns as single entities for easy modification. + +**Animation and Simulation**: When animating multiple objects that need to move together, compounds ensure perfect synchronization without the complexity of coordinating individual transformations. + +When implementing compounds in your projects, consider grouping logically related shapes, maintaining reasonable compound sizes for optimal performance, and using nested compounds for hierarchical organization when dealing with very complex assemblies. The examples above demonstrate the fundamental patterns that scale effectively from simple arrays to complex industrial applications. From 846f1f33472fe7492e4ce362f317fa7432520181 Mon Sep 17 00:00:00 2001 From: Matas Ubarevicius Date: Tue, 7 Oct 2025 14:06:27 +0300 Subject: [PATCH 03/11] update file name --- .../{compounds-for-rendering.md => compounded-drawing.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename docs/learn/code/common/occt/shapes/compound/{compounds-for-rendering.md => compounded-drawing.md} (100%) diff --git a/docs/learn/code/common/occt/shapes/compound/compounds-for-rendering.md b/docs/learn/code/common/occt/shapes/compound/compounded-drawing.md similarity index 100% rename from docs/learn/code/common/occt/shapes/compound/compounds-for-rendering.md rename to docs/learn/code/common/occt/shapes/compound/compounded-drawing.md From b8456cf639d3c21f1f95b0d4f7bcd2ac43099e99 Mon Sep 17 00:00:00 2001 From: Matas Ubarevicius Date: Wed, 8 Oct 2025 08:50:35 +0300 Subject: [PATCH 04/11] intro to shells, solids and solid area and volume --- .../occt/shapes/compound/_category_.json | 2 +- .../common/occt/shapes/shells/_category_.json | 10 ++ .../common/occt/shapes/shells/intro-shells.md | 132 ++++++++++++++++++ .../common/occt/shapes/solids/_category_.json | 10 ++ .../common/occt/shapes/solids/intro-solids.md | 55 ++++++++ .../shapes/solids/volume-and-surface-area.md | 53 +++++++ 6 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 docs/learn/code/common/occt/shapes/shells/_category_.json create mode 100644 docs/learn/code/common/occt/shapes/shells/intro-shells.md create mode 100644 docs/learn/code/common/occt/shapes/solids/_category_.json create mode 100644 docs/learn/code/common/occt/shapes/solids/intro-solids.md create mode 100644 docs/learn/code/common/occt/shapes/solids/volume-and-surface-area.md diff --git a/docs/learn/code/common/occt/shapes/compound/_category_.json b/docs/learn/code/common/occt/shapes/compound/_category_.json index 3d8d41c8..94df59f4 100644 --- a/docs/learn/code/common/occt/shapes/compound/_category_.json +++ b/docs/learn/code/common/occt/shapes/compound/_category_.json @@ -1,6 +1,6 @@ { "label": "Compound", - "position": 4, + "position": 6, "link": { "type": "generated-index", "title": "Compound Shapes", diff --git a/docs/learn/code/common/occt/shapes/shells/_category_.json b/docs/learn/code/common/occt/shapes/shells/_category_.json new file mode 100644 index 00000000..5d45b5d0 --- /dev/null +++ b/docs/learn/code/common/occt/shapes/shells/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Shells", + "position": 4, + "link": { + "type": "generated-index", + "title": "Shells", + "description": "Shells are made out of multiple faces connected together. These tutorials will guide you through the process of creating and manipulating shell shapes in your 3D models.", + "slug": "/code/common/occt/shapes/shells" + } +} \ No newline at end of file diff --git a/docs/learn/code/common/occt/shapes/shells/intro-shells.md b/docs/learn/code/common/occt/shapes/shells/intro-shells.md new file mode 100644 index 00000000..255196bc --- /dev/null +++ b/docs/learn/code/common/occt/shapes/shells/intro-shells.md @@ -0,0 +1,132 @@ +--- +sidebar_position: 1 +title: Shells +sidebar_label: Intro Shells +description: Learn how to create shells +tags: [code, occt, rete, blockly, typescript] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +OCCT category icon with a stylized logo representation + +Shells are fundamental geometric constructs in OCCT that represent connected collections of faces. Think of a shell as the "skin" of a 3D object - it defines the boundary between the interior and exterior of a shape but doesn't necessarily enclose a volume. Shells are particularly useful for creating complex surfaces, modeling thin-walled objects, or as intermediate steps toward creating solid geometries. + +## What Are Shells? + +A shell is essentially a collection of faces that are sewn together along their common edges. Unlike individual faces that exist independently, shells maintain topological connections between faces, creating a unified surface structure. This connectivity is crucial for many geometric operations and enables OCCT to understand the relationship between adjacent surfaces. + +Shells can be either **open** (like a curved sheet of paper) or **closed** (like a complete sphere surface). Closed shells that properly enclose a volume can be converted into solid geometries, making them valuable intermediate representations in 3D modeling workflows. + +## The Sewing Process + +The process of creating shells involves "sewing" faces together by identifying and connecting their common edges. OCCT's sewing algorithm automatically detects edges that are geometrically coincident within a specified tolerance and merges them into shared boundaries. This process ensures topological consistency and creates the connected face structure that defines a shell. + +:::important Face Order and Direction +When creating shells, the **first face in the collection often dictates how other face normals and orientations behave** during the sewing process. OCCT uses the orientation of the first face as a reference to determine the consistent orientation for the entire shell. This is particularly important when creating closed shells that will be converted to solids, as inconsistent face orientations can prevent successful solid creation. +::: + +## Simple Shell Example: Two Square Faces + +This first example demonstrates the fundamental concept of shell creation by sewing two square faces together. We create two identical square faces, position one of them to share an edge with the first, and then sew them together to form a simple shell. + + + + + + + sizeface1face2rotatedFace2translatedFace2facesshellsize5face1size000010face2size000010rotatedFace2face200190translatedFace2rotatedFace2DIVIDEsize2DIVIDEsize20facesface1translatedFace2shellfaces0.0000001shell","version":"0.20.7","type":"blockly"}} + title="Creating shells by sewing two square faces" + /> + + + {\n // Define the size for both square faces\n const size = 5;\n\n // Create first square face at origin\n const face1Options = new SquareDto();\n face1Options.size = size;\n face1Options.center = [0, 0, 0] as Point3;\n face1Options.direction = [0, 1, 0] as Vector3; // Y-up orientation\n\n const face1 = await face.createSquareFace(face1Options);\n\n // Create second square face (initially identical to first)\n const face2Options = new SquareDto();\n face2Options.size = size;\n face2Options.center = [0, 0, 0] as Point3;\n face2Options.direction = [0, 1, 0] as Vector3;\n\n const face2 = await face.createSquareFace(face2Options);\n\n // Rotate the second face 90 degrees around Z-axis to create perpendicular orientation\n const rotateOptions = new RotateDto();\n rotateOptions.shape = face2;\n rotateOptions.axis = [0, 0, 1] as Vector3; // Z-axis\n rotateOptions.angle = 90; // 90 degrees\n\n const rotatedFace2 = await transforms.rotate(rotateOptions);\n\n // Translate the rotated face to share an edge with the first face\n const translateOptions = new TranslateDto();\n translateOptions.shape = rotatedFace2;\n translateOptions.translation = [size / 2, size / 2, 0] as Vector3;\n\n const translatedFace2 = await transforms.translate(translateOptions);\n\n // Create array of faces to sew together\n const faces = [face1, translatedFace2];\n\n // Sew the faces together to create a shell\n const sewOptions = new SewDto(faces);\n sewOptions.tolerance = 1e-7; // Very tight tolerance for precise sewing\n\n const resultShell = await shell.sewFaces(sewOptions);\n\n // Verify that we created a shell (not just individual faces)\n const shapeType = await shape.getShapeType({ shape: resultShell });\n console.log('Shell shape type:', shapeType); // Should output \"shell\"\n\n // Draw the resulting shell\n bitbybit.draw.drawAnyAsync({\n entity: resultShell\n });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating shells by sewing two square faces" + /> + + + +The workflow demonstrates several key concepts: + +1. **Face Creation**: Two identical square faces are created with the same dimensions and orientation. +2. **Geometric Transformation**: The second face is rotated 90 degrees and then translated to position it perpendicular to the first face, sharing a common edge. +3. **Sewing Process**: The `sewFaces` operation identifies the shared edge and creates topological connections between the faces. +4. **Validation**: The `getShapeType` function confirms that the result is indeed a shell rather than separate faces. + +This simple example shows how shells maintain the relationship between connected faces, creating a unified geometric entity that can be used in further operations. + +## Advanced Shell Example: Creating a Closed Solid + +This more sophisticated example demonstrates how to create a complex shell from multiple faces that form a closed surface, which can then be converted into a solid. We'll construct a cylindrical shape by creating circular faces and an extruded cylindrical surface, then sew them together to form a closed shell. + +:::note Alternative Construction Methods +While this cylindrical solid **can be constructed in Bitbybit using the simple solid cylinder command**, this example is created for **demonstration purposes** to show the face-based shell construction process. Understanding face-based construction is valuable for creating complex custom geometries that cannot be easily generated using primitive solid operations. +::: + + + + + + + radiusheightcircleWireextrusionVectorcylindricalSurfacebottomFacetopFacefacesshellsolidradius5height5circleWireradius000010extrusionVector0height0cylindricalSurfacecircleWireextrusionVectorbottomFacecircleWireTRUEtopFacebottomFaceextrusionVectorfacestopFacecylindricalSurfacebottomFaceshellfaces1e-7solidshellsolid","version":"0.20.7","type":"blockly"}} + title="Creating closed shells and converting to solids" + /> + + + {\n // Define geometric parameters\n const radius = 5;\n const height = 5;\n\n // Step 1: Create base circle wire\n const circleOptions = new CircleDto();\n circleOptions.radius = radius;\n circleOptions.center = [0, 0, 0] as Point3;\n circleOptions.direction = [0, 1, 0] as Vector3; // Y-up orientation\n\n const circleWire = await wire.createCircleWire(circleOptions);\n\n // Step 2: Create extrusion vector for cylindrical surface\n const extrusionVector: Vector3 = [0, height, 0];\n\n // Step 3: Create cylindrical surface by extruding the circle wire\n const extrudeOptions = new ExtrudeDto();\n extrudeOptions.shape = circleWire;\n extrudeOptions.direction = extrusionVector;\n\n const cylindricalSurface = await operations.extrude(extrudeOptions);\n\n // Step 4: Create bottom face from the circle wire\n const bottomFaceOptions = new FaceFromWireDto();\n bottomFaceOptions.shape = circleWire;\n bottomFaceOptions.planar = true; // Ensure flat circular face\n\n const bottomFace = await face.createFaceFromWire(bottomFaceOptions);\n\n // Step 5: Create top face by translating bottom face\n const translateOptions = new TranslateDto();\n translateOptions.shape = bottomFace;\n translateOptions.translation = extrusionVector;\n\n const topFace = await transforms.translate(translateOptions);\n\n // Step 6: Collect all faces that will form the closed shell\n const faces = [topFace, cylindricalSurface, bottomFace];\n\n // Step 7: Sew faces together to create a closed shell\n const sewOptions = new SewDto(faces);\n sewOptions.tolerance = 1e-7; // High precision for closed shell\n\n const closedShell = await shell.sewFaces(sewOptions);\n\n // Step 8: Convert closed shell to solid\n const solidOptions = new ShapeDto();\n solidOptions.shape = closedShell;\n\n const cylinderSolid = await solid.fromClosedShell(solidOptions);\n\n // Step 9: Verify the shape types\n const shellType = await shape.getShapeType({ shape: closedShell });\n const solidType = await shape.getShapeType({ shape: cylinderSolid });\n\n console.log('Shell type:', shellType); // Should output \"shell\"\n console.log('Solid type:', solidType); // Should output \"solid\"\n\n // Step 10: Draw the final solid\n bitbybit.draw.drawAnyAsync({\n entity: cylinderSolid\n });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating closed shells and converting to solids" + /> + + + +This advanced example demonstrates several sophisticated concepts: + +## The Construction Process + +1. **Base Geometry Creation**: We start by creating a circular wire that serves as the foundation for our cylindrical shape. + +2. **Surface Generation**: The circular wire is extruded to create the cylindrical surface that will form the sides of our shape. + +3. **End Cap Creation**: Two circular faces are created - one at the bottom (from the original circle wire) and one at the top (by translating the bottom face upward). + +4. **Shell Assembly**: All three faces (bottom, top, and cylindrical surface) are sewn together using the `sewFaces` operation to create a closed shell. + +5. **Solid Conversion**: The closed shell is converted into a solid using `fromClosedShell`, which validates that the shell properly encloses a volume. + +## Key Advantages of This Workflow + +**Topological Validity**: By creating shells first and then converting to solids, we ensure that the resulting geometry has proper topological relationships between faces, edges, and vertices. + +**Error Detection**: If the shell is not properly closed or has topological issues, the `fromClosedShell` operation will fail. + +**Geometric Flexibility**: This approach allows for complex surface creation that might be difficult to achieve with direct solid modeling operations. + +**Intermediate Inspection**: You can examine and validate the shell before converting it to a solid, making debugging easier in complex workflows. + +:::tip Performance Advantage +**Making geometry from faces is usually way faster than performing boolean operations** such as union or difference. When designing complex geometries, **it pays to think in terms of faces** and shell construction rather than relying heavily on boolean operations. This face-based approach not only provides better performance but also gives you more precise control over the final geometry and better error handling for invalid operations. +::: + +This tutorial demonstrates how shells serve as a crucial intermediate representation in OCCT, bridging the gap between individual faces and complete solid geometries while providing powerful tools for surface-based modeling. diff --git a/docs/learn/code/common/occt/shapes/solids/_category_.json b/docs/learn/code/common/occt/shapes/solids/_category_.json new file mode 100644 index 00000000..551a212e --- /dev/null +++ b/docs/learn/code/common/occt/shapes/solids/_category_.json @@ -0,0 +1,10 @@ +{ + "label": "Solids", + "position": 5, + "link": { + "type": "generated-index", + "title": "Solids", + "description": "Solids are three-dimensional shapes that have a definite volume and shape. These tutorials will help you understand how to create and manipulate solid shapes in your 3D models.", + "slug": "/code/common/occt/shapes/solids" + } +} \ No newline at end of file diff --git a/docs/learn/code/common/occt/shapes/solids/intro-solids.md b/docs/learn/code/common/occt/shapes/solids/intro-solids.md new file mode 100644 index 00000000..ab256a6b --- /dev/null +++ b/docs/learn/code/common/occt/shapes/solids/intro-solids.md @@ -0,0 +1,55 @@ +--- +sidebar_position: 1 +title: Solids +sidebar_label: Intro Solids +description: Learn how to create solids +tags: [code, occt, rete, blockly, typescript] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +OCCT category icon with a stylized logo representation + +# Introduction to OCCT Solids + +Solids are three-dimensional shapes that represent complete geometric objects with volume. OCCT provides several primitive solid types that serve as building blocks for more complex 3D modeling operations. These primitives are commonly used in CAD applications and can be combined, modified, and transformed to create sophisticated geometries. + +This example demonstrates the creation of the most common primitive solid types: + +- **Box**: A rectangular solid with specified width, length, and height +- **Cube**: A special case of a box where all dimensions are equal +- **Cylinder**: A circular solid with specified radius and height +- **Sphere**: A perfectly round solid with a specified radius +- **Cone**: A tapered solid with different radii at top and bottom + + + + + + + boxcubecylindersphereconebox378000TRUEcube5500TRUEcylinder23-500010360TRUEsphere1.51000cone213360-1000010boxcubecylinderspherecone","version":"0.20.7","type":"blockly"}} + title="Creating primitive solids" + /> + + + {\n // Create a rectangular box\n const boxOptions = new BoxDto();\n boxOptions.width = 3;\n boxOptions.length = 7;\n boxOptions.height = 8;\n boxOptions.center = [0, 0, 0] as Point3;\n boxOptions.originOnCenter = true;\n \n const box = await solid.createBox(boxOptions);\n \n // Create a cube at a different position\n const cubeOptions = new CubeDto();\n cubeOptions.size = 5;\n cubeOptions.center = [5, 0, 0] as Point3;\n cubeOptions.originOnCenter = true;\n \n const cube = await solid.createCube(cubeOptions);\n \n // Create a cylinder\n const cylinderOptions = new CylinderDto();\n cylinderOptions.radius = 2;\n cylinderOptions.height = 3;\n cylinderOptions.center = [-5, 0, 0] as Point3;\n cylinderOptions.direction = [0, 1, 0] as Vector3;\n cylinderOptions.angle = 360;\n cylinderOptions.originOnCenter = true;\n \n const cylinder = await solid.createCylinder(cylinderOptions);\n \n // Create a sphere\n const sphereOptions = new SphereDto();\n sphereOptions.radius = 1.5;\n sphereOptions.center = [10, 0, 0] as Point3;\n \n const sphere = await solid.createSphere(sphereOptions);\n \n // Create a cone\n const coneOptions = new ConeDto();\n coneOptions.radius1 = 2;\n coneOptions.radius2 = 1;\n coneOptions.height = 3;\n coneOptions.angle = 360;\n coneOptions.center = [-10, 0, 0] as Point3;\n coneOptions.direction = [0, 1, 0] as Vector3;\n \n const cone = await solid.createCone(coneOptions);\n \n // Draw all the created solids\n bitbybit.draw.drawAnyAsync({ entity: box });\n bitbybit.draw.drawAnyAsync({ entity: cube });\n bitbybit.draw.drawAnyAsync({ entity: cylinder });\n bitbybit.draw.drawAnyAsync({ entity: sphere });\n bitbybit.draw.drawAnyAsync({ entity: cone });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating primitive solids" + /> + + + +These primitive solids serve as the foundation for more complex 3D modeling operations. They can be combined using boolean operations (union, intersection, difference), transformed, and modified to create sophisticated geometries for engineering and design applications. \ No newline at end of file diff --git a/docs/learn/code/common/occt/shapes/solids/volume-and-surface-area.md b/docs/learn/code/common/occt/shapes/solids/volume-and-surface-area.md new file mode 100644 index 00000000..dffd9762 --- /dev/null +++ b/docs/learn/code/common/occt/shapes/solids/volume-and-surface-area.md @@ -0,0 +1,53 @@ +--- +sidebar_position: 1 +title: Solids +sidebar_label: Volume and Surface Area +description: Learn how to get volume and surface area of a solid +tags: [code, occt, rete, blockly, typescript] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +OCCT category icon with a stylized logo representation + +# Calculating Volume and Surface Area + +OCCT provides built-in functions to calculate geometric properties of solid shapes, including volume and surface area. This tutorial demonstrates how to: + +- Create a parametric cone solid +- Calculate the volume of the solid using `getSolidVolume` +- Calculate the surface area using `getSolidSurfaceArea` +- Format and display the results with proper units +- Use pin labels for visual annotation + +The example shows a practical workflow for measuring and displaying geometric properties, which is essential for engineering calculations, material estimates, and design validation. + + + + + + + heightconevolumesurfaceArearoundedVolumeroundedSurfaceAreavolumeTextareaTextvolumePinareaPinheight5cone21height360000010volumeconesurfaceAreaconeroundedVolumevolume2roundedSurfaceAreasurfaceArea2volumeTextVolume {0} m3roundedVolumeareaTextArea {0} m3roundedSurfaceAreavolumePin0height01ADDheight301000volumeText0.30.3areaPin0height01ADDheight401000areaText0.30.3conevolumePinareaPin","version":"0.20.7","type":"blockly"}} + title="Get volume and surface area from solid" + /> + + + {\n // Parametric height value\n const height = 5;\n\n // Create a cone\n const coneOptions = new ConeDto();\n coneOptions.radius1 = 2;\n coneOptions.radius2 = 1;\n coneOptions.height = height;\n coneOptions.angle = 360;\n coneOptions.center = [0, 0, 0] as Point3;\n coneOptions.direction = [0, 1, 0] as Vector3;\n\n const cone = await solid.createCone(coneOptions);\n\n // Get volume and surface area\n const volume = await solid.getSolidVolume({ shape: cone });\n const surfaceArea = await solid.getSolidSurfaceArea({ shape: cone });\n\n // Round to 2 decimal places\n const roundedVolume = math.roundToDecimals({ number: volume, decimalPlaces: 2 });\n const roundedSurfaceArea = math.roundToDecimals({ number: surfaceArea, decimalPlaces: 2 });\n\n // Format as text with units\n const volumeText = text.format({\n text: \"Volume {0} m3\",\n values: [text.toString({ item: roundedVolume })]\n });\n const areaText = text.format({\n text: \"Area {0} m2\",\n values: [text.toString({ item: roundedSurfaceArea })]\n });\n\n // Create pin labels to display the measurements\n const volumePinOptions = new PinWithLabelDto();\n volumePinOptions.startPoint = [0, height, 0] as Point3;\n volumePinOptions.endPoint = [1, height + 3, 0] as Point3;\n volumePinOptions.direction = [1, 0, 0] as Vector3;\n volumePinOptions.offsetFromStart = 0;\n volumePinOptions.label = volumeText;\n volumePinOptions.labelOffset = 0.3;\n volumePinOptions.labelSize = 0.3;\n\n const volumePin = await dimensions.pinWithLabel(volumePinOptions);\n\n const areaPinOptions = new PinWithLabelDto();\n areaPinOptions.startPoint = [0, height, 0] as Point3;\n areaPinOptions.endPoint = [1, height + 4, 0] as Point3;\n areaPinOptions.direction = [1, 0, 0] as Vector3;\n areaPinOptions.offsetFromStart = 0;\n areaPinOptions.label = areaText;\n areaPinOptions.labelOffset = 0.3;\n areaPinOptions.labelSize = 0.3;\n\n const areaPin = await dimensions.pinWithLabel(areaPinOptions);\n\n // Draw the cone and labels\n bitbybit.draw.drawAnyAsync({ entity: cone });\n bitbybit.draw.drawAnyAsync({ entity: volumePin });\n bitbybit.draw.drawAnyAsync({ entity: areaPin });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Get volume and surface area from solid" + /> + + From 1981b724372c8a1ff16ca123922998a047d4cf05 Mon Sep 17 00:00:00 2001 From: Matas Ubarevicius Date: Wed, 8 Oct 2025 14:10:10 +0300 Subject: [PATCH 05/11] pin with label docs --- .../common/occt/dimensions/pin-with-label.md | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 docs/learn/code/common/occt/dimensions/pin-with-label.md diff --git a/docs/learn/code/common/occt/dimensions/pin-with-label.md b/docs/learn/code/common/occt/dimensions/pin-with-label.md new file mode 100644 index 00000000..a2738bbc --- /dev/null +++ b/docs/learn/code/common/occt/dimensions/pin-with-label.md @@ -0,0 +1,105 @@ +--- +sidebar_position: 3 +title: Pin with Label +sidebar_label: Pin with Label +description: Learn how to create annotated pins with labels for marking important points and displaying information in your 3D models. +tags: [code, occt, rete, blockly, typescript] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +OCCT category icon with a stylized logo representation + +# Pin with Label + +Pin with label is a powerful annotation tool that creates visual markers with text labels to highlight important points, display calculated values, or provide contextual information in your 3D models. These pins consist of a line connecting two points with customizable text labels, making them perfect for technical documentation, design reviews, and educational materials. + +## Understanding Pin with Label + +Pin with label annotations combine geometric positioning with text information to create clear, professional annotations. They're essential for communicating design intent, displaying calculated properties, and marking critical features in your models. + +Key components include: +- **Start Point**: The point where the pin originates (usually on or near your geometry) +- **End Point**: The point where the pin terminates (typically positioned for optimal label visibility) +- **Direction Vector**: Controls the orientation of the label text +- **Label Text**: The information to display (can be static text or dynamic calculated values) +- **Label Positioning**: Offset and size controls for optimal readability + +## Simple Pin with Static Label + +The most basic use case is creating a pin with static text to mark important points in your model. + + + + + + + 0003211000Important Point0.30.4","version":"0.20.7","type":"blockly"}} + title="Simple pin with static label" + /> + + + {\n // Define points for the pin\n const startPoint: Point3 = [0, 0, 0];\n const endPoint: Point3 = [3, 2, 1];\n const direction: Vector3 = [1, 0, 0];\n\n // Create pin with label options\n const pinOptions = new PinWithLabelDto();\n pinOptions.startPoint = startPoint;\n pinOptions.endPoint = endPoint;\n pinOptions.direction = direction;\n pinOptions.offsetFromStart = 0;\n pinOptions.label = \"Important Point\";\n pinOptions.labelOffset = 0.3;\n pinOptions.labelSize = 0.4;\n\n // Create and draw the pin\n const pin = await bitbybit.occt.dimensions.pinWithLabel(pinOptions);\n bitbybit.draw.drawAnyAsync({ entity: pin });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Simple pin with static label" + /> + + + +This basic example demonstrates the essential components of a pin with label: +- **Start Point** at origin `[0, 0, 0]` - where the pin begins +- **End Point** at `[3, 2, 1]` - where the pin terminates and the label appears +- **Direction Vector** `[1, 0, 0]` - controls label text orientation (pointing along X-axis) +- **Static Label** text "Important Point" - simple text annotation +- **Label positioning** with 0.3 offset and 0.4 size for good readability + +## Pin with Calculated Properties + +A more practical application combines pin labels with calculated geometric properties, similar to how technical drawings display measurements and specifications. + + + + + + + radiusspherevolumeradius2.5sphereradius000volumesphere00radius43ADDradius21000Vol: {0} m3volume20.30.4sphere","version":"0.20.7","type":"blockly"}} + title="Sphere with volume pin label" + /> + + + {\n // Parametric radius value\n const radius = 2.5;\n\n // Create a sphere\n const sphereOptions = new SphereDto();\n sphereOptions.radius = radius;\n sphereOptions.center = [0, 0, 0] as Point3;\n\n const sphere = await solid.createSphere(sphereOptions);\n\n // Calculate sphere volume\n const volume = await solid.getSolidVolume({ shape: sphere });\n const roundedVolume = math.roundToDecimals({ number: volume, decimalPlaces: 2 });\n\n // Format volume as text with units\n const volumeText = text.format({\n text: \"Vol: {0} m3\",\n values: [text.toString({ item: roundedVolume })]\n });\n\n // Create pin with calculated volume label\n const pinOptions = new PinWithLabelDto();\n pinOptions.startPoint = [0, 0, radius] as Point3; // Start at top of sphere\n pinOptions.endPoint = [4, 3, radius + 2] as Point3; // Position for visibility\n pinOptions.direction = [1, 0, 0] as Vector3;\n pinOptions.offsetFromStart = 0;\n pinOptions.label = volumeText;\n pinOptions.labelOffset = 0.3;\n pinOptions.labelSize = 0.4;\n\n // Create and draw the pin\n const pin = await dimensions.pinWithLabel(pinOptions);\n \n // Draw both sphere and pin\n bitbybit.draw.drawAnyAsync({ entity: sphere });\n bitbybit.draw.drawAnyAsync({ entity: pin });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Sphere with volume pin label" + /> + + + +This example demonstrates how to combine pin labels with calculated geometric properties: + +- **Parametric Sphere**: Created with a configurable radius (2.5 units) +- **Volume Calculation**: Uses `getSolidVolume` to compute the sphere's volume +- **Dynamic Formatting**: Rounds volume to 2 decimal places and formats with units ("Vol: 65.45 m³") +- **Smart Positioning**: Pin starts at the sphere's top surface and extends to a clear viewing position +- **Responsive Layout**: Pin height adjusts based on sphere radius for consistent visual presentation + +This pattern is commonly used in engineering applications where you need to annotate models with calculated properties that update automatically when geometry parameters change. From 12c9f68c523f5463e13629a814a5961564ecc17d Mon Sep 17 00:00:00 2001 From: Matas Ubarevicius Date: Wed, 8 Oct 2025 15:33:04 +0300 Subject: [PATCH 06/11] edge primitives explained in docs --- .../occt/shapes/edge/edge-primitives.md | 374 ++++++++++++++++++ 1 file changed, 374 insertions(+) create mode 100644 docs/learn/code/common/occt/shapes/edge/edge-primitives.md diff --git a/docs/learn/code/common/occt/shapes/edge/edge-primitives.md b/docs/learn/code/common/occt/shapes/edge/edge-primitives.md new file mode 100644 index 00000000..befb86a9 --- /dev/null +++ b/docs/learn/code/common/occt/shapes/edge/edge-primitives.md @@ -0,0 +1,374 @@ +--- +sidebar_position: 3 +title: "Edge Primitives" +sidebar_label: Edge Primitives +description: Master the fundamentals of edge creation in OCCT - from simple lines and circles to complex arcs and ellipses. Learn multiple methods to create precise geometric boundaries for your 3D models. +tags: [occt] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +# Edge Primitives + +OCCT category icon with a stylized logo representation + + +Edge primitives are the fundamental building blocks for creating geometric boundaries in 3D modeling. In OCCT (Open CASCADE Technology), edges define the boundaries between faces and form the skeleton of complex 3D shapes. This tutorial covers the essential edge types you'll use in most modeling scenarios. + +## What You'll Learn + +In this tutorial, you'll discover how to create: + +- **Linear edges** - straight lines between two points +- **Circular arcs** - curved segments using various definition methods +- **Complete circles** - closed circular boundaries +- **Elliptical edges** - oval-shaped curves with dual radii + +Each example is provided in three formats: **Rete** (visual node-based), **Blockly** (block-based), and **TypeScript** (code-based), so you can learn using your preferred approach. + +## Why Edge Primitives Matter + +Understanding edge primitives is crucial because: +- They form the boundaries of all 3D shapes +- They enable precise geometric control in your models +- They provide multiple creation methods for different design scenarios +- They serve as the foundation for more complex geometric operations + +Let's start with the most basic edge primitive - the line edge. + +--- + + + + + + + startPointendPointstartPoint-500endPoint500startPointendPointstartPointendPoint","version":"0.20.7","type":"blockly"}} + title="Creating primitive solids" + /> + + + {\n // Create start and end points\n const startPoint: Point3 = [-5, 0, 0];\n const endPoint: Point3 = [5, 0, 0];\n\n // Create a line between the points\n const lineOptions = new LineDto();\n lineOptions.start = startPoint;\n lineOptions.end = endPoint;\n\n const line = await bitbybit.occt.shapes.edge.line(lineOptions);\n\n // Draw the line and points\n bitbybit.draw.drawAnyAsync({ entity: line });\n bitbybit.draw.drawAnyAsync({ entity: startPoint });\n bitbybit.draw.drawAnyAsync({ entity: endPoint });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating primitive solids" + /> + + + +## Line Edge + +This example demonstrates how to create a simple straight line edge in 3D space. A line edge is the most basic type of edge primitive, defined by two points: a start point and an end point. + +**What's happening:** +- We define two points: `startPoint` at `[-5, 0, 0]` and `endPoint` at `[5, 0, 0]` +- These points create a horizontal line along the X-axis, 10 units long +- The `LineDto` object packages our start and end points for the OCCT line creation function +- The result is a straight edge that can be used in more complex geometries or displayed on its own + +**Key concepts:** +- **Start and End Points**: Every line needs exactly two points to define its position and direction +- **3D Coordinates**: Points are specified as `[x, y, z]` coordinates in 3D space +- **Edge vs Line**: An edge is a geometric boundary that can be part of a face or solid, while a line is the mathematical definition + + + + + + + + startPointmidPointendPointstartPoint-500midPoint060endPoint500startPointmidPointendPointstartPointmidPointendPoint","version":"0.20.7","type":"blockly"}} + title="Arc edge through 3 points" + /> + + + {\n // Create start and end points\n const startPoint: Point3 = [-5, 0, 0];\n const midPoint: Point3 = [0, 6, 0];\n const endPoint: Point3 = [5, 0, 0];\n\n // Create a arc between three points\n const arcOptions = new ArcEdgeThreePointsDto();\n arcOptions.start = startPoint;\n arcOptions.middle = midPoint;\n arcOptions.end = endPoint;\n\n const arc = await bitbybit.occt.shapes.edge.arcThroughThreePoints(arcOptions);\n\n // Draw the arc and points\n bitbybit.draw.drawAnyAsync({ entity: arc });\n bitbybit.draw.drawAnyAsync({ entity: [startPoint, midPoint, endPoint] });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Arc edge through 3 points" + /> + + + +## Arc Through Three Points + +This example shows how to create an arc edge that passes through three specific points. This is one of the most intuitive ways to define an arc since you can directly control three points that the arc must pass through. + +**What's happening:** +- We define three points: `startPoint` at `[-5, 0, 0]`, `midPoint` at `[0, 6, 0]`, and `endPoint` at `[5, 0, 0]` +- The arc starts at the first point, curves through the middle point, and ends at the third point +- OCCT automatically calculates the circular arc that best fits these three points +- The middle point determines how much the arc curves - higher Y values create more pronounced curves + +**Key concepts:** +- **Three-Point Definition**: The arc is uniquely defined by exactly three non-collinear points +- **Curve Direction**: The order of points matters - the arc flows from start to middle to end +- **Geometric Constraint**: The three points cannot be in a straight line (collinear) as this wouldn't define a unique arc + + + + + + + + startPointvecEndPtendPointvectorstartPoint-500vecEndPt-230endPoint500vectorstartPointvecEndPtstartPointvectorendPointstartPointvecEndPtendPointstartPointvecEndPt","version":"0.20.7","type":"blockly"}} + title="Arc edge from two points and tangent" + /> + + + {\n // Create start and end points\n const startPoint: Point3 = [-5, 0, 0];\n const vecEndPt: Point3 = [-2, 3, 0];\n const endPoint: Point3 = [5, 0, 0];\n\n // Create tangent vector\n const vecOpt = new TwoVectorsDto();\n vecOpt.first = startPoint;\n vecOpt.second = vecEndPt;\n const vector = bitbybit.vector.sub(vecOpt) as Vector3;\n\n // Create an arc\n const arcOptions = new ArcEdgeTwoPointsTangentDto();\n arcOptions.start = startPoint;\n arcOptions.tangentVec = vector;\n arcOptions.end = endPoint;\n\n const arc = await bitbybit.occt.shapes.edge.arcThroughTwoPointsAndTangent(arcOptions);\n\n // Draw the arc, points and tangent\n bitbybit.draw.drawAnyAsync({ entity: arc });\n bitbybit.draw.drawAnyAsync({ entity: [startPoint, vecEndPt, endPoint] });\n\n // When two points are provided Bitbybit draws them as a line segment\n bitbybit.draw.drawAnyAsync({ entity: [startPoint, vecEndPt] });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Arc edge from two points and tangent" + /> + + + +## Arc From Two Points and Tangent + +This example demonstrates creating an arc using two endpoints and a tangent vector that controls the arc's curvature at the start point. This method gives you precise control over both the arc's endpoints and its initial direction. + +**What's happening:** +- We define two endpoints: `startPoint` at `[-5, 0, 0]` and `endPoint` at `[5, 0, 0]` +- We create a tangent vector by subtracting two points: from `startPoint` to `vecEndPt` at `[-2, 3, 0]` +- This tangent vector controls how the arc curves away from the start point +- The arc begins at the start point, follows the tangent direction initially, then curves to reach the end point + +**Key concepts:** +- **Tangent Vector**: Defines the direction the arc travels when leaving the start point +- **Vector Calculation**: We calculate the tangent by finding the direction from one point to another +- **Curvature Control**: The tangent vector's direction and magnitude influence how sharply the arc curves +- **Helper Visualization**: The example draws additional lines to show the tangent direction and reference points + + + + + + + + circlestartPointendPointcenterPointarccircle5000010startPoint800endPoint808centerPoint000arccirclestartPointendPointTRUEarccenterPointstartPointcenterPointendPointstartPointcenterPointendPoint","version":"0.20.7","type":"blockly"}} + title="Arc edge from circle and two points" + /> + + + {\n // Create a circle edge\n const circleOptions = new CircleDto();\n circleOptions.radius = 5;\n circleOptions.center = [0, 0, 0] as Point3;\n circleOptions.direction = [0, 1, 0] as Vector3;\n\n const circle = await bitbybit.occt.shapes.edge.createCircleEdge(circleOptions);\n\n // Create start and end points for the arc\n const startPoint: Point3 = [8, 0, 0];\n const endPoint: Point3 = [8, 0, 8];\n const centerPoint: Point3 = [0, 0, 0];\n\n // Create arc from circle and two points\n const arcOptions = new ArcEdgeCircleTwoPointsDto();\n arcOptions.circle = circle;\n arcOptions.start = startPoint;\n arcOptions.end = endPoint;\n arcOptions.sense = true;\n\n const arc = await bitbybit.occt.shapes.edge.arcFromCircleAndTwoPoints(arcOptions);\n // Draw the arc and helper points\n bitbybit.draw.drawAnyAsync({ entity: arc });\n bitbybit.draw.drawAnyAsync({ entity: [endPoint, centerPoint, startPoint] });\n bitbybit.draw.drawAnyAsync({ entity: [centerPoint, endPoint] });\n bitbybit.draw.drawAnyAsync({ entity: [centerPoint, startPoint] });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Arc edge from circle and two points" + /> + + + +## Arc From Circle and Two Points + +This example shows how to create an arc by extracting a portion of an existing circle edge between two specified points. This method is useful when you want to create an arc that follows a specific circular path. + +**What's happening:** +- First, we create a complete circle edge with radius 5, centered at the origin +- We define two points: `startPoint` at `[8, 0, 0]` and `endPoint` at `[8, 0, 8]` +- The system finds where these points would intersect the circle (projected onto the circle if needed) +- An arc is created along the circle's circumference between these two intersection points +- Helper lines are drawn to visualize the relationship between the center and the arc endpoints + +**Key concepts:** +- **Base Circle**: The arc follows the exact curvature of the parent circle +- **Point Projection**: Points are projected onto the circle to find valid start/end positions +- **Arc Direction**: The `sense` parameter controls whether the arc goes clockwise or counterclockwise +- **Geometric Relationship**: The resulting arc maintains the same radius and center as the original circle + + + + + + + + 500001045270TRUE","version":"0.20.7","type":"blockly"}} + title="Arc edge from circle and two points" + /> + + + {\n // Create a circle edge\n const circleOptions = new CircleDto();\n circleOptions.radius = 5;\n circleOptions.center = [0, 0, 0] as Point3;\n circleOptions.direction = [0, 1, 0] as Vector3;\n\n const circle = await bitbybit.occt.shapes.edge.createCircleEdge(circleOptions);\n\n // Create arc from circle and two angles\n const arcOptions = new ArcEdgeCircleTwoAnglesDto();\n arcOptions.circle = circle;\n arcOptions.alphaAngle1 = 45;\n arcOptions.alphaAngle2 = 270;\n arcOptions.sense = true;\n\n const arc = await bitbybit.occt.shapes.edge.arcFromCircleAndTwoAngles(arcOptions);\n\n // Draw the arc\n bitbybit.draw.drawAnyAsync({ entity: arc });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Arc edge from circle and two angles" + /> + + + +## Arc From Circle and Two Angles + +This example demonstrates creating an arc by specifying a base circle and two angular positions. This method provides precise control over the arc's span using angle measurements. + +**What's happening:** +- We start with a circle edge (radius 5, centered at origin) +- Two angles are specified: `alphaAngle1` at 45° and `alphaAngle2` at 270° +- The arc is created between these two angular positions on the circle +- The result is a portion of the circle spanning from 45° to 270° (a 225° arc) + +**Key concepts:** +- **Angular Definition**: Angles are measured in degrees from a reference direction (typically the positive X-axis) +- **Arc Span**: The difference between the two angles determines how much of the circle becomes the arc +- **Direction Control**: The `sense` parameter determines if the arc goes from angle1 to angle2 or the other way +- **Precise Control**: This method is ideal when you know exactly what angular portion of a circle you need + + + + + + + + circlepointcenterPointarccircle5000010point808centerPoint000arccirclepoint360TRUEarccenterPointpointcenterPointpoint","version":"0.20.7","type":"blockly"}} + title="Arc edge from circle point and an angle" + /> + + + {\n // Create a circle edge\n const circleOptions = new CircleDto();\n circleOptions.radius = 5;\n circleOptions.center = [0, 0, 0] as Point3;\n circleOptions.direction = [0, 1, 0] as Vector3;\n\n const circle = await bitbybit.occt.shapes.edge.createCircleEdge(circleOptions);\n\n // Create a point on the circle\n const point: Point3 = [8, 0, 8];\n const centerPoint: Point3 = [0, 0, 0];\n\n // Create arc from circle, point and angle\n const arcOptions = new ArcEdgeCirclePointAngleDto();\n arcOptions.circle = circle;\n arcOptions.point = point;\n arcOptions.alphaAngle = 360;\n arcOptions.sense = true;\n\n const arc = await bitbybit.occt.shapes.edge.arcFromCirclePointAndAngle(arcOptions);\n\n // Draw the arc and helper elements\n bitbybit.draw.drawAnyAsync({ entity: arc });\n bitbybit.draw.drawAnyAsync({ entity: [centerPoint, point] });\n bitbybit.draw.drawAnyAsync({ entity: [centerPoint] });\n bitbybit.draw.drawAnyAsync({ entity: [point] });\n\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Arc edge from circle point and an angle" + /> + + + +## Arc From Circle, Point and Angle + +This example shows how to create an arc starting from a specific point on a circle and extending through a specified angular distance. This method combines point-based positioning with angular measurement. + +**What's happening:** +- We create a base circle (radius 5, centered at origin) +- A starting point is defined at `[8, 0, 8]` which gets projected onto the circle +- An angle of 360° is specified, creating a complete circular arc (full circle) +- The arc begins at the projected point location and sweeps through the specified angle +- Helper elements show the center point, the reference point, and connecting lines + +**Key concepts:** +- **Point Projection**: The specified point is projected onto the circle to find the actual start position +- **Angular Sweep**: The angle determines how far around the circle the arc extends +- **Complete Circle**: A 360° angle creates a full circular arc, essentially recreating the original circle +- **Starting Position**: Unlike other methods, this gives you control over exactly where on the circle the arc begins + + + + + + + + 5000010","version":"0.20.7","type":"blockly"}} + title="Circle edge" + /> + + + {\n // Create a circle edge\n const circleOptions = new CircleDto();\n circleOptions.radius = 5;\n circleOptions.center = [0, 0, 0] as Point3;\n circleOptions.direction = [0, 1, 0] as Vector3;\n\n const circle = await bitbybit.occt.shapes.edge.createCircleEdge(circleOptions);\n\n // Draw the circle\n bitbybit.draw.drawAnyAsync({ entity: circle });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Circle edge" + /> + + + +## Circle Edge + +This example demonstrates creating a complete circular edge, which is one of the most fundamental curved primitives in 3D modeling. A circle edge represents a perfect circular boundary that can be used as a standalone geometry or as part of more complex shapes. + +**What's happening:** +- We define a circle with radius 5 units, centered at the origin `[0, 0, 0]` +- The direction vector `[0, 1, 0]` specifies that the circle lies in a plane perpendicular to the Y-axis (horizontal plane) +- The `CircleDto` object packages all the circle parameters for the OCCT creation function +- The result is a complete circular edge that forms a closed loop + +**Key concepts:** +- **Radius**: Determines the size of the circle (distance from center to edge) +- **Center Point**: The position in 3D space where the circle is located +- **Direction Vector**: Defines the orientation of the plane containing the circle +- **Closed Curve**: A circle is a closed curve, meaning it has no start or end points + + + + + + + + 000010310","version":"0.20.7","type":"blockly"}} + title="Ellipse edge" + /> + + + {\n // Create an ellipse edge\n const ellipseOptions = new EllipseDto();\n ellipseOptions.center = [0, 0, 0] as Point3;\n ellipseOptions.direction = [0, 1, 0] as Vector3;\n ellipseOptions.radiusMinor = 3;\n ellipseOptions.radiusMajor = 10;\n\n const ellipse = await bitbybit.occt.shapes.edge.createEllipseEdge(ellipseOptions);\n\n // Draw the ellipse\n bitbybit.draw.drawAnyAsync({ entity: ellipse });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Ellipse edge" + /> + + + +## Ellipse Edge + +This example demonstrates creating an elliptical edge, which is an oval-shaped curve that extends the concept of a circle to have two different radii. Ellipses are commonly used in technical drawings and 3D modeling for creating elongated circular shapes. + +**What's happening:** +- We define an ellipse centered at the origin `[0, 0, 0]` +- The direction vector `[0, 1, 0]` specifies the orientation plane (horizontal, like the circle) +- Two radii are specified: `radiusMinor` = 3 (shorter radius) and `radiusMajor` = 10 (longer radius) +- The result is an oval shape that is 20 units wide and 6 units tall +- The `EllipseDto` object packages all parameters for the OCCT creation function + +**Key concepts:** +- **Major Radius**: The longer radius that defines the ellipse's widest dimension +- **Minor Radius**: The shorter radius that defines the ellipse's narrower dimension +- **Aspect Ratio**: The relationship between major and minor radii determines how "stretched" the ellipse appears +- **Closed Curve**: Like a circle, an ellipse is a closed curve with no endpoints +- **Geometric Relationship**: When major and minor radii are equal, the ellipse becomes a perfect circle From e41ef4f858b4f0f979f8741ece4fd4e6b7b01814 Mon Sep 17 00:00:00 2001 From: Matas Ubarevicius Date: Wed, 8 Oct 2025 16:48:39 +0300 Subject: [PATCH 07/11] edge constraints examples --- .../occt/shapes/edge/edge-constraints.md | 214 ++++++++++++++++++ 1 file changed, 214 insertions(+) create mode 100644 docs/learn/code/common/occt/shapes/edge/edge-constraints.md diff --git a/docs/learn/code/common/occt/shapes/edge/edge-constraints.md b/docs/learn/code/common/occt/shapes/edge/edge-constraints.md new file mode 100644 index 00000000..04c9cc75 --- /dev/null +++ b/docs/learn/code/common/occt/shapes/edge/edge-constraints.md @@ -0,0 +1,214 @@ +--- +sidebar_position: 4 +title: "Edge Constraints" +sidebar_label: Edge Constraints +description: Learn +tags: [occt] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +# Edge Constraints + +OCCT category icon with a stylized logo representation + +Edge constraints in OCCT (Open CASCADE Technology) provide powerful geometric constraint solving capabilities for creating tangent lines and circles based on existing geometric entities. These operations are essential for parametric modeling, geometric construction, and constraint-based design workflows. + +## Overview + +Edge constraints help you create geometry that follows specific rules or relationships with existing shapes. Think of them as intelligent drawing tools that automatically calculate where new lines or circles should be placed to maintain tangent relationships with your existing geometry. + +The system offers five main constraint operations that solve common geometric problems. You can create tangent lines between points and circles, tangent lines between two circles, and even tangent circles that touch existing circles or points. Each operation automatically calculates the mathematically correct positions and orientations. + +## Understanding the Examples + +Each constraint operation is demonstrated using three different programming approaches. The Rete interface lets you build constraint solutions visually by connecting nodes. Blockly provides a block-based approach that's great for learning the logical flow. TypeScript gives you direct code control for advanced customization and integration into larger projects. + +All examples use similar patterns - they create the base geometry (circles and points), set up the constraint parameters, execute the constraint operation, and then display the results. The constraint functions handle all the complex mathematical calculations automatically. + +## Working with Tolerance and Precision + +Most constraint operations include a tolerance setting that controls how precisely the calculations are performed. The default value works well for most situations, but you might need to adjust it when working with very large or very small geometry. Think of tolerance as how "strict" the geometric relationships need to be. + +## Constraint Tangent Lines from Two Points to Circle + +This operation solves a classic geometric problem: given two points and a circle, find the lines that connect both points and are tangent to the circle. The function automatically calculates all possible solutions and returns the tangent lines. + +This is particularly useful in mechanical design when you need to connect two specific locations with smooth curves that don't intersect existing circular features. + + + + + + + circlepoint1point2tangentLinescircle4000010point1007point2909tangentLinescirclepoint1point21e-7'all''none'tangentLinescirclepoint1point2","version":"0.20.7","type":"blockly"}} + title="Constraint tangent lines from two points to circle" + /> + + + {\n // Create a circle edge\n const circleOptions = new CircleDto();\n circleOptions.radius = 4;\n circleOptions.center = [0, 0, 0] as Point3;\n circleOptions.direction = [0, 1, 0] as Vector3;\n\n const circle = await bitbybit.occt.shapes.edge.createCircleEdge(circleOptions);\n\n // Define two points\n const point1: Point3 = [0, 0, 7];\n const point2: Point3 = [9, 0, 9];\n\n // Create constraint options for tangent lines from two points to circle\n const constraintOptions = new ConstraintTanLinesFromTwoPtsToCircleDto();\n constraintOptions.circle = circle;\n constraintOptions.point1 = point1;\n constraintOptions.point2 = point2;\n constraintOptions.tolerance = 1e-7;\n constraintOptions.positionResult = positionResultEnum.all;\n constraintOptions.circleRemainder = circleInclusionEnum.none;\n\n // Create the constraint tangent lines\n const tangentLines = await bitbybit.occt.shapes.edge.constraintTanLinesFromTwoPtsToCircle(constraintOptions);\n\n // Draw the tangent lines\n bitbybit.draw.drawAnyAsync({ entity: tangentLines });\n // Draw the circle\n bitbybit.draw.drawAnyAsync({ entity: circle });\n // Draw the two points\n bitbybit.draw.drawAnyAsync({ entity: [point1] });\n bitbybit.draw.drawAnyAsync({ entity: [point2] });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Constraint tangent lines from two points to circle" + /> + + + + +## Constraint Tangent Lines from Point to Circle + +When you need to draw lines from a single point that just touch a circle without crossing it, this constraint operation provides the solution. It's simpler than the two-point version and automatically finds both possible tangent lines from your point to the circle. + +This operation is commonly used in architectural drawings when you need to create sight lines or in mechanical design for clearance calculations. + + + + + + + circlepointtangentLinescircle4000010point807tangentLinescirclepoint1e-7'all''none'tangentLinescirclepoint","version":"0.20.7","type":"blockly"}} + title="Constraint tangent lines from point to circle" + /> + + + {\n // Create a circle edge\n const circleOptions = new CircleDto();\n circleOptions.radius = 4;\n circleOptions.center = [0, 0, 0] as Point3;\n circleOptions.direction = [0, 1, 0] as Vector3;\n\n const circle = await bitbybit.occt.shapes.edge.createCircleEdge(circleOptions);\n\n // Define a point\n const point: Point3 = [8, 0, 7];\n\n // Create constraint options for tangent lines from point to circle\n const constraintOptions = new ConstraintTanLinesFromPtToCircleDto();\n constraintOptions.circle = circle;\n constraintOptions.point = point;\n constraintOptions.tolerance = 1e-7;\n constraintOptions.positionResult = positionResultEnum.all;\n constraintOptions.circleRemainder = circleInclusionEnum.none;\n\n // Create the constraint tangent lines\n const tangentLines = await bitbybit.occt.shapes.edge.constraintTanLinesFromPtToCircle(constraintOptions);\n\n // Draw the tangent lines\n bitbybit.draw.drawAnyAsync({ entity: tangentLines });\n // Draw the circle\n bitbybit.draw.drawAnyAsync({ entity: circle });\n // Draw the point\n bitbybit.draw.drawAnyAsync({ entity: point });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Constraint tangent lines from point to circle" + /> + + + +## Constraint Tangent Lines on Two Circles + +This operation finds all the lines that touch two circles without crossing them. Depending on how the circles are positioned relative to each other, you might get external tangent lines (that don't pass between the circles) or internal tangent lines (that cross between them). + +This is especially valuable in gear design, pulley systems, or any mechanical application where you need smooth transitions between circular components. + + + + + + + circle1circle2tangentLinescircle13000010circle22700010tangentLinescircle1circle21e-7'all''none'tangentLinescircle1circle2","version":"0.20.7","type":"blockly"}} + title="Constraint tangent lines on two circles" + /> + + + {\n // Create first circle edge\n const circle1Options = new CircleDto();\n circle1Options.radius = 3;\n circle1Options.center = [0, 0, 0] as Point3;\n circle1Options.direction = [0, 1, 0] as Vector3;\n\n const circle1 = await bitbybit.occt.shapes.edge.createCircleEdge(circle1Options);\n\n // Create second circle edge\n const circle2Options = new CircleDto();\n circle2Options.radius = 2;\n circle2Options.center = [7, 0, 0] as Point3;\n circle2Options.direction = [0, 1, 0] as Vector3;\n\n const circle2 = await bitbybit.occt.shapes.edge.createCircleEdge(circle2Options);\n\n // Create constraint options for tangent lines between two circles\n const constraintOptions = new ConstraintTanLinesOnTwoCirclesDto();\n constraintOptions.circle1 = circle1;\n constraintOptions.circle2 = circle2;\n constraintOptions.tolerance = 1e-7;\n constraintOptions.positionResult = positionResultEnum.all;\n constraintOptions.circleRemainders = twoCircleInclusionEnum.none;\n\n // Create the constraint tangent lines\n const tangentLines = await bitbybit.occt.shapes.edge.constraintTanLinesOnTwoCircles(constraintOptions);\n\n // Draw the tangent lines\n bitbybit.draw.drawAnyAsync({ entity: tangentLines });\n // Draw the first circle\n bitbybit.draw.drawAnyAsync({ entity: circle1 });\n // Draw the second circle\n bitbybit.draw.drawAnyAsync({ entity: circle2 });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Constraint tangent lines on two circles" + /> + + + + +## Constraint Tangent Circles on Two Circles + +Sometimes you need to create circles that touch two existing circles. This operation calculates where to place new circles of a specified size so they're tangent to both input circles. You control the radius of the new circles, and the system figures out all the valid positions. + +This is particularly useful for creating buffer zones around existing circular features or for designing complex mechanical linkages where multiple circular components need to interact smoothly. + + + + + + + circle1circle2tangentCirclescircle13000010circle21.5500010tangentCirclescircle1circle21e-70.8tangentCirclescircle1circle2","version":"0.20.7","type":"blockly"}} + title="Constraint tangent circles on two circles" + /> + + + {\n // Create first circle edge\n const circle1Options = new CircleDto();\n circle1Options.radius = 3;\n circle1Options.center = [0, 0, 0] as Point3;\n circle1Options.direction = [0, 1, 0] as Vector3;\n\n const circle1 = await bitbybit.occt.shapes.edge.createCircleEdge(circle1Options);\n\n // Create second circle edge\n const circle2Options = new CircleDto();\n circle2Options.radius = 1.5;\n circle2Options.center = [5, 0, 0] as Point3;\n circle2Options.direction = [0, 1, 0] as Vector3;\n\n const circle2 = await bitbybit.occt.shapes.edge.createCircleEdge(circle2Options);\n\n // Create constraint options for tangent circles between two circles\n const constraintOptions = new ConstraintTanCirclesOnTwoCirclesDto();\n constraintOptions.circle1 = circle1;\n constraintOptions.circle2 = circle2;\n constraintOptions.tolerance = 1e-7;\n constraintOptions.radius = 0.8;\n\n // Create the constraint tangent circles\n const tangentCircles = await bitbybit.occt.shapes.edge.constraintTanCirclesOnTwoCircles(constraintOptions);\n\n // Draw the tangent circles\n bitbybit.draw.drawAnyAsync({ entity: tangentCircles });\n // Draw the first circle\n bitbybit.draw.drawAnyAsync({ entity: circle1 });\n // Draw the second circle\n bitbybit.draw.drawAnyAsync({ entity: circle2 });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Constraint tangent circles on two circles" + /> + + + + +## Constraint Tangent Circles on Circle and Point + +This operation creates circles that touch an existing circle and are positioned relative to a specific point. The new circles will be tangent to your input circle and either pass through the point or maintain a specific relationship with it, depending on the radius you specify. + +This constraint is perfect for creating rounded transitions in designs where you need a smooth connection between a circular feature and a specific location in your model. + + + + + + + circlepointtangentCirclescircle3000010point400tangentCirclescirclepoint1e-72tangentCirclescirclepoint","version":"0.20.7","type":"blockly"}} + title="Constraint tangent circles on circle and point" + /> + + + {\n // Create a circle edge\n const circleOptions = new CircleDto();\n circleOptions.radius = 3;\n circleOptions.center = [0, 0, 0] as Point3;\n circleOptions.direction = [0, 1, 0] as Vector3;\n\n const circle = await bitbybit.occt.shapes.edge.createCircleEdge(circleOptions);\n\n // Define a point\n const point: Point3 = [4, 0, 0];\n\n // Create constraint options for tangent circles between circle and point\n const constraintOptions = new ConstraintTanCirclesOnCircleAndPntDto();\n constraintOptions.circle = circle;\n constraintOptions.point = point;\n constraintOptions.tolerance = 1e-7;\n constraintOptions.radius = 2;\n\n // Create the constraint tangent circles\n const tangentCircles = await bitbybit.occt.shapes.edge.constraintTanCirclesOnCircleAndPnt(constraintOptions);\n\n // Draw the tangent circles\n bitbybit.draw.drawAnyAsync({ entity: tangentCircles });\n // Draw the circle\n bitbybit.draw.drawAnyAsync({ entity: circle });\n // Draw the point\n bitbybit.draw.drawAnyAsync({ entity: point });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Constraint tangent circles on circle and point" + /> + + + +## Getting the Best Results + +### Working with Precision +The default precision settings work well for most projects. If you're working with very large structures like buildings, you might want to be a bit less strict with the precision. For tiny, detailed mechanical parts, you might need more precision. Think of it like adjusting the zoom level on your calculations. + +### Choosing Which Solutions to Keep +Many constraint operations find multiple valid solutions. You can ask for all of them to see your options, or specify that you only want the first or second solution if you know which arrangement you prefer. This is especially helpful when you're building parametric models where consistency matters. + +### Understanding Circle Splitting +Some operations can optionally split your input circles at the points where the tangent lines touch them. This creates separate circle segments that you can use for other operations. Most of the time you won't need this feature, but it's there when you do. + +### Sizing Tangent Circles +When creating tangent circles, start with smaller sizes to understand how the geometry behaves. You can always increase the radius once you see how the circles position themselves. Very large circles might not have valid tangent solutions depending on your input geometry. + +### Real-World Applications +These constraint operations solve problems that come up frequently in design work. Architects use them for creating smooth transitions in floor plans. Mechanical engineers use them for designing gear systems and smooth mechanical linkages. Even in artistic applications, they help create flowing, mathematically precise curves and connections. + +### Performance Tips +Constraint calculations can take some time with complex geometry. It's a good idea to test your setup with simple shapes first, then apply the same approach to your full model. This helps you catch any setup issues early and ensures your final results will be what you expect. + +## Building Complete Workflows + +Think of edge constraints as one tool in a larger toolkit. They excel at solving specific geometric relationship problems, and they integrate seamlessly with other modeling operations to help you build exactly what you envision. The mathematical precision they provide becomes the foundation for reliable, parametric design workflows in BitByBit. From 57ac8cc3ce609f61f22af6f7726bb405af6f7ca4 Mon Sep 17 00:00:00 2001 From: Matas Ubarevicius Date: Wed, 8 Oct 2025 20:22:58 +0300 Subject: [PATCH 08/11] hexagon wire docs --- .../code/common/occt/shapes/wire/intro.md | 2 +- .../wire/wire-hexagons-advanced-pattern.md | 145 ++++++++++++++++++ .../occt/shapes/wire/wire-hexagons-in-grid.md | 81 ++++++++++ 3 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 docs/learn/code/common/occt/shapes/wire/wire-hexagons-advanced-pattern.md create mode 100644 docs/learn/code/common/occt/shapes/wire/wire-hexagons-in-grid.md diff --git a/docs/learn/code/common/occt/shapes/wire/intro.md b/docs/learn/code/common/occt/shapes/wire/intro.md index c5e60793..e5aa8162 100644 --- a/docs/learn/code/common/occt/shapes/wire/intro.md +++ b/docs/learn/code/common/occt/shapes/wire/intro.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 1 title: "Working with Wires in OCCT" sidebar_label: Intro Wires description: Learn about OCCT wires, how to create them from edges or points (polylines, splines, Bezier curves), their role in constructing faces, and how faces can have multiple wires (e.g., for holes). diff --git a/docs/learn/code/common/occt/shapes/wire/wire-hexagons-advanced-pattern.md b/docs/learn/code/common/occt/shapes/wire/wire-hexagons-advanced-pattern.md new file mode 100644 index 00000000..746c01f5 --- /dev/null +++ b/docs/learn/code/common/occt/shapes/wire/wire-hexagons-advanced-pattern.md @@ -0,0 +1,145 @@ +--- +sidebar_position: 3 +title: Hexagons Advanced Pattern +sidebar_label: Hexagons Advanced Pattern +description: Learn how to use advanced hexagon pattern parameters to create intricate designs. +tags: [code, occt, rete, blockly, typescript] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +# Advanced Pattern Creation with Distance-Based Scaling + +OCCT category icon with a stylized logo representation + + +This advanced example demonstrates how to create sophisticated hexagonal patterns by combining multiple BitByBit components. The technique uses distance calculations to create organic, gradient-like effects that transition smoothly across the hexagonal grid. + +The process begins by generating a reference hexagon grid using `point.hexGridScaledToFit` to obtain the center points of each hexagon position. These center points become the foundation for our distance-based pattern calculation. + +A control point is established in 3D space, and the system calculates the distance from this point to every hexagon center. These distances are then remapped from their natural range to a scale factor range between 0.111 and 0.999, creating a smooth gradient effect that radiates outward from the control point. + +The remapped distance values serve as scaling factors applied to each hexagon through the `scalePatternWidth` and `scalePatternHeight` parameters. This creates hexagons that grow and shrink based on their proximity to the control point, generating organic, wave-like patterns that feel naturally integrated with the underlying grid structure. + +An additional `inclusionPattern` array selectively removes certain hexagons from the grid, creating rhythmic openings that add visual complexity and can serve functional purposes in architectural or design applications. The pattern `[true, true, false]` creates a regular removal pattern that repeats across the entire grid. + +This approach demonstrates the power of parametric design thinking, where simple distance relationships generate complex visual outcomes. By adjusting the control point position, remapping ranges, or inclusion patterns, you can create infinite variations while maintaining the underlying hexagonal structure. + + + + + + + gridWidthgridHeighthexagonsInWidthhexagonsInHeightcontrolPointXcontrolPointZcontrolPointhexGridhexCentersdistancesminDistancemaxDistancescalePatternidistancescaledValueinclusionPatternhexagonWiresboundaryWiregridWidth16.5gridHeight9hexagonsInWidth20hexagonsInHeight20controlPointX2.2controlPointZ2.8controlPointcontrolPointX0controlPointZhexGridgridWidthgridHeighthexagonsInWidthhexagonsInHeightTRUEFALSEFALSEFALSEFALSETRUETRUEhexCentershexGridcentersdistancescontrolPointhexCentersminDistancedistancesmaxDistancedistancesscalePatterndistancedistancesscaledValuedistanceminDistancemaxDistance0.1110.999INSERTLASTscalePatternscaledValueinclusionPattern[true, true, false]hexagonWiresgridWidthgridHeighthexagonsInWidthhexagonsInHeightTRUEFALSEFALSEFALSEFALSEscalePatternscalePatterninclusionPatternboundaryWiregridWidthgridHeight000010hexagonWiresboundaryWirecontrolPoint","version":"0.20.7","type":"blockly"}} + title="Creating hexagon grids in beautiful patterns" + /> + + + {\n // Define grid dimensions\n const gridWidth = 16.5;\n const gridHeight = 9;\n const hexagonsInWidth = 20;\n const hexagonsInHeight = 20;\n\n // Control point for distance calculation\n const controlPointX = 2.2;\n const controlPointZ = 2.8;\n const controlPoint: Point3 = [controlPointX, 0, controlPointZ];\n\n // Generate hex grid to get center points\n const hexGridOptions = new HexGridScaledToFitDto();\n hexGridOptions.width = gridWidth;\n hexGridOptions.height = gridHeight;\n hexGridOptions.nrHexagonsInWidth = hexagonsInWidth;\n hexGridOptions.nrHexagonsInHeight = hexagonsInHeight;\n hexGridOptions.flatTop = true;\n hexGridOptions.extendTop = false;\n hexGridOptions.extendBottom = false;\n hexGridOptions.extendLeft = false;\n hexGridOptions.extendRight = false;\n hexGridOptions.centerGrid = true;\n hexGridOptions.pointsOnGround = true;\n\n const hexGrid: HexGridData = bitbybit.point.hexGridScaledToFit(hexGridOptions);\n const hexCenters = hexGrid.centers;\n\n // Calculate distances from control point to all hex centers\n const distanceOptions = new StartEndPointsListDto();\n distanceOptions.startPoint = controlPoint;\n distanceOptions.endPoints = hexCenters;\n\n const distances = bitbybit.point.distancesToPoints(distanceOptions);\n\n // Find min and max distances for remapping\n const minDistance = bitbybit.vector.min({ vector: distances });\n const maxDistance = bitbybit.vector.max({ vector: distances });\n\n // Remap distances to scale values between 0.111 and 0.999\n const scalePattern: number[] = [];\n\n for (const distance of distances) {\n const remapOptions = new RemapNumberDto();\n remapOptions.number = distance;\n remapOptions.fromLow = minDistance;\n remapOptions.fromHigh = maxDistance;\n remapOptions.toLow = 0.111;\n remapOptions.toHigh = 0.999;\n\n const scaledValue = bitbybit.math.remap(remapOptions);\n scalePattern.push(scaledValue);\n }\n\n // Create hexagonal grid with patterns\n const hexGridPatternOptions = new HexagonsInGridDto();\n hexGridPatternOptions.width = gridWidth;\n hexGridPatternOptions.height = gridHeight;\n hexGridPatternOptions.nrHexagonsInWidth = hexagonsInWidth;\n hexGridPatternOptions.nrHexagonsInHeight = hexagonsInHeight;\n hexGridPatternOptions.flatTop = true;\n hexGridPatternOptions.extendTop = false;\n hexGridPatternOptions.extendBottom = false;\n hexGridPatternOptions.extendLeft = false;\n hexGridPatternOptions.extendRight = false;\n\n // Apply the distance-based scale pattern to both width and height\n hexGridPatternOptions.scalePatternWidth = scalePattern;\n hexGridPatternOptions.scalePatternHeight = scalePattern;\n\n // Apply inclusion pattern to selectively remove some hexagons\n const inclusionPattern = [true, true, false]; // Pattern repeats across the grid\n hexGridPatternOptions.inclusionPattern = inclusionPattern;\n\n // Generate the patterned hexagon grid\n const hexagonWires = await bitbybit.occt.shapes.wire.hexagonsInGrid(hexGridPatternOptions);\n\n // Create a boundary rectangle for reference\n const boundaryOptions = new RectangleDto();\n boundaryOptions.width = gridWidth;\n boundaryOptions.length = gridHeight;\n boundaryOptions.center = [0, 0, 0] as Point3;\n boundaryOptions.direction = [0, 1, 0] as Vector3;\n\n const boundaryWire = await bitbybit.occt.shapes.wire.createRectangleWire(boundaryOptions);\n\n // Draw the patterned hexagon grid and boundary\n bitbybit.draw.drawAnyAsync({ entity: hexagonWires });\n bitbybit.draw.drawAnyAsync({ entity: boundaryWire });\n\n // Optionally draw the control point for reference\n bitbybit.draw.drawAnyAsync({ entity: controlPoint });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating hexagon grids" + /> + + + +## Understanding the Advanced Implementation + +This sophisticated example demonstrates the power of parametric design by combining multiple BitByBit components to create complex, data-driven patterns. The implementation showcases several key concepts that make parametric design so powerful for creating dynamic, responsive geometries. + +### The Parametric Design Philosophy + +Parametric design fundamentally changes how we approach geometric creation by defining relationships rather than manually placing each element. This approach creates intelligent systems where changing grid dimensions automatically adapts the entire pattern while preserving all underlying relationships. The control point can be repositioned to organically reorganize the pattern around a new focus, while mathematical foundations ensure consistency across any scale or parameter variation. + +### Phase-by-Phase Implementation Analysis + +#### Phase 1: Foundation Grid Generation + +The implementation begins by creating a reference hexagonal grid using `point.hexGridScaledToFit`. This crucial step establishes the coordinate framework that drives the entire pattern: + +```typescript +const hexGrid: HexGridData = bitbybit.point.hexGridScaledToFit(hexGridOptions); +const hexCenters = hexGrid.centers; +``` + +This generates not just the hexagon positions, but a complete data structure containing center points, boundary information, and geometric relationships. The `centers` array becomes our **geometric database** - each point represents a potential hexagon location with its own coordinate identity. + +#### Phase 2: Distance Field Calculation + +The breakthrough moment comes when we calculate distances from a control point to every hexagon center: + +```typescript +const distances = bitbybit.point.distancesToPoints(distanceOptions); +``` + +This creates what computational designers call a **distance field** - a mathematical landscape where every point has a value representing its proximity to our control point. This field becomes the foundation for all subsequent pattern variations. + +The beauty of distance fields lies in their smooth, continuous nature. Adjacent hexagons have similar distance values, creating natural gradients that feel organic rather than mechanical. + +#### Phase 3: Mathematical Transformation + +The raw distance values are then remapped to useful scale factors: + +```typescript +const remapOptions = new RemapNumberDto(); +remapOptions.fromLow = minDistance; +remapOptions.fromHigh = maxDistance; +remapOptions.toLow = 0.111; +remapOptions.toHigh = 0.999; +``` + +The remapping operation transforms raw distance values into a proportional response system. The closest hexagon receives maximum scaling (0.999), the furthest receives minimum scaling (0.111), and all intermediate hexagons get proportionally scaled values. The 0.111 to 0.999 range ensures visible variation while maintaining structural integrity. + +#### Phase 4: Pattern Application and Selective Filtering + +The final phase applies multiple pattern layers simultaneously: + +```typescript +hexGridPatternOptions.scalePatternWidth = scalePattern; +hexGridPatternOptions.scalePatternHeight = scalePattern; +hexGridPatternOptions.inclusionPattern = inclusionPattern; +``` + +The final phase applies multiple pattern layers simultaneously. Scale patterns create size variation based on distance relationships, inclusion patterns create rhythmic openings through selective removal, and uniform application to both width and height maintains hexagon proportions. The `[true, true, false]` inclusion pattern creates a tertiary rhythm where two hexagons appear followed by one removal, adding visual breathing space and structural variety. + +### The Power of Parametric Relationships + +This implementation demonstrates several fundamental parametric design principles: + +#### 1. **Emergent Complexity from Simple Rules** + +The complex final pattern emerges from simple mathematical relationships: distance calculation using Euclidean geometry, linear remapping through basic algebra, and pattern repetition via modular arithmetic. These simple rules combine to create visually sophisticated, naturally flowing patterns that would be extremely difficult to design manually. + +#### 2. **Responsive Design Systems** + +Every element in the pattern responds intelligently to changes in the control point position. Moving the control point automatically recalculates distance fields, adjusts scale patterns to new proximity relationships, shifts visual focus organically to the new location, and maintains overall pattern coherence. This responsiveness makes the design system understand relationships rather than just storing static positions. + +#### 3. **Scalable Complexity** + +The same algorithm works equally well for 5×5 grids or 50×50 grids, multiple control points through superposition of distance fields, different geometric shapes like triangular or circular grids, and various mathematical transformations including exponential, logarithmic, or custom functions. + +#### 4. **Predictable Variation** + +While the patterns appear organic and natural, they're completely **predictable** and **reproducible**. The same parameters always generate the same result, making the system reliable for design development while maintaining the ability to create infinite variations through parameter adjustment. + +### Real-World Applications + +This parametric approach has profound applications across multiple design disciplines. In architecture, building façades can respond to solar orientation by creating denser shading where sun exposure is highest. Product designers can create material distribution patterns that concentrate strength where structural loads are greatest. Interior designers can develop ceiling or wall patterns that create visual focus around specific areas or circulation paths. + +### Advanced Parametric Possibilities + +This example opens the door to even more sophisticated parametric explorations. Multiple control points can create complex interference patterns through superimposed distance fields. Environmental sensors can drive control points to make patterns respond to temperature, sound, or occupancy. Scale factors can control material properties like transparency, color, or structural thickness beyond just size. The same distance-based logic can drive rotation, translation, or complex geometric transformations. + +The power of this parametric approach lies not just in creating beautiful patterns, but in establishing **intelligent design systems** that can adapt, respond, and evolve while maintaining their underlying organizational logic. This represents a fundamental shift from static design to dynamic, responsive geometry that can grow and change while preserving its essential character. diff --git a/docs/learn/code/common/occt/shapes/wire/wire-hexagons-in-grid.md b/docs/learn/code/common/occt/shapes/wire/wire-hexagons-in-grid.md new file mode 100644 index 00000000..2c3a6b4a --- /dev/null +++ b/docs/learn/code/common/occt/shapes/wire/wire-hexagons-in-grid.md @@ -0,0 +1,81 @@ +--- +sidebar_position: 2 +title: Hexagons Grid +sidebar_label: Hexagons Grid +description: Learn how to create wire based hexagon grids +tags: [code, occt, rete, blockly, typescript] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +# Wire Hexagons Grid + +OCCT category icon with a stylized logo representation + +Hexagonal grids are nature's elegant solution for efficient space filling, appearing in honeycombs, molecular structures, and architectural designs. The wire hexagon grid component creates an array of hexagonal wire boundaries that can be used as building blocks for complex geometric patterns and structures. + +## Understanding Hexagon Grid Patterns + +The `hexagonsInGrid` function generates a collection of hexagonal wire shapes arranged in a grid pattern. Unlike simple rectangular grids, hexagonal grids offer unique advantages: they provide optimal packing efficiency, create natural interlocking patterns, and distribute structural forces more evenly across the grid. + +The component works by fitting a specified number of hexagons within defined width and height boundaries. Each hexagon is automatically sized to maintain proper proportions while filling the designated space. This smart scaling ensures that your hexagonal patterns always fit perfectly within their intended boundaries, whether you're designing architectural screens, decorative panels, or structural frameworks. + +## Essential Parameters + +The hexagon grid system offers several key controls that shape how your pattern develops: + +**Dimensional Control** through `width` and `height` parameters defines the overall boundary of your grid area. The system automatically calculates hexagon sizes to fit precisely within these limits. + +**Grid Density** is controlled by `nrHexagonsInWidth` and `nrHexagonsInHeight`, which specify exactly how many hexagons you want across each dimension. Higher numbers create finer, more detailed grids with smaller individual hexagons. + +**Orientation Options** via the `flatTop` parameter fundamentally change how hexagons are oriented. When false (the default), hexagons have pointed tops creating a more dynamic appearance. When true, hexagons sit flat, creating horizontal emphasis that works well for certain architectural applications. + +**Edge Extension** controls allow you to extend the grid beyond its natural boundaries. The `extendTop`, `extendBottom`, `extendLeft`, and `extendRight` parameters can shift the entire grid by half-hexagon increments, helping you align patterns with existing geometry or create specific edge conditions. + +## Pattern Applications + +Wire hexagon grids excel in numerous design scenarios. In architectural work, they create stunning façade patterns, interior screens, and decorative elements that balance visual interest with structural efficiency. The wire format makes them perfect for defining boundaries that can later be filled with solid faces or used as cutting patterns for more complex shapes. + +For parametric design, these grids serve as excellent starting points for creating complex geometric relationships. Each hexagon maintains its proportional relationship to its neighbors, allowing for systematic modifications that preserve the overall pattern integrity while enabling local variations. + +The component also includes advanced patterning capabilities through optional arrays: `scalePatternWidth` and `scalePatternHeight` allow selective sizing of individual hexagons, `filletPattern` can soften corners with varying radii, and `inclusionPattern` lets you selectively remove hexagons to create openings or decorative voids. + + + + + + + widthheightwidth16.5height9widthheight2318FALSEFALSEFALSEFALSEFALSEwidthheight000010","version":"0.20.7","type":"blockly"}} + title="Creating hexagon grids" + /> + + + {\n // Define grid dimensions\n const gridWidth = 16.5;\n const gridHeight = 9;\n const hexagonsInWidth = 23;\n const hexagonsInHeight = 18;\n\n // Create hexagonal grid parameters\n const hexGridOptions = new HexagonsInGridDto();\n hexGridOptions.width = gridWidth;\n hexGridOptions.height = gridHeight;\n hexGridOptions.nrHexagonsInWidth = hexagonsInWidth;\n hexGridOptions.nrHexagonsInHeight = hexagonsInHeight;\n hexGridOptions.flatTop = false; // Pointed-top hexagons\n hexGridOptions.extendTop = false;\n hexGridOptions.extendBottom = false;\n hexGridOptions.extendLeft = false;\n hexGridOptions.extendRight = false;\n\n // Generate the hexagon grid\n const hexagonWires = await bitbybit.occt.shapes.wire.hexagonsInGrid(hexGridOptions);\n\n // Create a boundary rectangle for reference\n const boundaryOptions = new RectangleDto();\n boundaryOptions.width = gridWidth;\n boundaryOptions.length = gridHeight;\n boundaryOptions.center = [0, 0, 0] as Point3;\n boundaryOptions.direction = [0, 1, 0] as Vector3;\n\n const boundaryWire = await bitbybit.occt.shapes.wire.createRectangleWire(boundaryOptions);\n\n // Draw the hexagon grid and boundary\n bitbybit.draw.drawAnyAsync({ entity: hexagonWires });\n bitbybit.draw.drawAnyAsync({ entity: boundaryWire });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating hexagon grids" + /> + + + +## Creating Your First Hexagon Grid + +This example demonstrates the fundamental approach to creating hexagonal wire grids. We start by defining the overall dimensions through `width` and `height` parameters, then specify how many hexagons we want to fit within those boundaries. + +The pattern emerges from the intersection of geometric constraints and design intent. By setting `nrHexagonsInWidth` to 13 and `nrHexagonsInHeight` to 18, we create a fine-grained grid where each hexagon is automatically sized to maintain proper proportions while filling the available space. + +The `flatTop` parameter controls orientation - when set to false, hexagons appear with pointed tops, creating the classic "honeycomb" appearance. The extension parameters remain false, keeping the grid neatly contained within its specified boundaries. + +A boundary rectangle is included for visual reference, helping you understand how the hexagonal pattern relates to its defining dimensions. This rectangle represents the target area that the hexagons fill, demonstrating the precision with which the grid system fits patterns to specified constraints. From 7f30256e8d1acab53db8c2212675ff7eb2364ba8 Mon Sep 17 00:00:00 2001 From: Matas Ubarevicius Date: Wed, 8 Oct 2025 20:37:08 +0300 Subject: [PATCH 09/11] docs wire basic primitives --- .../occt/shapes/wire/wire-basic-primitives.md | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 docs/learn/code/common/occt/shapes/wire/wire-basic-primitives.md diff --git a/docs/learn/code/common/occt/shapes/wire/wire-basic-primitives.md b/docs/learn/code/common/occt/shapes/wire/wire-basic-primitives.md new file mode 100644 index 00000000..fe51f7ec --- /dev/null +++ b/docs/learn/code/common/occt/shapes/wire/wire-basic-primitives.md @@ -0,0 +1,56 @@ +--- +sidebar_position: 1 +title: Wire Basic Primitives +sidebar_label: Wire Basic Primitives +description: Learn how to create basic wire primitives composed out of multiple edges +tags: [code, occt, rete, blockly, typescript] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +OCCT category icon with a stylized logo representation + +# Introduction to OCCT Wire Basic Primitives + +Wires are one-dimensional geometric entities that represent connected sequences of edges forming open or closed curves. OCCT provides several primitive wire types that serve as building blocks for more complex 2D and 3D modeling operations. These wire primitives are commonly used to create profiles for extrusion, sweeping, and other advanced geometric operations. + +This example demonstrates the creation of the most common primitive wire types: + +- **Circle Wire**: A circular wire with specified radius and center +- **Square Wire**: A square-shaped wire with specified size and center +- **NGon Wire**: A regular polygon wire with specified number of corners +- **Parallelogram Wire**: A parallelogram-shaped wire with width, height, and angle +- **Rectangle Wire**: A rectangular wire with specified width and length +- **Ellipse Wire**: An elliptical wire with major and minor radii + + + + + + + circleWiresquareWirengonWireparallelogramWirerectangleWireellipseWirecircleWire3000010squareWire3500010ngonWire-60001062parallelogramWire-1100010TRUE3230rectangleWire26900010ellipseWire120001014circleWiresquareWirengonWireparallelogramWirerectangleWireellipseWire","version":"0.20.7","type":"blockly"}} + title="Creating basic wire primitives" + /> + + + {\n // Create a circle wire\n const circleOptions = new CircleDto();\n circleOptions.radius = 3;\n circleOptions.center = [0, 0, 0] as Point3;\n circleOptions.direction = [0, 1, 0] as Vector3;\n\n const circleWire = await wire.createCircleWire(circleOptions);\n\n // Create a square wire at a different position\n const squareOptions = new SquareDto();\n squareOptions.size = 3;\n squareOptions.center = [5, 0, 0] as Point3;\n squareOptions.direction = [0, 1, 0] as Vector3;\n\n const squareWire = await wire.createSquareWire(squareOptions);\n\n // Create an NGon wire (hexagon)\n const ngonOptions = new NGonWireDto();\n ngonOptions.center = [-6, 0, 0] as Point3;\n ngonOptions.direction = [0, 1, 0] as Vector3;\n ngonOptions.nrCorners = 6;\n ngonOptions.radius = 2;\n\n const ngonWire = await wire.createNGonWire(ngonOptions);\n\n // Create a parallelogram wire\n const parallelogramOptions = new ParallelogramDto();\n parallelogramOptions.center = [-11, 0, 0] as Point3;\n parallelogramOptions.direction = [0, 1, 0] as Vector3;\n parallelogramOptions.aroundCenter = true;\n parallelogramOptions.width = 3;\n parallelogramOptions.height = 2;\n parallelogramOptions.angle = 30;\n\n const parallelogramWire = await wire.createParallelogramWire(parallelogramOptions);\n\n // Create a rectangle wire\n const rectangleOptions = new RectangleDto();\n rectangleOptions.width = 2;\n rectangleOptions.length = 6;\n rectangleOptions.center = [9, 0, 0] as Point3;\n rectangleOptions.direction = [0, 1, 0] as Vector3;\n\n const rectangleWire = await wire.createRectangleWire(rectangleOptions);\n\n // Create an ellipse wire\n const ellipseOptions = new EllipseDto();\n ellipseOptions.center = [12, 0, 0] as Point3;\n ellipseOptions.direction = [0, 1, 0] as Vector3;\n ellipseOptions.radiusMinor = 1;\n ellipseOptions.radiusMajor = 4;\n\n const ellipseWire = await wire.createEllipseWire(ellipseOptions);\n\n // Draw all the created wires\n bitbybit.draw.drawAnyAsync({ entity: circleWire });\n bitbybit.draw.drawAnyAsync({ entity: squareWire });\n bitbybit.draw.drawAnyAsync({ entity: ngonWire });\n bitbybit.draw.drawAnyAsync({ entity: parallelogramWire });\n bitbybit.draw.drawAnyAsync({ entity: rectangleWire });\n bitbybit.draw.drawAnyAsync({ entity: ellipseWire });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating basic wire primitives" + /> + + + +These primitive wires serve as the foundation for more complex 2D and 3D modeling operations. They can be used to create faces through surface generation, extruded into solids, used as profiles for sweeping operations, or combined and modified to create sophisticated wireframe geometries for engineering and design applications. From ac64aabcf645eed3b7491e11d11b49d0c1e8d588 Mon Sep 17 00:00:00 2001 From: Matas Ubarevicius Date: Wed, 8 Oct 2025 21:14:32 +0300 Subject: [PATCH 10/11] wire shape primitive tutorials --- .../wire/wire-hexagons-advanced-pattern.md | 2 +- .../occt/shapes/wire/wire-hexagons-in-grid.md | 2 +- .../occt/shapes/wire/wire-shape-primitives.md | 217 ++++++++++++++++++ 3 files changed, 219 insertions(+), 2 deletions(-) create mode 100644 docs/learn/code/common/occt/shapes/wire/wire-shape-primitives.md diff --git a/docs/learn/code/common/occt/shapes/wire/wire-hexagons-advanced-pattern.md b/docs/learn/code/common/occt/shapes/wire/wire-hexagons-advanced-pattern.md index 746c01f5..7836848b 100644 --- a/docs/learn/code/common/occt/shapes/wire/wire-hexagons-advanced-pattern.md +++ b/docs/learn/code/common/occt/shapes/wire/wire-hexagons-advanced-pattern.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 4 title: Hexagons Advanced Pattern sidebar_label: Hexagons Advanced Pattern description: Learn how to use advanced hexagon pattern parameters to create intricate designs. diff --git a/docs/learn/code/common/occt/shapes/wire/wire-hexagons-in-grid.md b/docs/learn/code/common/occt/shapes/wire/wire-hexagons-in-grid.md index 2c3a6b4a..b64d38ed 100644 --- a/docs/learn/code/common/occt/shapes/wire/wire-hexagons-in-grid.md +++ b/docs/learn/code/common/occt/shapes/wire/wire-hexagons-in-grid.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 title: Hexagons Grid sidebar_label: Hexagons Grid description: Learn how to create wire based hexagon grids diff --git a/docs/learn/code/common/occt/shapes/wire/wire-shape-primitives.md b/docs/learn/code/common/occt/shapes/wire/wire-shape-primitives.md new file mode 100644 index 00000000..6a1ebdb7 --- /dev/null +++ b/docs/learn/code/common/occt/shapes/wire/wire-shape-primitives.md @@ -0,0 +1,217 @@ +--- +sidebar_position: 2 +title: Wire Shape Primitives +sidebar_label: Wire Shape Primitives +description: Learn how to create shape wire primitives composed out of multiple edges +tags: [code, occt, rete, blockly, typescript] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +OCCT category icon with a stylized logo representation + +# Introduction to OCCT Wire Shape Primitives + +Wire shape primitives are specialized geometric entities that create more complex and decorative wire patterns beyond basic geometric shapes. While basic wire primitives like circles and rectangles are useful for fundamental geometry, wire shape primitives offer creative and practical solutions for specialized design needs. + +In this tutorial, we'll explore four fascinating wire shape primitives that demonstrate the versatility and power of OCCT's wire creation capabilities: + +## What You'll Learn + +- **Star Wire**: Perfect for creating decorative elements, logos, or technical drawings requiring star patterns +- **Christmas Tree Wire**: Ideal for seasonal designs, architectural elements, or creating tree-like structures +- **Heart Wire**: Great for decorative applications, artistic designs, or romantic themed projects +- **L-Polygon Wire**: Essential for architectural drawings, floor plans, or any L-shaped structural elements + +Each primitive comes with customizable parameters that allow you to fine-tune the shape according to your specific requirements. Whether you're working on architectural drawings, decorative patterns, or technical illustrations, these wire shapes provide the building blocks for more complex designs. + +## Understanding Wire Shape Parameters + +Before diving into the examples, it's helpful to understand some common parameters you'll encounter: + +- **Center/Origin**: The position where the shape will be placed in 3D space +- **Direction**: Controls the orientation plane of the wire (typically [0,1,0] for XZ plane) +- **Rotation**: Allows you to rotate the shape around its center point +- **Size Parameters**: Various dimensions that control the overall scale and proportions + +Now let's explore each wire shape primitive with interactive examples in three different programming approaches. + +## Star Wire + +The star wire creates beautiful star-shaped patterns with customizable rays, radii, and proportions. It's particularly useful for decorative elements, logos, or technical drawings requiring star patterns. + + + + + + + starWirestarWire000010107.83.70FALSEstarWire","version":"0.20.7","type":"blockly"}} + title="Creating basic wire star primitive" + /> + + + {\n // Create a star wire with customizable parameters\n const starOptions = new StarDto();\n starOptions.center = [0, 0, 0] as Point3;\n starOptions.direction = [0, 1, 0] as Vector3;\n starOptions.numRays = 10;\n starOptions.outerRadius = 7.8;\n starOptions.innerRadius = 3.7;\n starOptions.offsetOuterEdges = 0;\n starOptions.half = false;\n\n const starWire = await wire.createStarWire(starOptions);\n\n // Draw the created star wire\n bitbybit.draw.drawAnyAsync({ entity: starWire });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating basic wire star primitive" + /> + + + +The star wire example above demonstrates several key concepts: +- **NumRays**: Controls how many points the star has (10 in our example) +- **OuterRadius**: Sets the distance from center to the star's points (7.8 units) +- **InnerRadius**: Sets the distance from center to the star's inner vertices (3.7 units) +- **OffsetOuterEdges**: Allows fine-tuning of the star's outer edge positioning (0 = no offset) + +The interactive Rete example includes sliders that let you experiment with these parameters in real-time, while the Blockly and TypeScript versions show you how to implement the same functionality programmatically. + +## Christmas Tree Wire + +The Christmas tree wire creates detailed tree-like structures perfect for seasonal designs, architectural elements, or any application requiring organic tree shapes. + + + + + + + christmasTreeWirechristmasTreeWire61.53511FALSE0000010christmasTreeWire","version":"0.20.7","type":"blockly"}} + title="Creating basic wire primitive of christmass tree" + /> + + + {\n // Create a Christmas tree wire with customizable parameters\n const treeOptions = new ChristmasTreeDto();\n treeOptions.height = 6;\n treeOptions.innerDist = 1.5;\n treeOptions.outerDist = 3;\n treeOptions.nrSkirts = 5;\n treeOptions.trunkHeight = 1;\n treeOptions.trunkWidth = 1;\n treeOptions.half = false;\n treeOptions.rotation = 0;\n treeOptions.origin = [0, 0, 0] as Point3;\n treeOptions.direction = [0, 1, 0] as Vector3;\n\n const christmasTreeWire = await wire.createChristmasTreeWire(treeOptions);\n\n // Draw the created Christmas tree wire\n bitbybit.draw.drawAnyAsync({ entity: christmasTreeWire });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating basic wire primitive of christmass tree" + /> + + + +The Christmas tree wire showcases more complex geometric construction: +- **Height**: Controls the overall tree height (6 units in our example) +- **InnerDist & OuterDist**: Define the inner and outer distances of each tree layer (1.5 and 3 units) +- **NrSkirts**: Determines how many layered sections the tree has (5 layers) +- **TrunkHeight & TrunkWidth**: Control the tree's base trunk dimensions (1x1 units) + +This primitive demonstrates how OCCT can create complex, organic-looking shapes that would be difficult to construct manually using basic geometric operations. + +## Heart Wire + +The heart wire creates elegant heart-shaped curves, perfect for decorative applications, artistic designs, or romantic-themed projects. + + + + + + + heartWireheartWire00001008heartWire","version":"0.20.7","type":"blockly"}} + title="Creating basic wire primitive of heart" + /> + + + {\n // Create a heart wire with customizable parameters\n const heartOptions = new Heart2DDto();\n heartOptions.center = [0, 0, 0] as Point3;\n heartOptions.direction = [0, 1, 0] as Vector3;\n heartOptions.rotation = 0;\n heartOptions.sizeApprox = 8;\n\n const heartWire = await wire.createHeartWire(heartOptions);\n\n // Draw the created heart wire\n bitbybit.draw.drawAnyAsync({ entity: heartWire });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating basic wire primitive of heart" + /> + + + +The heart wire is elegantly simple yet mathematically sophisticated: +- **SizeApprox**: Controls the approximate overall size of the heart shape (8 units) +- **Rotation**: Allows you to rotate the heart around its center (0 = upright position) + +Despite its simplicity in parameters, the heart wire uses complex mathematical curves to create the characteristic heart shape with smooth transitions and proper proportions. + +## L-Polygon Wire + +The L-polygon wire creates precise L-shaped structures essential for architectural drawings, floor plans, or any application requiring L-shaped structural elements. + + + + + + + lPolygonWirelPolygonWire3537'outside'0000010lPolygonWire","version":"0.20.7","type":"blockly"}} + title="Creating basic wire primitive of L polygon" + /> + + + {\n // Create an L polygon wire with customizable parameters\n const lPolygonOptions = new LPolygonDto();\n lPolygonOptions.widthFirst = 3;\n lPolygonOptions.lengthFirst = 5;\n lPolygonOptions.widthSecond = 3;\n lPolygonOptions.lengthSecond = 7;\n lPolygonOptions.align = directionEnum.outside;\n lPolygonOptions.rotation = 0;\n lPolygonOptions.center = [0, 0, 0] as Point3;\n lPolygonOptions.direction = [0, 1, 0] as Vector3;\n\n const lPolygonWire = await wire.createLPolygonWire(lPolygonOptions);\n\n // Draw the created L polygon wire\n bitbybit.draw.drawAnyAsync({ entity: lPolygonWire });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Creating basic wire primitive of L polygon" + /> + + + +The L-polygon wire demonstrates precision in architectural and technical applications: +- **WidthFirst & LengthFirst**: Define the dimensions of the first segment (3x5 units) +- **WidthSecond & LengthSecond**: Define the dimensions of the second segment (3x7 units) +- **Align**: Controls how the two segments connect ("outside" alignment in our example) + +This primitive is particularly valuable for creating floor plans, structural drawings, or any design requiring precise L-shaped elements. + +## Key Takeaways + +Wire shape primitives offer several advantages over constructing complex shapes manually: + +### 1. **Consistency and Precision** +Each primitive uses mathematical formulas to ensure perfect proportions and smooth curves every time. This eliminates human error and ensures professional results. + +### 2. **Parametric Control** +All primitives accept parameters that allow you to customize the shape without rebuilding the geometry from scratch. This makes them perfect for creating families of related shapes or iterating on designs. + +### 3. **Performance Benefits** +These primitives are optimized at the OCCT level, making them much faster than constructing equivalent shapes using multiple basic operations. + +### 4. **Professional Applications** +- **Architecture**: L-polygons for floor plans, stars for decorative elements +- **Manufacturing**: Precise shapes for technical drawings and CAD applications +- **Art & Design**: Hearts and stars for decorative and artistic projects +- **Seasonal Design**: Christmas trees for themed applications + +## Next Steps + +Now that you understand wire shape primitives, you can: + +1. **Experiment** with different parameter values to see how they affect the shapes +2. **Combine** multiple primitives to create more complex designs +3. **Transform** these wires using translation, rotation, and scaling operations +4. **Convert** wires to faces or solids for 3D modeling applications +5. **Use** these shapes as profiles for extrusion or sweeping operations + +Remember that these wire primitives serve as building blocks for more advanced geometric operations. + +The beauty of OCCT wire shape primitives lies in their simplicity of use combined with mathematical precision—they provide professional-grade geometric capabilities while remaining accessible to users at any skill level. From 7993ffd178c58b8a0f85f6152804e3fd79e464ea Mon Sep 17 00:00:00 2001 From: Matas Ubarevicius Date: Wed, 8 Oct 2025 21:35:48 +0300 Subject: [PATCH 11/11] wire from edges tutorial --- .../occt/shapes/wire/wire-from-edges.md | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 docs/learn/code/common/occt/shapes/wire/wire-from-edges.md diff --git a/docs/learn/code/common/occt/shapes/wire/wire-from-edges.md b/docs/learn/code/common/occt/shapes/wire/wire-from-edges.md new file mode 100644 index 00000000..67980b87 --- /dev/null +++ b/docs/learn/code/common/occt/shapes/wire/wire-from-edges.md @@ -0,0 +1,81 @@ +--- +sidebar_position: 5 +title: Wire From Edges +sidebar_label: Wire From Edges +description: Learn how to create wires by combining multiple edges +tags: [code, occt, rete, blockly, typescript] +--- + +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; +import BitByBitRenderCanvas from '@site/src/components/BitByBitRenderCanvas'; + +OCCT category icon with a stylized logo representation + +# Creating Wires from Edges + +Combining edges into a wire is one of the most fundamental operations in 3D modeling and computational geometry. While individual edges represent simple geometric elements like lines, arcs, or splines, wires allow us to connect these edges into more complex, continuous shapes that form the backbone of sophisticated geometric models. + +## Why Combine Edges into Wires? + +In practical 3D modeling scenarios, you rarely work with isolated geometric elements. Instead, you need to create connected paths, profiles, and contours that can serve various purposes: + +- **Creating complex profiles** for extrusion or sweeping operations +- **Building wireframe models** that define the skeleton of 3D objects +- **Generating paths** for manufacturing tools, robot movements, or animation curves +- **Forming closed loops** that can later be converted into faces and surfaces +- **Constructing architectural elements** like floor plans, structural frameworks, or decorative patterns + +## The Power of Edge Combination + +When you combine individual edges into a wire, you gain several important capabilities: + +### 1. **Continuity Control** +OCCT automatically ensures that edges connect properly at their endpoints, maintaining geometric continuity throughout the wire. + +### 2. **Complex Shape Creation** +By combining different types of edges (lines, arcs, splines), you can create sophisticated shapes that would be impossible to achieve with single geometric primitives. + +### 3. **Topology Management** +Wires maintain the topological relationships between edges, making them suitable for advanced operations like face creation, boolean operations, and geometric analysis. + +### 4. **Manufacturing Applications** +Combined wires can represent tool paths, cutting profiles, or assembly sequences in manufacturing and CAD applications. + +## Understanding the Example + +In this tutorial, we'll demonstrate edge combination by creating a flower-like pattern from four arc segments. The process involves: + +1. **Creating a base arc** through three specific points +2. **Generating variations** by rotating the base arc in 90-degree increments +3. **Combining all arcs** into a single, continuous wire structure + +This example showcases how simple geometric operations (arc creation and rotation) can be combined with wire operations to create complex, aesthetically pleasing shapes that would be challenging to define manually. + + + + + + + arc1arc2arc3arc4edgesListcombinedWirearc1505003-505arc2arc101090arc3arc201090arc4arc301090edgesListarc1arc2arc3arc4combinedWireedgesListcombinedWire","version":"0.20.7","type":"blockly"}} + title="Combining edges into a wire" + /> + + + {\n // Create the first arc through three points\n const arcOptions = new ArcEdgeThreePointsDto();\n arcOptions.start = [5, 0, 5] as Point3;\n arcOptions.middle = [0, 0, 3] as Point3;\n arcOptions.end = [-5, 0, 5] as Point3;\n\n const arc1 = await edge.arcThroughThreePoints(arcOptions);\n\n // Create rotation options for Y-axis rotation\n const rotateOptions = new RotateDto();\n rotateOptions.axis = [0, 1, 0] as Vector3;\n rotateOptions.angle = 90; // 90 degrees\n\n // Create three more arcs by rotating the first arc\n rotateOptions.shape = arc1;\n const arc2 = await transforms.rotate(rotateOptions);\n\n rotateOptions.shape = arc2;\n const arc3 = await transforms.rotate(rotateOptions);\n\n rotateOptions.shape = arc3;\n const arc4 = await transforms.rotate(rotateOptions);\n\n // Combine all arc edges into a single wire\n const combineOptions = new ShapesDto();\n combineOptions.shapes = [arc1, arc2, arc3, arc4];\n\n const combinedWire = await wire.combineEdgesAndWiresIntoAWire(combineOptions);\n\n // Draw the combined wire\n bitbybit.draw.drawAnyAsync({ entity: combinedWire });\n}\n\n// Execute the function\nstart();","version":"0.20.7","type":"typescript"}} + title="Combining edges into a wire" + /> + +