Struct CSG

Source
pub struct CSG<S: Clone> {
    pub polygons: Vec<Polygon<S>>,
    pub geometry: GeometryCollection<Real>,
    pub metadata: Option<S>,
}
Expand description

The main CSG solid structure. Contains a list of 3D polygons, 2D polylines, and some metadata.

Fields§

§polygons: Vec<Polygon<S>>

3D polygons for volumetric shapes

§geometry: GeometryCollection<Real>

2D geometry

§metadata: Option<S>

Metadata

Implementations§

Source§

impl<S: Clone + Debug + Send + Sync> CSG<S>

Source

pub fn new() -> Self

Create an empty CSG

Source

pub fn vertices(&self) -> Vec<Vertex>

Helper to collect all vertices from the CSG.

Source

pub fn from_polygons(polygons: &[Polygon<S>]) -> Self

Build a CSG from an existing polygon list

Source

pub fn to_polygons(&self) -> Vec<Polygon<S>>

Convert internal polylines into polygons and return along with any existing internal polygons.

Source

pub fn from_geo(geometry: GeometryCollection<Real>, metadata: Option<S>) -> Self

Create a CSG that holds only 2D geometry in a geo::GeometryCollection.

Source

pub fn to_multipolygon(&self) -> MultiPolygon<Real>

Take the geo::Polygon’s from the CSG’s geometry collection

Source

pub fn tessellate_2d( outer: &[[Real; 2]], holes: &[&[[Real; 2]]], ) -> Vec<[Point3<Real>; 3]>

Source

pub fn union(&self, other: &CSG<S>) -> CSG<S>

Return a new CSG representing union of the two CSG’s.

let c = a.union(b);
    +-------+            +-------+
    |       |            |       |
    |   a   |            |   c   |
    |    +--+----+   =   |       +----+
    +----+--+    |       +----+       |
         |   b   |            |   c   |
         |       |            |       |
         +-------+            +-------+
Source

pub fn difference(&self, other: &CSG<S>) -> CSG<S>

Return a new CSG representing diffarence of the two CSG’s.

let c = a.difference(b);
    +-------+            +-------+
    |       |            |       |
    |   a   |            |   c   |
    |    +--+----+   =   |    +--+
    +----+--+    |       +----+
         |   b   |
         |       |
         +-------+
Source

pub fn intersection(&self, other: &CSG<S>) -> CSG<S>

Return a new CSG representing intersection of the two CSG’s.

let c = a.intersect(b);
    +-------+
    |       |
    |   a   |
    |    +--+----+   =   +--+
    +----+--+    |       +--+
         |   b   |
         |       |
         +-------+
Source

pub fn xor(&self, other: &CSG<S>) -> CSG<S>

Return a new CSG representing space in this CSG excluding the space in the other CSG plus the space in the other CSG excluding the space in this CSG.

let c = a.xor(b);
    +-------+            +-------+
    |       |            |       |
    |   a   |            |   a   |
    |    +--+----+   =   |    +--+----+
    +----+--+    |       +----+--+    |
         |   b   |            |       |
         |       |            |       |
         +-------+            +-------+
Source

pub fn inverse(&self) -> CSG<S>

Invert this CSG (flip inside vs. outside)

Source

pub fn transform(&self, mat: &Matrix4<Real>) -> CSG<S>

Apply an arbitrary 3D transform (as a 4x4 matrix) to both polygons and polylines. The polygon z-coordinates and normal vectors are fully transformed in 3D, and the 2D polylines are updated by ignoring the resulting z after transform.

Source

pub fn translate(&self, x: Real, y: Real, z: Real) -> CSG<S>

Returns a new CSG translated by x, y, and z.

Source

pub fn translate_vector(&self, vector: Vector3<Real>) -> CSG<S>

Returns a new CSG translated by vector.

Source

pub fn center(&self) -> Self

Returns a new CSG translated so that its bounding-box center is at the origin (0,0,0).

Source

pub fn float(&self) -> Self

Translates the CSG so that its bottommost point(s) sit exactly at z=0.

  • Shifts all vertices up or down such that the minimum z coordinate of the bounding box becomes 0.
§Example
let csg = CSG::cube(1.0, 1.0, 3.0, None).translate(2.0, 1.0, -2.0);
let floated = csg.float();
assert_eq!(floated.bounding_box().mins.z, 0.0);
Source

pub fn rotate(&self, x_deg: Real, y_deg: Real, z_deg: Real) -> CSG<S>

Rotates the CSG by x_degrees, y_degrees, z_degrees

Source

pub fn scale(&self, sx: Real, sy: Real, sz: Real) -> CSG<S>

Scales the CSG by scale_x, scale_y, scale_z

Source

pub fn mirror(&self, plane: Plane) -> Self

Reflect (mirror) this CSG about an arbitrary plane plane.

The plane is specified by: plane.normal = the plane’s normal vector (need not be unit), plane.w = the dot-product with that normal for points on the plane (offset).

Returns a new CSG whose geometry is mirrored accordingly.

Source

pub fn distribute_arc( &self, count: usize, radius: Real, start_angle_deg: Real, end_angle_deg: Real, ) -> CSG<S>

Distribute this CSG count times around an arc (in XY plane) of radius, from start_angle_deg to end_angle_deg. Returns a new CSG with all copies (their polygons).

Source

pub fn distribute_linear( &self, count: usize, dir: Vector3<Real>, spacing: Real, ) -> CSG<S>

Distribute this CSG count times along a straight line (vector), each copy spaced by spacing. E.g. if dir=(1.0,0.0,0.0) and spacing=2.0, you get copies at x=0, x=2, x=4, … etc.

Source

pub fn distribute_grid( &self, rows: usize, cols: usize, dx: Real, dy: Real, ) -> CSG<S>

Distribute this CSG in a grid of rows x cols, with spacing dx, dy in XY plane. top-left or bottom-left depends on your usage of row/col iteration.

Source

pub fn subdivide_triangles(&self, levels: u32) -> CSG<S>

Subdivide all polygons in this CSG ‘levels’ times, returning a new CSG. This results in a triangular mesh with more detail.

Source

pub fn renormalize(&mut self)

Renormalize all polygons in this CSG by re-computing each polygon’s plane and assigning that plane’s normal to all vertices.

Source

pub fn ray_intersections( &self, origin: &Point3<Real>, direction: &Vector3<Real>, ) -> Vec<(Point3<Real>, Real)>

Casts a ray defined by origin + t * direction against all triangles of this CSG and returns a list of (intersection_point, distance), sorted by ascending distance.

§Parameters
  • origin: The ray’s start point.
  • direction: The ray’s direction vector.
§Returns

A Vec of (Point3<Real>, Real) where:

  • Point3<Real> is the intersection coordinate in 3D,
  • Real is the distance (the ray parameter t) from origin.
Source

pub fn bounding_box(&self) -> Aabb

Returns a [parry3d::bounding_volume::Aabb] by merging:

  1. The 3D bounds of all polygons.
  2. The 2D bounding rectangle of self.geometry, interpreted at z=0.
Source

pub fn tessellate(&self) -> CSG<S>

Triangulate each polygon in the CSG returning a CSG containing triangles

Source

pub fn to_trimesh(&self) -> SharedShape

Convert the polygons in this CSG to a Parry TriMesh. Useful for collision detection or physics simulations.

Source

pub fn mass_properties( &self, density: Real, ) -> (Real, Point3<Real>, Unit<Quaternion<Real>>)

Approximate mass properties using Rapier.

Source

pub fn to_rigid_body( &self, rb_set: &mut RigidBodySet, co_set: &mut ColliderSet, translation: Vector3<Real>, rotation: Vector3<Real>, density: Real, ) -> RigidBodyHandle

Create a Rapier rigid body + collider from this CSG, using an axis-angle rotation in 3D (the vector’s length is the rotation in radians, and its direction is the axis).

Source§

impl<S> CSG<S>
where S: Clone + Send + Sync + Debug,

Source

pub fn square(width: Real, length: Real, metadata: Option<S>) -> Self

Creates a 2D square in the XY plane.

§Parameters
  • width: the width of the square
  • length: the height of the square
  • metadata: optional metadata
§Example

let sq2 = CSG::square(2.0, 3.0, None);

Source

pub fn circle(radius: Real, segments: usize, metadata: Option<S>) -> Self

Creates a 2D circle in the XY plane.

Source

pub fn right_triangle(width: Real, height: Real, metadata: Option<S>) -> Self

Right triangle from (0,0) to (width,0) to (0,height).

Source

pub fn polygon(points: &[[Real; 2]], metadata: Option<S>) -> Self

Creates a 2D polygon in the XY plane from a list of [x, y] points.

§Parameters
  • points: a sequence of 2D points (e.g. [[0.0,0.0], [1.0,0.0], [0.5,1.0]]) describing the polygon boundary in order.
§Example

let pts = vec![[0.0, 0.0], [2.0, 0.0], [1.0, 1.5]]; let poly2d = CSG::polygon(&pts, metadata);

Source

pub fn rounded_rectangle( width: Real, height: Real, corner_radius: Real, corner_segments: usize, metadata: Option<S>, ) -> Self

Rounded rectangle in XY plane, from (0,0) to (width,height) with radius for corners. corner_segments controls the smoothness of each rounded corner.

Source

pub fn ellipse( width: Real, height: Real, segments: usize, metadata: Option<S>, ) -> Self

Ellipse in XY plane, centered at (0,0), with full width width, full height height. segments is the number of polygon edges approximating the ellipse.

Source

pub fn regular_ngon(sides: usize, radius: Real, metadata: Option<S>) -> Self

Regular N-gon in XY plane, centered at (0,0), with circumscribed radius radius. sides is how many edges (>=3).

Source

pub fn trapezoid( top_width: Real, bottom_width: Real, height: Real, top_offset: Real, metadata: Option<S>, ) -> Self

Trapezoid from (0,0) -> (bottom_width,0) -> (top_width+top_offset,height) -> (top_offset,height) Note: this is a simple shape that can represent many trapezoids or parallelograms.

Source

pub fn star( num_points: usize, outer_radius: Real, inner_radius: Real, metadata: Option<S>, ) -> Self

Star shape (typical “spiky star”) with num_points, outer_radius, inner_radius. The star is centered at (0,0).

Source

pub fn teardrop_outline( width: Real, length: Real, segments: usize, metadata: Option<S>, ) -> CSG<S>

Teardrop shape. A simple approach:

  • a circle arc for the “round” top
  • it tapers down to a cusp at bottom. This is just one of many possible “teardrop” definitions.
Source

pub fn egg_outline( width: Real, length: Real, segments: usize, metadata: Option<S>, ) -> CSG<S>

Egg outline. Approximate an egg shape using a parametric approach. This is only a toy approximation. It creates a closed “egg-ish” outline around the origin.

Source

pub fn squircle( width: Real, height: Real, segments: usize, metadata: Option<S>, ) -> CSG<S>

Squircle (superellipse) centered at (0,0) with bounding box width×height. We use an exponent = 4.0 for “classic” squircle shape. segments controls the resolution.

Source

pub fn keyhole( circle_radius: Real, handle_width: Real, handle_height: Real, segments: usize, metadata: Option<S>, ) -> CSG<S>

Keyhole shape (simple version): a large circle + a rectangle “handle”. This does not have a hole. If you want a literal hole, you’d do difference ops. Here we do union of a circle and a rectangle.

Source

pub fn reuleaux_polygon( sides: usize, diameter: Real, circle_segments: usize, metadata: Option<S>, ) -> CSG<S>

Reuleaux polygon (constant–width curve) built as the intersection of sides equal–radius disks whose centres are the vertices of a regular n-gon.

  • sides ≥ 3
  • diameter desired constant width (equals the distance between adjacent vertices, i.e. the polygon’s edge length)
  • circle_segments how many segments to use for each disk

For sides == 3 this gives the canonical Reuleaux triangle; for any larger sides it yields the natural generalisation (odd-sided shapes retain constant width, even-sided ones do not but are still smooth).

Source

pub fn ring( id: Real, thickness: Real, segments: usize, metadata: Option<S>, ) -> CSG<S>

Ring with inner diameter = id and (radial) thickness = thickness. Outer diameter = id + 2*thickness. This yields an annulus in the XY plane. segments controls how smooth the outer/inner circles are.

Internally, we do: outer = circle(outer_radius) inner = circle(inner_radius) ring = outer.difference(inner) Then we call flatten() to unify into a single shape that has a hole.

Source

pub fn pie_slice( radius: Real, start_angle_deg: Real, end_angle_deg: Real, segments: usize, metadata: Option<S>, ) -> CSG<S>

Create a 2D “pie slice” (wedge) in the XY plane.

  • radius: outer radius of the slice.
  • start_angle_deg: starting angle in degrees (measured from X-axis).
  • end_angle_deg: ending angle in degrees.
  • segments: how many segments to use to approximate the arc.
  • metadata: optional user metadata for this polygon.
Source

pub fn supershape( a: Real, b: Real, m: Real, n1: Real, n2: Real, n3: Real, segments: usize, metadata: Option<S>, ) -> CSG<S>

Create a 2D supershape in the XY plane, approximated by segments edges. The superformula parameters are typically: r(θ) = [ (|cos(mθ/4)/a|^n2 + |sin(mθ/4)/b|^n3) ^ (-1/n1) ] Adjust as needed for your use-case.

Source

pub fn circle_with_keyway( radius: Real, segments: usize, key_width: Real, key_depth: Real, metadata: Option<S>, ) -> CSG<S>

Creates a 2D circle with a rectangular keyway slot cut out on the +X side.

Source

pub fn circle_with_flat( radius: Real, segments: usize, flat_dist: Real, metadata: Option<S>, ) -> CSG<S>

Creates a 2D “D” shape (circle with one flat chord). radius is the circle radius, flat_dist is how far from the center the flat chord is placed.

  • If flat_dist == 0.0 => chord passes through center => a half-circle
  • If flat_dist < radius => chord is inside the circle => typical “D” shape

Solve for distance from center using width of flat: let half_c = chord_len / 2.0; let flat_dist = (radiusradius - half_chalf_c).sqrt();

Source

pub fn circle_with_two_flats( radius: Real, segments: usize, flat_dist: Real, metadata: Option<S>, ) -> CSG<S>

Circle with two parallel flat chords on opposing sides (e.g., “double D” shape). radius => circle radius segments => how many segments in the circle approximation flat_dist => half-distance between flats measured from the center.

  • chord at y=+flat_dist and chord at y=-flat_dist
Source

pub fn airfoil( code: &str, chord: Real, samples: usize, metadata: Option<S>, ) -> CSG<S>
where S: Clone + Send + Sync,

Generate a NACA 4-digit airfoil (e.g. “2412”, “0015”).

  • code – 4 ASCII digits describing camber, camber-pos, thickness
  • chord – physical chord length you want (same units as the rest of your model)
  • samples – number of points per surface (≥ 10 is sensible; NP total = 2 × samples + 1)

The function returns a single closed polygon lying in the XY plane with its leading edge at the origin and the chord running along +X.

Source

pub fn bezier( control: &[[Real; 2]], segments: usize, metadata: Option<S>, ) -> Self

Sample an arbitrary-degree Bézier curve (de Casteljau). Returns a poly-line (closed if the first = last point).

  • control: list of 2-D control points
  • segments: number of straight-line segments used for the tessellation
Source

pub fn bspline( control: &[[Real; 2]], p: usize, segments_per_span: usize, metadata: Option<S>, ) -> Self

Sample an open-uniform B-spline of arbitrary degree (p) using the Cox-de Boor recursion. Returns a poly-line (or a filled region if closed).

  • control: control points
  • p: spline degree (e.g. 3 for a cubic)
  • segments_per_span: tessellation resolution inside every knot span
Source

pub fn involute_gear_2d( module_: Real, teeth: usize, pressure_angle_deg: Real, clearance: Real, backlash: Real, segments_per_flank: usize, metadata: Option<S>, ) -> CSG<S>

Involute gear outline (2‑D).

Source

pub fn cycloidal_gear_2d( module_: Real, teeth: usize, pin_teeth: usize, clearance: Real, segments_per_flank: usize, metadata: Option<S>, ) -> CSG<S>

(Epicyclic) cycloidal gear outline (2‑D).

Source

pub fn involute_rack_2d( module_: Real, num_teeth: usize, pressure_angle_deg: Real, clearance: Real, backlash: Real, metadata: Option<S>, ) -> CSG<S>

Linear involute rack profile (lying in the XY plane, pitch‑line on Y = 0). The returned polygon is CCW and spans num_teeth pitches along +X.

Source

pub fn cycloidal_rack_2d( module_: Real, num_teeth: usize, generating_radius: Real, clearance: Real, segments_per_flank: usize, metadata: Option<S>, ) -> CSG<S>

Linear cycloidal rack profile. The cycloidal rack is generated by rolling a circle of radius r_p along the rack’s pitch‑line. The flanks become a trochoid; for practical purposes we approximate with the classic curtate cycloid equations.

Source§

impl<S> CSG<S>
where S: Clone + Send + Sync + Debug,

Source

pub fn cube( width: Real, length: Real, height: Real, metadata: Option<S>, ) -> CSG<S>

Create a right prism (a box) that spans from (0, 0, 0) to (width, length, height). All dimensions must be >= 0.

Source

pub fn sphere( radius: Real, segments: usize, stacks: usize, metadata: Option<S>, ) -> CSG<S>

Construct a sphere with radius, segments, stacks

Source

pub fn frustum_ptp( start: Point3<Real>, end: Point3<Real>, radius1: Real, radius2: Real, segments: usize, metadata: Option<S>, ) -> CSG<S>

Constructs a frustum between start and end with bottom radius = radius1 and top radius = radius2. In the normal case, it creates side quads and cap triangles. However, if one of the radii is 0 (within EPSILON), then the degenerate face is treated as a single point and the side is stitched using triangles.

§Parameters
  • start: the center of the bottom face
  • end: the center of the top face
  • radius1: the radius at the bottom face
  • radius2: the radius at the top face
  • segments: number of segments around the circle (must be ≥ 3)
  • metadata: optional metadata
§Example
let bottom = Point3::new(0.0, 0.0, 0.0);
let top = Point3::new(0.0, 0.0, 5.0);
// This will create a cone (bottom degenerate) because radius1 is 0:
let cone = CSG::frustum_ptp_special(bottom, top, 0.0, 2.0, 32, None);
Source

pub fn frustum( radius1: Real, radius2: Real, height: Real, segments: usize, metadata: Option<S>, ) -> CSG<S>

A helper to create a vertical cylinder along Z from z=0..z=height with the specified radius (NOT diameter).

Source

pub fn cylinder( radius: Real, height: Real, segments: usize, metadata: Option<S>, ) -> CSG<S>

A helper to create a vertical cylinder along Z from z=0..z=height

Source

pub fn polyhedron( points: &[[Real; 3]], faces: &[Vec<usize>], metadata: Option<S>, ) -> CSG<S>

Creates a CSG polyhedron from raw vertex data (points) and face indices.

§Parameters
  • points: a slice of [x,y,z] coordinates.
  • faces: each element is a list of indices into points, describing one face. Each face must have at least 3 indices.
§Example
let pts = &[
    [0.0, 0.0, 0.0], // point0
    [1.0, 0.0, 0.0], // point1
    [1.0, 1.0, 0.0], // point2
    [0.0, 1.0, 0.0], // point3
    [0.5, 0.5, 1.0], // point4 - top
];

// Two faces: bottom square [0,1,2,3], and a pyramid side [0,1,4]
let fcs = vec![
    vec![0, 1, 2, 3],
    vec![0, 1, 4],
    vec![1, 2, 4],
    vec![2, 3, 4],
    vec![3, 0, 4],
];

let csg_poly = CSG::polyhedron(pts, &fcs);
Source

pub fn egg( width: Real, length: Real, revolve_segments: usize, outline_segments: usize, metadata: Option<S>, ) -> Self

Creates a 3D “egg” shape by revolving the existing 2D egg_outline profile.

§Parameters
  • width: The “width” of the 2D egg outline.
  • length: The “length” (height) of the 2D egg outline.
  • revolve_segments: Number of segments for the revolution.
  • outline_segments: Number of segments for the 2D egg outline itself.
  • metadata: Optional metadata.
Source

pub fn teardrop( width: Real, length: Real, revolve_segments: usize, shape_segments: usize, metadata: Option<S>, ) -> Self

Creates a 3D “teardrop” solid by revolving the existing 2D teardrop profile 360° around the Y-axis (via rotate_extrude).

§Parameters
  • width: Width of the 2D teardrop profile.
  • length: Length of the 2D teardrop profile.
  • revolve_segments: Number of segments for the revolution (the “circular” direction).
  • shape_segments: Number of segments for the 2D teardrop outline itself.
  • metadata: Optional metadata.
Source

pub fn teardrop_cylinder( width: Real, length: Real, height: Real, shape_segments: usize, metadata: Option<S>, ) -> Self

Creates a 3D “teardrop cylinder” by extruding the existing 2D teardrop in the Z+ axis.

§Parameters
  • width: Width of the 2D teardrop profile.
  • length: Length of the 2D teardrop profile.
  • revolve_segments: Number of segments for the revolution (the “circular” direction).
  • shape_segments: Number of segments for the 2D teardrop outline itself.
  • metadata: Optional metadata.
Source

pub fn ellipsoid( rx: Real, ry: Real, rz: Real, segments: usize, stacks: usize, metadata: Option<S>, ) -> Self

Creates an ellipsoid by taking a sphere of radius=1 and scaling it by (rx, ry, rz).

§Parameters
  • rx: X-axis radius.
  • ry: Y-axis radius.
  • rz: Z-axis radius.
  • segments: Number of horizontal segments.
  • stacks: Number of vertical stacks.
  • metadata: Optional metadata.
Source

pub fn arrow( start: Point3<Real>, direction: Vector3<Real>, segments: usize, orientation: bool, metadata: Option<S>, ) -> CSG<S>

Creates an arrow CSG. The arrow is composed of:

  • a cylindrical shaft, and
  • a cone–like head (a frustum from a larger base to a small tip) built along the canonical +Z axis. The arrow is then rotated so that +Z aligns with the given direction, and finally translated so that either its base (if orientation is false) or its tip (if orientation is true) is located at start.

The arrow’s dimensions (shaft radius, head dimensions, etc.) are scaled proportionally to the total arrow length (the norm of the provided direction).

§Parameters
  • start: the reference point (base or tip, depending on orientation)
  • direction: the vector defining arrow length and intended pointing direction
  • segments: number of segments for approximating the cylinder and frustum
  • orientation: when false (default) the arrow points away from start (its base is at start); when true the arrow points toward start (its tip is at start).
  • metadata: optional metadata for the generated polygons.
Source

pub fn gyroid( &self, resolution: usize, period: Real, iso_value: Real, metadata: Option<S>, ) -> CSG<S>

Generate a Triply Periodic Minimal Surface (Gyroid) inside the volume of self.

§Parameters
  • resolution: how many sampling steps along each axis (larger = finer mesh).
  • period: controls the spatial period of the gyroid function. Larger = repeats more slowly.
  • iso_value: the implicit surface is f(x,y,z) = iso_value. Usually 0.0 for a “standard” gyroid.
§Returns

A new CSG whose polygons approximate the gyroid surface inside the volume of self.

§Example
// Suppose `shape` is a CSG volume, e.g. a box or sphere.
let gyroid_csg = shape.tpms_gyroid(50, 2.0, 0.0);
Source

pub fn spur_gear_involute( module_: Real, teeth: usize, pressure_angle_deg: Real, clearance: Real, backlash: Real, segments_per_flank: usize, thickness: Real, metadata: Option<S>, ) -> CSG<S>

Source

pub fn spur_gear_cycloid( module_: Real, teeth: usize, pin_teeth: usize, clearance: Real, segments_per_flank: usize, thickness: Real, metadata: Option<S>, ) -> CSG<S>

Source

pub fn helical_involute_gear( module_: Real, teeth: usize, pressure_angle_deg: Real, clearance: Real, backlash: Real, segments_per_flank: usize, thickness: Real, helix_angle_deg: Real, slices: usize, metadata: Option<S>, ) -> CSG<S>

Source§

impl<S> CSG<S>
where S: Clone + Send + Sync + Debug,

Source

pub fn extrude(&self, height: Real) -> CSG<S>

Linearly extrude this (2D) shape in the +Z direction by height.

This is just a convenience wrapper around extrude_vector using Vector3::new(0.0, 0.0, height)

Source

pub fn extrude_vector(&self, direction: Vector3<Real>) -> CSG<S>

Linearly extrude any 2D geometry (Polygons, MultiPolygons, or sub-geometries in a GeometryCollection) in self.geometry along the given direction.

Builds top, bottom, and side polygons in 3D, storing them in csg.polygons. Returns a new CSG containing these extruded polygons (plus any existing 3D polygons you already had in self.polygons).

Source

pub fn extrude_between( bottom: &Polygon<S>, top: &Polygon<S>, flip_bottom_polygon: bool, ) -> CSG<S>

Extrudes (or “lofts”) a closed 3D volume between two polygons in space.

  • bottom and top each have the same number of vertices n, in matching order.
  • Returns a new CSG whose faces are:
    • The bottom polygon,
    • The top polygon,
    • n rectangular side polygons bridging each edge of bottom to the corresponding edge of top.
Source

pub fn rotate_extrude(&self, angle_degs: Real, segments: usize) -> CSG<S>

Rotate-extrude (revolve) only the Polygon and MultiPolygon geometry in self.geometry around the Y-axis from 0..angle_degs in segments steps, producing side walls in an orientation consistent with the polygon’s winding.

  • Ignores self.polygons.
  • Returns a new CSG containing only the newly extruded side polygons (no end caps).
  • angle_degs: how far to revolve, in degrees (e.g. 360 for a full revolve).
  • segments: number of subdivisions around the revolve.
§Key Points
  • Only 2D geometry in self.geometry is used. Any self.polygons are ignored.
  • Axis of revolution: Y-axis. We treat each ring’s (x,y) -> revolve_around_y(x,y,theta).
  • Exterior rings (CCW in Geo) produce outward-facing side polygons.
  • Interior rings (CW) produce inward-facing side polygons (“holes”).
  • If angle_degs < 360, we add two caps: one at angle=0, one at angle=angle_degs.
    • Cap orientation is set so that normals face outward, consistent with a solid.
  • Returns a new CSG with .polygons containing only the side walls + any caps. The .geometry is empty, i.e. GeometryCollection::default().
Source§

impl<S: Clone + Debug + Send + Sync> CSG<S>

Source

pub fn to_stl_ascii(&self, name: &str) -> String

Export to ASCII STL

  1. 3D polygons in self.polygons,
  2. any 2D Polygons or MultiPolygons in self.geometry (tessellated in XY).

Convert this CSG to an ASCII STL string with the given name.

let csg = CSG::cube(None);
let stl_text = csg.to_stl("my_solid");
println!("{}", stl_text);
Source

pub fn to_stl_binary(&self, _name: &str) -> Result<Vec<u8>>

Export to BINARY STL (returns Vec)

Convert this CSG to a binary STL byte vector with the given name.

The resulting Vec<u8> can then be written to a file or handled in memory:

let bytes = csg.to_stl_binary("my_solid")?;
std::fs::write("my_solid.stl", bytes)?;
Source

pub fn from_stl(stl_data: &[u8], metadata: Option<S>) -> Result<CSG<S>, Error>

Create a CSG object from STL data using stl_io.

Source§

impl<S: Clone + Debug + Send + Sync> CSG<S>

Source

pub fn from_dxf( dxf_data: &[u8], metadata: Option<S>, ) -> Result<CSG<S>, Box<dyn Error>>

Import a CSG object from DXF data.

§Parameters
  • dxf_data: A byte slice containing the DXF file data.
  • metadata: metadata that will be attached to all polygons of the resulting CSG
§Returns

A Result containing the CSG object or an error if parsing fails.

Source

pub fn to_dxf(&self) -> Result<Vec<u8>, Box<dyn Error>>

Export the CSG object to DXF format.

§Returns

A Result containing the DXF file as a byte vector or an error if exporting fails.

Source§

impl<S> CSG<S>
where S: Clone + Send + Sync + Debug,

Source

pub fn flatten(&self) -> CSG<S>

Flattens any 3D polygons by projecting them onto the XY plane (z=0), unifies them into one or more 2D polygons, and returns a purely 2D CSG.

  • If this CSG is already 2D (self.polygons is empty), just returns self.clone().
  • Otherwise, all polygons are tessellated, projected into XY, and unioned.
  • We also union any existing 2D geometry (self.geometry).
  • The output has .polygons empty and .geometry containing the final 2D shape.
Source

pub fn slice(&self, plane: Plane) -> CSG<S>

Slice this solid by a given plane, returning a new CSG whose polygons are either:

  • The polygons that lie exactly in the slicing plane (coplanar), or
  • Polygons formed by the intersection edges (each a line, possibly open or closed).

The returned CSG can contain:

  • Closed polygons that are coplanar,
  • Open polygons (poly-lines) if the plane cuts through edges,
  • Potentially closed loops if the intersection lines form a cycle.
§Example
let cylinder = CSG::cylinder(1.0, 2.0, 32, None);
let plane_z0 = Plane { normal: Vector3::z(), w: 0.0 };
let cross_section = cylinder.slice(plane_z0);
// `cross_section` will contain:
//   - Possibly an open or closed polygon(s) at z=0
//   - Or empty if no intersection
Source

pub fn is_manifold(&self) -> bool

Checks if the CSG object is manifold.

This function defines a comparison function which takes EPSILON into account for Real coordinates, builds a hashmap key from the string representation of the coordinates, tessellates the CSG polygons, gathers each of their three edges, counts how many times each edge appears across all triangles, and returns true if every edge appears exactly 2 times, else false.

We should also check that all faces have consistent orientation and no neighbors have flipped normals.

We should also check for zero-area triangles

§Returns
  • true: If the CSG object is manifold.
  • false: If the CSG object is not manifold.
Source§

impl<S> CSG<S>
where S: Clone + Send + Sync + Debug,

Source

pub fn text( text: &str, font_data: &[u8], scale: Real, metadata: Option<S>, ) -> Self

Create 2D text (outlines only) in the XY plane using ttf-utils + ttf-parser.

Each glyph’s closed contours become one or more Polygons (with holes if needed), and any open contours become LineStrings.

§Arguments
  • text: the text string (no multiline logic here)
  • font_data: raw bytes of a TTF file
  • scale: a uniform scale factor for glyphs
  • metadata: optional metadata for the resulting CSG
§Returns

A CSG whose geometry contains:

  • One or more Polygons for each glyph,
  • A set of LineStrings for any open contours (rare in standard fonts), all positioned in the XY plane at z=0.
Source§

impl<S> CSG<S>
where S: Clone + Send + Sync + Debug,

Source

pub fn offset(&self, distance: Real) -> CSG<S>

Grows/shrinks/offsets all polygons in the XY plane by distance using cavalier_contours parallel_offset. for each Polygon we convert to a cavalier_contours Polyline and call parallel_offset

Source§

impl<S: Clone + Debug + Send + Sync> CSG<S>

Source

pub fn convex_hull(&self) -> CSG<S>

Compute the convex hull of all vertices in this CSG.

Source

pub fn minkowski_sum(&self, other: &CSG<S>) -> CSG<S>

Compute the Minkowski sum: self ⊕ other

Naive approach: Take every vertex in self, add it to every vertex in other, then compute the convex hull of all resulting points.

Source§

impl<S> CSG<S>
where S: Clone + Send + Sync + Debug,

Source

pub fn sdf<F>( sdf: F, resolution: (usize, usize, usize), min_pt: Point3<Real>, max_pt: Point3<Real>, iso_value: Real, metadata: Option<S>, ) -> CSG<S>
where F: Fn(&Point3<Real>) -> Real + Sync + Send,

Return a CSG created by meshing a signed distance field within a bounding box

// Example SDF for a sphere of radius 1.5 centered at (0,0,0) let my_sdf = |p: &Point3| p.coords.norm() - 1.5;

let resolution = (60, 60, 60); let min_pt = Point3::new(-2.0, -2.0, -2.0); let max_pt = Point3::new( 2.0, 2.0, 2.0); let iso_value = 0.0; // Typically zero for SDF-based surfaces

let csg_shape = CSG::from_sdf(my_sdf, resolution, min_pt, max_pt, iso_value);

// Now csg_shape is your polygon mesh as a CSG you can union, subtract, or export: let _ = std::fs::write(“stl/sdf_sphere.stl”, csg_shape.to_stl_binary(“sdf_sphere”).unwrap());

Source§

impl<S> CSG<S>
where S: Clone + Send + Sync + Debug,

Source

pub fn metaballs2d( balls: &[(Point2<Real>, Real)], resolution: (usize, usize), iso_value: Real, padding: Real, metadata: Option<S>, ) -> CSG<S>

Create a 2D metaball iso-contour in XY plane from a set of 2D metaballs.

  • balls: array of (center, radius).
  • resolution: (nx, ny) grid resolution for marching squares.
  • iso_value: threshold for the iso-surface.
  • padding: extra boundary beyond each ball’s radius.
  • metadata: optional user metadata.
Source

pub fn metaballs( balls: &[MetaBall], resolution: (usize, usize, usize), iso_value: Real, padding: Real, metadata: Option<S>, ) -> CSG<S>

Creates a CSG from a list of metaballs by sampling a 3D grid and using marching cubes.

  • balls: slice of metaball definitions (center + radius).
  • resolution: (nx, ny, nz) defines how many steps along x, y, z.
  • iso_value: threshold at which the isosurface is extracted.
  • padding: extra margin around the bounding region (e.g. 0.5) so the surface doesn’t get truncated.

Trait Implementations§

Source§

impl<S: Clone + Clone> Clone for CSG<S>

Source§

fn clone(&self) -> CSG<S>

Returns a copy of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<S: Debug + Clone> Debug for CSG<S>

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl<S> Freeze for CSG<S>
where S: Freeze,

§

impl<S> RefUnwindSafe for CSG<S>
where S: RefUnwindSafe,

§

impl<S> Send for CSG<S>
where S: Send,

§

impl<S> Sync for CSG<S>
where S: Sync,

§

impl<S> Unpin for CSG<S>
where S: Unpin,

§

impl<S> UnwindSafe for CSG<S>
where S: UnwindSafe,

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_sync(self: Box<T>) -> Box<dyn Any + Sync + Send>

Converts Box<Trait> (where Trait: DowncastSync) to Box<dyn Any + Send + Sync>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Converts Arc<Trait> (where Trait: DowncastSync) to Arc<Any>, which can then be downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<SS, SP> SupersetOf<SS> for SP
where SS: SubsetOf<SP>,

Source§

fn to_subset(&self) -> Option<SS>

The inverse inclusion map: attempts to construct self from the equivalent element of its superset. Read more
Source§

fn is_in_subset(&self) -> bool

Checks if self is actually part of its subset T (and can be converted to it).
Source§

fn to_subset_unchecked(&self) -> SS

Use with care! Same as self.to_subset but without any property checks. Always succeeds.
Source§

fn from_subset(element: &SS) -> SP

The inclusion map: converts self to the equivalent element of its superset.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<G1, G2> Within<G2> for G1
where G2: Contains<G1>,

Source§

fn is_within(&self, b: &G2) -> bool