UNPKG

manifold-3d

Version:

Geometry library for topological robustness

1,322 lines (1,183 loc) 60.7 kB
/** * The core WASM bindings with no frills. * * @packageDocumentation * @primaryExport * @group none * @see {@link "Using Manifold" | Using Manifold} * @see {@link "Manifold Examples" | Manifold Examples} */ /** * A three dimensional box, aligned to the coordinate system. * * @see {@link Manifold.boundingBox} * @see {@link Manifold.levelSet} */ export declare type Box = { min: Vec3, max: Vec3 }; /** * Two-dimensional cross sections guaranteed to be without self-intersections, * or overlaps between polygons (from construction onwards). This class makes * use of the Clipper2 library for polygon clipping (boolean) and offsetting * operations. * * @see {@link https://manifoldcad.org/docs/html/classmanifold_1_1_cross_section.html | C++ API: CrossSection Class Reference} * @see {@link https://www.angusj.com/clipper2/Docs/Overview.htm | Clipper2 - Polygon Clipping Offsetting & Triangulating} * @group Basics */ export declare class CrossSection { /** * Create a 2d cross-section from a set of contours (complex polygons). A * boolean union operation (with Positive filling rule by default) is * performed to combine overlapping polygons and ensure the resulting * CrossSection is free of intersections. * * @param contours A set of closed paths describing zero or more complex * polygons. * @param fillRule The filling rule used to interpret polygon sub-regions in * contours. * @group Basics */ constructor(contours: Polygons, fillRule?: FillRule); // Shapes /** * Constructs a square with the given XY dimensions. By default it is * positioned in the first quadrant, touching the origin. If any dimensions in * size are negative, or if all are zero, an empty Manifold will be returned. * * @param size The X, and Y dimensions of the square. * @param center Set to true to shift the center to the origin. * @group Constructors */ static square(size?: Readonly<Vec2>|number, center?: boolean): CrossSection; /** * Constructs a circle of a given radius. * * @param radius Radius of the circle. Must be positive. * @param circularSegments Number of segments along its diameter. Default is * calculated by the static Quality defaults according to the radius. * @group Constructors */ static circle(radius: number, circularSegments?: number): CrossSection; // Extrusions (2d to 3d manifold) /** * Constructs a manifold by extruding the cross-section along Z-axis. * * @param height Z-extent of extrusion. * @param nDivisions Number of extra copies of the crossSection to insert into * the shape vertically; especially useful in combination with twistDegrees to * avoid interpolation artifacts. Default is none. * @param twistDegrees Amount to twist the top crossSection relative to the * bottom, interpolated linearly for the divisions in between. * @param scaleTop Amount to scale the top (independently in X and Y). If the * scale is {0, 0}, a pure cone is formed with only a single vertex at the * top. Default {1, 1}. * @param center If true, the extrusion is centered on the z-axis through the * origin * as opposed to resting on the XY plane as is default. * @group Transformations */ extrude( height: number, nDivisions?: number, twistDegrees?: number, scaleTop?: Readonly<Vec2>|number, center?: boolean): Manifold; /** * Constructs a manifold by revolving this cross-section around its Y-axis and * then setting this as the Z-axis of the resulting manifold. If the contours * cross the Y-axis, only the part on the positive X side is used. * Geometrically valid input will result in geometrically valid output. * * @param circularSegments Number of segments along its diameter. Default is * calculated by the static Defaults. * @group Transformations */ revolve(circularSegments?: number, revolveDegrees?: number): Manifold; // Transformations /** * Transform this CrossSection in space. Stored in column-major order. This * operation can be chained. Transforms are combined and applied lazily. * * @param m The affine transformation matrix to apply to all the vertices. The * last row is ignored. * @group Transformations */ transform(m: Mat3): CrossSection; /** * Move this CrossSection in space. This operation can be chained. Transforms * are combined and applied lazily. * * @param v The vector to add to every vertex. * @group Transformations */ translate(v: Readonly<Vec2>): CrossSection; translate(x: number, y?: number): CrossSection; /** * Applies a (Z-axis) rotation to the CrossSection, in degrees. This operation * can be chained. Transforms are combined and applied lazily. * * @param degrees degrees about the Z-axis to rotate. * @group Transformations */ rotate(degrees: number): CrossSection; /** * Scale this CrossSection in space. This operation can be chained. Transforms * are combined and applied lazily. * * @param v The vector to multiply every vertex by per component. * @group Transformations */ scale(v: Readonly<Vec2>|number): CrossSection; /** * Mirror this CrossSection over the arbitrary axis described by the unit form * of the given vector. If the length of the vector is zero, an empty * CrossSection is returned. This operation can be chained. Transforms are * combined and applied lazily. * * @param ax the axis to be mirrored over * @group Transformations */ mirror(ax: Readonly<Vec2>): CrossSection; /** * Move the vertices of this CrossSection (creating a new one) according to * any arbitrary input function, followed by a union operation (with a * Positive fill rule) that ensures any introduced intersections are not * included in the result. * * @param warpFunc A function that modifies a given vertex position. * @group Transformations */ warp(warpFunc: (vert: Vec2) => void): CrossSection; /** * Inflate the contours in CrossSection by the specified delta, handling * corners according to the given JoinType. * * @param delta Positive deltas will cause the expansion of outlining contours * to expand, and retraction of inner (hole) contours. Negative deltas will * have the opposite effect. * @param joinType The join type specifying the treatment of contour joins * (corners). Defaults to Round * @param miterLimit The maximum distance in multiples of delta that vertices * can be offset from their original positions with before squaring is * applied, **when the join type is Miter** (default is 2, which is the * minimum allowed). See the [Clipper2 * MiterLimit](http://www.angusj.com/clipper2/Docs/Units/Clipper.Offset/Classes/ClipperOffset/Properties/MiterLimit.htm) * page for a visual example. * @param circularSegments Number of segments per 360 degrees of * <B>JoinType::Round</B> corners (roughly, the number of vertices that * will be added to each contour). Default is calculated by the static Quality * defaults according to the radius. * @group Transformations */ offset( delta: number, joinType?: JoinType, miterLimit?: number, circularSegments?: number): CrossSection; /** * Remove vertices from the contours in this CrossSection that are less than * the specified distance epsilon from an imaginary line that passes through * its two adjacent vertices. Near duplicate vertices and collinear points * will be removed at lower epsilons, with elimination of line segments * becoming increasingly aggressive with larger epsilons. * * It is recommended to apply this function following Offset, in order to * clean up any spurious tiny line segments introduced that do not improve * quality in any meaningful way. This is particularly important if further * offseting operations are to be performed, which would compound the issue. * * @param epsilon minimum distance vertices must diverge from the hypothetical * outline without them in order to be included in the output (default * 1e-6) * @group Transformations */ simplify(epsilon?: number): CrossSection; // Clipping Operations /** * Boolean union * @group Boolean */ add(other: CrossSection|Polygons): CrossSection; /** * Boolean difference * @group Boolean */ subtract(other: CrossSection|Polygons): CrossSection; /** * Boolean intersection * @group Boolean */ intersect(other: CrossSection|Polygons): CrossSection; /** * Boolean union of the cross-sections a and b * @group Boolean */ static union(a: CrossSection|Polygons, b: CrossSection|Polygons): CrossSection; /** * Boolean difference of the cross-section b from the cross-section a * @group Boolean */ static difference(a: CrossSection|Polygons, b: CrossSection|Polygons): CrossSection; /** * Boolean intersection of the cross-sections a and b * @group Boolean */ static intersection(a: CrossSection|Polygons, b: CrossSection|Polygons): CrossSection; /** * Boolean union of a list of cross-sections * @group Boolean */ static union(polygons: readonly(CrossSection|Polygons)[]): CrossSection; /** * Boolean difference of the tail of a list of cross-sections from its head * @group Boolean */ static difference(polygons: readonly(CrossSection|Polygons)[]): CrossSection; /** * Boolean intersection of a list of cross-sections */ static intersection(polygons: readonly(CrossSection|Polygons)[]): CrossSection; // Convex Hulls /** * Compute the convex hull of the contours in this CrossSection. * @group Convex Hull */ hull(): CrossSection; /** * Compute the convex hull of all points in a list of polygons/cross-sections. * @group Convex Hull */ static hull(polygons: readonly(CrossSection|Polygons)[]): CrossSection; // Topological Operations /** * Construct a CrossSection from a vector of other Polygons (batch * boolean union). * @group Boolean */ static compose(polygons: readonly(CrossSection|Polygons)[]): CrossSection; /** * This operation returns a vector of CrossSections that are topologically * disconnected, each containing one outline contour with zero or more * holes. * @group Constructors */ decompose(): CrossSection[]; // Polygon Conversion /** * Create a 2d cross-section from a set of contours (complex polygons). A * boolean union operation (with Positive filling rule by default) is * performed to combine overlapping polygons and ensure the resulting * CrossSection is free of intersections. * * @param contours A set of closed paths describing zero or more complex * polygons. * @param fillRule The filling rule used to interpret polygon sub-regions in * contours. * @group Input & Output */ static ofPolygons(contours: Polygons, fillRule?: FillRule): CrossSection; /** * Return the contours of this CrossSection as a list of simple polygons. * @group Input & Output */ toPolygons(): SimplePolygon[]; // Properties /** * Return the total area covered by complex polygons making up the * CrossSection. * @group Information */ area(): number; /** * Does the CrossSection (not) have any contours? * @group Information */ isEmpty(): boolean; /** * The number of vertices in the CrossSection. * @group Information */ numVert(): number; /** * The number of contours in the CrossSection. * @group Information */ numContour(): number; /** * Returns the axis-aligned bounding rectangle of all the CrossSection's * vertices. * @group Information */ bounds(): Rect; // Memory /** * Frees the WASM memory of this CrossSection, since these cannot be * garbage-collected automatically. * @group Basics */ delete(): void; } /** * @see {@link Manifold.status} */ export declare type ErrorStatus = 'NoError'|'NonFiniteVertex'|'NotManifold'| 'VertexOutOfBounds'|'PropertiesWrongLength'|'MissingPositionProperties'| 'MergeVectorsDifferentLengths'|'MergeIndexOutOfBounds'| 'TransformWrongLength'|'RunIndexWrongLength'|'FaceIDWrongLength'| 'InvalidConstruction'|'ResultTooLarge'|'InvalidTangents'|'Cancelled'; /** * Observe and control a long-running Manifold evaluation. Attach to a * Manifold via Manifold.withContext(); the next eager op invoked on the * result (status(), one of the refine* family, hull(), or minkowskiSum() / * minkowskiDifference()) snapshots the ctx and reports progress / observes * cancellation through it. Deferred ops (Boolean, transforms, batch ops) * ignore any attached ctx. Safe to read/write from any thread/worker. * * Cancellation is permanent for a Manifold: once cancelled and detected, * the Manifold's status becomes 'Cancelled' and stays 'Cancelled'. */ export declare interface ExecutionContext { /** Request cancellation. Can be called from any context. Idempotent. */ cancel(): void; /** Has cancellation been requested? */ cancelled(): boolean; /** * Normalized progress in [0, 1]. Monotonic within an evaluation. * Returns 1 when no work has been scheduled (interpreted as trivially * complete -- e.g. a single-leaf manifold has nothing to evaluate). */ progress(): number; // Memory /** * Frees the WASM memory of this ExecutionContext, since these cannot be * garbage-collected automatically. * @group Basics */ delete(): void; } export declare type FillRule = 'EvenOdd'|'NonZero'|'Positive'|'Negative'; /** * Determine the result of the {@link setMinCircularAngle}, * {@link setMinCircularEdgeLength}, and {@link setCircularSegments} defaults. * * @param radius For a given radius of circle, determine how many default * segments there will be. */ export declare function getCircularSegments(radius: number): number; export declare type JoinType = 'Square'|'Round'|'Miter'; /** * This library's internal representation of an oriented, 2-manifold, triangle * mesh - a simple boundary-representation of a solid object. Use this class to * store and operate on solids, and use MeshGL for input and output, or * potentially Mesh if only basic geometry is required. * * In addition to storing geometric data, a Manifold can also store an arbitrary * number of vertex properties. These could be anything, e.g. normals, UV * coordinates, colors, etc, but this library is completely agnostic. All * properties are merely float values indexed by channel number. It is up to the * user to associate channel numbers with meaning. * * Manifold allows vertex properties to be shared for efficient storage, or to * have multiple property verts associated with a single geometric vertex, * allowing sudden property changes, e.g. at Boolean intersections, without * sacrificing manifoldness. * * Manifolds also keep track of their relationships to their inputs, via * OriginalIDs and the faceIDs and transforms accessible through MeshGL. This * allows object-level properties to be re-associated with the output after many * operations, particularly useful for materials. Since separate object's * properties are not mixed, there is no requirement that channels have * consistent meaning between different inputs. * * @see {@link https://manifoldcad.org/docs/html/classmanifold_1_1_manifold.html | C++ API: Manifold Class Reference} * @group Basics */ export declare class Manifold { /** * Convert a Mesh into a Manifold, retaining its properties and merging only * the positions according to the merge vectors. Will throw an error if the * result is not an oriented 2-manifold. Will collapse degenerate triangles * and unnecessary vertices. * * All fields are read, making this structure suitable for a lossless * round-trip of data from getMesh(). For multi-material input, use * reserveIDs() to set a unique originalID for each material, and sort the * materials into triangle runs. * * @group Basics */ constructor(mesh: Mesh); // Shapes /** * Constructs a tetrahedron centered at the origin with one vertex at (1,1,1) * and the rest at similarly symmetric points. * @group Constructors */ static tetrahedron(): Manifold; /** * Constructs a unit cube (edge lengths all one), by default in the first * octant, touching the origin. * * @param size The X, Y, and Z dimensions of the box. * @param center Set to true to shift the center to the origin. * @group Constructors */ static cube(size?: Readonly<Vec3>|number, center?: boolean): Manifold; /** * A convenience constructor for the common case of extruding a circle. Can * also form cones if both radii are specified. * * @param height Z-extent * @param radiusLow Radius of bottom circle. Must be positive. * @param radiusHigh Radius of top circle. Can equal zero. Default is equal to * radiusLow. * @param circularSegments How many line segments to use around the circle. * Default is calculated by the static Defaults. * @param center Set to true to shift the center to the origin. Default is * origin at the bottom. * @group Constructors */ static cylinder( height: number, radiusLow: number, radiusHigh?: number, circularSegments?: number, center?: boolean): Manifold; /** * Constructs a geodesic sphere of a given radius. * * @param radius Radius of the sphere. Must be positive. * @param circularSegments Number of segments along its * diameter. This number will always be rounded up to the nearest factor of * four, as this sphere is constructed by refining an octahedron. This means * there are a circle of vertices on all three of the axis planes. Default is * calculated by the static Defaults. * @group Constructors */ static sphere(radius: number, circularSegments?: number): Manifold; // Extrusions from 2d shapes /** * Constructs a manifold from a set of polygons/cross-section by extruding * them along the Z-axis. * * @param polygons A set of non-overlapping polygons to extrude. * @param height Z-extent of extrusion. * @param nDivisions Number of extra copies of the crossSection to insert into * the shape vertically; especially useful in combination with twistDegrees to * avoid interpolation artifacts. Default is none. * @param twistDegrees Amount to twist the top crossSection relative to the * bottom, interpolated linearly for the divisions in between. * @param scaleTop Amount to scale the top (independently in X and Y). If the * scale is {0, 0}, a pure cone is formed with only a single vertex at the * top. Default {1, 1}. * @param center If true, the extrusion is centered on the z-axis through the * origin * as opposed to resting on the XY plane as is default. * @group Polygons */ static extrude( polygons: CrossSection|Polygons, height: number, nDivisions?: number, twistDegrees?: number, scaleTop?: Readonly<Vec2>|number, center?: boolean): Manifold; /** * Constructs a manifold from a set of polygons/cross-section by revolving * them around the Y-axis and then setting this as the Z-axis of the resulting * manifold. If the polygons cross the Y-axis, only the part on the positive X * side is used. Geometrically valid input will result in geometrically valid * output. * * @param polygons A set of non-overlapping polygons to revolve. * @param circularSegments Number of segments along its diameter. Default is * calculated by the static Defaults. * @param revolveDegrees Number of degrees to revolve. Default is 360 degrees. * @group Polygons */ static revolve( polygons: CrossSection|Polygons, circularSegments?: number, revolveDegrees?: number): Manifold; // Mesh Conversion /** * Convert a Mesh into a Manifold, retaining its properties and merging only * the positions according to the merge vectors. Will throw an error if the * result is not an oriented 2-manifold. Will collapse degenerate triangles * and unnecessary vertices. * * All fields are read, making this structure suitable for a lossless * round-trip of data from getMesh(). For multi-material input, use * reserveIDs() to set a unique originalID for each material, and sort the * materials into triangle runs. * @group Input & Output */ static ofMesh(mesh: Mesh): Manifold; /** * Constructs a smooth version of the input mesh by creating tangents; this * method will throw if you have supplied tangents with your mesh already. The * actual triangle resolution is unchanged; use the Refine() method to * interpolate to a higher-resolution curve. * * By default, every edge is calculated for maximum smoothness (very much * approximately), attempting to minimize the maximum mean Curvature * magnitude. No higher-order derivatives are considered, as the interpolation * is independent per triangle, only sharing constraints on their boundaries. * * @param mesh input Mesh. * @param sharpenedEdges If desired, you can supply a vector of sharpened * halfedges, which should in general be a small subset of all halfedges. * Order of entries doesn't matter, as each one specifies the desired * smoothness (between zero and one, with one the default for all unspecified * halfedges) and the halfedge index (3 * triangle index + [0,1,2] where 0 is * the edge between triVert 0 and 1, etc). * * At a smoothness value of zero, a sharp crease is made. The smoothness is * interpolated along each edge, so the specified value should be thought of * as an average. Where exactly two sharpened edges meet at a vertex, their * tangents are rotated to be colinear so that the sharpened edge can be * continuous. Vertices with only one sharpened edge are completely smooth, * allowing sharpened edges to smoothly vanish at termination. A single vertex * can be sharpened by sharping all edges that are incident on it, allowing * cones to be formed. * * @group Smoothing */ static smooth(mesh: Mesh, sharpenedEdges?: readonly Smoothness[]): Manifold; // Signed Distance Functions /** * Constructs a level-set Mesh from the input Signed-Distance Function (SDF). * This uses a form of Marching Tetrahedra (akin to Marching Cubes, but better * for manifoldness). Instead of using a cubic grid, it uses a body-centered * cubic grid (two shifted cubic grids). This means if your function's * interior exceeds the given bounds, you will see a kind of egg-crate shape * closing off the manifold, which is due to the underlying grid. * * @param sdf The signed-distance function which returns the signed distance * of * a given point in R^3. Positive values are inside, negative outside. * @param bounds An axis-aligned box that defines the extent of the grid. * @param edgeLength Approximate maximum edge length of the triangles in the * final result. This affects grid spacing, and hence has a strong effect on * performance. * @param level You can inset your Mesh by using a positive value, or outset * it with a negative value. * @param tolerance Ensure each vertex is within this distance of the true * surface. Defaults to -1, which will return the interpolated * crossing-point based on the two nearest grid points. Small positive values * will require more sdf evaluations per output vertex. * @group Constructors */ static levelSet( sdf: (point: Vec3) => number, bounds: Box, edgeLength: number, level?: number, tolerance?: number): Manifold; // Transformations /** * Transform this Manifold in space. Stored in column-major order. This * operation can be chained. Transforms are combined and applied lazily. * * @param m The affine transformation matrix to apply to all the vertices. The * last row is ignored. * @group Transformations */ transform(m: Mat4): Manifold; /** * Move this Manifold in space. This operation can be chained. Transforms are * combined and applied lazily. * * @param v The vector to add to every vertex. * @group Transformations */ translate(v: Readonly<Vec3>): Manifold; translate(x: number, y?: number, z?: number): Manifold; /** * Applies an Euler or Tait-Bryan angle rotation to the manifold. This * operation can be chained. Transforms are combined and applied lazily. * * We use degrees so that we can minimize rounding error, and eliminate it * completely for any multiples of 90 degrees. Additionally, more efficient * code paths are used to update the manifold when the transforms only rotate * by multiples of 90 degrees. * * From the reference frame of the model being rotated, rotations are applied * in *z-y'-x"* order. That is yaw first, then pitch and finally roll. * * From the global reference frame, a model will be rotated in *x-y-z* order. * That is about the global X axis, then global Y axis, and finally global Z. * * @param v [X, Y, Z] rotation in degrees. * @group Transformations */ rotate(v: Readonly<Vec3>): Manifold; rotate(x: number, y?: number, z?: number): Manifold; /** * Scale this Manifold in space. This operation can be chained. Transforms are * combined and applied lazily. * * @param v The vector to multiply every vertex by per component. * @group Transformations */ scale(v: Readonly<Vec3>|number): Manifold; /** * Mirror this Manifold over the plane described by the unit form of the given * normal vector. If the length of the normal is zero, an empty Manifold is * returned. This operation can be chained. Transforms are combined and * applied lazily. * * @param normal The normal vector of the plane to be mirrored over * @group Transformations */ mirror(normal: Readonly<Vec3>): Manifold; /** * This function does not change the topology, but allows the vertices to be * moved according to any arbitrary input function. It is easy to create a * function that warps a geometrically valid object into one which overlaps, * but that is not checked here, so it is up to the user to choose their * function with discretion. * * @param warpFunc A function that modifies a given vertex position. * @group Transformations */ warp(warpFunc: (vert: Vec3) => void): Manifold; /** * Batch version of warp(). The callback receives a flat array of xyzxyz... * (length = count * 3) and may modify it in-place. */ warpBatch(warpFunc: (verts: Float64Array, count: number) => void): Manifold; /** * Smooths out the Manifold by filling in the halfedgeTangent vectors. The * geometry will remain unchanged until Refine or RefineToLength is called to * interpolate the surface. This version uses the supplied vertex normal * properties to define the tangent vectors. * * @param normalIdx The first property channel of the normals. NumProp must be * at least normalIdx + 3. Any vertex where multiple normals exist and don't * agree will result in a sharp edge. Default is 0, the standard slot. * Non-zero values are retained for compatibility and will not be supported * in a future release. * @group Smoothing */ smoothByNormals(normalIdx?: number): Manifold; /** * Smooths out the Manifold by filling in the halfedgeTangent vectors. The * geometry will remain unchanged until Refine or RefineToLength is called to * interpolate the surface. This version uses the geometry of the triangles * and pseudo-normals to define the tangent vectors. * * @param minSharpAngle degrees, default 52.5. Any edges with angles greater * than this value will remain sharp. The rest will be smoothed to G1 * continuity, with the caveat that flat faces of three or more triangles will * always remain flat. With a value of zero, the model is faceted, but in this * case there is no point in smoothing. * * @param minSmoothness range: 0 - 1, default 0. The smoothness applied to * sharp angles. The default gives a hard edge, while values > 0 will give a * small fillet on these sharp edges. A value of 1 is equivalent to a * minSharpAngle of 180 - all edges will be smooth. * @group Smoothing */ smoothOut(minSharpAngle?: number, minSmoothness?: number): Manifold; /** * Increase the density of the mesh by splitting every edge into n pieces. For * instance, with n = 2, each triangle will be split into 4 triangles. These * will all be coplanar (and will not be immediately collapsed) unless the * Mesh/Manifold has halfedgeTangents specified (e.g. from the Smooth() * constructor), in which case the new vertices will be moved to the * interpolated surface according to their barycentric coordinates. * * @param n The number of pieces to split every edge into. Must be > 1. * @group Smoothing */ refine(n: number): Manifold; /** * Increase the density of the mesh by splitting each edge into pieces of * roughly the input length. Interior verts are added to keep the rest of the * triangulation edges also of roughly the same length. If halfedgeTangents * are present (e.g. from the Smooth() constructor), the new vertices will be * moved to the interpolated surface according to their barycentric * coordinates. * * @param length The length that edges will be broken down to. * @group Smoothing */ refineToLength(length: number): Manifold; /** * Increase the density of the mesh by splitting each edge into pieces such * that any point on the resulting triangles is roughly within tolerance of * the smoothly curved surface defined by the tangent vectors. This means * tightly curving regions will be divided more finely than smoother regions. * If halfedgeTangents are not present, the result will simply be a copy of * the original. Quads will ignore their interior triangle bisector. * * @param tolerance The desired maximum distance between the faceted mesh * produced and the exact smoothly curving surface. All vertices are exactly * on the surface, within rounding error. * @group Smoothing */ refineToTolerance(tolerance: number): Manifold; /** * Create a new copy of this manifold with updated vertex properties by * supplying a function that takes the existing position and properties as * input. You may specify any number of output properties, allowing creation * and removal of channels. Note: undefined behavior will result if you read * past the number of input properties or write past the number of output * properties. * * @param numProp The new number of properties per vertex. * @param propFunc A function that modifies the properties of a given vertex. * @group Properties */ setProperties( numProp: number, propFunc: (newProp: number[], position: Vec3, oldProp: number[]) => void): Manifold; /** * Curvature is the inverse of the radius of curvature, and signed such that * positive is convex and negative is concave. There are two orthogonal * principal curvatures at any point on a manifold, with one maximum and the * other minimum. Gaussian curvature is their product, while mean * curvature is their sum. This approximates them for every vertex and assigns * them as vertex properties on the given channels. * * @param gaussianIdx The property channel index in which to store the * Gaussian curvature. An index < 0 will be ignored (stores nothing). The * property set will be automatically expanded to include the channel * index specified. * @param meanIdx The property channel index in which to store the mean * curvature. An index < 0 will be ignored (stores nothing). The property * set will be automatically expanded to include the channel index * specified. * @group Properties */ calculateCurvature(gaussianIdx: number, meanIdx: number): Manifold; /** * Fills in vertex properties for normal vectors, calculated from the mesh * geometry. Flat faces composed of three or more triangles will remain flat. * * @param normalIdx The property channel in which to store the X values of the * normals. The X, Y, and Z channels will be sequential. The property set will * be automatically expanded to include up through normalIdx + 2. Default is * 0, the standard slot; in that case the Manifold records the recording so * a subsequent getMesh() without an explicit normalIdx returns solid-frame * normals. Non-zero values are retained for compatibility and will not be * supported in a future release. * * @param minSharpAngle Any edges with angles greater than this value will * remain sharp, getting different normal vector properties on each side of * the edge. By default, no edges are sharp and all normals are shared. With a * value of zero, the model is faceted and all normals match their triangle * normals, but in this case it would be better not to calculate normals at * all. * @group Properties */ calculateNormals(normalIdx?: number, minSharpAngle?: number): Manifold; // Boolean Operations /** * Boolean union * * @group Boolean */ add(other: Manifold): Manifold; /** * Boolean difference * * @group Boolean */ subtract(other: Manifold): Manifold; /** * Boolean intersection * * @group Boolean */ intersect(other: Manifold): Manifold; /** * Boolean union of the manifolds a and b * * @group Boolean */ static union(a: Manifold, b: Manifold): Manifold; /** * Boolean difference of the manifold b from the manifold a * * @group Boolean */ static difference(a: Manifold, b: Manifold): Manifold; /** * Boolean intersection of the manifolds a and b * * @group Boolean */ static intersection(a: Manifold, b: Manifold): Manifold; /** * Boolean union of a list of manifolds * * @group Boolean */ static union(manifolds: readonly Manifold[]): Manifold; /** * Boolean difference of the tail of a list of manifolds from its head * * @group Boolean */ static difference(manifolds: readonly Manifold[]): Manifold; /** * Boolean intersection of a list of manifolds * * @group Boolean */ static intersection(manifolds: readonly Manifold[]): Manifold; /** * Split cuts this manifold in two using the cutter manifold. The first result * is the intersection, second is the difference. This is more efficient than * doing them separately. * * @param cutter * @group Boolean */ split(cutter: Manifold): [Manifold, Manifold]; /** * Convenient version of Split() for a half-space. * * @param normal This vector is normal to the cutting plane and its length * does * not matter. The first result is in the direction of this vector, the second * result is on the opposite side. * @param originOffset The distance of the plane from the origin in the * direction of the normal vector. * @group Boolean */ splitByPlane(normal: Readonly<Vec3>, originOffset: number): [Manifold, Manifold]; /** * Removes everything behind the given half-space plane. * * @param normal This vector is normal to the cutting plane and its length * does not matter. The result is in the direction of this vector from the * plane. * @param originOffset The distance of the plane from the origin in the * direction of the normal vector. * * @group Boolean */ trimByPlane(normal: Readonly<Vec3>, originOffset: number): Manifold; /** * Compute the minkowski sum of this manifold with another. * This corresponds to the morphological dilation of the manifold. * * @param other The other manifold to minkowski sum to this one. * @group Boolean */ minkowskiSum(other: Manifold): Manifold; /** * Subtract the sweep of the other manifold across this manifold's surface. * This corresponds to the morphological erosion of the manifold. * * @param other The other manifold to minkowski subtract from this one. * @group Boolean */ minkowskiDifference(other: Manifold): Manifold; /** * Returns the cross section of this object parallel to the X-Y plane at the * specified height. Using a height equal to the bottom * of the bounding box will return the bottom faces, while using a height * equal to the top of the bounding box will return empty. * * @param height Z-level of slice. * @group Polygons */ slice(height: number): CrossSection; /** * Returns a cross section representing the projected outline of this object * onto the X-Y plane. * * @group Polygons */ project(): CrossSection; // Convex Hulls /** * Compute the convex hull of all points in this Manifold. * * @group Convex Hull */ hull(): Manifold; /** * Compute the convex hull of all points contained within a set of Manifolds * and point vectors. * * @group Convex Hull */ static hull(points: readonly(Manifold|Vec3)[]): Manifold; // Topological Operations /** * Constructs a new manifold from a list of other manifolds. This is a purely * topological operation, so care should be taken to avoid creating * overlapping results. It is the inverse operation of Decompose(). * * @param manifolds A list of Manifolds to lazy-union together. * @deprecated Please use {@link add} or {@link union} instead. * @group Constructors */ static compose(manifolds: readonly Manifold[]): Manifold; /** * This operation returns a vector of Manifolds that are topologically * disconnected. If everything is connected, the vector is length one, * containing a copy of the original. It is the inverse operation of * Compose(). * * @group Constructors */ decompose(): Manifold[]; // Property Access /** * Does the Manifold have any triangles? * @group Information */ isEmpty(): boolean; /** * The number of vertices in the Manifold. * @group Information */ numVert(): number; /** * The number of triangles in the Manifold. * @group Information */ numTri(): number; /** * The number of edges in the Manifold. * @group Information */ numEdge(): number; /** * The number of properties per vertex in the Manifold. * @group Information */ numProp(): number; /** * The number of property vertices in the Manifold. This will always be >= * numVert, as some physical vertices may be duplicated to account for * different properties on different neighboring triangles. * @group Information */ numPropVert(): number /** * Returns the axis-aligned bounding box of all the Manifold's vertices. * @group Information */ boundingBox(): Box; /** * Returns the tolerance of this Manifold's vertices, which tracks the * approximate rounding error over all the transforms and operations that have * led to this state. Any triangles that are colinear within this tolerance * are considered degenerate and removed. This is the value of &epsilon; * defining * [&epsilon;-valid](https://github.com/elalish/manifold/wiki/Manifold-Library#definition-of-%CE%B5-valid). * @group Information */ tolerance(): number; /** * Return a copy of the manifold with the set tolerance value. * This performs mesh simplification when the tolerance value is increased. * @group Transformations */ setTolerance(tolerance: number): Manifold; /** * Return a copy of the manifold simplified to the given tolerance, but with * its actual tolerance value unchanged. The result will contain a subset of * the original verts and all surfaces will have moved by less than tolerance. * * @param tolerance The maximum distance between the original and simplified * meshes. If not given or is less than the current tolerance, the current * tolerance is used. * @group Transformations */ simplify(tolerance?: number): Manifold; /** * The genus is a topological property of the manifold, representing the * number of "handles". A sphere is 0, torus 1, etc. It is only meaningful for * a single mesh, so it is best to call Decompose() first. * @group Information */ genus(): number; /** * Returns the surface area of the manifold. * * @group Measurement */ surfaceArea(): number; /** * Returns the volume of the manifold. * * @group Measurement */ volume(): number; /** * Returns the minimum gap between two manifolds. Returns a float between * 0 and searchLength. * * @group Measurement */ minGap(other: Manifold, searchLength: number): number; /** * Cast a ray segment, returning all hits sorted by distance. * * @param origin The start point of the ray segment. * @param endpoint The end point of the ray segment. * @returns Array of RayHit sorted by distance, empty on miss. * * @group Spatial Queries */ rayCast(origin: Vec3, endpoint: Vec3): RayHit[]; /** * Returns the reason for an input Mesh producing an empty Manifold. This * Status will carry on through operations like NaN propogation, ensuring an * errored mesh doesn't get mysteriously lost. Empty meshes may still show * NoError, for instance the intersection of non-overlapping meshes. * * @group Information */ status(): ErrorStatus; /** * Returns a copy of this Manifold with the given ExecutionContext attached. * The attachment is consumed by the next eager op invoked on the result: * status() for a deferred CSG tree, refine() / refineToLength() / * refineToTolerance(), hull(), or minkowskiSum() / minkowskiDifference(). * Deferred ops (Boolean operators, transforms, batch ops) ignore any * attached ctx and produce a result with no attached ctx. See * ExecutionContext for the full model. * * @group Information */ withContext(ctx: ExecutionContext): Manifold; // Export /** * Returns a Mesh that is designed to easily push into a renderer, including * all interleaved vertex properties that may have been input. It also * includes relations to all the input meshes that form a part of this result * and the transforms applied to each. * * @param normalIdx If the original MeshGL inputs that formed this manifold * had properties corresponding to normal vectors, you can specify the first * of the three consecutive property channels forming the (x, y, z) normals, * which will cause this output MeshGL to automatically update these normals * according to the applied transforms and front/back side. normalIdx + 3 must * be <= numProp, and all original MeshGLs must use the same channels for * their normals. * @group Input & Output */ getMesh(normalIdx?: number): Mesh; // ID Management /** * If you copy a manifold, but you want this new copy to have new properties * (e.g. a different UV mapping), you can reset its IDs to a new original, * meaning it will now be referenced by its descendants instead of the meshes * it was built from, allowing you to differentiate the copies when applying * your properties to the final result. * * This function also condenses all coplanar faces in the relation, and * collapses those edges. If you want to have inconsistent properties across * these faces, meaning you want to preserve some of these edges, you should * instead call GetMesh(), calculate your properties and use these to * construct a new manifold. * * @group Mesh ID */ asOriginal(): Manifold; /** * If this mesh is an original, this returns its ID that can be referenced * by product manifolds. If this manifold is a product, this * returns -1. * * @group Mesh ID */ originalID(): number; /** * Returns the first of n sequential new unique mesh IDs for marking sets of * triangles that can be looked up after further operations. Assign to * Mesh.runOriginalID vector. * * @group Mesh ID */ static reserveIDs(count: number): number; // Memory /** * Frees the WASM memory of this Manifold, since these cannot be * garbage-collected automatically. * @group Basics */ delete(): void; } export declare interface ManifoldToplevel { CrossSection: typeof CrossSection; Manifold: typeof Manifold; Mesh: typeof Mesh; triangulate: typeof triangulate; setMinCircularAngle: typeof setMinCircularAngle; setMinCircularEdgeLength: typeof setMinCircularEdgeLength; setCircularSegments: typeof setCircularSegments; getCircularSegments: typeof getCircularSegments; resetToCircularDefaults: typeof resetToCircularDefaults; setup: () => void; } /** * 3x3 matrix stored in column-major order. */ export declare type Mat3 = [ number, number, number, number, number, number, number, number, number, ]; /** * 4x4 matrix stored in column-major order. */ export declare type Mat4 = [ number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, number, ]; /** * An alternative to Mesh for output suitable for pushing into graphics * libraries directly. This may not be manifold since the verts are duplicated * along property boundaries that do not match. The additional merge vectors * store this missing information, allowing the manifold to be reconstructed. * * @see {@link https://manifoldcad.org/docs/html/structmanifold_1_1_mesh_g_l_p.html | C++ API: MeshGLP< Precision, I > Struct Template Reference} * @group Input & Output * @internal */ export declare class Mesh { constructor(options: MeshOptions); /** * Number of properties per vertex, always >= 3. */ numProp: number; /** * Flat, GL-style interleaved list of all vertex properties: propVal = * vertProperties[vert * numProp + propIdx]. The first three properties are * always the position x, y, z. */ vertProperties: Float32Array; /** * The vertex indices of the three triangle corners in CCW (from the outside) * order, for each triangle. */ triVerts: Uint32Array; /** * Optional: A list of only the vertex indicies that need to be merged to * reconstruct the manifold. */ mergeFrom