Surfaces3D

Heightfields, function plots, fillets, textured tiles and the ruler annotation

Heightfields, function plots, fillets, textured tiles and the ruler annotation.

pybosl2.surfaces3d.interior_fillet(length=1.0, radius=None, angle=90, overlap=0.01, diameter=None, anchor=Point(-1.0, -1.0, 0.0), spin=0, orient=Anchor.TOP, fn=None, fa=None, fs=None)[source]

Return a shape to fillet an interior corner between two faces.

Parameters:
length : float

length of the edge to fillet (default 1.0)

radius : float | None

radius of the fillet

angle : float

angle between the faces to fillet in degrees (default 90)

overlap : float

overlap size for unioning with the faces (default 0.01)

diameter : float | None

diameter of the fillet

anchor : Anchor | Sequence[float]

anchor point in the anchor language (default FRONT+LEFT), as every other constructor takes it (SPEC C-10, PLAN O-6b)

spin : float

Z-axis rotation in degrees after anchor (default 0)

orient : Anchor | Sequence[float]

direction to rotate the top towards, after spin (default UP)

fn : int | None

Fixed fragment count for the fillet arc; ambient default when omitted. Omitted, the ambient use_defaults(fn=...) value applies; fn=0 opts back out to fa/fs.

fa : float | None

Minimum fragment angle for the fillet arc. Omitted, the ambient use_defaults(fa=...) value applies.

fs : float | None

Minimum fragment size for the fillet arc. Omitted, the ambient use_defaults(fs=...) value applies.

Return type:

Bosl2Solid

pybosl2.surfaces3d.heightfield(data, size=(100, 100), bottom=-20, maxz=99, xrange=(-1, 0.04, 1), yrange=(-1, 0.04, 1), style=VNFStyle.DEFAULT, convexity=10, anchor=Anchor.CENTER, spin=0, orient=Anchor.TOP)[source]

Return a 3-D surface from a 2-D array of heights or a function literal.

Parameters:
data : Callable[[float, float], float | None] | Sequence[Sequence[float]]

2-D rectangular array of heights, or a function literal taking (x, y)

size : Sequence[float]

[X,Y] size of the surface (default [100,100])

bottom : float

Z coordinate for the bottom of the object (default -20)

maxz : float

maximum height to model, taller values are truncated (default 99)

xrange : Sequence[float]

[start, step, stop] range of X values for a function-literal surface

yrange : Sequence[float]

[start, step, stop] range of Y values for a function-literal surface

style : VNFStyle

quad subdivision style: “default”, “alt”, “quincunx” (default “default”)

convexity : int

max number of times a line can cross the surface wall (default 10)

anchor : Anchor | Sequence[float]

anchor point (default CENTER)

spin : float

Z-axis rotation in degrees (default 0)

orient : Anchor | Sequence[float]

direction to rotate the top towards (default UP)

Return type:

Bosl2Solid

pybosl2.surfaces3d.cylindrical_heightfield(data, length=None, radius=None, base=1, transpose=False, aspect=1, style=VNFStyle.MIN_EDGE, convexity=10, xrange=(-1, 0.01, 1), yrange=(-1, 0.01, 1), maxh=99, radius1=None, radius2=None, diameter=None, diameter1=None, diameter2=None, height=None, anchor=Anchor.CENTER, spin=0, orient=Anchor.TOP)[source]

Return a heightfield surface wrapped around a cylinder.

Parameters:
data : Callable[[float, float], float | None] | Sequence[Sequence[float]]

2-D rectangular array of heights, or a function literal taking (x, y)

length : float | None

length of the cylinder to wrap around

radius : float | None

radius of the cylinder to wrap around

base : float

radius for the bottom of the object (default 1)

transpose : bool

swap the radial and length axes of the data (default False)

aspect : float

aspect ratio of the generated heightfield at the cylinder surface (default 1)

style : VNFStyle

quad subdivision style: “default”, “alt”, “quincunx” (default “min_edge”)

convexity : int

max number of times a line can cross the surface wall (default 10)

xrange : Sequence[float]

[start, step, stop] range of X values for a function-literal surface

yrange : Sequence[float]

[start, step, stop] range of Y values for a function-literal surface

maxh : float

maximum height above the radius to model (default 99)

radius1 : float | None

radius of the bottom/top of the cylinder to wrap around

radius2 : float | None

radius of the bottom/top of the cylinder to wrap around

diameter : float | None

diameter of the cylinder to wrap around / bottom / top

diameter1 : float | None

diameter of the cylinder to wrap around / bottom / top

diameter2 : float | None

diameter of the cylinder to wrap around / bottom / top

height : float | None

alternate names for length (length of the cylinder)

anchor : Anchor | Sequence[float]

anchor point (default CENTER)

spin : float

Z-axis rotation in degrees (default 0)

orient : Anchor | Sequence[float]

direction to rotate the top towards (default UP)

Return type:

Bosl2Solid

pybosl2.surfaces3d.plot3d(f, x, y, zclip=None, zspan=None, base=1, style=VNFStyle.DEFAULT)[source]

Return a surface plot of z = f(x, y) over a grid of x, y values.

Parameters:
f : Callable[[float, float], float]

a callable f(x, y) -> z

x : Sequence[float]

strictly increasing list of X-axis sample coordinates.

y : Sequence[float]

strictly increasing list of Y-axis sample coordinates.

zclip : Sequence[float] | None

[zmin, zmax] to clamp the surface (default no clip)

zspan : Sequence[float] | None

[zmin, zmax] to rescale the surface height into (default no rescale)

base : float

thickness of solid base below the surface; 0 gives just the (open) surface (default 1)

style : VNFStyle

vnf_vertex_array quad-subdivision style

Return type:

Solid

Examples

A rippled surface plotted as a solid slab:

import math
from pybosl2.shapes3d import plot3d

plot3d(lambda x, y: 6 * math.cos(math.hypot(x, y) / 6),
          list(range(-30, 31, 3)), list(range(-30, 31, 3))).show()
Loading 3-D preview…

⬇ Download STL mesh

pybosl2.surfaces3d.plot_revolution(f, angle, z=None, radius=None, radius1=None, radius2=None, diameter=None, diameter1=None, diameter2=None, path=None, rclip=None, rspan=None, horiz=False, style=VNFStyle.MIN_EDGE)[source]

Return a surface of revolution whose radius is modulated by radius = f(angle, z).

The profile is either a straight taper (z plus radius1/radius2) or an explicit 2-D path of [radius, z] points; f(theta, z) displaces each profile point along its normal (or radially, with horiz). A full 360-degree angle range revolves seamlessly; a partial range is capped to the axis. The BOSL2 arclength form is not ported.

Parameters:
f : Callable[[float, float], float]

a callable f(theta_degrees, z) -> radial displacement

angle : Sequence[float]

a strictly increasing list/range of revolution angles in degrees

z : Sequence[float] | None

strictly increasing profile heights (with radius1/radius2)

radius1 : float | None

the profile’s bottom/top radius (straight taper form)

radius2 : float | None

the profile’s bottom/top radius (straight taper form)

radius : float | None

the profile’s bottom/top radius (straight taper form)

diameter1 : float | None

the profile’s bottom/top radius (straight taper form)

diameter2 : float | None

the profile’s bottom/top radius (straight taper form)

diameter : float | None

the profile’s bottom/top radius (straight taper form)

path : Path2D | None

an explicit [[radius, z], ...] profile as a Path2D (instead of z + radii)

rclip : Sequence[float] | None

[rmin, rmax] to clamp the modulated radius

rspan : Sequence[float] | None

[rmin, rmax] to rescale the displacement into

horiz : bool

displace radially (normal [1, 0]) instead of along the profile normal

style : VNFStyle

vnf_vertex_array quad-subdivision style

Return type:

Solid

Examples

A vase whose radius ripples with height and angle:

import math
from pybosl2.shapes3d import plot_revolution

plot_revolution(lambda a, z: 3 * math.sin(math.radians(4 * a)) * (z / 30),
                   angle=list(range(0, 361, 6)), z=list(range(0, 31, 2)),
                   radius1=12, radius2=8).show()
Loading 3-D preview…

⬇ Download STL mesh

pybosl2.surfaces3d.fillet(length=None, radius=None, angle=90, radius1=None, radius2=None, diameter=None, diameter1=None, diameter2=None, excess=0.01, height=None, fn=None, fa=None, fs=None)[source]

Return a concave edge-fillet mask of length length and radius radius.

A cutter you subtract to round a 90-degree edge (the concave complement of a rounded corner). Positioned manually like rounding_edge_mask – origin at the sharp edge, +X/+Y into the material, centered along its own Z. Only 90-degree edges are ported (BOSL2’s angle for other dihedral angles is not).

Parameters:
length : float | None

Length of the cutter along its axis (default 1).

radius : float | None

Rounding radius (both ends).

angle : float

Angle in degrees between the two faces the fillet sits in.

radius1 : float | None

Rounding radius at the first end, for a tapered cutter.

radius2 : float | None

Rounding radius at the second end, for a tapered cutter.

diameter : float | None

Rounding diameter (both ends).

diameter1 : float | None

Rounding diameter at the first end.

diameter2 : float | None

Rounding diameter at the second end.

excess : float

Extra length added at each end, so the cutter reaches past the solid it trims.

height : float | None

Length of the cutter along its axis (default 1).

fn : int | None

Arc smoothness overrides. Omitted, the ambient use_defaults(fn=...) value applies; fn=0 opts back out to fa/fs.

fa : float | None

Arc smoothness overrides. Omitted, the ambient use_defaults(fa=...) value applies.

fs : float | None

Arc smoothness overrides. Omitted, the ambient use_defaults(fs=...) value applies.

Return type:

CsgSolid

Examples

from pybosl2.solid import cuboid
from pybosl2.shapes3d import fillet

block = cuboid([30, 30, 20])
mask = fillet(length=20, radius=6).right(15).forward(15)
(block - mask).show()
Loading 3-D preview…

⬇ Download STL mesh

pybosl2.surfaces3d.textured_tile(texture, size, tex_reps=None, tex_size=None, tex_depth=1, tex_inset=False, style=VNFStyle.MIN_EDGE, sides=None, border=None, gap=None, roughness=None, fn=None)[source]

Return a rectangular tile carrying a repeated texture.

texture is either a name from the ported texture() engine (e.g. "pyramids", "diamonds", "hills", "bricks", "pyramids_vnf"), a raw height-field (a 2-D array of scalar heights in [0, 1]), or a raw VNF tile (verts, faces). It is tiled tex_reps times (or tex_size chosen) across the size rectangle and raised by tex_depth.

Parameters:
texture : Any

a texture name, a 2-D height-field array, or a VNF tile (verts, faces)

size : Sequence[float]

[x, y] size of the tile

tex_reps : Any

integer or [nx, ny] tile repetitions (give this or tex_size)

tex_size : Any

target tile size, from which the repetition count is computed

tex_depth : float

how far the texture is raised (default 1); negative inverts it

tex_inset : Any

lower the texture into the surface by this fraction (True == full depth)

style : VNFStyle

vnf_vertex_array quad-subdivision style (height-field textures only)

sides : Any

number of sides for named texture geometry.

border : Any

border width for named textures.

fn : int | None

number of fragments for circle resolution in named textures. Omitted, the ambient use_defaults(fn=...) value applies; fn=0 opts back out to fa/fs.

gap : float | None

spacing between texture elements for named textures.

roughness : Any

roughness parameter for named textures.

Return type:

Solid

Examples

A named pyramid texture:

from pybosl2.shapes3d import textured_tile

textured_tile("pyramids", size=[40, 40], tex_reps=[6, 6], tex_depth=3).show()
Loading 3-D preview…

⬇ Download STL mesh

A raw height-field:

from pybosl2.shapes3d import textured_tile

bump = [[0, 0, 0], [0, 1, 0], [0, 0, 0]]
textured_tile(bump, size=[40, 40], tex_reps=[4, 4], tex_depth=3).show()
Loading 3-D preview…

⬇ Download STL mesh

pybosl2.surfaces3d.ruler(length=100, width=None, thickness=1, depth=3, labels=False, pipscale=0.3333333333333333, maxscale=None, colors=None, alpha=1.0, unit=1, inch=False, anchor=Point(-1.0, 1.0, 1.0), spin=0, orient=Anchor.TOP, fn=None, fa=None, fs=None)[source]

Return a ruler for measuring objects in the viewport.

Parameters:
length : float

length of the ruler (default 100)

width : float | None

width of the ruler (default: size of the largest unit division)

thickness : float

thickness of the ruler (default 1)

depth : int

depth of the mark subdivisions (default 3)

labels : bool

draw numeric labels for depths larger than 1 (default False)

pipscale : float

width scale of the pips relative to the next size up (default 1/3)

maxscale : float | None

log10 of the maximum width divisions to display (default: based on length)

colors : list[Any] | None

two colours to alternate for the ruler (default [“black”,”white”])

alpha : float

transparency value (default 1.0)

unit : float

unit to mark; scales the ruler marks to a different length (default 1)

inch : bool

scale the ruler to inches, assuming a mm base dimension (default False)

anchor : Anchor | Sequence[float]

anchor point (default LEFT+BACK+TOP)

spin : float

Z-axis rotation in degrees (default 0)

orient : Anchor | Sequence[float]

direction to rotate the top towards (default UP)

fn : int | None

number of fragments for circle resolution. Omitted, the ambient use_defaults(fn=...) value applies; fn=0 opts back out to fa/fs.

fa : float | None

minimum fragment angle for circle resolution. Omitted, the ambient use_defaults(fa=...) value applies.

fs : float | None

minimum fragment size for circle resolution. Omitted, the ambient use_defaults(fs=...) value applies.

Return type:

Bosl2Solid