Skip to main content

Static flexible modeling

cadflow.flexible converts sparse 3D control grids into deterministic indexed triangle meshes. Use it for cloth, leather, membranes, covers, garments, and other flexible parts when the intended final form is known.

Scope

Here, static describes an authored final shape. The module does not solve equilibrium, advance time, or derive deformation from loads, gravity, contact, or material laws.

Choose the modeling object

ObjectRole
FlexibleMaterialStores thickness and appearance metadata
FlexiblePanelDefines one control-grid surface and its sampling density
FlexiblePanelMeshHolds the built vertices, normals, and triangles for one panel
FlexibleModelCombines named panels into one deterministic mesh
FlexibleMeshProvides measurements, panel ranges, and OBJ/STL/JSON export
RingSection / sectioned_panelBuilds a periodic panel from designed elliptical sections

Build a panel from a control grid

Control points have shape (rows, columns, 3). The grid describes the form; sampling density controls the output tessellation.

from cadflow.flexible import FlexibleMaterial, FlexibleModel, FlexiblePanel


control_points = [
[(0, 0, 0), (0, 50, 6), (0, 100, 0)],
[(60, 0, 4), (60, 50, 18), (60, 100, 4)],
[(120, 0, 0), (120, 50, 6), (120, 100, 0)],
]

panel = FlexiblePanel(
name="formed cover",
control_points=control_points,
sample_rows=40,
sample_columns=48,
material=FlexibleMaterial(
name="coated fabric",
thickness=1.2,
color=(0.16, 0.42, 0.58),
roughness=0.7,
),
)

model = FlexibleModel("protective cover")
model.add_panel(panel)
mesh = model.build()

print(mesh.vertex_count, mesh.triangle_count)
print(mesh.bounds, mesh.surface_area, mesh.is_watertight)

The control grid must contain at least two rows and two columns, and all coordinates must be finite. sample_rows and sample_columns must be integers no smaller than their corresponding control-grid dimensions.

Control seams, thickness, and resolution

  • Set periodic_columns=True when columns wrap around a closed section. Supply distinct columns around the loop; do not repeat the first column at the end.
  • Set material thickness to 0 for a single surface. A positive thickness builds two normal-offset surfaces and triangulates the remaining boundaries into a closed thin shell.
  • Increase sample counts when downstream output needs finer triangles. Sampling changes mesh density, not the authored control grid.
  • Keep dimensions, thickness, and downstream tolerances in one consistent unit system.

Build a periodic panel from sections

sectioned_panel is convenient for tubular or garment-like forms. Each RingSection defines an ellipse in an arbitrary 3D plane; optional wrinkle parameters apply a deterministic radial modulation.

from cadflow.flexible import (
FlexibleMaterial,
FlexibleModel,
RingSection,
sectioned_panel,
)


sections = [
RingSection(
center=(0, 0, 0),
axis_u=(1, 0, 0),
axis_v=(0, 1, 0),
radius_u=200,
radius_v=120,
wrinkle_amplitude=0.02,
wrinkle_count=7,
),
RingSection(
center=(0, 0, 500),
axis_u=(1, 0, 0),
axis_v=(0, 1, 0),
radius_u=240,
radius_v=140,
),
]

panel = sectioned_panel(
"sleeve",
sections,
control_columns=24,
sample_rows=48,
sample_columns=72,
material=FlexibleMaterial(name="woven shell", thickness=1.5),
)

model = FlexibleModel("sectioned shell")
model.add_panel(panel)
mesh = model.build()

wrinkle_amplitude is part of the designed geometry; it is not a displacement computed from physical loading. Add more uniquely named panels to the same FlexibleModel when an artifact contains separate pieces. mesh.panels preserves the vertex range, triangle range, and material of every panel.

Inspect and export

if mesh.vertex_count == 0 or mesh.triangle_count == 0:
raise RuntimeError("flexible mesh is empty")

for panel_range in mesh.panels:
print(panel_range.name, panel_range.vertex_count, panel_range.triangle_count)

mesh.write_obj("outputs/sectioned-shell.obj")
mesh.write_stl("outputs/sectioned-shell.stl")
mesh.write_json("outputs/sectioned-shell.json")

OBJ preserves panel groups and vertex normals. Binary STL contains the combined triangle mesh. JSON records panel ranges, material metadata, bounds, surface area, and watertightness.

Before delivery, inspect counts and bounds, verify that periodic seams are continuous, and confirm is_watertight when positive-thickness panels are expected to be closed. Also check that every output file exists and is non-empty.

Execution boundary

The native C++ builder performs Catmull-Rom sampling, periodic seam handling, vertex-normal construction, normal-offset thickness, and boundary-wall triangulation. Python owns control geometry, material metadata, multi-panel composition, measurements, and export. Each panel crosses this boundary through one stateless array call; no motion state or Python callback remains in the native builder.