Skip to content

STL export

Turning a Riemann relief into a printable mesh. See the physical workflow.

complexplorer.OrnamentGenerator

OrnamentGenerator(func: Callable, resolution: int = 150, scaling: str | None = None, scaling_params: dict[str, Any] | None = None, cmap: Colormap | None = None, domain: Domain | None = None, *, normalize: str | float | None = DEFAULT_NORMALIZE, pointiness: float = DEFAULT_POINTINESS, pole_order: float = DEFAULT_POLE_ORDER, sharpness: float | None = None, contrast: tuple[float, float] | None = None)

Generate 3D-printable ornaments from complex functions.

This version directly uses the modulus-scaled mesh from the Riemann sphere visualization without complex healing steps.

Parameters:

Name Type Description Default
func callable

Complex function f(z) to visualize.

required
resolution int

Mesh resolution (n_theta = n_phi).

150
scaling str

Modulus scaling method. Defaults to 'logarithmic': a logistic in the log modulus, which is self-dual about |f| = 1 and, unlike 'arctan', admits a scale, so pointiness has something to set. 'arctan' reaches 90% of its height at |f| = 6.3 whatever the function, which is a tip exponent well above 1 on a typical rational function -- a rounded pebble on every piece, regardless of the mathematics behind it.

None
scaling_params dict

Parameters for the scaling method. Anything given here wins over the values derived from pointiness, sharpness and contrast.

None
cmap Colormap

Colormap for visualization. Default is Phase colormap.

None
domain Domain

Domain to restrict evaluation. Helps avoid numerical issues.

None
normalize (geometric, median)

How to rescale |f| before the transfer, so the arbitrary constant in front of f stops changing the ornament's shape. 'geometric' puts the area-weighted geometric mean of |f| at sea level; 'median' uses the area-weighted median instead, which holds up better when a high-order feature at infinity covers enough of the sphere to drag sea level away from the structure worth seeing. A float is used as the constant directly, and None disables normalization, reproducing the pre-3.1 mapping. The constant is estimated from the samples the relief is built from, so f is never evaluated twice.

'geometric'
pointiness float

Tip sharpness, as the reciprocal of the tip exponent: the surface approaches a feature like distance ** (1 / pointiness). Larger is sharper. Sets the transfer's log-modulus scale to pointiness * pole_order. Ignored by transfers that have no scale, such as 'arctan'.

2.0
pole_order float

The order of the features being shaped. Scaling the transfer by it makes a double pole print as sharp as a simple one instead of twice as blunt. The resulting scale is capped at SHARPNESS_CAP (6.0), so orders above 3 do not ask for a dynamic range the mesh cannot deliver -- see that constant. It is not inferred from the function: fitting the scale to a piece's log-modulus spread is a known dead end that produces tip exponents from 1 to 8 and blunts most pieces, so the order is yours to state.

1.0
sharpness float

The log-modulus scale, set directly, bypassing pointiness * pole_order and its cap. ln(10) makes one unit of relief exactly one decade of gain -- 20 dB -- which turns a transfer function's relief into a calibrated scale readable like a Bode magnitude curve along a meridian. That is not expressible as a tip exponent, which is why it is settable on its own.

None
contrast tuple of (float, float)

(boost, weight) for the two-scale transfer, which mixes a narrow logistic at scale / boost for bulk contrast with the wide one for the tips. Off by default: applied globally it degrades the pieces whose tips are the point of the piece, so it is a per-piece choice. Use it where a few widely separated features leave the body a near-perfect sphere. See :meth:~complexplorer.core.scaling.ModulusScaling.log_mixture.

None

Initialize ornament generator.

from_preset classmethod

from_preset(preset, **overrides) -> OrnamentGenerator

Build a generator from a catalog preset, honouring the relief settings it carries.

A printable preset records the order of its features and the resolution its detail needs. Rendering it without those gives the blunt version of the piece: the tip exponent is the feature order divided by the transfer's scale, and the scale is derived from the order, so an order-2 piece rendered as order 1 comes out as an exact cone where a cusp was intended.

Anything passed in overrides wins over the preset, so a caller can explore a piece at a lower resolution or a different sharpness without editing the catalog.

Parameters:

Name Type Description Default
preset FunctionPreset

A preset from cp.catalog.

required
**overrides

Any :class:OrnamentGenerator argument, taking precedence over the preset.

{}

Returns:

Type Description
OrnamentGenerator

Examples:

>>> import complexplorer as cp
>>> gen = OrnamentGenerator.from_preset(cp.catalog.get("pole_flower_10"))

generate_ornament

generate_ornament(verbose: bool = False) -> pv.PolyData

Generate the ornament mesh.

Parameters:

Name Type Description Default
verbose bool

Print progress information.

False

Returns:

Type Description
PolyData

Generated ornament mesh with color information.

validate_mesh

validate_mesh(size_mm: float = 50, verbose: bool = True) -> dict[str, Any]

Validate mesh for 3D printing.

Parameters:

Name Type Description Default
size_mm float

Target size in millimeters.

50
verbose bool

Print validation results.

True

Returns:

Type Description
dict

Validation results.

save_stl

save_stl(filename: str, size_mm: float = 50, center: bool = True, repair: bool = True, binary: bool = True, validate: bool = True, verbose: bool = True, size_measure: str = 'extent') -> str

Save the ornament as STL file.

Parameters:

Name Type Description Default
filename str

Output filename (should end with .stl).

required
size_mm float

Scale mesh to this size in millimeters, measured per size_measure.

50
size_measure (extent, max)

What size_mm measures. 'extent' is the object's true tip-to-tip width, which is a property of the shape; 'max' is the largest axis-aligned bounding-box dimension, which depends on how the piece sits in the coordinate frame and is what versions before 3.1 used. A relief with spikes on the cube diagonals is understated by sqrt(3) under 'max'. Use 'max' when the box is what matters, such as fitting a build plate.

'extent'
center bool

Center the mesh at origin.

True
repair bool

Apply simple mesh repair (fill holes).

True
binary bool

Save as binary STL (smaller file size).

True
validate bool

Validate before saving.

True
verbose bool

Print progress information.

True

Returns:

Type Description
str

Path to saved file.

generate_and_save

generate_and_save(filename: str, size_mm: float = 50, center: bool = True, repair: bool = True, binary: bool = True, validate: bool = True, verbose: bool = True, size_measure: str = 'extent') -> str

Generate ornament and save as STL in one step.

Parameters:

Name Type Description Default
filename str

Output filename.

required
size_mm float

Target size in millimeters, measured per size_measure.

50
size_measure (extent, max)

What size_mm measures -- see :meth:save_stl.

'extent'
center bool

Center the mesh.

True
repair bool

Apply simple mesh repair.

True
binary bool

Use binary STL format.

True
validate bool

Validate before saving.

True
verbose bool

Print progress.

True

Returns:

Type Description
str

Path to saved file.

complexplorer.create_ornament

create_ornament(func: Callable, filename: str, size_mm: float = 50, resolution: int = 150, scaling: str | None = None, scaling_params: dict[str, Any] | None = None, cmap: Colormap | None = None, domain: Domain | None = None, verbose: bool = True, *, size_measure: str = 'extent', normalize: str | float | None = DEFAULT_NORMALIZE, pointiness: float = DEFAULT_POINTINESS, pole_order: float = DEFAULT_POLE_ORDER, sharpness: float | None = None, contrast: tuple[float, float] | None = None) -> str

Create a 3D-printable ornament from a complex function.

Convenience function for creating STL files from complex functions.

Parameters:

Name Type Description Default
func callable

Complex function to visualize.

required
filename str

Output STL filename.

required
size_mm float

Size in millimeters, measured per size_measure.

50
size_measure (extent, max)

What size_mm measures -- see :meth:OrnamentGenerator.save_stl.

'extent'
resolution int

Mesh resolution.

150
scaling str

Modulus scaling method. Defaults to the ornament transfer, a logistic in the log modulus.

None
scaling_params dict

Scaling parameters.

None
cmap Colormap

Color mapping.

None
domain Domain

Domain restriction.

None
verbose bool

Print progress.

True
normalize str | float | None

Relief shaping, passed through to :class:OrnamentGenerator -- see it for the details.

DEFAULT_NORMALIZE
pointiness str | float | None

Relief shaping, passed through to :class:OrnamentGenerator -- see it for the details.

DEFAULT_NORMALIZE
pole_order str | float | None

Relief shaping, passed through to :class:OrnamentGenerator -- see it for the details.

DEFAULT_NORMALIZE
sharpness str | float | None

Relief shaping, passed through to :class:OrnamentGenerator -- see it for the details.

DEFAULT_NORMALIZE
contrast str | float | None

Relief shaping, passed through to :class:OrnamentGenerator -- see it for the details.

DEFAULT_NORMALIZE

Returns:

Type Description
str

Path to saved STL file.