(filters)= # Filters This reference contains all 328 filters found in the descriptor registry when it was generated. Each filter can be called as a method on a `MeshSet` object, for example `ms.apply_filter("remove_duplicate_vertices", ...)`, or using the dynamically-bound snake_case name: `ms.remove_duplicate_vertices(...)`. A combined bibliography for cited algorithms is available as {download}`BibTeX `. (filter-apply-face-color-function)= ## Compute Face Color by Expression **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.expression Computes per-face RGBA colors from expressions. ```{py:function} ms.apply_face_color_function(**params) :module: _qmeshlab Color function using muparser lib to generate new RGBA color for every face
Red, Green, Blue and Alpha channels may be defined specifying a function in their respective fields.
**Parameters:** - **r** (*string*, default: `255`) — Expression for red output in range [0, 255]. - **g** (*string*, default: `0`) — Expression for green output in range [0, 255]. - **b** (*string*, default: `255`) — Expression for blue output in range [0, 255]. - **a** (*string*, default: `255`) — Expression for alpha output in range [0, 255]. - **onselected** (*bool*, default: `False`) — If enabled, the filter affects only selected elements. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-apply-vertex-color-function)= ## Compute Vertex Color by Expression **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.expression Computes per-vertex RGBA colors from expressions. ```{py:function} ms.apply_vertex_color_function(**params) :module: _qmeshlab Color function using muparser lib to generate new RGBA color for every vertex
Red, Green, Blue and Alpha channels may be defined specifying a function in their respective fields.
**Parameters:** - **x** (*string*, default: `255`) — Expression for X output. - **y** (*string*, default: `255`) — Expression for Y output. - **z** (*string*, default: `0`) — Expression for Z output. - **a** (*string*, default: `255`) — Expression for alpha output in range [0, 255]. - **onselected** (*bool*, default: `False`) — If enabled, the filter affects only selected elements. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-color-noise)= ## Add Noise to Vertex Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Add random noise bits independently to RGB channels. ```{py:function} ms.color_noise(**params) :module: _qmeshlab Adds to the color the requested amount of bits of noise. Bits of noise are added independently for each RGB channel. **Parameters:** - **noiseBits** (*int*, default: `1`) — Bits of noise added to each RGB channel. - **onSelected** (*bool*, default: `False`) — If checked, only affects selected vertices. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the added noise exactly reproducible. ``` --- (filter-color-scattering)= ## Set Random Layer Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Assign a distinct random color to each visible mesh layer. ```{py:function} ms.color_scattering(**params) :module: _qmeshlab Assigns a random color to each visible mesh layer in the document. Colors change every time the filter is executed, but are always chosen so that they differ as much as possible. **Parameters:** - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the color assignment exactly reproducible. ``` --- (filter-colorize-by-face-quality)= ## Colorize Faces by Scalar **Categories:** `Attribute/Color`, `Attribute/Scalar` **Plugin:** qmeshlab.filter.colorproc Map face quality into face colors. ```{py:function} ms.colorize_by_face_quality(**params) :module: _qmeshlab Color faces depending on their quality field (manually equalized). **Parameters:** - **minVal** (*double*, default: `@qualityFMin`) — The value mapped to the lower end of the scale. - **maxVal** (*double*, default: `@qualityFMax`) — The value mapped to the upper end of the scale. - **perc** (*double*, default: `0.0`) — If not zero this value is used for percentile cropping of the quality values. - **zeroSym** (*bool*, default: `False`) — If true the min/max range is enlarged to be symmetric around zero. - **colorMap** (*enum*, default: `rgb`) — The color map to use. RGB is the VCGLib default, other colormaps are sampled from Matplotlib. ``` --- (filter-colorize-by-vertex-quality)= ## Colorize Vertices by Scalar **Categories:** `Attribute/Color`, `Attribute/Scalar` **Plugin:** qmeshlab.filter.colorproc Map vertex quality into vertex colors. ```{py:function} ms.colorize_by_vertex_quality(**params) :module: _qmeshlab Color vertices depending on their quality field. The filter uses the same colormap sampling and range normalization used by QMeshLab quality visualization, so it can bake the current quality display into vertex colors. **Parameters:** - **minVal** (*double*, default: `@qualityVMin`) — The value mapped to the lower end of the scale. - **maxVal** (*double*, default: `@qualityVMax`) — The value mapped to the upper end of the scale. - **perc** (*double*, default: `0.0`) — If not zero this value is used for percentile cropping of the quality values. - **zeroSym** (*bool*, default: `False`) — If true the min/max range is enlarged to be symmetric around zero. - **colorMap** (*enum*, default: `rainbow`) — The color map to use. Built-in QMeshLab maps match the quality visualization panel; RGB and RdPu preserve legacy VCGLib behavior. - **invert** (*bool*, default: `False`) — Invert the selected QMeshLab colormap before sampling, matching the quality visualization panel. Legacy RGB/RdPu maps ignore this option. - **colorMapId** (*string*, default: ``) — Optional exact QMeshLab colormap id. Leave empty for the selected Color Map enum. This is mainly used internally when baking the current view and also supports external colormaps loaded by QMeshLab. ``` --- (filter-disk-vertex-coloring)= ## Colorize Vertices by Disk Distance **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.sampling Color a mesh according to the distance from projected point-cloud disks. ```{py:function} ms.disk_vertex_coloring(**params) :module: _qmeshlab Given a Mesh M and a Pointset P, The filter project each vertex of P over M and color M according to the Euclidean distance from these projected points. Projection and coloring are done on a per vertex basis. **Parameters:** - **ColoredMesh** (*mesh*, default: `@currentMeshIndex`) — The mesh whose vertices will be colored. - **VertexMesh** (*mesh*, default: `@otherMeshIndex`) — The point cloud whose vertices are used as disk centers. - **Radius** (*absperc*, default: `@bboxDiagTenth`) — Disk radius around each point-cloud seed. - **SampleRadius** (*bool*, default: `False`) — Use the per-vertex quality of the seed cloud as the disk radius. - **ApproximateGeodetic** (*bool*, default: `False`) — Weight the Euclidean distance by the normal difference between the two points. ``` --- (filter-equalize-vertex-color)= ## Equalize Vertex Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Equalize the vertex-color histogram. ```{py:function} ms.equalize_vertex_color(**params) :module: _qmeshlab The filter equalizes the colors histogram. It is a kind of automatic regulation of contrast; the colors histogram is expanded to fit all the range of colors. **Parameters:** - **rCh** (*bool*, default: `True`) — Select the red channel. - **gCh** (*bool*, default: `True`) — Select the green channel. - **bCh** (*bool*, default: `True`) — Select the blue channel. If no channel is selected the filter works on Lightness. - **onSelected** (*bool*, default: `False`) — If checked, only affects selected vertices. ``` --- (filter-perlin-color)= ## Colorize Vertices by Perlin Noise **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Color the mesh with a Perlin-based color field. ```{py:function} ms.perlin_color(**params) :module: _qmeshlab Paints the mesh using PerlinColor function. The color assigned to vertices depends on their position in the space; it means that near vertices will be painted with similar colors. **Parameters:** - **color1** (*color*, default: `#000000`) — Sets the first color to mix with Perlin Noise function. - **color2** (*color*, default: `#ffffff`) — Sets the second color to mix with Perlin Noise function. - **freq** (*double*, default: `10.0`) — Frequency of the Perlin Noise function, expressed as multiples of mesh bbox. - **offset** (*point3f*, default: `[0.0, 0.0, 0.0]`) — XYZ frequency offset of the noise function. - **onSelected** (*bool*, default: `False`) — If checked, only affects selected vertices. ``` --- (filter-random-component-color)= ## Set Random Component Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Assign a random color to each connected component. ```{py:function} ms.random_component_color(**params) :module: _qmeshlab Colorize each connected component randomly. This filter has no parameters. ``` --- (filter-random-face-color)= ## Set Random Face Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Assign random colors to faces or faux-connected polygons. ```{py:function} ms.random_face_color(**params) :module: _qmeshlab Colorize Faces randomly. If internal edges are present they are used. Useful for quads. This filter has no parameters. ``` --- (filter-set-per-mesh-color)= ## Set Mesh Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Set a solid per-mesh color used by the plain rendering material. ```{py:function} ms.set_per_mesh_color(**params) :module: _qmeshlab Set a solid per-mesh color that overrides the plain fill material's color for this mesh. The color is stored in the mesh data and survives undo/redo. **Parameters:** - **color** (*color*, default: `#808080ff`) — The solid color to assign to this mesh. ``` --- (filter-smooth-laplacian-face-color)= ## Smooth Face Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Laplacian smooth face colors. ```{py:function} ms.smooth_laplacian_face_color(**params) :module: _qmeshlab Laplacian Smooth Face Color **Parameters:** - **iteration** (*int*, default: `1`) — The number of iterations of the smoothing algorithm. ``` --- (filter-smooth-laplacian-vertex-color)= ## Smooth Vertex Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Laplacian smooth vertex colors. ```{py:function} ms.smooth_laplacian_vertex_color(**params) :module: _qmeshlab Laplacian Smooth Vertex Color **Parameters:** - **iteration** (*int*, default: `1`) — The number of iterations of the smoothing algorithm. ``` --- (filter-unsharp-mask-color)= ## Sharpen Vertex Color by Unsharp Mask **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.unsharp Enhance per-vertex color variation with an unsharp mask. ```{py:function} ms.unsharp_mask_color(**params) :module: _qmeshlab Sharpens the **per-vertex color**, pulling out variation that is hard to see in a low-contrast or noisy color field.\n\nUnsharp masking exaggerates local variation by adding back the difference between the signal and a smoothed copy of it: $$s' = s + \lambda\,(s - \mathrm{smooth}(s)).$$ **Weight** is $\lambda$; larger values sharpen harder and amplify noise along with the features. **Smoothing steps** sets how blurred the subtracted copy is, which fixes the scale of the detail being enhanced.\n\n **References:** - Paolo Cignoni, Roberto Scopigno, Marco Tarini. **A simple normal enhancement technique for interactive non-photorealistic renderings**. *Computers & Graphics* (2005). [DOI](https://doi.org/10.1016/j.cag.2004.11.012) [Web](https://www.sciencedirect.com/science/article/pii/S0097849304001980) **Parameters:** - **weight** (*double*, default: `0.3`) — Unsharp weight applied to the high-frequency color component. - **weightOrig** (*double*, default: `1.0`) — Weight of the original color signal. - **iterations** (*int*, default: `5`) — Number of Laplacian smoothing iterations used to build the low-pass color signal. ``` --- (filter-vertex-color-brightness-contrast-gamma)= ## Adjust Vertex Color Brightness/Contrast/Gamma **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Adjust vertex-color brightness, contrast, and gamma. ```{py:function} ms.vertex_color_brightness_contrast_gamma(**params) :module: _qmeshlab Change the color the vertices of the mesh adjusting brightness, contrast and gamma. **Parameters:** - **brightness** (*double*, default: `0.0`) — Sets the amount of brightness that will be added/subtracted to the colors. - **contrast** (*double*, default: `0.0`) — Sets the amount of contrast of the mesh. - **gamma** (*double*, default: `1.0`) — Sets the values of the exponent gamma. - **onSelected** (*bool*, default: `False`) — If checked, only affects selected vertices. ``` --- (filter-vertex-color-colourisation)= ## Tint Vertex Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Blend a chosen color into the existing vertex colors. ```{py:function} ms.vertex_color_colourisation(**params) :module: _qmeshlab Allows the application of a color to the mesh. In spite of the Fill operation, the color is blended with the mesh according to a given intensity. **Parameters:** - **hue** (*double*, default: `0.0`) — Changes the hue of the mesh. - **saturation** (*double*, default: `100.0`) — Changes the saturation of the mesh. - **luminance** (*double*, default: `50.0`) — Changes the luminance of the mesh. - **intensity** (*double*, default: `50.0`) — Sets the blending factor used in adding the new color to the existing one. - **onSelected** (*bool*, default: `False`) — If checked, only affects selected vertices. ``` --- (filter-vertex-color-desaturation)= ## Desaturate Vertex Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Convert vertex colors to grayscale using a chosen method. ```{py:function} ms.vertex_color_desaturation(**params) :module: _qmeshlab The filter desaturates the colors of the mesh. This provides a simple way to convert a mesh in gray tones. The user can choose the desaturation method to apply; they are based on Lightness, Luminosity and Average. **Parameters:** - **method** (*enum*, default: `lightness`) — Lightness is computed as (Max(r,g,b)+Min(r,g,b))/2; Luminosity as 0.212*r + 0.715*g + 0.072*b; Average as (r+g+b)/3. - **onSelected** (*bool*, default: `False`) — If checked, only affects selected vertices. ``` --- (filter-vertex-color-filling)= ## Set Vertex Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Fill vertex colors with a chosen color. ```{py:function} ms.vertex_color_filling(**params) :module: _qmeshlab Fills the color of the vertices of the mesh with a color chosen by the user. **Parameters:** - **color1** (*color*, default: `#000000`) — Sets the color to apply to vertices. - **onSelected** (*bool*, default: `False`) — If checked, only affects selected vertices. ``` --- (filter-vertex-color-invert)= ## Invert Vertex Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Invert vertex colors. ```{py:function} ms.vertex_color_invert(**params) :module: _qmeshlab Inverts the colors of the vertices of the mesh. **Parameters:** - **onSelected** (*bool*, default: `False`) — If checked, only affects selected vertices. ``` --- (filter-vertex-color-levels-adjustment)= ## Adjust Vertex Color Levels **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Remap an input color interval into an output interval. ```{py:function} ms.vertex_color_levels_adjustment(**params) :module: _qmeshlab The filter allows adjustment of color levels. It is a custom way to map an interval of color into another one. The user can set the input minimum and maximum levels, gamma and the output minimum and maximum levels (many tools call them respectively input black point, white point, gray point, output black point and white point). **Parameters:** - **gamma** (*double*, default: `1.0`) — Gamma correction factor. - **in_min** (*double*, default: `0.0`) — Minimum input level. - **in_max** (*double*, default: `255.0`) — Maximum input level. - **out_min** (*double*, default: `0.0`) — Minimum output level. - **out_max** (*double*, default: `255.0`) — Maximum output level. - **rCh** (*bool*, default: `True`) — Apply to red channel. - **gCh** (*bool*, default: `True`) — Apply to green channel. - **bCh** (*bool*, default: `True`) — Apply to blue channel. - **onSelected** (*bool*, default: `False`) — If checked, only affects selected vertices. ``` --- (filter-vertex-color-thresholding)= ## Threshold Vertex Color **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Apply two colors according to a lightness threshold. ```{py:function} ms.vertex_color_thresholding(**params) :module: _qmeshlab Colors the vertices of the mesh using two colors according to a lightness threshold (on the original color). **Parameters:** - **color1** (*color*, default: `#000000`) — Sets the color to apply below the threshold. - **color2** (*color*, default: `#ffffff`) — Sets the color to apply above the threshold. - **threshold** (*double*, default: `128.0`) — Vertices with color above the lightness threshold become Color 2, the others Color 1. - **onSelected** (*bool*, default: `False`) — If checked, only affects selected vertices. ``` --- (filter-vertex-color-white-balance)= ## Adjust Vertex Color White Balance **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Apply white balance so a chosen color becomes white. ```{py:function} ms.vertex_color_white_balance(**params) :module: _qmeshlab The filter provides a standard white balance transformation. It is done correcting the RGB channels with a factor such that, the brighter color in the mesh, that is supposed to be white, becomes really white. **Parameters:** - **color** (*color*, default: `#ffffff`) — The color that is supposed to be white. - **onSelected** (*bool*, default: `False`) — If checked, only affects selected vertices. ``` --- (filter-voronoi-vertex-coloring)= ## Colorize Vertices by Voronoi Regions **Categories:** `Attribute/Color` **Plugin:** qmeshlab.filter.sampling Color a mesh according to projected seed points from another layer. ```{py:function} ms.voronoi_vertex_coloring(**params) :module: _qmeshlab Given a Mesh M and a Pointset P, The filter project each vertex of P over M and color M according to the geodesic distance from these projected points. Projection and coloring are done on a per vertex basis. **Parameters:** - **ColoredMesh** (*mesh*, default: `@currentMeshIndex`) — The mesh whose surface will be colored. - **VertexMesh** (*mesh*, default: `@otherMeshIndex`) — The point cloud whose vertices are used as Voronoi seeds. - **backward** (*bool*, default: `False`) — Color according to the distance from the Voronoi frontier instead of from the seed. ``` --- (filter-compute-apss-curvature)= ## Compute Curvature (APSS) **Categories:** `Attribute/Curvature` **Plugin:** qmeshlab.filter.mls Compute APSS curvature estimates and store them in vertex quality. ```{py:function} ms.compute_apss_curvature(**params) :module: _qmeshlab Computes curvature at each vertex of a mesh or point set and stores it in the vertex scalar field. No color is baked; the view switches to scalar visualization when the filter finishes.\n\nThis is the **algebraic point set surfaces** (APSS) variant: the local approximation fitted at each point is an algebraic sphere rather than a plane, which keeps curved regions from flattening out. It needs points carrying oriented normals. **References:** - Gaël Guennebaud, Markus Gross. **Algebraic point set surfaces**. *ACM Transactions on Graphics (SIGGRAPH 2007)* (2007). [DOI](https://doi.org/10.1145/1276377.1276406) - Gaël Guennebaud, Marcel Germann, Markus Gross. **Dynamic Sampling and Rendering of Algebraic Point Set Surfaces**. *Computer Graphics Forum (Eurographics 2008)* (2008). [DOI](https://doi.org/10.1111/j.1467-8659.2008.01163.x) **Parameters:** - **SelectionOnly** (*bool*, default: `False`) — If checked, only selected vertices will be projected. - **CurvatureType** (*enum*, default: `mean`) — The type of the curvature to plot.
ApproxMean uses the radius of the fitted sphere as an approximation of the mean curvature. - **FilterScale** (*double*, default: `2.0`) — Scale of the spatial low pass filter. It is relative to the radius (local point spacing) of the vertices. - **SphericalParameter** (*double*, default: `1.0`) — Control the curvature of the fitted spheres: 0 is equivalent to a pure plane fit, 1 to a pure spherical fit, values between 0 and 1 give intermediate results, while other real values might give interesting results, but take care with extreme settings. - **ProjectionAccuracy** (*double*, default: `0.0001`) — Threshold value used to stop the projections. This value is scaled by the mean point spacing to get the actual threshold. - **MaxProjectionIters** (*int*, default: `15`) — Max number of iterations for the projection. ``` --- (filter-compute-curvature-principal-directions)= ## Compute Principal Curvature Directions (vcglib) **Categories:** `Attribute/Curvature` **Plugin:** qmeshlab.filter.meshing Compute principal curvature directions. ```{py:function} ms.compute_curvature_principal_directions(**params) :module: _qmeshlab Compute the principal directions of curvature with different algorithms. The selected curvature scalar is stored in vertex quality; the filter does not bake colors, and QMeshLab switches the view to vertex-quality color visualization after it runs. **Parameters:** - **Method** (*enum*, default: `quadric_fitting`) — Choose method. - **CurvColorMethod** (*enum*, default: `mean`) — Choose the curvature value stored in vertex quality and shown through automatic quality visualization. - **Scale** (*absperc*, default: `@bboxDiagTenth`) — Scale for scale-dependent methods. - **Autoclean** (*bool*, default: `True`) — Remove unreferenced vertices before computing. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the PCA method's point sampling exactly reproducible. ``` --- (filter-compute-curvature-principal-directions-per-vertex-libigl)= ## Compute Principal Curvature Directions (libigl) **Categories:** `Attribute/Curvature`, `Attribute/Scalar` **Plugin:** qmeshlab.filter.igl Estimate principal curvature values and directions with libigl's multi-scale fitting method. ```{py:function} ms.compute_curvature_principal_directions_per_vertex_libigl(**params) :module: _qmeshlab Estimates the two principal curvatures and their tangent directions using libigl's multi-scale local fitting implementation. The maximal and minimal values are stored in the mesh curvature component as $k_1$ and $k_2$, with their corresponding directions. **Quality Mapping** also stores one derived value in **vertex scalar** for immediate visualization. **Neighborhood Radius** is measured in vertex rings when **Use K-ring Neighborhood** is enabled. Otherwise libigl interprets it relative to average edge length. Larger neighborhoods suppress noise but also smooth small features. Vertices for which libigl cannot form a valid fit are reported and assigned zero curvature and zero directions. Faux-edge polygon groups are processed through their stored triangle representation. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) - Daniele Panozzo, Enrico Puppo, Luigi Rocca. **Efficient Multi-scale Curvature and Crease Estimation**. *Proceedings of the 4th International Conference on Computer Graphics, Computer Vision and Mathematics (GraVisMa 2010)* (2010). **Parameters:** - **neighborhood_radius** (*int*, default: `5`) — Neighborhood size passed to libigl. With K-ring mode it is the number of adjacent vertex rings; otherwise it is relative to average edge length. - **use_k_ring** (*bool*, default: `True`) — Use a topological K-ring neighborhood. Disable it to use libigl's metric ball neighborhood. - **quality_mapping** (*enum*, default: `mean`) — Choose the curvature value also stored in vertex scalar and shown after completion. ``` --- (filter-compute-gaussian-curvature-per-vertex-libigl)= ## Compute Gaussian Curvature (libigl) **Categories:** `Attribute/Curvature`, `Attribute/Scalar` **Plugin:** qmeshlab.filter.igl Compute the integrated Gaussian curvature at each vertex with libigl. ```{py:function} ms.compute_gaussian_curvature_per_vertex_libigl(**params) :module: _qmeshlab Computes libigl's discrete **angle deficit** at every face-referenced vertex and stores it in **vertex scalar**: $$K_i = 2\pi - \sum_{f \ni} \theta_{if}.$$ This is integrated Gaussian curvature, not curvature divided by a vertex area. On a closed manifold mesh its sum is governed by Gauss-Bonnet. At boundary vertices the expression is not an intrinsic Gaussian-curvature estimate; the reported value still uses $2\pi$, so interpret boundary values with care. Faux-edge polygon groups are processed through their stored triangle representation. No colors are baked into the mesh; QMeshLab switches to vertex-scalar visualization after completion. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) - Mark Meyer, Mathieu Desbrun, Peter Schröder, Alan H. Barr. **Discrete Differential-Geometry Operators for Triangulated 2-Manifolds**. *Visualization and Mathematics III* (2003). [DOI](https://doi.org/10.1007/978-3-662-05105-4_2) This filter has no parameters. ``` --- (filter-compute-rimls-curvature)= ## Compute Curvature (RIMLS) **Categories:** `Attribute/Curvature` **Plugin:** qmeshlab.filter.mls Compute RIMLS curvature estimates and store them in vertex quality. ```{py:function} ms.compute_rimls_curvature(**params) :module: _qmeshlab Computes curvature at each vertex of a mesh or point set and stores it in the vertex scalar field. No color is baked; the view switches to scalar visualization when the filter finishes.\n\nThis is the **robust implicit MLS** (RIMLS) variant: it extends implicit MLS with non-linear kernel regression, so sharp edges survive instead of being rounded away with the noise. It needs points carrying oriented normals. **References:** - A. Cengiz Öztireli, Gaël Guennebaud, Markus Gross. **Feature Preserving Point Set Surfaces based on Non-Linear Kernel Regression**. *Computer Graphics Forum (Eurographics 2009)* (2009). [DOI](https://doi.org/10.1111/j.1467-8659.2009.01388.x) **Parameters:** - **SelectionOnly** (*bool*, default: `False`) — If checked, only selected vertices will be projected. - **CurvatureType** (*enum*, default: `mean`) — The type of the curvature to plot. - **FilterScale** (*double*, default: `2.0`) — Scale of the spatial low pass filter. It is relative to the radius (local point spacing) of the vertices. - **SigmaN** (*double*, default: `0.75`) — Width of the filter used by the normal refitting weight. This weight function is a Gaussian on the distance between two unit vectors: the current gradient and the input normal. Typical values range between 0.5 (sharp) and 2 (smooth). - **MaxRefittingIters** (*int*, default: `3`) — Max number of fitting iterations. (0 or 1 is equivalent to the standard IMLS). - **ProjectionAccuracy** (*double*, default: `0.0001`) — Threshold value used to stop the projections. This value is scaled by the mean point spacing to get the actual threshold. - **MaxProjectionIters** (*int*, default: `15`) — Max number of iterations for the projection. ``` --- (filter-compute-scalar-by-curvature-trueform)= ## Compute Curvature (TrueForm) **Categories:** `Attribute/Curvature` **Plugin:** qmeshlab.filter.trueform Estimate principal curvatures by local fitting and store one measure in vertex scalar. ```{py:function} ms.compute_scalar_by_curvature_trueform(**params) :module: _qmeshlab Fits a local surface around each vertex over its k-ring neighbourhood and derives the two principal curvatures, then stores the chosen measure in **vertex scalar**.\n\n**Measure** selects what is written:\n\n| Measure | Meaning |\n|---|---|\n| Mean | (k1 + k2) / 2 |\n| Gaussian | k1 * k2 — positive on domes and bowls, negative on saddles |\n| Minimum / Maximum | the individual principal curvatures |\n| Shape index | scale-free descriptor of local shape, from cup through saddle to cap |\n\n**Ring** is the neighbourhood radius in rings of adjacent vertices. Larger values smooth the estimate and cost more; it is the knob to turn when noise dominates the result.\n\nThe shape index is worth knowing about: unlike the curvature values it is **independent of scale**, so it describes the *kind* of shape at a point rather than how strongly curved it is, which makes it comparable across models of different sizes.\n\nCompeting implementation: see also *Compute Curvature (Discrete)*, *(APSS)* and *(RIMLS)*. **Parameters:** - **measure** (*enum*, default: `mean`) — Which curvature measure to store in vertex scalar. - **ring** (*int*, default: `2`) — Neighbourhood radius in vertex rings. Larger is smoother and slower. ``` --- (filter-discrete-curvatures)= ## Compute Curvature (Discrete) **Categories:** `Attribute/Curvature` **Plugin:** qmeshlab.filter.colorproc Compute discrete curvature and store it in vertex quality. ```{py:function} ms.discrete_curvatures(**params) :module: _qmeshlab Compute discrete curvature and store it in vertex quality. The filter does not bake colors; after it runs QMeshLab switches the view to vertex-quality color visualization.
Computed as described in:
'Discrete Differential-Geometry Operators for Triangulated 2-Manifolds'
M. Meyer, M. Desbrun, P. Schroder, A. H. Barr **Parameters:** - **CurvatureType** (*enum*, default: `mean`) — Choose the curvature value that you want transferred onto the scalar Quality. ``` --- (filter-define-face-point-attribute)= ## Define Custom Face Point Attribute **Categories:** `Attribute/Custom` **Plugin:** qmeshlab.filter.expression Defines and fills a custom per-face point attribute. ```{py:function} ms.define_face_point_attribute(**params) :module: _qmeshlab Add a new Per-Face custom point attribute to current mesh and fill it with the defined functions.
Attribute names must contain only letters, numbers and underscores.
The name specified for the attribute can be used in other filter functions.
**Parameters:** - **name** (*string*, default: `CustomAttrName`) — Name of the new custom attribute. - **x_expr** (*string*, default: `x0`) — Expression for X component. - **y_expr** (*string*, default: `y0`) — Expression for Y component. - **z_expr** (*string*, default: `z0`) — Expression for Z component. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-define-face-scalar-attribute)= ## Define Custom Face Scalar Attribute **Categories:** `Attribute/Custom` **Plugin:** qmeshlab.filter.expression Defines and fills a custom per-face scalar attribute. ```{py:function} ms.define_face_scalar_attribute(**params) :module: _qmeshlab Add a new Per-Face custom scalar attribute to current mesh and fill it with the defined function.
Attribute names must contain only letters, numbers and underscores.
The name specified for the attribute can be used in other filter functions.
**Parameters:** - **name** (*string*, default: `CustomAttrName`) — Name of the new custom attribute. - **expr** (*string*, default: `fi`) — Expression used to compute the scalar attribute. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-define-vertex-point-attribute)= ## Define Custom Vertex Point Attribute **Categories:** `Attribute/Custom` **Plugin:** qmeshlab.filter.expression Defines and fills a custom per-vertex point attribute. ```{py:function} ms.define_vertex_point_attribute(**params) :module: _qmeshlab Add a new Per-Vertex custom point attribute to current mesh and fill it with the defined functions.
Attribute names must contain only letters, numbers and underscores.
The name specified for the attribute can be used in other filter functions.
**Parameters:** - **name** (*string*, default: `CustomAttrName`) — Name of the new custom attribute. - **x_expr** (*string*, default: `x`) — Expression for X component. - **y_expr** (*string*, default: `y`) — Expression for Y component. - **z_expr** (*string*, default: `z`) — Expression for Z component. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-define-vertex-scalar-attribute)= ## Define Custom Vertex Scalar Attribute **Categories:** `Attribute/Custom` **Plugin:** qmeshlab.filter.expression Defines and fills a custom per-vertex scalar attribute. ```{py:function} ms.define_vertex_scalar_attribute(**params) :module: _qmeshlab Add a new Per-Vertex custom scalar attribute to current mesh and fill it with the defined function.
Attribute names must contain only letters, numbers and underscores.
The name specified for the attribute can be used in other filter functions.
**Parameters:** - **name** (*string*, default: `CustomAttrName`) — Name of the new custom attribute. - **expr** (*string*, default: `x`) — Expression used to compute the scalar attribute. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-apply-face-normal-function)= ## Compute Face Normals by Expression **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.expression Computes new per-face normals from expressions. ```{py:function} ms.apply_face_normal_function(**params) :module: _qmeshlab Normal function using muparser to generate new Normal for every face
**Parameters:** - **x** (*string*, default: `-fnx`) — Expression for X output. - **y** (*string*, default: `-fny`) — Expression for Y output. - **z** (*string*, default: `-fnz`) — Expression for Z output. - **onselected** (*bool*, default: `False`) — If enabled, the filter affects only selected elements. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-apply-vertex-normal-function)= ## Compute Vertex Normals by Expression **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.expression Computes new per-vertex normals from expressions. ```{py:function} ms.apply_vertex_normal_function(**params) :module: _qmeshlab Normal function using muparser to generate new Normal for every vertex
**Parameters:** - **x** (*string*, default: `-nx`) — Expression for X output. - **y** (*string*, default: `-ny`) — Expression for Y output. - **z** (*string*, default: `-nz`) — Expression for Z output. - **onselected** (*bool*, default: `False`) — If enabled, the filter affects only selected elements. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-compute-face-normals)= ## Compute Face Normals **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.unsharp Recompute face normals from geometry. ```{py:function} ms.compute_face_normals(**params) :module: _qmeshlab Recompute face normals as the normal of the plane of the face.
See How to find surface normal of a triangle This filter has no parameters. ``` --- (filter-compute-normal-from-cameras-per-vertex)= ## Orient Vertex Normals by Cameras **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.camera Reorient vertex normals to point toward the cameras that see them best. ```{py:function} ms.compute_normal_from_cameras_per_vertex(**params) :module: _qmeshlab Reorient vertex normals using visible rasters. For each vertex, the best camera is chosen among all visible rasters and the normal is oriented to face toward that camera. If the per-vertex attribute 'correspondences' exists (from Bundler .out imports), the original Bundler camera indices are used instead. This filter has no parameters. ``` --- (filter-compute-normal-orientation-per-vertex)= ## Orient Point Cloud Normals **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.cgal Make an unoriented normal field consistently point outward, using a minimum spanning tree. ```{py:function} ms.compute_normal_orientation_per_vertex(**params) :module: _qmeshlab Orients the vertex normals of a point cloud so that neighbouring normals agree in sign, by propagating orientation along a **minimum spanning tree of the Riemannian graph** (Hoppe et al.). This is the missing step between normal *estimation* and surface *reconstruction*. Filters such as *Compute Point Cloud Normals* fit a local surface and give each normal an arbitrary sign; Poisson-family and kinetic reconstruction all need normals that consistently point outward, and produce unusable results otherwise. **Neighbors** sets how many nearest neighbours are linked in the Riemannian graph. Larger values bridge gaps in sparse data but can propagate orientation across thin structures that should stay separate. A cloud in several disconnected pieces cannot be oriented as a whole: the normals of every component after the first are reported as unoriented and left untouched. Enable **Remove Unoriented Vertices** to delete them instead. Implemented with CGAL's Point Set Processing. Reference: Hugues Hoppe, Tony DeRose, Tom Duchamp, John McDonald, Werner Stuetzle, **Surface Reconstruction from Unorganized Points**, SIGGRAPH 1992. **Parameters:** - **neighbors** (*int*, default: `18`) — Number of nearest neighbours linked in the Riemannian graph. Larger values bridge sparse regions but risk propagating orientation across thin structures. - **removeUnoriented** (*bool*, default: `False`) — Delete the vertices whose normals could not be oriented instead of leaving them untouched. They are usually disconnected components. ``` --- (filter-compute-normals-trueform)= ## Compute Normals (TrueForm) **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.trueform Recompute per-vertex or per-face normals from the geometry. ```{py:function} ms.compute_normals_trueform(**params) :module: _qmeshlab Recomputes normals from the current geometry, either one per face or one per vertex (area-weighted from the incident faces).\n\nNormals are computed in world space and mapped back through the layer matrix, so a layer carrying a non-uniform scale gets correct normals rather than merely rotated ones.\n\nCompeting implementation: *Compute Vertex Normals* and *Compute Face Normals* do the same with vcglib. This one is parallelised. **Parameters:** - **target** (*enum*, default: `vertex`) — Whether to write per-vertex or per-face normals. ``` --- (filter-compute-per-polygon-face-normals)= ## Compute Polygon Face Normals **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.unsharp Recompute polygon-shading normals for faux-edge polygon meshes. ```{py:function} ms.compute_per_polygon_face_normals(**params) :module: _qmeshlab Recompute face normals as the average of the normals of the triangles that builds a polygon. Useful for showing uniformly shaded quad or polygonal meshes represented using faux edges. This filter has no parameters. ``` --- (filter-compute-point-cloud-normals)= ## Compute Point Cloud Normals **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.meshing Estimate normals for point clouds. ```{py:function} ms.compute_point_cloud_normals(**params) :module: _qmeshlab Compute the normals of the vertices of a mesh without exploiting the triangle connectivity, useful for dataset with no faces **Parameters:** - **K** (*int*, default: `10`) — Number of neighbors used to estimate normals. - **smoothIter** (*int*, default: `0`) — Number of smoothing iterations. - **flipFlag** (*bool*, default: `False`) — Use viewpoint to orient normals consistently. - **viewPos** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Viewpoint position for normal orientation. ``` --- (filter-compute-vertex-normals)= ## Compute Vertex Normals **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.unsharp Recompute vertex normals using one of several weighting schemes. ```{py:function} ms.compute_vertex_normals(**params) :module: _qmeshlab Recompute vertex normals according to four different schemes:
1) Simple (no weights) average of normals of the incident faces
2) Area weighted average of normals of the incident faces
3) Angle weighted sum of normals of the incident faces according to the article [1]. Probably this is the best all-purpose choice. It could slightly bias the result for degenerate, fat triangles.
4) Weighted sum of normals of the incident faces, as defined by article [2]. The weight for each wedge is the cross product of the two edges over the product of the square of the two edge lengths.According to the original article it is perfect only for spherical surface, but it should perform well also in practice.
[1]: Computing Vertex Normals from Polygonal Facet by G Thurmer and CA Wuthrich, JGT volume3, num 1. 1998
doi:10.1080/10867651.1998.10487487
[2]: Weights for Computing Vertex Normals from Facet Normals by Nelson Max, JGT vol4, num 2. 1999
doi:10.1080/10867651.1999.10487501 **Parameters:** - **weightMode** (*enum*, default: `simple_average`) — Choose how incident face normals contribute to each vertex normal. ``` --- (filter-normalize-face-normals)= ## Normalize Face Normals **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.unsharp Normalize face normals to unit length. ```{py:function} ms.normalize_face_normals(**params) :module: _qmeshlab Normalize Face Normal Lengths to unit vectors. This filter has no parameters. ``` --- (filter-normalize-vertex-normals)= ## Normalize Vertex Normals **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.unsharp Normalize vertex normals to unit length. ```{py:function} ms.normalize_vertex_normals(**params) :module: _qmeshlab Normalize Vertex Normal Lengths to unit vectors. This filter has no parameters. ``` --- (filter-reorient-face-normals)= ## Orient Face Normals by Ray Casting **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.embree Reorients wrongly oriented faces using Embree ray casting. ```{py:function} ms.reorient_face_normals(**params) :module: _qmeshlab Reorient face normals by geometry.Given the input mesh, this filter uses raytracing to determine if any faces are pointing inward and corrects their orientation. The number of rays is defined by the user; the higher the number, the higher the precision, but at the cost of computation time.This filter requires two values: For further details, see the reference paper: Kenshi Takayama, Alec Jacobson, Ladislav Kavan, Olga Sorkine-Hornung.
A Simple Method for Correcting Facet Orientations in Polygon Meshes Based on Ray Casting. Journal of Computer Graphics Techniques 3(4), 2014. This filter uses the Embree3 library by Intel. **Parameters:** - **rays** (*int*, default: `64`) — Number of rays shot from each face barycenter. - **parity_sampling** (*bool*, default: `False`) — Uses parity sampling instead of visibility sampling. ``` --- (filter-smooth-face-normals)= ## Smooth Face Normals **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.unsharp Laplacian smoothing of face normals. ```{py:function} ms.smooth_face_normals(**params) :module: _qmeshlab Laplacian smooth of the face normals, without touching the position of the vertices. This filter has no parameters. ``` --- (filter-smooth-point-cloud-normals)= ## Smooth Point Cloud Normals **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.meshing Smooth point-cloud normals. ```{py:function} ms.smooth_point_cloud_normals(**params) :module: _qmeshlab Smooth the normals of the vertices of a mesh without exploiting the triangle connectivity, useful for dataset with no faces **Parameters:** - **K** (*int*, default: `10`) — Number of neighbors used to smooth normals. - **useDist** (*bool*, default: `False`) — Weight neighbor normals according to distance. ``` --- (filter-unsharp-mask-normals)= ## Sharpen Face Normals by Unsharp Mask **Categories:** `Attribute/Normal` **Plugin:** qmeshlab.filter.unsharp Enhance face normal variation using an unsharp mask. ```{py:function} ms.unsharp_mask_normals(**params) :module: _qmeshlab Sharpens the **per-face normals**, so that shading brings out variations in orientation that a flat rendering hides. The geometry is untouched -- only the normals change -- which makes it a rendering aid rather than a modelling operation.\n\nUnsharp masking exaggerates local variation by adding back the difference between the signal and a smoothed copy of it: $$s' = s + \lambda\,(s - \mathrm{smooth}(s)).$$ **Weight** is $\lambda$; larger values sharpen harder and amplify noise along with the features. **Smoothing steps** sets how blurred the subtracted copy is, which fixes the scale of the detail being enhanced.\n\n **References:** - Paolo Cignoni, Roberto Scopigno, Marco Tarini. **A simple normal enhancement technique for interactive non-photorealistic renderings**. *Computers & Graphics* (2005). [DOI](https://doi.org/10.1016/j.cag.2004.11.012) [Web](https://www.sciencedirect.com/science/article/pii/S0097849304001980) **Parameters:** - **recalc** (*bool*, default: `False`) — Recompute face normals from geometry before applying the unsharp mask. - **weight** (*double*, default: `0.3`) — Unsharp weight applied to the high-frequency component. - **weightOrig** (*double*, default: `1.0`) — Weight of the original normal signal. - **iterations** (*int*, default: `5`) — Number of Laplacian smoothing iterations used to build the low-pass component. ``` --- (filter-apply-face-quality-function)= ## Compute Face Scalar by Expression **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.expression Computes per-face scalar quality from an expression. ```{py:function} ms.apply_face_quality_function(**params) :module: _qmeshlab Quality function using muparser to generate new Quality for every face
Insert three function each one for quality of the three vertex of a face
**Parameters:** - **q** (*string*, default: `x0+y0+z0`) — Expression for quality output. - **normalize** (*bool*, default: `False`) — Normalize computed quality into range [0, 1]. - **map** (*bool*, default: `False`) — Also write a per-face color ramp. Disabled by default because QMeshLab automatically switches to face-quality visualization after the quality is computed. - **onselected** (*bool*, default: `False`) — If enabled, the filter affects only selected elements. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-apply-scalar-hessian-smoothing-per-vertex-libigl)= ## Smooth Vertex Scalar by Hessian Energy (libigl) **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.igl Smooth vertex scalar values with Hessian energy and natural boundary conditions. ```{py:function} ms.apply_scalar_hessian_smoothing_per_vertex_libigl(**params) :module: _qmeshlab Smooths the current **vertex scalar** field by minimizing $$\alpha\,u^T H u + (1-\alpha)(u-f)^T M(u-f),$$ where $f$ is the input scalar field, $H$ is libigl's mixed finite-element Hessian-energy matrix, and $M$ is the Voronoi mass matrix. Unlike a squared-Laplacian construction, Hessian energy supplies natural high-order boundary conditions, so the geometric shape of an open boundary does not impose the usual low-order boundary bias. **Smoothing Weight** is $\alpha$: zero preserves the input and values near one favor an affine field. Its effect depends on mesh scale because the two energy terms have different physical dimensions. The filter changes scalar values only, not geometry or colors. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) - Oded Stein, Eitan Grinspun, Max Wardetzky, Alec Jacobson. **Natural Boundary Conditions for Smoothing in Geometry Processing**. *ACM Transactions on Graphics* (2018). [DOI](https://doi.org/10.1145/3186564) [Web](https://arxiv.org/abs/1707.04348) **Parameters:** - **smoothing_weight** (*double*, default: `0.01`) — Tradeoff alpha between Hessian smoothness and fidelity to the input scalar values. ``` --- (filter-apply-vertex-quality-function)= ## Compute Vertex Scalar by Expression **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.expression Computes per-vertex scalar quality from an expression. ```{py:function} ms.apply_vertex_quality_function(**params) :module: _qmeshlab Quality function using muparser to generate new Quality for every vertex
**Parameters:** - **q** (*string*, default: `vi`) — Expression for quality output. - **normalize** (*bool*, default: `False`) — Normalize computed quality into range [0, 1]. - **map** (*bool*, default: `False`) — Also write a per-vertex color ramp. Disabled by default because QMeshLab automatically switches to vertex-quality visualization after the quality is computed. - **onselected** (*bool*, default: `False`) — If enabled, the filter affects only selected elements. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-clamp-vertex-quality)= ## Clamp Vertex Scalar **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.colorproc Clamp vertex quality to a chosen range or percentile crop. ```{py:function} ms.clamp_vertex_quality(**params) :module: _qmeshlab Clamp vertex quality values to a given range according to specific values or to percentiles **Parameters:** - **minVal** (*double*, default: `@qualityVMin`) — Lower clamp bound. - **maxVal** (*double*, default: `@qualityVMax`) — Upper clamp bound. - **perc** (*double*, default: `0.0`) — If not zero this value is used for percentile cropping of the quality values. - **zeroSym** (*bool*, default: `False`) — If true the min/max range is enlarged to be symmetric around zero. ``` --- (filter-compute-border-distance-quality)= ## Compute Geodesic Distance from Border **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.geodesic Compute geodesic distance from mesh borders into vertex quality. ```{py:function} ms.compute_border_distance_quality(**params) :module: _qmeshlab Store in the vertex quality field the geodesic distance from borders. The filter does not bake colors; after it runs QMeshLab switches the view to vertex-quality color visualization. This filter has no parameters. ``` --- (filter-compute-exact-geodesic-distance-from-selection-per-vertex-libigl)= ## Compute Exact Geodesic Distance from Selection (libigl) **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.igl Compute exact surface distance from selected vertices with libigl. ```{py:function} ms.compute_exact_geodesic_distance_from_selection_per_vertex_libigl(**params) :module: _qmeshlab Computes the exact polyhedral geodesic distance from the nearest selected, face-referenced vertex to every face-referenced vertex and stores it in **vertex scalar**. Distances follow the piecewise-linear triangle surface, not only mesh edges. Faux edges therefore remain ordinary edges of the stored surface triangulation. This implementation is substantially more expensive than graph or heat-method approximations and is intended when exact distances are required. At least one face-referenced vertex must be selected. No colors are baked into the mesh; QMeshLab switches to vertex-scalar visualization after completion. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) - Joseph S. B. Mitchell, David M. Mount, Christos H. Papadimitriou. **The Discrete Geodesic Problem**. *SIAM Journal on Computing* (1987). [DOI](https://doi.org/10.1137/0216045) This filter has no parameters. ``` --- (filter-compute-face-ambient-occlusion)= ## Compute Face Ambient Occlusion **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.embree Computes cosine-weighted ambient visibility on a surface mesh. ```{py:function} ms.compute_face_ambient_occlusion(**params) :module: _qmeshlab Computes self-occlusion on a surface mesh by tracing rays with Intel Embree. Rays start at each face barycenter and only directions in the outward hemisphere contribute, weighted by the cosine of their angle to the face normal. The resulting ambient-visibility scalar is stored in face quality and interpolated to vertex quality; a larger value means that more ambient light reaches the surface. The average unoccluded direction is also stored in the per-face custom attribute `BentNormal`. By default directions cover the sphere uniformly. **Directional Bias** replaces a fraction of them with directions inside the cone defined by **Lighting Direction** and **Cone Half-Angle**: `0` is fully uniform ambient illumination and `1` uses only the cone. More rays improve angular sampling at greater cost. The filter does not bake colors; QMeshLab switches to face-quality visualization after completion. **Parameters:** - **rays** (*int*, default: `64`) — Number of lighting directions tested at each face barycenter. - **directional_bias** (*double*, default: `0.0`) — Fraction of ray directions sampled inside the lighting cone: 0 is uniform ambient light, 1 uses only the cone. - **cone_direction** (*point3f*, default: `[0.0, 1.0, 0.0]`) — Axis of the directionally biased lighting cone. - **cone_half_angle** (*double*, default: `30.0`) — Half-angle in degrees of the directionally biased lighting cone. ``` --- (filter-compute-generalized-winding-number-per-vertex-libigl)= ## Compute Generalized Winding Number (libigl) **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.igl Evaluate another layer's generalized winding-number field at every current-layer vertex. ```{py:function} ms.compute_generalized_winding_number_per_vertex_libigl(**params) :module: _qmeshlab Evaluates the oriented **Surface Mesh** winding-number field at every vertex of the current mesh or point cloud and stores it in **vertex scalar**. Layer transforms are applied before evaluation. For a consistently oriented closed surface, values are approximately $1$ inside and $0$ outside; reversing its orientation reverses the sign. On open, self-intersecting, or non-manifold triangle soups the field remains continuous and useful, but the value $0.5$ is only a conventional classification threshold. **Fast Approximation** builds libigl's second-order hierarchy and is the practical default for large inputs. **Exact** directly accumulates triangle solid angles and can be prohibitively expensive because its work grows with both surface triangles and query vertices. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) - Alec Jacobson, Ladislav Kavan, Olga Sorkine-Hornung. **Robust Inside-Outside Segmentation using Generalized Winding Numbers**. *ACM Transactions on Graphics* (2013). [DOI](https://doi.org/10.1145/2461912.2461916) - Gavin Barill, Neil G. Dickson, Ryan Schmidt, David I. W. Levin, Alec Jacobson. **Fast Winding Numbers for Soups and Clouds**. *ACM Transactions on Graphics* (2018). [DOI](https://doi.org/10.1145/3197517.3201337) [Web](https://www.dgp.toronto.edu/projects/fast-winding-numbers/) **Parameters:** - **surface_mesh** (*mesh*, default: `@otherMeshIndex`) — Oriented triangle surface whose winding-number field is evaluated. - **method** (*enum*, default: `fast`) — Use the hierarchical approximation for speed or direct solid-angle accumulation for exact values. ``` --- (filter-compute-geodesic-distance-from-point)= ## Compute Geodesic Distance from Point **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.geodesic Compute geodesic distance from a given point into vertex quality. ```{py:function} ms.compute_geodesic_distance_from_point(**params) :module: _qmeshlab Store in the vertex quality field the geodesic distance from a given point on the mesh surface. The filter does not bake colors; after it runs QMeshLab switches the view to vertex-quality color visualization. **Parameters:** - **startPoint** (*point3f*, default: `[0.0, 0.0, 0.0]`) — The point from which geodesic distance is measured. The closest surface vertex is used as seed. - **maxDistance** (*absperc*, default: `@bboxDiag`) — Cut-off distance. Vertices beyond this threshold are assigned distance 0. Set to 0 to compute everywhere. ``` --- (filter-compute-geodesic-distance-from-selection)= ## Compute Geodesic Distance from Selection (vcglib) **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.geodesic Compute geodesic distance from selected vertices into vertex quality. ```{py:function} ms.compute_geodesic_distance_from_selection(**params) :module: _qmeshlab Store in the vertex quality field the geodesic distance from the selected points on the mesh surface. The filter does not bake colors; after it runs QMeshLab switches the view to vertex-quality color visualization. **Parameters:** - **maxDistance** (*absperc*, default: `@bboxDiag`) — Cut-off distance. Vertices beyond this threshold are assigned distance 0. Set to 0 to compute everywhere. ``` --- (filter-compute-heat-geodesic-distance)= ## Compute Heat Geodesic Distance from Selection (vcglib) **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.geodesic Approximate geodesic distance via the heat method into vertex quality. ```{py:function} ms.compute_heat_geodesic_distance(**params) :module: _qmeshlab Store in the vertex quality field the approximated geodesic distance, computed via the heat method (Crane et al.), from the selected points on the mesh surface. The filter does not bake colors; after it runs QMeshLab switches the view to vertex-quality color visualization. As this implementation does not use intrinsic triangulation it is very sensitive to triangulation. First run takes longer because factorization has to be built. **Parameters:** - **m** (*double*, default: `1.0`) — Multiplier applied to the squared average edge length to compute the backward-Euler timestep. Larger values give smoother but less accurate results. ``` --- (filter-compute-heat-geodesic-distance-from-selection-per-vertex-libigl)= ## Compute Heat Geodesic Distance from Selection (libigl) **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.igl Approximate surface distance from selected vertices with libigl's heat method. ```{py:function} ms.compute_heat_geodesic_distance_from_selection_per_vertex_libigl(**params) :module: _qmeshlab Approximates geodesic distance from the nearest selected, face-referenced vertex with the heat method and stores it in **vertex scalar**. The method diffuses heat for a short time, normalizes its gradient, and solves a Poisson equation. It is generally much faster than the exact method for large source-to-all queries. The timestep is $t = m h^2$, where $h$ is average edge length and **Time Step Multiplier** is $m$. Smaller values preserve finer detail but may be less stable. **Intrinsic Delaunay Operators** uses libigl's intrinsic Delaunay cotangent, mass, and gradient operators, reducing sensitivity to poor input triangulations without changing connectivity. At least one face-referenced vertex must be selected. Faux-edge polygon groups are processed through their stored triangle representation. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) - Keenan Crane, Clarisse Weischedel, Max Wardetzky. **Geodesics in Heat: A New Approach to Computing Distance Based on Heat Flow**. *ACM Transactions on Graphics* (2013). [DOI](https://doi.org/10.1145/2516971.2516977) [Web](https://www.cs.cmu.edu/~kmcrane/Projects/HeatMethod/paperCACM.pdf) **Parameters:** - **time_step_multiplier** (*double*, default: `1.0`) — Multiplier m in t = m h², where h is average edge length. Smaller values are more local but can be less stable. - **use_intrinsic_delaunay** (*bool*, default: `False`) — Build the heat-method operators from libigl's intrinsic Delaunay triangulation. This often improves robustness on poorly shaped triangles. ``` --- (filter-compute-obscurance)= ## Compute Obscurance **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.embree Computes volumetric obscurance and stores it in quality. ```{py:function} ms.compute_obscurance(**params) :module: _qmeshlab Compute ambient Obscurance.
Ambient obscurance is a computer graphics technique used to simulate the effect of global ambient light in a 3D scene, making the mesh appear more realistic.
This filter requires two values:The resulting values for the obscurance are saved into face quality. The filter does not bake colors; after it runs QMeshLab switches the view to face-quality color visualization.
For further details see the reference paper: Iones Krupkin Sbert Zhukov Fast, Realistic Lighting for Video Games IEEECG&A 2003
This filter uses Embree3 library by INTEL. **Parameters:** - **rays** (*int*, default: `64`) — Number of rays shot from each face barycenter. - **tau** (*double*, default: `0.1`) — Spatial decay factor used in obscurance accumulation. ``` --- (filter-compute-point-cloud-ambient-occlusion)= ## Compute Point Cloud Ambient Occlusion **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.embree Computes point-cloud visibility against a surface occluder. ```{py:function} ms.compute_point_cloud_ambient_occlusion(**params) :module: _qmeshlab Traces rays from every point of the current point-cloud layer against a separate **Occluder Mesh**, using Intel Embree. The result is stored in vertex quality; a larger value means that the point is more exposed. Layer transforms are respected, and the average direction of escaping rays is stored in the per-vertex custom attribute `BentNormal`. **Normal Source** selects the meaning of the measurement:By default directions cover the sphere uniformly. **Directional Bias** replaces a fraction of them with directions inside the cone defined by **Lighting Direction** and **Cone Half-Angle**: `0` is fully uniform and `1` uses only the cone. More rays improve angular sampling at greater cost. The filter does not bake colors; QMeshLab switches to vertex-quality visualization after completion. **Parameters:** - **occluder_mesh** (*mesh*, default: `@otherMeshIndex`) — Surface mesh tested by rays from the current point cloud. - **normal_source** (*enum*, default: `closest_occluder_surface`) — Selects an existing point normal, the closest occluder triangle normal, or orientation-independent spherical visibility. - **rays** (*int*, default: `64`) — Number of visibility directions tested at each point. - **directional_bias** (*double*, default: `0.0`) — Fraction of ray directions sampled inside the lighting cone: 0 is uniform ambient light, 1 uses only the cone. - **cone_direction** (*point3f*, default: `[0.0, 1.0, 0.0]`) — Axis of the directionally biased lighting cone. - **cone_half_angle** (*double*, default: `30.0`) — Half-angle in degrees of the directionally biased lighting cone. ``` --- (filter-compute-scalar-by-signed-distance-per-vertex)= ## Compute Signed Distance to Mesh (TrueForm) **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.trueform Store each vertex's signed distance to another layer's surface in vertex scalar. ```{py:function} ms.compute_scalar_by_signed_distance_per_vertex(**params) :module: _qmeshlab Writes, for every vertex, its distance to the nearest point of the reference layer's surface — **negative inside, positive outside**.\n\nThe sign is what makes this a field rather than a proximity readout. It can be contoured with *Create Polyline from Scalar Isocontour (TrueForm)* (the zero contour is the intersection curve), thresholded to select a shell of given thickness, or used to measure how far a simplified or reconstructed model departs from its original and in which direction.\n\nBoth layers are taken in world space. The reference must be a **closed surface** for the sign to mean anything; on an open sheet the inside is undefined and the sign follows the surface orientation instead.\n\nEnable **Unsigned** for absolute distance, which is what you want when only proximity matters.\n\nCompare with *Measure Hausdorff Distance*, which reports a single worst-case number, and *Measure Chamfer Distance (TrueForm)*, which reports a mean. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The layer whose vertices are measured. - **referenceMesh** (*mesh*, default: `@otherMeshIndex`) — The closed surface distances are measured to. - **unsigned** (*bool*, default: `False`) — Store absolute distance, discarding inside/outside. ``` --- (filter-compute-scalar-from-camera-per-vertex)= ## Compute Vertex Scalar from Camera **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.camera Compute vertex quality using the camera definition, according to viewing angle or distance. ```{py:function} ms.compute_scalar_from_camera_per_vertex(**params) :module: _qmeshlab Compute vertex quality using the camera definition, according to viewing angle or distance. Uses the current raster camera if available. **Parameters:** - **depth** (*bool*, default: `True`) — Use depth from camera as a factor (quality proportional to distance). - **facing** (*bool*, default: `False`) — Use cosine of viewing angle as a factor. - **clip** (*bool*, default: `False`) — Clip quality values to zero for vertices outside the camera viewport. - **normalize** (*bool*, default: `False`) — If checked normalize all quality values in range [0..1]. - **map** (*bool*, default: `False`) — If checked map quality generated values into per-vertex color. ``` --- (filter-compute-scalar-from-raster-coverage-per-face)= ## Compute Face Scalar from Raster Coverage **Categories:** `Attribute/Scalar`, `Transfer/Raster to Mesh` **Plugin:** qmeshlab.filter.img_patch_param Compute a quality value representing the number of images into which each face of the active mesh is visible. ```{py:function} ms.compute_scalar_from_raster_coverage_per_face(**params) :module: _qmeshlab Compute a quality value representing the number of images into which each face of the active mesh is visible. For each active raster, a software depth buffer is built and each face is tested for visibility. A face is considered visible if at least one of its three vertices is visible. The quality value counts how many rasters each face is visible in. Optionally normalizes to [0,1]. **Parameters:** - **normalizeQuality** (*bool*, default: `False`) — Rescale quality values to the range [0,1]. - **depthEpsilon** (*double*, default: `0.5`) — Tolerance for depth test when checking vertex visibility. Increase for noisy registrations. ``` --- (filter-compute-scalar-from-raster-coverage-per-vertex)= ## Compute Vertex Scalar from Raster Coverage **Categories:** `Attribute/Scalar`, `Transfer/Raster to Mesh` **Plugin:** qmeshlab.filter.img_patch_param Compute a quality value representing the number of images into which each vertex of the active mesh is visible. ```{py:function} ms.compute_scalar_from_raster_coverage_per_vertex(**params) :module: _qmeshlab Compute a quality value representing the number of images into which each vertex of the active mesh is visible. For each active raster, a software depth buffer is built and each vertex is tested for visibility (inside the image bounds, front-facing, and passing the depth test). The quality value counts how many rasters each vertex is visible in. Optionally normalizes to [0,1]. **Parameters:** - **normalizeQuality** (*bool*, default: `False`) — Rescale quality values to the range [0,1]. - **depthEpsilon** (*double*, default: `0.5`) — Tolerance for depth test when checking vertex visibility. Increase for noisy registrations. ``` --- (filter-compute-shape-diameter-function)= ## Compute Shape Diameter Function **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.embree Computes SDF and stores it in quality. ```{py:function} ms.compute_shape_diameter_function(**params) :module: _qmeshlab Compute Shape-Diameter Function
The SDF defines the distance between a point in 3D space and the nearest point on the object's surface.This filter can be used to find out the thickness of the mesh
Given a face, a set of rays are shot inward, and an average of the distance to hit a face is saved in the face quality. The filter does not bake colors; after it runs QMeshLab switches the view to face-quality color visualization.This filter requires two values:
For further details see the reference paper: Shapira Shamir Cohen-Or, Consistent Mesh Partitioning and Skeletonisation using the shaper diameter function, Visual Comput. J. (2008)
This filter uses Embree3 library by INTEL. **Parameters:** - **rays** (*int*, default: `64`) — Number of rays shot from each face barycenter. - **cone_amplitude** (*double*, default: `90.0`) — Cone opening angle in degrees used for SDF ray directions. ``` --- (filter-generate-scalar-harmonic-field)= ## Compute Harmonic Scalar Field **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.unsharp Compute a harmonic scalar field over the mesh. ```{py:function} ms.generate_scalar_harmonic_field(**params) :module: _qmeshlab Generates a scalar harmonic field over the mesh. Input scalar values must be assigned to two vertices as Dirichlet boundary conditions. Applying the filter, a discrete Laplace operator generates the harmonic field values for all the mesh vertices, which are stored in the quality per vertex attribute of the mesh.
For more details see:Dynamic Harmonic Fields for Surface Processing by Kai Xua, Hao Zhang, Daniel Cohen-Or, Yueshan Xionga. Computers & Graphics, 2009
doi:10.1016/j.cag.2009.03.022 **Parameters:** - **point1** (*point3f*, default: `[0.0, 0.0, 0.0]`) — A vertex on the mesh representing one harmonic field boundary condition. - **point2** (*point3f*, default: `[1.0, 1.0, 1.0]`) — A vertex on the mesh representing the other harmonic field boundary condition. - **value1** (*double*, default: `0.0`) — Harmonic field value assigned to the first constrained vertex. - **value2** (*double*, default: `1.0`) — Harmonic field value assigned to the second constrained vertex. - **colorize** (*bool*, default: `False`) — Also write a per-vertex color ramp after computing the harmonic field. Disabled by default because QMeshLab automatically switches to vertex-quality visualization. ``` --- (filter-per-face-quality-by-geometric-measure)= ## Compute Face Scalar from Geometry **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.colorproc Compute face quality from triangle shape, area, or polygonal planarity. ```{py:function} ms.per_face_quality_by_geometric_measure(**params) :module: _qmeshlab Computes a geometric measure for every face and stores the result in **face quality**. No colors are baked into the mesh; after completion QMeshLab switches the view to face-quality visualization. The triangle-shape measures are scale independent and approach zero for degenerate triangles: - **Area / squared maximum side**: $2A/L_{\max}^2$, where $A$ is triangle area and $L_{\max}$ is its longest side. Its range is $[0,\sqrt{3}/2]$; an equilateral triangle reaches $\sqrt{3}/2$. - **Normalized radius ratio**: $2r/R$, where $r$ and $R$ are the inradius and circumradius. Its range is $[0,1]$; an equilateral triangle reaches $1$. - **Mean ratio**: $4\sqrt{3}A/(a^2+b^2+c^2)$. Its range is $[0,1]$; an equilateral triangle reaches $1$. - **Area**: the triangle area in the mesh's squared coordinate units. This measure is not scale independent. The planarity measures apply only to polygonal meshes represented by faux-edge triangle groups. QMeshLab fits a support plane to each polygon and assigns the same result to all its component triangles: - **Polygonal planarity (maximum)**: maximum vertex distance from the fitted plane. - **Polygonal planarity (relative)**: mean vertex-to-plane distance divided by the polygon's half-perimeter. **Parameters:** - **metric** (*enum*, default: `area_max_side`) — Choose the geometric measure stored in face quality. ``` --- (filter-per-face-quality-by-texture-distortion)= ## Compute UV Distortion **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.colorproc Measure angular, area, edge-length, or directional stretch distortion in a UV mapping. ```{py:function} ms.per_face_quality_by_texture_distortion(**params) :module: _qmeshlab Compares every triangle in 3D with its mapping in UV space and stores the resulting dimensionless distortion in **face quality**. No colors are baked into the mesh; after completion QMeshLab switches the view to face-quality visualization. Both per-wedge and per-vertex texture coordinates are supported, and texture image files are not required. - **Angle distortion**: the mean relative angular error over the three corners, $$D_{\mathrm{angle}}=\frac{1}{3}\sum_{i=1}^{3}\frac{|\theta_i^{UV}-\theta_i^{3D}|}{\theta_i^{3D}}.$$ A value of $0$ means that the mapping preserves all triangle angles; larger values indicate increasing conformal distortion. Uniform scaling and rigid transformations of the UV triangle do not affect this measure. - **Area distortion**: first computes one global area scale $s_A=\sum A_{3D}/\sum A_{UV}$, then evaluates each face as $$D_{\mathrm{area}}=\frac{|s_A A_{UV}-A_{3D}|}{A_{3D}}.$$ A value of $0$ means that the face has the globally expected texel density; larger values identify local expansion or compression relative to the mesh-wide average. - **Edge-length distortion**: uses the global length scale $s_L=\sum l_{3D}/\sum l_{UV}$ and averages the relative error of the three edges, $$D_{\mathrm{edge}}=\frac{1}{3}\sum_{i=1}^{3}\frac{|s_L l_i^{UV}-l_i^{3D}|}{l_i^{3D}}.$$ The ideal value is $0$. Unlike angle distortion, this measure responds to local changes in scale as well as triangle shape. - **L2 stretch**: measures the root-mean-square directional stretch of the locally linear map from texture space to the surface, $$L_2=\sqrt{\frac{a+c}{2}},\qquad a=\frac{\|S_s\|^2}{s_A},\quad c=\frac{\|S_t\|^2}{s_A}.$$ The ideal value is $1$. It summarizes average sampling distortion within the triangle. - **L-infinity stretch**: measures the largest directional stretch, $$L_\infty=\sqrt{\frac{a+c+\sqrt{(a-c)^2+4b^2}}{2}},\qquad b=\frac{S_s\cdot S_t}{s_A}.$$ The ideal value is $1$. It highlights the worst local undersampling direction and is therefore more conservative than L2 stretch. The global normalization makes every metric invariant to uniform resizing of the complete UV map. UV area is oriented, matching VCGLib's distortion implementation. A zero total oriented UV area makes area normalization undefined; stretch additionally requires that total to be positive. For L2 and L-infinity stretch, folded or degenerate individual UV triangles produce non-finite quality values, which are excluded from the displayed finite quality range. **Parameters:** - **metric** (*enum*, default: `angle`) — Choose the UV distortion measure stored in face quality. ``` --- (filter-saturate-vertex-quality)= ## Clamp Vertex Scalar Gradient **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.colorproc Limit the spatial gradient of vertex quality. ```{py:function} ms.saturate_vertex_quality(**params) :module: _qmeshlab Saturate vertex quality, so that for each vertex the gradient of the quality is lower than the given threshold value (in absolute value) The saturation is done in a conservative way (quality is always decreased and never increased) **Parameters:** - **gradientThr** (*double*, default: `1.0`) — The maximum value admitted for the quality gradient (in absolute value). - **updateColor** (*bool*, default: `False`) — Also write a per-vertex color ramp after saturating quality. Disabled by default because QMeshLab automatically switches to vertex-quality visualization. ``` --- (filter-smooth-vertex-quality)= ## Smooth Vertex Scalar **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.unsharp Laplacian smoothing of vertex quality values. ```{py:function} ms.smooth_vertex_quality(**params) :module: _qmeshlab Laplacian smooth of the quality per vertex values. This filter has no parameters. ``` --- (filter-unsharp-mask-quality)= ## Sharpen Vertex Scalar by Unsharp Mask **Categories:** `Attribute/Scalar` **Plugin:** qmeshlab.filter.unsharp Enhance per-vertex quality variations with an unsharp mask. ```{py:function} ms.unsharp_mask_quality(**params) :module: _qmeshlab Sharpens the **per-vertex scalar field**, so that gentle gradients in the values become steeper and easier to read once the field is mapped to color.\n\nUnsharp masking exaggerates local variation by adding back the difference between the signal and a smoothed copy of it: $$s' = s + \lambda\,(s - \mathrm{smooth}(s)).$$ **Weight** is $\lambda$; larger values sharpen harder and amplify noise along with the features. **Smoothing steps** sets how blurred the subtracted copy is, which fixes the scale of the detail being enhanced.\n\n **References:** - Paolo Cignoni, Roberto Scopigno, Marco Tarini. **A simple normal enhancement technique for interactive non-photorealistic renderings**. *Computers & Graphics* (2005). [DOI](https://doi.org/10.1016/j.cag.2004.11.012) [Web](https://www.sciencedirect.com/science/article/pii/S0097849304001980) **Parameters:** - **weight** (*double*, default: `0.3`) — Unsharp weight applied to the high-frequency quality component. - **weightOrig** (*double*, default: `1.0`) — Weight of the original quality signal. - **iterations** (*int*, default: `5`) — Number of Laplacian smoothing iterations used to build the low-pass quality signal. ``` --- (filter-build-polyline-from-selection)= ## Create Polyline from Selected Edges **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.meshing Create edge mesh from selected edges. ```{py:function} ms.build_polyline_from_selection(**params) :module: _qmeshlab Create a new Layer with an edge mesh composed only by the selected edges of the current mesh This filter has no parameters. ``` --- (filter-compute-planar-section)= ## Create Polyline from Planar Section **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.meshing Compute planar section polyline. ```{py:function} ms.compute_planar_section(**params) :module: _qmeshlab Compute the polyline representing a planar section (a slice) of a mesh; if the resulting polyline is closed the result is filled and also a triangular mesh representing the section is saved **Parameters:** - **planeAxis** (*enum*, default: `x`) — Slicing plane normal axis. - **customAxis** (*point3f*, default: `[0.0, 1.0, 0.0]`) — Custom slicing plane normal direction. - **planeOffset** (*double*, default: `0.0`) — Offset from reference point. - **relativeTo** (*enum*, default: `origin`) — Reference frame for plane offset. - **createSectionSurface** (*bool*, default: `False`) — Create triangulated sections from closed contours, including holes and disconnected regions. - **splitSurfaceWithSection** (*bool*, default: `False`) — Create under/over split layers (requires manifold mesh). ``` --- (filter-create-annulus)= ## Create Annulus **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates a flat annulus (holed disk). ```{py:function} ms.create_annulus(**params) :module: _qmeshlab Create an Annulus e.g. a flat region bounded by two concentric circles, or a holed disk. **Parameters:** - **inner_radius** (*double*, default: `0.5`) — Inner radius of the annulus. - **outer_radius** (*double*, default: `1.0`) — Outer radius of the annulus. - **sides** (*int*, default: `32`) — Number of sides of the polygonal approximation. ``` --- (filter-create-box)= ## Create Box **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates a Box or Cube. ```{py:function} ms.create_box(**params) :module: _qmeshlab Create a Box, Cube, Hexahedron. You can specify the side length. **Parameters:** - **size** (*double*, default: `1.0`) — Length of each side of the box. ``` --- (filter-create-cone)= ## Create Cone **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates a Cone or truncated cone. ```{py:function} ms.create_cone(**params) :module: _qmeshlab Create a Cone **Parameters:** - **r0** (*double*, default: `1.0`) — Radius of the bottom circle. - **r1** (*double*, default: `2.0`) — Radius of the top circle. - **h** (*double*, default: `3.0`) — Height of the cone. - **subdiv** (*int*, default: `36`) — Number of sides of the polygonal approximation. ``` --- (filter-create-dodecahedron)= ## Create Dodecahedron **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates a Dodecahedron. ```{py:function} ms.create_dodecahedron(**params) :module: _qmeshlab Create a Dodecahedron This filter has no parameters. ``` --- (filter-create-dodecahedron-symmetric)= ## Create Symmetric Dodecahedron **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates a symmetrically triangulated Dodecahedron. ```{py:function} ms.create_dodecahedron_symmetric(**params) :module: _qmeshlab Create a Dodecahedron, but triangulated with an additional vertex in the middle of each face to preserve symmetry. This filter has no parameters. ``` --- (filter-create-grid)= ## Create Grid **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.expression Generates a regular 2D grid mesh. ```{py:function} ms.create_grid(**params) :module: _qmeshlab Generate a new 2D Grid mesh with number of vertices on X and Y axis specified by user with absolute length/height.
It's possible to center Grid on origin. **Parameters:** - **numVertX** (*int*, default: `10`) — Number of vertices along X. - **numVertY** (*int*, default: `10`) — Number of vertices along Y. - **absScaleX** (*double*, default: `0.3`) — Absolute scale along X. - **absScaleY** (*double*, default: `0.3`) — Absolute scale along Y. - **center** (*bool*, default: `False`) — Centers the generated grid on origin. ``` --- (filter-create-icosahedron)= ## Create Icosahedron **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates an Icosahedron. ```{py:function} ms.create_icosahedron(**params) :module: _qmeshlab Create an Icosahedron This filter has no parameters. ``` --- (filter-create-implicit-surface)= ## Create Isosurface from Expression **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.expression Extracts an isosurface from an implicit scalar field. ```{py:function} ms.create_implicit_surface(**params) :module: _qmeshlab Generate a new mesh that corresponds to the 0 valued isosurface defined by the scalar field generated by the given expression **Parameters:** - **voxelSize** (*double*, default: `0.05`) — Sampling step used for volumetric evaluation. - **minX** (*double*, default: `-1.0`) — Sampling range parameter. - **minY** (*double*, default: `-1.0`) — Sampling range parameter. - **minZ** (*double*, default: `-1.0`) — Sampling range parameter. - **maxX** (*double*, default: `1.0`) — Sampling range parameter. - **maxY** (*double*, default: `1.0`) — Sampling range parameter. - **maxZ** (*double*, default: `1.0`) — Sampling range parameter. - **expr** (*string*, default: `x*x+y*y+z*z-0.5`) — Scalar field expression f(x,y,z). The 0-isovalue is extracted. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-create-octahedron)= ## Create Octahedron **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates an Octahedron. ```{py:function} ms.create_octahedron(**params) :module: _qmeshlab Create an Octahedron This filter has no parameters. ``` --- (filter-create-points-on-a-spherical-cap)= ## Create Points on a Spherical Cap **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates an area-uniform point cloud on a unit-sphere cap. ```{py:function} ms.create_points_on_a_spherical_cap(**params) :module: _qmeshlab Creates points on the surface of a unit-sphere cap centred on **Cap Direction** and bounded by **Cap Half-Angle** $\alpha$. Every generated point also receives its outward radial normal. Both techniques are uniform with respect to spherical surface area: equivalently, $\cos\theta$ is distributed uniformly in $[\cos\alpha,1]$, rather than $\theta$ being distributed uniformly. **Monte Carlo** generates independent random samples and can be reproduced with a non-zero seed. **Fibonacci** is deterministic and uses VCGLib's direct equal-area spherical-cap construction, producing the exact requested count without first generating and discarding points from a complete sphere. A half-angle of $180^\circ$ covers the complete sphere. **Parameters:** - **point_num** (*int*, default: `100`) — Exact number of points to generate. - **direction** (*point3f*, default: `[0.0, 1.0, 0.0]`) — Direction from the sphere centre to the centre of the cap. - **half_angle** (*double*, default: `30.0`) — Polar angle in degrees from the cap axis to its boundary; 90 is a hemisphere and 180 covers the complete sphere. - **technique** (*enum*, default: `fibonacci`) — Random Monte Carlo sampling or deterministic Fibonacci sampling. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run; any other value makes Monte Carlo sampling exactly reproducible. ``` --- (filter-create-points-on-sphere)= ## Create Points on a Sphere **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates a point cloud distributed on a unit sphere. ```{py:function} ms.create_points_on_sphere(**params) :module: _qmeshlab Create a spherical point cloud, it can be random or regularly distributed. **Parameters:** - **point_num** (*int*, default: `100`) — Approximate number of points to generate. - **technique** (*enum*, default: `fibonacci`) — Strategy used to distribute points on the sphere. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the Monte Carlo point set exactly reproducible. ``` --- (filter-create-selection-perimeter)= ## Create Polyline from Selection Perimeter **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.meshing Create polyline from selection perimeter. ```{py:function} ms.create_selection_perimeter(**params) :module: _qmeshlab Create a new Layer with an edge mesh (polyline) tracing the perimeter of the **selected faces**: every edge of a selected face whose adjacent face is not selected. Selecting all the faces of the mesh therefore converts its boundary edges into a polyline.
To build a polyline from an *edge* selection instead, use *Build a Polyline from Selected Edges*. This filter has no parameters. ``` --- (filter-create-sphere)= ## Create Sphere **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates a Sphere by recursive subdivision of an Icosahedron. ```{py:function} ms.create_sphere(**params) :module: _qmeshlab Create a Sphere, whose topology is obtained as regular subdivision of an icosahedron. **Parameters:** - **radius** (*double*, default: `1.0`) — Radius of the sphere. - **subdiv** (*int*, default: `3`) — Number of recursive subdivisions. 0=icosahedron, 3=1280 faces, max=8. ``` --- (filter-create-sphere-cap)= ## Create Sphere Cap **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates a triangulated unit-radius spherical cap from a refined hexagonal disk. ```{py:function} ms.create_sphere_cap(**params) :module: _qmeshlab Creates a unit-radius spherical cap above the XY plane, with its circular boundary in the plane and its axis along +Z. The cap starts as a six-triangle disk; each subdivision splits every triangle into four, redistributes the interior vertices by Laplacian smoothing, and then lifts all vertices onto the sphere. This construction gives a regular, compact triangulation for shallow caps, but it is not a general-purpose spherical mesher. Triangle distortion grows toward the boundary for wide caps, becoming severe as the cap approaches a hemisphere. **Cap Half-Angle** is the polar angle from the +Z axis out to the cap boundary, so it is half the cap's full angular diameter: 30° spans a 60° cap, and a hemisphere would be 90°. The filter stops at 89.5° because this disk-based parameterization degenerates at the hemisphere limit. For a well-shaped hemisphere or a wider spherical patch, start from a complete sphere and extract the required region instead. **Parameters:** - **half_angle** (*double*, default: `30.0`) — Polar angle in degrees from the cap axis to its boundary, i.e. half the full angular diameter. A hemisphere would be 90°, where this construction degenerates. - **subdiv** (*int*, default: `3`) — Number of recursive refinements of the initial six triangles. Level n creates 6 × 4^n faces. ``` --- (filter-create-tetrahedron)= ## Create Tetrahedron **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates a Tetrahedron. ```{py:function} ms.create_tetrahedron(**params) :module: _qmeshlab Create a Tetrahedron This filter has no parameters. ``` --- (filter-create-torus)= ## Create Torus **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.create Creates a Torus. ```{py:function} ms.create_torus(**params) :module: _qmeshlab Create a Torus **Parameters:** - **h_radius** (*double*, default: `3.0`) — Radius of the whole horizontal ring of the torus. - **v_radius** (*double*, default: `1.0`) — Radius of the vertical cross-section of the ring. - **h_subdiv** (*int*, default: `24`) — Subdivision steps around the ring. - **v_subdiv** (*int*, default: `12`) — Subdivision steps of the cross-section circle. ``` --- (filter-fit-plane-to-selection)= ## Create Plane from Selection **Categories:** `Creation/Primitives`, `Measurement/Geometric` **Plugin:** qmeshlab.filter.create Creates a quad on the plane fitting the current selection. ```{py:function} ms.fit_plane_to_selection(**params) :module: _qmeshlab Fits a plane to the selected vertices (or vertices of selected faces) of the current mesh and creates a new planar quad mesh aligned to that plane. **Parameters:** - **extent** (*double*, default: `1.0`) — Size of the plane relative to the selection bounding box on the plane. 1.0 = same size, 1.1 = 10% larger. - **subdiv** (*int*, default: `3`) — Number of subdivisions along each side of the plane. ``` --- (filter-generate-noisy-isosurface)= ## Create Isosurface from Perlin Noise **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.basic Creates an isosurface perturbed by 3D Perlin noise. ```{py:function} ms.generate_noisy_isosurface(**params) :module: _qmeshlab Generates a scalar field over a cubic grid and extracts an isosurface using marching cubes. **Parameters:** - **resolution** (*int*, default: `64`) — Resolution of the side of the cubic grid used for volume creation. ``` --- (filter-generate-polyline-from-mesh-intersection)= ## Create Polyline from Mesh Intersection (TrueForm) **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.trueform Extract the curve where two layers cross, as a polyline layer. ```{py:function} ms.generate_polyline_from_mesh_intersection(**params) :module: _qmeshlab Extracts the exact curve along which two layers intersect, as a new polyline layer. Both are taken in world space, so their layer matrices are applied first.\n\nThe curve is computed with the same exact arrangement the booleans use, so it is the true intersection rather than a sampled approximation, and it is usable as a construction line — a seam to cut along, a profile to sweep, or a measurement.\n\nLayers that do not touch produce nothing. **Parameters:** - **firstMesh** (*mesh*, default: `@currentMeshIndex`) — The first layer. - **secondMesh** (*mesh*, default: `@otherMeshIndex`) — The second layer. ``` --- (filter-generate-polyline-from-scalar-isocontour)= ## Create Polyline from Scalar Isocontour (TrueForm) **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.trueform Extract contour lines of the per-vertex scalar field as polylines on the surface. ```{py:function} ms.generate_polyline_from_scalar_isocontour(**params) :module: _qmeshlab Extracts level sets of the **per-vertex scalar field** as polylines lying exactly on the surface.\n\nThis turns every scalar QMeshLab can compute into something with extractable contours: geodesic distance from a point or a border, curvature, ambient occlusion, shape diameter, raster coverage, or anything written by *Compute Vertex Scalar by Expression*. Contours of a geodesic distance are isodistance rings; of a height field, topographic contour lines.\n\n**Contours** sets how many levels are extracted. They are spaced evenly and placed strictly *inside* the range, never at its extremes, where a contour is either empty or the whole boundary.\n\nBy default the range is the field's own minimum and maximum. Enable **Use Custom Range** to contour a chosen band instead — useful when a few outliers would otherwise compress every contour into a corner of the model.\n\nA constant field has no contours, and the filter says so rather than returning an empty layer. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The layer whose scalar field is contoured. - **contourCount** (*int*, default: `10`) — How many evenly spaced contour levels to extract. - **useCustomRange** (*bool*, default: `False`) — Contour a chosen value band instead of the field's full min-max range. - **minValue** (*double*, default: `@qualityVMin`) — Lower end of the contoured range. Ignored unless Use Custom Range is on. - **maxValue** (*double*, default: `@qualityVMax`) — Upper end of the contoured range. Ignored unless Use Custom Range is on. ``` --- (filter-generate-polyline-from-self-intersections)= ## Create Polyline from Self-Intersections (TrueForm) **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.trueform Extract the curve where a mesh passes through itself, as a polyline layer. ```{py:function} ms.generate_polyline_from_self_intersections(**params) :module: _qmeshlab Extracts the exact curve along which the layer intersects **itself**, as a new polyline layer.\n\n*Select Self Intersecting Faces* marks the faces involved; this gives the intersection itself, which is what you need to see where the problem is rather than merely that it exists — and, being exact geometry rather than a selection, it can be measured, exported, or swept into a tube.\n\nA clean mesh produces nothing, and the filter says so. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The layer to examine. ``` --- (filter-generate-solid-wireframe)= ## Create Solid Wireframe **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.voronoi Convert the current mesh into a solid shell made of cylinders, spheres, and face prisms. ```{py:function} ms.generate_solid_wireframe(**params) :module: _qmeshlab Create a new solid wireframe layer by replacing edges with cylinders, vertices with spheres or short cylinders, and faces with prisms. **Parameters:** - **edgeCylFlag** (*bool*, default: `True`) — Replace edges with cylinders. - **edgeCylRadius** (*absperc*, default: `@bboxDiag01`) — Radius of each edge cylinder. - **vertCylFlag** (*bool*, default: `False`) — Replace vertices with short normal-aligned cylinders. - **vertCylRadius** (*absperc*, default: `@bboxDiag01`) — Radius of each vertex cylinder. - **vertSphFlag** (*bool*, default: `True`) — Replace vertices with spheres. - **vertSphRadius** (*absperc*, default: `@bboxDiag01`) — Radius of each vertex sphere. - **faceExtFlag** (*bool*, default: `True`) — Replace faces with extruded prisms. - **faceExtHeight** (*absperc*, default: `@bboxDiag0005`) — Height of each face prism. - **faceExtInset** (*absperc*, default: `@bboxDiag0005`) — Inset amount used to shrink each face prism toward its center. - **edgeFauxFlag** (*bool*, default: `True`) — Preserved for MeshLab compatibility. The current VCG shell builder consumes the unique real edge set. - **cylinderSideNum** (*int*, default: `16`) — Number of sides used for edge and vertex cylinders. ``` --- (filter-generate-tube-from-polyline)= ## Create Tube from Polyline (TrueForm) **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.trueform Sweep a circular profile along a polyline to make a solid tube. ```{py:function} ms.generate_tube_from_polyline(**params) :module: _qmeshlab Sweeps a circular profile along each path of a polyline layer, producing a solid tube.\n\nThe *Create Polyline* filters produce edge meshes, which render as hairlines and cannot be shaded, exported to a solid format, or printed. This turns one into geometry — so a measured cross-section, an intersection seam, or a set of isocontours becomes something you can look at properly or fabricate.\n\n**Radius** is the tube radius and **Sides** the number of segments around it; 8 is smooth enough for most uses, more for close-ups.\n\nEdges are chained into paths first. A vertex where three or more edges meet cannot be swept unambiguously, so the polyline is **split** there rather than branched, and the count of such junctions is reported. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — An edge-mesh layer, such as one made by the Create Polyline filters. - **radius** (*absperc*, default: `@bboxDiag001`) — Radius of the swept profile. - **segments** (*int*, default: `8`) — Number of segments around the tube. Higher is smoother and heavier. ``` --- (filter-generate-voronoi-scaffolding)= ## Create Voronoi Scaffolding **Categories:** `Creation/Primitives` **Plugin:** qmeshlab.filter.voronoi Build a scaffold mesh from a volumetric Voronoi sampling of a watertight mesh. ```{py:function} ms.generate_voronoi_scaffolding(**params) :module: _qmeshlab Build a volumetric Voronoi sampling of the current mesh, relax the internal seeds, and extract a scaffold mesh from the implicit Voronoi structure. **Parameters:** - **sampleSurfRadius** (*absperc*, default: `@bboxDiag01`) — Surface Poisson radius used as an acceleration structure for signed-distance queries. - **sampleVolNum** (*int*, default: `100000`) — Number of volumetric samples used to choose and relax Voronoi seeds. - **voxelRes** (*int*, default: `50`) — Number of voxels along the longest side of the implicit extraction grid. - **isoThr** (*double*, default: `1.0`) — Width of the generated scaffold element expressed in voxel units. - **smoothStep** (*int*, default: `3`) — Number of Laplacian smoothing iterations applied to the scaffold mesh. - **relaxStep** (*int*, default: `5`) — Number of volumetric Lloyd relaxation steps for the Voronoi seeds. - **surfFlag** (*bool*, default: `True`) — Extract the scaffold as a structure joined to the original surface envelope. - **elemType** (*enum*, default: `edge`) — Voronoi feature type to extract. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the scaffolding exactly reproducible. ``` --- (filter-create-convex-hull)= ## Create Convex Hull **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.create Create the convex hull of the current mesh or point cloud. ```{py:function} ms.create_convex_hull(**params) :module: _qmeshlab Creates a new layer holding the **convex hull** of the current layer: the boundary of the smallest convex set containing all of its vertices. Only the vertex positions are used, so this works on a point cloud just as well as on a mesh; faces, if any, are ignored. Every hull vertex is one of the input points, and interior points are discarded — which is why the result is a new layer rather than a modification of the current one. At least 4 vertices are required, and they must not all be coincident, collinear, or coplanar. Implemented with VCGLib's Quickhull. Reference: C. Bradford Barber, David P. Dobkin, Hannu Huhdanpaa, **The Quickhull Algorithm for Convex Hulls**, ACM Transactions on Mathematical Software 22(4), 1996. This filter has no parameters. ``` --- (filter-generate-advancing-front-reconstruction)= ## Reconstruct Surface by Advancing Front **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.cgal Reconstruct a surface from an unoriented point cloud by growing a triangulation outward. ```{py:function} ms.generate_advancing_front_reconstruction(**params) :module: _qmeshlab Grows a triangulation outward from a seed facet, repeatedly choosing the most plausible candidate triangle on the advancing boundary. It is an **interpolating** reconstruction: every output vertex is one of the input points, and no normals are required. **Radius Ratio Bound** rejects candidate triangles whose circumradius is more than this multiple of the shortest edge, which is what stops the front from bridging across gaps. Raise it on sparse or uneven sampling; lower it to keep holes open rather than filling them with sliver triangles. **Beta** is half the angle of the wedge in which only the triangle radius decides plausibility. This is CGAL's counterpart to *Reconstruct Surface by Ball Pivoting*: both grow a surface outward and interpolate the input points, but they are different algorithms and are worth comparing on the same cloud. CGAL has no ball-pivoting implementation of its own. Implemented with CGAL's Advancing Front Surface Reconstruction. Reference: David Cohen-Steiner, Frank Da, **A greedy Delaunay-based surface reconstruction algorithm**, The Visual Computer 20(1), 2004. **Parameters:** - **radiusRatioBound** (*double*, default: `5.0`) — Reject a candidate triangle whose circumradius exceeds this multiple of its shortest edge. Larger values close more holes; smaller values leave sparse regions open. - **beta** (*double*, default: `30.0`) — Half the angle of the wedge in which only the triangle radius counts towards plausibility. CGAL's default is 0.52 rad, about 30 degrees. ``` --- (filter-generate-alpha-shape)= ## Reconstruct Surface by Alpha Shape **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.cgal Build the alpha complex or alpha shape of the current mesh or point cloud. ```{py:function} ms.generate_alpha_shape(**params) :module: _qmeshlab Builds the **alpha shape** of the current layer's vertices: the subcomplex of their Delaunay triangulation kept by a ball of radius `Alpha` that can reach it without enclosing any point. Small `Alpha` values give a sparse, pitted result; as `Alpha` grows the shape fills in and converges to the convex hull. Only vertex positions are used, so a raw point cloud with no faces and no normals works — it is an *interpolating* reconstruction, meaning every output vertex is one of the input points. **Output** selects what is written: - *Alpha Shape* — the boundary of the alpha complex (CGAL `REGULAR` facets). This is the surface. - *Alpha Complex* — also keeps the `SINGULAR` facets, the lower-dimensional sheets that the boundary drops. Useful for seeing what the complex contains, not for a clean surface. Each face carries its **circumradius in face scalar**, so the scalar histogram shows the alpha distribution and helps pick a better value. Facet orientation comes from the Delaunay triangulation and is not made globally coherent; run *Orient Faces Consistently* if you need it. Implemented with CGAL's 3D Alpha Shapes. Reference: Herbert Edelsbrunner, Ernst P. Mucke, **Three-Dimensional Alpha Shapes**, ACM Transactions on Graphics 13(1), 1994. **Parameters:** - **alpha** (*absperc*, default: `@bboxDiag002`) — Radius of the probing ball, as a percentage of the bounding box diagonal. Small values carve the shape away; large values converge to the convex hull. - **output** (*enum*, default: `shape`) — Alpha Shape writes the boundary surface. Alpha Complex additionally writes the singular facets held by the complex. ``` --- (filter-generate-alpha-wrap)= ## Reconstruct Surface by Alpha Wrapping **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.cgal Generate a watertight alpha wrapping of the current mesh or point cloud using CGAL. ```{py:function} ms.generate_alpha_wrap(**params) :module: _qmeshlab Compute an alpha wrapping with an offset around the current mesh and add the result as a new mesh layer. Alpha wrapping is useful for producing robust watertight approximations of defective, self-intersecting, open, or highly detailed input geometry. Smaller `Alpha` values follow the input more tightly but increase output complexity and computation time. `Offset` controls the clearance added around the input surface and must be strictly positive. Faces are optional, but they are **used**, not merely a container for the vertices: - A layer **with faces** is wrapped as a *triangle soup*. Triangle interiors are part of the input, so a large flat face is solid to the rolling ball, and CGAL subdivides oversized faces so that the spatial structure resolves at the `Alpha` scale. - A layer with **only vertices** is wrapped as a *point set*, which makes this a point-cloud reconstruction method. Unlike Poisson-family reconstruction it needs no vertex normals, because the positive offset is what defines the envelope. The two paths therefore give **different results on the same geometry**. Where a triangle spans a wide gap, the point-set path sees only its three corners and the ball can roll into the space between them, denting or holing the wrap. Wrap a point cloud only when the sampling is dense relative to `Alpha` and `Offset`; if the layer has faces, keep them. The result is an *approximating* reconstruction: the offset is strictly positive, so the output surface never passes through the input points. The filter uses CGAL's 3D Alpha Wrapping implementation. Reference: Cédric Portaneri, Mael Rouxel-Labbé, Michael Hemmer, David Cohen-Steiner, Pierre Alliez, **Alpha Wrapping with an Offset**, 2022. Original MeshLab plugin contribution: Lex van der Sluijs, PTC. **Parameters:** - **Alpha** (*absperc*, default: `@bboxDiag002`) — Radius of the rolling ball used by CGAL alpha wrapping. Smaller values produce a tighter and more detailed wrap, but increase computation time and output mesh size. MeshLab default: 2% of the bounding-box diagonal. - **Offset** (*absperc*, default: `@bboxDiag001`) — Positive offset added around the input surface. Larger values make a looser, more conservative envelope; very small values can make the computation heavier. MeshLab default: 0.1% of the bounding-box diagonal. ``` --- (filter-generate-kinetic-reconstruction)= ## Reconstruct Surface by Kinetic Partition **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.cgal Reconstruct a piecewise-planar surface from oriented points by kinetic space partition and min-cut. ```{py:function} ms.generate_kinetic_reconstruction(**params) :module: _qmeshlab A piecewise-planar reconstruction pipeline, run end to end by this one filter: 1. **Shape detection** finds planar regions in the point cloud. 2. **Regularization** aligns those planes where they are nearly parallel, coplanar or orthogonal. 3. **Kinetic space partition** propagates the planes until they collide, cutting the bounding box into convex volumes. 4. **Min-cut** labels each volume inside or outside; the surface is the boundary between the two labels. Because the output is built from detected planes rather than fitted to the samples, it is planar **by construction** — which suits buildings, rooms and other man-made shapes far better than a smooth reconstruction, and is quite unsuitable for organic ones. **Requires oriented normals.** Run *Compute Point Cloud Normals* and then *Orient Point Cloud Normals* first if the layer has none. **Maximum Distance** is the most important setting: it is how far a point may sit from a plane and still belong to it, so it must be set to the scale of the noise in the data. **Lambda** trades faithfulness against simplicity — higher values give fewer, larger facets. The reconstruction emits convex polygons, which this filter fan-triangulates because QMeshLab stores triangle meshes. Implemented with CGAL's Kinetic Surface Reconstruction. Reference: Sven Oesau, Florent Lafarge, **Kinetic Shape Reconstruction**, ACM Transactions on Graphics 39(5), 2020. **Parameters:** - **maximumDistance** (*absperc*, default: `@bboxDiag01`) — How far a point may lie from a plane and still be assigned to it. Set this to the noise scale of the data; it is the setting that most affects the result. - **maximumAngle** (*double*, default: `15.0`) — Largest angle between a point's normal and its plane's normal for the point to be assigned to that plane. - **lambda** (*double*, default: `0.5`) — Trades data faithfulness against model complexity, in [0, 1). Higher values give a simpler surface with fewer facets. - **minimumRegionSize** (*int*, default: `50`) — Smallest number of points a detected planar region must contain to be kept. - **kNeighbors** (*int*, default: `12`) — Number of nearest neighbours used when growing planar regions. - **intersections** (*int*, default: `1`) — How many times propagating planes may intersect before the partition stops. Higher values give a finer partition and cost considerably more. ``` --- (filter-generate-marching-cubes-apss)= ## Reconstruct Surface by Marching Cubes (APSS) **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.mls Extract an APSS iso-surface as a new mesh with marching cubes. ```{py:function} ms.generate_marching_cubes_apss(**params) :module: _qmeshlab Extracts the iso-surface of an MLS surface as a mesh, using marching cubes. The coarse extraction is followed by an accurate projection onto the MLS surface and a zero-removal pass.\n\nThis is the **algebraic point set surfaces** (APSS) variant: the local approximation fitted at each point is an algebraic sphere rather than a plane, which keeps curved regions from flattening out. It needs points carrying oriented normals. **References:** - Gaël Guennebaud, Markus Gross. **Algebraic point set surfaces**. *ACM Transactions on Graphics (SIGGRAPH 2007)* (2007). [DOI](https://doi.org/10.1145/1276377.1276406) - Gaël Guennebaud, Marcel Germann, Markus Gross. **Dynamic Sampling and Rendering of Algebraic Point Set Surfaces**. *Computer Graphics Forum (Eurographics 2008)* (2008). [DOI](https://doi.org/10.1111/j.1467-8659.2008.01163.x) **Parameters:** - **FilterScale** (*double*, default: `2.0`) — Scale of the spatial low pass filter. It is relative to the radius (local point spacing) of the vertices. - **SphericalParameter** (*double*, default: `1.0`) — Control the curvature of the fitted spheres: 0 is equivalent to a pure plane fit, 1 to a pure spherical fit, values between 0 and 1 give intermediate results, while other real values might give interesting results, but take care with extreme settings. - **AccurateNormal** (*bool*, default: `True`) — If checked, use the accurate MLS gradient instead of the local approximation to compute the normals. - **Resolution** (*int*, default: `200`) — The resolution of the grid on which we run the marching cubes. This marching cubes is memory friendly, so you can safely set large values up to 1000 or even more. - **ProjectionAccuracy** (*double*, default: `0.0001`) — Threshold value used to stop the projections. This value is scaled by the mean point spacing to get the actual threshold. - **MaxProjectionIters** (*int*, default: `15`) — Max number of iterations for the projection. ``` --- (filter-generate-marching-cubes-rimls)= ## Reconstruct Surface by Marching Cubes (RIMLS) **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.mls Extract a Robust Implicit MLS iso-surface as a new mesh with marching cubes. ```{py:function} ms.generate_marching_cubes_rimls(**params) :module: _qmeshlab Extracts the iso-surface of an MLS surface as a mesh, using marching cubes. The coarse extraction is followed by an accurate projection onto the MLS surface and a zero-removal pass.\n\nThis is the **robust implicit MLS** (RIMLS) variant: it extends implicit MLS with non-linear kernel regression, so sharp edges survive instead of being rounded away with the noise. It needs points carrying oriented normals. **References:** - A. Cengiz Öztireli, Gaël Guennebaud, Markus Gross. **Feature Preserving Point Set Surfaces based on Non-Linear Kernel Regression**. *Computer Graphics Forum (Eurographics 2009)* (2009). [DOI](https://doi.org/10.1111/j.1467-8659.2009.01388.x) **Parameters:** - **FilterScale** (*double*, default: `2.0`) — Scale of the spatial low pass filter. It is relative to the radius (local point spacing) of the vertices. - **SigmaN** (*double*, default: `0.75`) — Width of the filter used by the normal refitting weight. This weight function is a Gaussian on the distance between two unit vectors: the current gradient and the input normal. Typical values range between 0.5 (sharp) and 2 (smooth). - **MaxRefittingIters** (*int*, default: `3`) — Max number of fitting iterations. (0 or 1 is equivalent to the standard IMLS). - **Resolution** (*int*, default: `200`) — The resolution of the grid on which we run the marching cubes. This marching cubes is memory friendly, so you can safely set large values up to 1000 or even more. - **ProjectionAccuracy** (*double*, default: `0.0001`) — Threshold value used to stop the projections. This value is scaled by the mean point spacing to get the actual threshold. - **MaxProjectionIters** (*int*, default: `15`) — Max number of iterations for the projection. ``` --- (filter-generate-poisson-reconstruction-cgal)= ## Reconstruct Surface by Poisson (CGAL) **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.cgal Reconstruct a watertight surface from oriented points with CGAL's Poisson solver. ```{py:function} ms.generate_poisson_reconstruction_cgal(**params) :module: _qmeshlab Solves the Poisson equation for an implicit function whose gradient best matches the input normal field, then extracts its zero level set. It differs from *Reconstruct Surface by Screened Poisson* in how that level set is **meshed**: CGAL uses Delaunay refinement rather than marching cubes, so the output is manifold with well-shaped triangles and a size driven by the sampling, at the cost of being slower. The two are worth comparing on the same cloud — that is why both are here. **Requires oriented normals.** If the layer has none, run *Compute Point Cloud Normals* and then *Orient Point Cloud Normals* first. Triangle size and quality are controlled relative to the estimated average point spacing: - **Minimum Angle** — the lower bound on triangle angles, in degrees. - **Maximum Radius** — largest triangle circumradius, as a multiple of the spacing. - **Approximation Error** — how far the mesh may deviate from the level set, as a multiple of the spacing. Implemented with CGAL's Poisson Surface Reconstruction. Reference: Michael Kazhdan, Matthew Bolitho, Hugues Hoppe, **Poisson Surface Reconstruction**, Symposium on Geometry Processing 2006. **Parameters:** - **smAngle** (*double*, default: `20.0`) — Lower bound on the angles of the output triangles. Lower values are easier to satisfy; CGAL's default is 20. - **smRadius** (*double*, default: `30.0`) — Largest triangle circumradius, as a multiple of the estimated average point spacing. Smaller values give a denser mesh. - **smDistance** (*double*, default: `0.375`) — How far the mesh may deviate from the implicit surface, as a multiple of the average point spacing. Smaller values follow the data more closely and cost more. - **spacingNeighbors** (*int*, default: `6`) — Number of neighbours used to estimate the average point spacing that the three settings above are relative to. ``` --- (filter-generate-scale-space-reconstruction)= ## Reconstruct Surface by Scale Space **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.cgal Reconstruct a surface by smoothing the point set to a coarser scale, then meshing it. ```{py:function} ms.generate_scale_space_reconstruction(**params) :module: _qmeshlab Smooths the current layer's points for a number of iterations — moving them to a coarser *scale* at which a surface is easier to extract — and then triangulates the smoothed points. Only vertex positions are used, so a raw point cloud with no faces and no normals works. **Iterations** controls how far the point set is smoothed: more iterations tolerate more noise but lose detail. **Neighbors** and **Samples** configure the weighted-PCA smoother. **Mesher** selects how the smoothed points are triangulated: - *Alpha Shape* — uses **Alpha** as the probing radius, and can be asked to separate shells or to force a manifold result. - *Advancing Front* — grows a triangulation outward and needs no radius. Unlike the other interpolating reconstructions here, the output vertices are the **smoothed** positions, not the original points: this filter moves the geometry before meshing it. Keep the input layer if you need the originals. Implemented with CGAL's 3D Scale-Space Surface Reconstruction. Reference: Thijs van Lankveld, Marc van Kreveld, Remco Veltkamp, **Watertight Scenes from Urban LiDAR and Planar Surfaces**, Computer Graphics Forum 32(5), 2013. **Parameters:** - **iterations** (*int*, default: `4`) — How many times the point set is smoothed before meshing. Zero meshes the points as they are; more iterations tolerate more noise but lose detail. - **mesher** (*enum*, default: `alpha_shape`) — How the smoothed points are triangulated. Alpha Shape uses the Alpha radius below; Advancing Front needs no radius. - **alpha** (*absperc*, default: `@bboxDiag002`) — Probing ball radius for the Alpha Shape mesher, as a percentage of the bounding box diagonal. Ignored by the Advancing Front mesher. - **neighbors** (*int*, default: `12`) — Number of nearest neighbours used by the weighted-PCA smoother at each point. - **samples** (*int*, default: `300`) — Number of points sampled to estimate the smoothing neighbourhood radius. - **forceManifold** (*bool*, default: `True`) — Ask the Alpha Shape mesher for a manifold result, dropping the facets that would violate it. - **separateShells** (*bool*, default: `False`) — Keep separate shells of the Alpha Shape mesher's output apart instead of merging them. ``` --- (filter-generate-screened-poisson)= ## Reconstruct Surface by Screened Poisson **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.screened_poisson Creates a watertight surface from an oriented point set. ```{py:function} ms.generate_screened_poisson(**params) :module: _qmeshlab Reconstructs a watertight surface from an oriented point set using the screened Poisson formulation. The implementation uses the original PoissonRecon code by Michael Kazhdan and Matthew Bolitho. **References:** - Michael Kazhdan, Hugues Hoppe. **Screened Poisson Surface Reconstruction**. *ACM Transactions on Graphics* (2013). [DOI](https://doi.org/10.1145/2487228.2487237) [Web](https://hhoppe.com/screenedpoisson.pdf) **Parameters:** - **visibleLayer** (*bool*, default: `False`) — Enabling this flag means that all the visible layers will be used for providing the points. - **preserveColor** (*bool*, default: `True`) — If enabled and input meshes have vertex colors, colors are propagated to the reconstructed surface. - **depth** (*int*, default: `8`) — This integer is the maximum depth of the tree that will be used for surface reconstruction. Running at depth d corresponds to solving on a voxel grid whose resolution is no larger than 2^d x 2^d x 2^d. The default value for this parameter is 8. - **fullDepth** (*int*, default: `5`) — This integer specifies the depth beyond which the octree will be adapted. At coarser depths, the octree will be complete, containing all 2^d x 2^d x 2^d nodes. The default value for this parameter is 5. - **cgDepth** (*int*, default: `0`) — This integer is the depth up to which a conjugate-gradients solver will be used to solve the linear system. Beyond this depth, Gauss-Seidel relaxation will be used. The default value for this parameter is 0. - **scale** (*double*, default: `1.1`) — This floating point value specifies the ratio between the diameter of the cube used for reconstruction and the diameter of the samples' bounding cube. The default value is 1.1. - **samplesPerNode** (*double*, default: `1.5`) — This floating point value specifies the minimum number of sample points that should fall within an octree node as the octree construction is adapted to sampling density. For noise-free samples, small values in the range [1.0 - 5.0] can be used. For noisy samples, larger values in the range [15.0 - 20.0] may be needed to provide a smoother, noise-reduced reconstruction. The default value is 1.5. - **pointWeight** (*double*, default: `4.0`) — This floating point value specifies the importance that interpolation of the point samples is given in the formulation of the screened Poisson equation. The results of the original unscreened Poisson reconstruction can be obtained by setting this value to 0. The default value for this parameter is 4. - **iters** (*int*, default: `8`) — This integer value specifies the number of Gauss-Seidel relaxations to be performed at each level of the hierarchy. The default value for this parameter is 8. - **confidence** (*bool*, default: `False`) — Enabling this flag tells the reconstructor to use the quality as confidence information. This is done by scaling the unit normals with the quality values. When the flag is not enabled, all normals are normalized to have unit length prior to reconstruction. - **preClean** (*bool*, default: `False`) — Enabling this flag forces a cleaning pre-pass on the data, removing all unreferenced vertices or vertices with null normals. - **threads** (*int*, default: `@hardwareThreads`) — Maximum number of threads that the reconstruction algorithm can use. ``` --- (filter-generate-ssd-reconstruction)= ## Reconstruct Surface by Smooth Signed Distance **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.screened_poisson Creates a watertight surface using smooth signed distance reconstruction. ```{py:function} ms.generate_ssd_reconstruction(**params) :module: _qmeshlab This filter reconstructs a surface from an oriented point set using the SSD reconstruction formulation provided by the `PoissonRecon` code base. Compared to Screened Poisson, the SSD formulation exposes separate weights for zero-crossing, gradient, and bi-Laplacian terms, making it useful when you want more direct control over smoothness and interpolation. **Parameters:** - **visibleLayer** (*bool*, default: `False`) — Enabling this flag means that all the visible layers will be used for providing the points. - **preserveColor** (*bool*, default: `True`) — If enabled and input meshes have vertex colors, colors are propagated to the reconstructed surface. - **depth** (*int*, default: `8`) — This integer is the maximum depth of the tree that will be used for surface reconstruction. Running at depth d corresponds to solving on a voxel grid whose resolution is no larger than 2^d x 2^d x 2^d. The default value for this parameter is 8. - **fullDepth** (*int*, default: `5`) — The depth at which the sample values (color, normal) are directly interpolated into the octree rather than pulled up from coarser depths. Set to a larger value if you want more detailed correct interpolation, at the price of a higher per-sample memory consumption. - **baseDepth** (*int*, default: `0`) — This integer specifies the depth of the coarsest multigrid solve level. Larger values make the coarse solve finer and more expensive. - **scale** (*double*, default: `1.1`) — This floating point value specifies the ratio between the diameter of the cube used for reconstruction and the diameter of the samples' bounding cube. The default value is 1.1. - **samplesPerNode** (*double*, default: `1.5`) — This floating point value specifies the minimum number of sample points that should fall within a node as the tree construction is adapted to sampling density. The default value is 1.5. - **valueWeight** (*double*, default: `1.0`) — This floating point value specifies the weight associated with the zero-crossing term of the SSD energy. Larger values make the reconstruction interpolate the input points more strongly. - **gradientWeight** (*double*, default: `1.0`) — This floating point value specifies the weight associated with the gradient fitting term of the SSD energy. The value must be strictly positive. - **biLapWeight** (*double*, default: `1.0`) — This floating point value specifies the weight associated with the bi-Laplacian smoothing term of the SSD energy. Larger values produce smoother surfaces. The value must be strictly positive. - **iters** (*int*, default: `8`) — This integer value specifies the number of Gauss-Seidel relaxations to be performed at each level of the hierarchy. The default value is 8. - **exactInterpolation** (*bool*, default: `False`) — If enabled, the exact interpolation formulation is used when building the SSD system. - **nonLinearFit** (*bool*, default: `False`) — If enabled, the extracted iso-surface uses the non-linear fit. If disabled, the linear fit is used. - **nonManifold** (*bool*, default: `False`) — If enabled, the extractor does not force the output mesh to be manifold. - **cgAccuracy** (*double*, default: `0.001`) — This floating point value specifies the accuracy used by the conjugate gradients solver. Smaller values make the linear solve more accurate and more expensive. - **dataScale** (*double*, default: `32.0`) — This floating point value specifies the pull factor used by the hierarchical SSD formulation. The default value is 32. - **confidence** (*bool*, default: `False`) — Enabling this flag tells the reconstructor to use the quality as confidence information. This is done by scaling the unit normals with the quality values. When the flag is not enabled, all normals are normalized to have unit length prior to reconstruction. - **preClean** (*bool*, default: `False`) — Enabling this flag forces a cleaning pre-pass on the data, removing all unreferenced vertices or vertices with null normals. - **threads** (*int*, default: `@hardwareThreads`) — Maximum number of threads that the reconstruction algorithm can use. ``` --- (filter-generate-surface-reconstruction-ball-pivoting)= ## Reconstruct Surface by Ball Pivoting **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.clean Reconstruct a surface from oriented points using Ball Pivoting. ```{py:function} ms.generate_surface_reconstruction_ball_pivoting(**params) :module: _qmeshlab Given a point cloud with normals it reconstructs a surface using the Ball Pivoting Algorithm.Starting with a seed triangle, the BPA algorithm pivots a ball of the given radius around the already formed edges until it touches another point, forming another triangle. The process continues until all reachable edges have been tried. This surface reconstruction algorithm uses the existing points without creating new ones. Works better with uniformly sampled point clouds. If needed first perform a poisson disk subsampling of the point cloud.
Bernardini F., Mittleman J., Rushmeier H., Silva C., Taubin G.
The ball-pivoting algorithm for surface reconstruction.
IEEE TVCG 1999 **Parameters:** - **ball_radius** (*absperc*, default: `0.0`) — The radius of the ball pivoting (rolling) over the set of points. Gaps that are larger than the ball radius will not be filled; similarly small pits smaller than the ball radius will be filled. Use `0` for autoguess. - **clustering_percent** (*double*, default: `20.0`) — To avoid creation of too small triangles, if a vertex is found too close to a previous one, it is clustered/merged with it. - **crease_threshold_deg** (*double*, default: `90.0`) — If we encounter a crease angle that is too large we should stop the ball rolling. - **delete_initial_faces** (*bool*, default: `False`) — If true all the initial faces of the mesh are deleted and the whole surface is rebuilt from scratch. Otherwise current faces are used as a starting point. ``` --- (filter-generate-surface-reconstruction-vcg)= ## Reconstruct Surface by Volumetric Merging **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.plymc A volumetric surface reconstruction algorithm that creates a mesh from all visible layers. ```{py:function} ms.generate_surface_reconstruction_vcg(**params) :module: _qmeshlab Surface reconstruction algorithm using volumetric distance fields and Marching Cubes. All visible meshes/point clouds are used to build the volumetric field. Supports sub-volume splitting for very high resolution reconstructions, geodesic weighting for smooth blending of overlapping range maps, hole filling via volume dilation, and optional vertex splatting. **Parameters:** - **voxSize** (*double*, default: `0.01`) — The side length of each voxel. A percentage of the bounding box diagonal. - **subdiv** (*int*, default: `1`) — The level of recursive splitting (1 = no split, 3 = 3×3×3 subdivision producing 27 sub-meshes). - **geodesic** (*double*, default: `2.0`) — Weight each range map by geodesic distance from borders for smooth blending of overlaps. - **smoothNum** (*int*, default: `1`) — Number of volume Laplacian smoothing steps to clean out noisy borders. - **wideNum** (*int*, default: `3`) — How many voxels the field is expanded. Larger values fill more holes. - **mergeColor** (*bool*, default: `False`) — Splat vertices into the grid instead of rasterizing faces. Requires at least one sample per voxel. - **simplification** (*bool*, default: `False`) — Automatically simplify the mesh after reconstruction. - **normalSmooth** (*int*, default: `3`) — Face normal Laplacian iterations before voxelization. Helps with noisy borders. ``` --- (filter-generate-voronoi-filtering)= ## Reconstruct Surface by Voronoi Filtering **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.cgal Reconstruct a surface from an unoriented point cloud with the Amenta-Bern crust. ```{py:function} ms.generate_voronoi_filtering(**params) :module: _qmeshlab Reconstructs a surface from the current layer's vertices using **Voronoi filtering**, the crust algorithm of Amenta and Bern. It needs **no vertex normals**, which is what distinguishes it from the Poisson-family filters. How it works, in two Delaunay passes: 1. Triangulate the samples. For each sample the two *poles* are found — the Voronoi vertices of its cell farthest from it, one on each side. Poles approximate the medial axis, so they lie far from the surface. 2. Triangulate samples and poles together. A Delaunay triangle whose three corners are all samples cannot span the medial axis, so those triangles are the reconstructed surface. This is an *interpolating* reconstruction: every output vertex is one of the input points, and no new positions are invented. **Limitations**, inherent to the algorithm rather than this implementation: it assumes a **closed, well-sampled, noise-free** surface. Points lying on the convex hull have unbounded Voronoi cells and therefore no finite outer pole, so open boundaries stay ragged; noisy input scatters the poles and thins the crust. For scanned or noisy data prefer *Reconstruct Surface by Screened Poisson*. **Threshold** discards Voronoi vertices farther from their sample than that multiple of the bounding box diagonal, keeping near-degenerate cells from throwing a pole off to infinity. Built on CGAL's 3D Delaunay triangulation. Reference: Nina Amenta, Marshall Bern, **Surface Reconstruction by Voronoi Filtering**, Discrete & Computational Geometry 22(4), 1999. **Parameters:** - **threshold** (*double*, default: `10.0`) — Discard Voronoi vertices farther from their sample than this multiple of the bounding box diagonal. Guards against near-degenerate cells sending a pole to infinity. ``` --- (filter-trim-reconstructed-surface)= ## Trim Surface by Scalar Isovalue **Categories:** `Creation/Reconstruction` **Plugin:** qmeshlab.filter.screened_poisson Trims a reconstructed mesh using the scalar values stored on the vertices. ```{py:function} ms.trim_reconstructed_surface(**params) :module: _qmeshlab This filter trims a reconstructed surface by cutting the mesh along an isovalue defined over the vertices. It is especially useful after Poisson-based reconstruction when the vertex quality stores the reconstruction density, allowing low-confidence regions to be removed. **Parameters:** - **trim** (*double*, default: `0.0`) — This floating point value specifies the trimming value. Faces whose scalar field is below this threshold are trimmed away; crossing faces are split along the threshold. - **islandAreaRatio** (*double*, default: `0.001`) — This floating point value specifies the relative area threshold used to detect small disconnected islands. Smaller components may be merged or removed according to the selected options. - **removeIslands** (*bool*, default: `False`) — If enabled, disconnected components whose area is below the island area ratio are removed instead of being preserved. - **polygonMesh** (*bool*, default: `False`) — The original tool can preserve polygonal output. QMeshLab stores triangle meshes, so the result is always triangulated even when this option is enabled. ``` --- (filter-generate-sampling-volumetric)= ## Sample Volume **Categories:** `Creation/Sampling` **Plugin:** qmeshlab.filter.voronoi Generate diagnostic Monte Carlo and surface samples inside a watertight mesh. ```{py:function} ms.generate_sampling_volumetric(**params) :module: _qmeshlab Compute a volumetric Monte Carlo sampling of a watertight mesh and add diagnostic sample layers. This follows the original MeshLab filter behavior: the Poisson-filtered volume point set is not emitted yet by the upstream implementation. **Parameters:** - **sampleSurfRadius** (*absperc*, default: `@bboxDiag01`) — Surface Poisson radius used as an acceleration structure for signed-distance queries. - **sampleVolNum** (*int*, default: `200000`) — Number of volumetric Monte Carlo samples to scatter inside the mesh. - **poissonFiltering** (*bool*, default: `True`) — Preserve the original MeshLab option. The current upstream implementation does not emit the filtered volume layer. - **poissonRadius** (*absperc*, default: `@bboxDiag01`) — Radius used by the internal Poisson pruning stage. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the generated sample set exactly reproducible. ``` --- (filter-generate-sampling-voronoi)= ## Sample Surface by Voronoi Relaxation **Categories:** `Creation/Sampling` **Plugin:** qmeshlab.filter.voronoi Sample a surface and relax the samples with a geodesic Voronoi/Lloyd process. ```{py:function} ms.generate_sampling_voronoi(**params) :module: _qmeshlab Compute a point sampling over the current mesh and perform Lloyd relaxation on the surface. The selected vertices of the current mesh become the final seeds, and two additional layers are produced: a Voronoi region mesh and a polyline representation of the Voronoi boundaries. **Parameters:** - **iterNum** (*int*, default: `10`) — Number of Lloyd relaxation iterations. - **sampleNum** (*int*, default: `10`) — Target number of surface samples. - **radiusVariance** (*double*, default: `1.0`) — For quality-weighted distance, the metric varies between 1/x and x according to per-vertex quality. - **colorStrategy** (*enum*, default: `seed_distance`) — How the current mesh should be colored during Voronoi relaxation. - **distanceType** (*enum*, default: `euclidean`) — Metric used by the Voronoi relaxation. - **preprocessFlag** (*bool*, default: `False`) — Refine the current mesh before relaxation so the supporting triangulation is dense enough for the requested sample count. - **refineFactor** (*int*, default: `10`) — Controls how much the mesh is refined during preprocessing. Larger values create a denser supporting triangulation. - **perturbProbability** (*double*, default: `0.0`) — Probability that each seed is slightly perturbed during restricted relaxation. - **perturbAmount** (*double*, default: `0.001`) — Perturbation amplitude as a fraction of the bounding-box diagonal. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the seed placement and relaxation exactly reproducible. - **relaxType** (*enum*, default: `squared_distance`) — How a new seed is chosen inside each Voronoi region. ``` --- (filter-sample-clustered-vertices)= ## Sample Vertices by Clustering **Categories:** `Creation/Sampling` **Plugin:** qmeshlab.filter.sampling Cluster the point set into grid cells and keep one representative per cell. ```{py:function} ms.sample_clustered_vertices(**params) :module: _qmeshlab Create a new layer populated with a subsampling of the vertices of the current mesh; the subsampling is driven by a simple one-per-gridded cell strategy. **Parameters:** - **Threshold** (*absperc*, default: `@bboxDiag01`) — Size of the clustering grid cell. Smaller cells preserve more detail. - **Sampling** (*enum*, default: `closest_to_center`) — Choose how each cell representative is computed. - **Selected** (*bool*, default: `False`) — If enabled, use only the selected subset of the mesh as input. ``` --- (filter-sample-mesh-elements)= ## Sample Mesh Elements **Categories:** `Creation/Sampling` **Plugin:** qmeshlab.filter.sampling Create a point set by subsampling mesh vertices, edges, or faces. ```{py:function} ms.sample_mesh_elements(**params) :module: _qmeshlab Create a new layer holding one sample per mesh element. **Number of samples** elements are drawn uniformly at random -- every element of the chosen kind is equally likely -- and one point is emitted for each: a **Vertex** contributes its own position, an **Edge** its midpoint, a **Face** its barycenter. Asking for at least as many samples as there are elements simply returns them all. Edge sampling ignores *faux* edges, the diagonals that triangulate a polygonal face, since those are not edges of the polygonal mesh and the wireframe does not draw them. Note that midpoints and barycenters lie slightly inside a curved surface, which is inherent to taking a single sample per element. To place several samples along each edge instead, in proportion to its length, use *Sample Surface by Stratified Triangles* with the **Sample Edges** strategy. **Parameters:** - **Sampling** (*enum*, default: `vertex`) — Choose which mesh elements are sampled. - **SampleNum** (*int*, default: `1000`) — How many elements to draw. Reaching or exceeding the element count returns every element. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the chosen subset of elements exactly reproducible. It has no effect when the requested number reaches the element count, since then every element is taken. ``` --- (filter-sample-montecarlo)= ## Sample Surface by Monte Carlo **Categories:** `Creation/Sampling` **Plugin:** qmeshlab.filter.sampling Create a random point cloud from the current surface. ```{py:function} ms.sample_montecarlo(**params) :module: _qmeshlab Create a new layer populated with a point sampling of the current mesh; samples are generated in a randomly uniform way, or with a distribution biased by the per-vertex quality values of the mesh. **Parameters:** - **SampleNum** (*int*, default: `1000`) — Desired number of generated samples. - **Weighted** (*bool*, default: `False`) — Use per-vertex quality to bias the sampling density. - **PerFaceNormal** (*bool*, default: `False`) — Store the face normal on each sample instead of interpolated vertex normals. - **RadiusVariance** (*double*, default: `1.0`) — When quality-weighted sampling is used, the sampling radius may vary between r/var and r*var. - **ExactNum** (*bool*, default: `True`) — If enabled, try to generate exactly the requested number of samples. - **EdgeSampling** (*bool*, default: `False`) — Restrict sampling to mesh edges. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the sample positions exactly reproducible. ``` --- (filter-sample-poisson-disk)= ## Sample Surface by Poisson Disk **Categories:** `Creation/Sampling` **Plugin:** qmeshlab.filter.sampling Generate well-spaced samples over a surface or point cloud. ```{py:function} ms.sample_poisson_disk(**params) :module: _qmeshlab Create a new layer populated with a point sampling of the current mesh;samples are generated according to a Poisson-disk distribution, using the algorithm described in:
'Efficient and Flexible Sampling with Blue Noise Properties of Triangular Meshes'
Massimiliano Corsini, Paolo Cignoni, Roberto Scopigno
IEEE TVCG 2012 **Parameters:** - **SampleNum** (*int*, default: `1000`) — Desired number of samples. Ignored if an explicit radius is provided. - **Radius** (*absperc*, default: `0.0`) — If non-zero, overrides the sample number and uses this radius directly. - **MontecarloRate** (*int*, default: `20`) — Oversampling factor used to generate the initial Montecarlo candidates. - **SaveMontecarlo** (*bool*, default: `False`) — Also create a layer containing the raw Montecarlo candidates. - **ApproximateGeodesicDistance** (*bool*, default: `False`) — Use a normal-aware approximate geodesic distance during Poisson pruning. - **Subsample** (*bool*, default: `False`) — Use the original vertices as the candidate set instead of generating Montecarlo samples. - **RefineFlag** (*bool*, default: `False`) — Use an existing sample layer as pre-generated seeds that are refined further. - **RefineMesh** (*mesh*, default: `@currentMeshIndex`) — Layer used as the initial sample set when Refine Existing Samples is enabled. - **BestSampleFlag** (*bool*, default: `True`) — Use a heuristic to improve the maximality of the chosen sample set. - **BestSamplePool** (*int*, default: `10`) — Number of candidate attempts used when the best-sample heuristic is enabled. - **ExactNumFlag** (*bool*, default: `False`) — Search for a radius that matches the requested number of samples within the given tolerance. - **ExactNumTolerance** (*double*, default: `0.005`) — Tolerance used by precise sample count search, expressed as a fraction of the requested sample count. - **RadiusVariance** (*double*, default: `1.0`) — Allow the Poisson disk radius to vary between r and r*var using vertex quality as a density bias. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the generated sample set exactly reproducible. ``` --- (filter-sample-regular-recursive)= ## Sample Offset Surface Recursively **Categories:** `Creation/Sampling` **Plugin:** qmeshlab.filter.sampling Generate offset surface samples by recursively subdividing the bounding box. ```{py:function} ms.sample_regular_recursive(**params) :module: _qmeshlab The bounding box is recursively partitioned in a octree style, center of bbox are considered, when the center is nearer to the surface than a given threshold it is projected on it. It works also for building offsetted samples. **Parameters:** - **CellSize** (*absperc*, default: `@bboxDiag01`) — Subdivision threshold. Smaller values generate denser samples. - **Offset** (*absperc*, default: `0.0`) — Offset distance applied to the projected samples. ``` --- (filter-sample-stratified-triangles)= ## Sample Surface by Stratified Triangles **Categories:** `Creation/Sampling` **Plugin:** qmeshlab.filter.sampling Generate structured samples over the triangle mesh. ```{py:function} ms.sample_stratified_triangles(**params) :module: _qmeshlab Create a new layer populated with a point sampling of the current mesh; to generate multiple samples inside a triangle each triangle is subdivided according to various stratified strategies. Distribution is often biased by triangle shape. **Parameters:** - **SampleNum** (*int*, default: `5000`) — Desired number of generated samples. - **Sampling** (*enum*, default: `similar_triangle`) — Choose the structured sampling strategy. - **Random** (*bool*, default: `False`) — For each virtual cell, choose a random sample instead of the midpoint. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the sample positions inside each face exactly reproducible. ``` --- (filter-sample-texels)= ## Sample Texels **Categories:** `Creation/Sampling` **Plugin:** qmeshlab.filter.sampling Create one point sample per covered texel in texture space. ```{py:function} ms.sample_texels(**params) :module: _qmeshlab Create a new layer with a point sampling of the current mesh, a sample for each texel of the mesh is generated **Parameters:** - **TextureW** (*int*, default: `512`) — Sampling resolution in texels. If 0 and Recover Color is enabled, use the current texture width. - **TextureH** (*int*, default: `512`) — Sampling resolution in texels. If 0 and Recover Color is enabled, use the current texture height. - **TextureSpace** (*bool*, default: `False`) — Place output points in UV space instead of the original mesh space. - **RecoverColor** (*bool*, default: `True`) — Sample the current texture image and store its colors on the generated points. - **sourceTexture** (*textureref*, default: `0`) — When Recover Color is enabled, choose which associated texture to sample. Automatic uses each face's per-wedge texture slot assignment. ``` --- (filter-apply-cameras-extrinsics-transformation)= ## Transform Camera Extrinsics **Categories:** `Document/Camera` **Plugin:** qmeshlab.filter.camera Apply a similarity transformation to the camera extrinsics. ```{py:function} ms.apply_cameras_extrinsics_transformation(**params) :module: _qmeshlab Apply a similarity transformation to the camera extrinsics, or all the cameras of the project. **Parameters:** - **camera** (*enum*, default: `raster`) — Choose the camera to transform. - **behaviour** (*enum*, default: `apply`) — How the transformation matrix is interpreted. - **rotationDeg** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Rotation angles around X, Y, Z axes in degrees. - **translation** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Translation vector. - **uniformScale** (*double*, default: `1.0`) — Uniform scale factor. - **toallRaster** (*bool*, default: `False`) — Apply the same transformation to all active raster layers. - **toall** (*bool*, default: `False`) — Apply the same transformation to all visible raster and mesh layers. ``` --- (filter-apply-cameras-rotation)= ## Rotate Cameras **Categories:** `Document/Camera` **Plugin:** qmeshlab.filter.camera Rotate the camera, or all the cameras of the project. ```{py:function} ms.apply_cameras_rotation(**params) :module: _qmeshlab Rotate the camera, or all the cameras of the project. The selected raster is the reference if viewpoint rotation is selected. **Parameters:** - **camera** (*enum*, default: `raster`) — Choose the camera to rotate. - **rotAxis** (*enum*, default: `x`) — Axis of rotation. - **rotCenter** (*enum*, default: `origin`) — Center of rotation. - **angle** (*double*, default: `0.0`) — Angle of rotation in degrees. - **customAxis** (*point3f*, default: `[1.0, 0.0, 0.0]`) — Rotation axis used only if 'custom axis' option is chosen. - **customCenter** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Rotation center used only if 'custom point' option is chosen. - **toallRaster** (*bool*, default: `False`) — Apply the same rotation to all active raster layers. Used only if 'Raster Camera' is selected. - **toall** (*bool*, default: `False`) — Apply the same rotation to all visible raster and mesh layers. ``` --- (filter-apply-cameras-scaling)= ## Scale Cameras **Categories:** `Document/Camera` **Plugin:** qmeshlab.filter.camera Scale the camera, or all the cameras of the project. ```{py:function} ms.apply_cameras_scaling(**params) :module: _qmeshlab **Parameters:** - **camera** (*enum*, default: `raster`) — Choose the camera to scale. - **scaleCenter** (*enum*, default: `origin`) — Center of scaling. - **customCenter** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Scaling center used only if 'custom point' option is chosen. - **scale** (*double*, default: `1.0`) — The scale factor to apply to the camera. - **toallRaster** (*bool*, default: `False`) — Apply the same scaling to all active raster layers. - **toall** (*bool*, default: `False`) — Apply the same scaling to all visible raster and mesh layers. ``` --- (filter-apply-cameras-translation)= ## Translate Cameras **Categories:** `Document/Camera` **Plugin:** qmeshlab.filter.camera Translate the camera, or all the cameras of the project. ```{py:function} ms.apply_cameras_translation(**params) :module: _qmeshlab **Parameters:** - **camera** (*enum*, default: `raster`) — Choose the camera to translate. - **tx** (*double*, default: `0.0`) — Absolute translation amount along the X axis. - **ty** (*double*, default: `0.0`) — Absolute translation amount along the Y axis. - **tz** (*double*, default: `0.0`) — Absolute translation amount along the Z axis. - **centerFlag** (*bool*, default: `False`) — If selected, the camera viewpoint is translated to the origin. - **toallRaster** (*bool*, default: `False`) — Apply the same translation to all active raster layers. - **toall** (*bool*, default: `False`) — Apply the same translation to all visible raster and mesh layers. ``` --- (filter-load-active-raster-cameras)= ## Import Cameras to Visible Rasters **Categories:** `Document/Camera` **Plugin:** qmeshlab.filter.layer Import cameras from a file into the visible raster layers. ```{py:function} ms.load_active_raster_cameras(**params) :module: _qmeshlab Imports MeshLab-compatible VCGCamera XML entries and assigns them, in file order, to visible raster layers. **Parameters:** - **camera_file** (*file_open*, default: ``) — XML file containing VCGCamera entries for the active raster layers. ``` --- (filter-save-active-raster-cameras)= ## Export Cameras from Visible Rasters **Categories:** `Document/Camera` **Plugin:** qmeshlab.filter.layer Export the cameras of the visible raster layers to a file. ```{py:function} ms.save_active_raster_cameras(**params) :module: _qmeshlab Exports the cameras of all visible raster layers as MeshLab-compatible VCGCamera XML entries. **Parameters:** - **camera_file** (*file_save*, default: ``) — Destination XML file for the active raster cameras. ``` --- (filter-set-camera-from-direction)= ## Set Camera from Direction **Categories:** `Document/Camera` **Plugin:** qmeshlab.filter.camera Position the camera looking toward a target from an explicit direction. ```{py:function} ms.set_camera_from_direction(**params) :module: _qmeshlab Compute a camera that looks toward a target (mesh bounding box center or current raster) from an explicit world-space direction. The camera is positioned so that the target fills the viewport. The resulting camera state JSON is written to the log and applied to the current raster if one is active. **Parameters:** - **direction** (*point3f*, default: `[0.0, 0.0, -1.0]`) — World-space direction from camera to target. - **target** (*enum*, default: `mesh_bbox`) — What the camera should look at. - **marginFactor** (*double*, default: `1.0`) — Viewport margin multiplier. 1.0 = tight fit, 2.0 = zoom out. - **fovYDeg** (*double*, default: `45.0`) — Vertical field of view in degrees. ``` --- (filter-set-camera-per-mesh)= ## Set Mesh Camera **Categories:** `Document/Camera` **Plugin:** qmeshlab.filter.camera Set the camera parameters for the current mesh. ```{py:function} ms.set_camera_per_mesh(**params) :module: _qmeshlab Set camera parameters for the current mesh. The camera is stored and used by other filters such as 'Vertex Quality from Camera'. **Parameters:** - **viewpoint** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Camera position in world space. - **direction** (*point3f*, default: `[0.0, 0.0, -1.0]`) — Camera viewing direction. - **focalMm** (*double*, default: `50.0`) — Camera focal length in millimeters. - **cameraType** (*enum*, default: `perspective`) — Type of camera projection. ``` --- (filter-set-camera-per-raster)= ## Set Raster Camera **Categories:** `Document/Camera` **Plugin:** qmeshlab.filter.camera Set the camera parameters for the current raster. ```{py:function} ms.set_camera_per_raster(**params) :module: _qmeshlab Set camera parameters for the current raster. The viewport is automatically recalculated from the raster image dimensions. **Parameters:** - **viewpoint** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Camera position in world space. - **direction** (*point3f*, default: `[0.0, 0.0, -1.0]`) — Camera viewing direction. - **focalMm** (*double*, default: `50.0`) — Camera focal length in millimeters. - **sensorWidthMm** (*double*, default: `36.0`) — Camera sensor width in millimeters. ``` --- (filter-set-camera-to-view-selection)= ## Set Camera to View Selection **Categories:** `Document/Camera` **Plugin:** qmeshlab.filter.camera Position the camera to frame the current selection, looking along the average selected normal direction. ```{py:function} ms.set_camera_to_view_selection(**params) :module: _qmeshlab Compute a camera that frames the current selection in the viewport. The camera is positioned so that the selected faces/vertices fill the viewport, looking along the average face/vertex normal direction of the selection. The resulting camera state JSON is written to the log and applied to the current raster if one is active. **Parameters:** - **marginFactor** (*double*, default: `1.0`) — Viewport margin multiplier. 1.0 = tight fit, 1.5 = some padding. - **fovYDeg** (*double*, default: `45.0`) — Vertical field of view in degrees. - **useFaceNormals** (*bool*, default: `True`) — Average face normals to determine the view direction. If no faces are selected, falls back to vertex normals. ``` --- (filter-delete-current-mesh)= ## Remove Current Mesh Layer **Categories:** `Document/Layer` **Plugin:** qmeshlab.filter.layer Remove the current mesh layer. ```{py:function} ms.delete_current_mesh(**params) :module: _qmeshlab The current mesh layer is deleted. This filter has no parameters. ``` --- (filter-delete-current-raster)= ## Remove Current Raster **Categories:** `Document/Layer` **Plugin:** qmeshlab.filter.layer Remove the current raster layer. ```{py:function} ms.delete_current_raster(**params) :module: _qmeshlab The current raster layer is deleted. This filter has no parameters. ``` --- (filter-delete-hidden-meshes)= ## Remove Hidden Mesh Layers **Categories:** `Document/Layer` **Plugin:** qmeshlab.filter.layer Remove every mesh layer that is currently hidden. ```{py:function} ms.delete_hidden_meshes(**params) :module: _qmeshlab All the non visible mesh layers are deleted. This filter has no parameters. ``` --- (filter-delete-non-active-rasters)= ## Remove Hidden Rasters **Categories:** `Document/Layer` **Plugin:** qmeshlab.filter.layer Remove every raster layer that is currently hidden. ```{py:function} ms.delete_non_active_rasters(**params) :module: _qmeshlab All non-active raster layers are deleted. As in MeshLab, active rasters are the visible raster layers. This filter has no parameters. ``` --- (filter-duplicate-layer)= ## Duplicate Current Layer **Categories:** `Document/Layer` **Plugin:** qmeshlab.filter.layer Create a new layer containing the same model as the current one. ```{py:function} ms.duplicate_layer(**params) :module: _qmeshlab This filter has no parameters. ``` --- (filter-flatten-visible-layers)= ## Merge Visible Layers **Categories:** `Document/Layer` **Plugin:** qmeshlab.filter.layer Merge all layers, or only the visible ones, into a single new mesh. Also known as flattening. ```{py:function} ms.flatten_visible_layers(**params) :module: _qmeshlab Merge all layers, or only the visible ones, into a single new mesh. Also known as flattening.
Transformations are preserved. Existing layers can be optionally deleted. **Parameters:** - **MergeVisible** (*bool*, default: `True`) — If true, flatten only visible layers, otherwise all layers are used. - **DeleteLayer** (*bool*, default: `True`) — Delete all the layers used as source in flattening. If all layers are visible only a single layer will remain after the invocation of this filter. - **MergeVertices** (*bool*, default: `True`) — Merge the vertices that are duplicated among different layers. Very useful when the layers are spliced portions of a single big mesh. - **AlsoUnreferenced** (*bool*, default: `True`) — Do not discard unreferenced vertices from source layers. Necessary for point-cloud layers. ``` --- (filter-move-faces-to-layer)= ## Extract Selected Faces **Categories:** `Document/Layer` **Plugin:** qmeshlab.filter.layer Extract the selected faces into a new mesh layer, moving or copying them. ```{py:function} ms.move_faces_to_layer(**params) :module: _qmeshlab Selected faces are moved (or duplicated) in a new layer. Warning! per-vertex and per-face user defined attributes will not be transferred. **Parameters:** - **DeleteOriginal** (*bool*, default: `True`) — Deletes the original selected faces, thus splitting the mesh among layers. If false, the selected faces are duplicated in the new layer. ``` --- (filter-move-vertices-to-layer)= ## Extract Selected Vertices **Categories:** `Document/Layer` **Plugin:** qmeshlab.filter.layer Extract the selected vertices into a new mesh layer, moving or copying them. ```{py:function} ms.move_vertices_to_layer(**params) :module: _qmeshlab Selected vertices are moved (or duplicated) in a new layer. Warning! per-vertex user defined attributes will not be transferred. **Parameters:** - **DeleteOriginal** (*bool*, default: `True`) — Deletes the original selected vertices, thus splitting the mesh among layers. If false, the selected vertices are duplicated in the new layer. ``` --- (filter-rename-mesh)= ## Rename Current Mesh Layer **Categories:** `Document/Layer` **Plugin:** qmeshlab.filter.layer Explicitly change the label shown for the current mesh. ```{py:function} ms.rename_mesh(**params) :module: _qmeshlab Explicitly change the label shown for a given mesh. **Parameters:** - **newName** (*string*, default: ``) — New label for the mesh. ``` --- (filter-set-raster-name)= ## Rename Current Raster **Categories:** `Document/Layer` **Plugin:** qmeshlab.filter.layer Explicitly change the label shown for the current raster. ```{py:function} ms.set_raster_name(**params) :module: _qmeshlab **Parameters:** - **newName** (*string*, default: ``) — New label for the raster. ``` --- (filter-split-in-connected-components)= ## Split into Connected Components **Categories:** `Document/Layer` **Plugin:** qmeshlab.filter.layer Split the current layer into one layer per connected component. ```{py:function} ms.split_in_connected_components(**params) :module: _qmeshlab Split current layer into many layers, one for each connected component. **Parameters:** - **delete_source_mesh** (*bool*, default: `False`) — Deletes the source mesh after all the connected component meshes are generated. ``` --- (filter-render-from-render-state-json)= ## Render from Render-State JSON **Categories:** `Document/Render` **Plugin:** qmeshlab.filter.layer Run a deterministic offscreen render from a serialized render-state JSON payload. ```{py:function} ms.render_from_render_state_json(**params) :module: _qmeshlab Applies a render-state JSON payload to the active view, renders an offscreen snapshot, and optionally saves it as PNG and/or adds it as a raster layer. Useful for reproducible filter-driven rendering workflows. **Parameters:** - **camera_state** (*camerastate*, default: ``) — Camera-state JSON payload (kind = QMeshLab.CameraState). Source can be Text, File, or Current View. - **render_state** (*renderstate*, default: ``) — Render-state JSON payload (kind = QMeshLab.RenderState). Source can be Text, File, or Current View. - **output_width** (*int*, default: `0`) — Output width in pixels. Use 0 to keep the current active view width. - **output_height** (*int*, default: `0`) — Output height in pixels. Use 0 to keep the current active view height. - **save_png_path** (*file_save*, default: ``) — Optional output PNG path. If empty, no PNG file is written. - **add_as_raster** (*bool*, default: `True`) — If true, adds the rendered snapshot as a new raster layer in the document. - **raster_name** (*string*, default: `Programmatic Render`) — Name used when adding the snapshot as a raster layer. ``` --- (filter-compute-matrix-by-corresponding-points)= ## Align to Corresponding Points (TrueForm) **Categories:** `Geometry/Alignment` **Plugin:** qmeshlab.filter.trueform Align two layers whose vertices already correspond one to one, optionally solving for scale. ```{py:function} ms.compute_matrix_by_corresponding_points(**params) :module: _qmeshlab Computes the transformation that best maps the source layer's vertices onto the reference's, assuming the two are already in **one-to-one correspondence**: same number of live vertices, in matching order. This is the Procrustes (Kabsch) fit. Use it when the correspondence is known by construction — two states of the same mesh, a mesh and its deformed copy, or point sets you have paired yourself. When the correspondence is unknown, use *Align by ICP* instead, which searches for it. **Allow Uniform Scale** is the reason to reach for this filter over ICP: with correspondences given, scale can be solved for as well as rotation and translation, which no ICP variant here does. Leave it off for a rigid fit. The result is written to the source layer's **matrix**; vertex coordinates are not touched. Implemented with TrueForm's `fit_rigid_alignment` and `fit_similarity_alignment`. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The layer that is moved. - **referenceMesh** (*mesh*, default: `@otherMeshIndex`) — The layer that stays put. - **allowScale** (*bool*, default: `False`) — Also solve for a single scale factor. Only possible because the correspondences are given rather than searched for. ``` --- (filter-compute-matrix-by-icp-between-meshes)= ## Align by ICP (vcglib) **Categories:** `Geometry/Alignment` **Plugin:** qmeshlab.filter.icp Compute an ICP transform that aligns one mesh layer to another. ```{py:function} ms.compute_matrix_by_icp_between_meshes(**params) :module: _qmeshlab Perform Iterative Closest Point alignment between a fixed reference layer and a moving source layer. The source layer transform is updated; vertex coordinates are not baked. Existing layer transforms are used as the initial pose, so the alignment follows what is visible in the 3D view. **References:** - Paul J. Besl, Neil D. McKay. **A Method for Registration of 3-D Shapes**. *IEEE Transactions on Pattern Analysis and Machine Intelligence* (1992). [DOI](https://doi.org/10.1109/34.121791) **Parameters:** - **ReferenceMesh** (*mesh*, default: `@currentMeshIndex`) — The mesh kept fixed during ICP. - **SourceMesh** (*mesh*, default: `@otherMeshIndex`) — The mesh whose transform will be updated to match the reference. - **SampleNum** (*int*, default: `2000`) — Number of source samples used at each ICP iteration. - **MinDistAbs** (*double*, default: `10.0`) — Initial maximum correspondence distance. Only source samples nearer than this value are used. - **TrgDistAbs** (*double*, default: `0.005`) — ICP stops when the median sample distance goes below this value. - **MaxIterNum** (*int*, default: `75`) — Maximum number of ICP iterations. - **SampleMode** (*bool*, default: `True`) — Distribute samples uniformly with respect to normal directions instead of spatial random sampling. - **ReduceFactorPerc** (*double*, default: `0.8`) — Percentile used to reduce the maximum correspondence distance at each iteration. - **PassHiFilter** (*double*, default: `0.75`) — Discard samples farther than this percentile of the current correspondence distances. - **MatchMode** (*bool*, default: `True`) — If enabled, ICP solves only rotations and translations. If disabled, similarity matching may include scale. - **UseVertexOnly** (*bool*, default: `False`) — Use closest vertices instead of closest points on faces. This is automatically used for point clouds. - **MaxAngleDeg** (*double*, default: `45.0`) — Maximum angle, in degrees, between source and reference normals for accepted correspondences. - **MinPointNum** (*int*, default: `30`) — Minimum number of accepted point pairs required for an ICP iteration to be valid. - **SaveLastIteration** (*bool*, default: `False`) — Create two diagnostic point layers containing the last accepted source samples and their reference correspondences. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the sub-sampling of the moving mesh exactly reproducible. ``` --- (filter-compute-matrix-by-icp-trueform)= ## Align by ICP (TrueForm) **Categories:** `Geometry/Alignment` **Plugin:** qmeshlab.filter.trueform Align one layer to another with iterative closest point, point-to-point or point-to-plane. ```{py:function} ms.compute_matrix_by_icp_trueform(**params) :module: _qmeshlab Refines the alignment of the source layer onto the reference by **iterative closest point**. **Metric** chooses the error being minimised: - *Point to point* — the classic formulation. Robust, but converges slowly across flat regions where many correspondences are nearly equivalent. - *Point to plane* — measures each correspondence along the reference's surface normal, so the source can slide freely along a surface. It converges in far fewer iterations on smooth geometry, and is the better default when the reference has reliable normals. ICP only refines **locally**: from a poor starting position it converges confidently to the wrong answer rather than failing. **Coarse Initialization** therefore runs *Align by Bounding Box (TrueForm)* first, which is usually enough to land in the right basin. **Samples** subsamples the source each iteration, which is what keeps large clouds tractable; 0 uses every point. **Outlier Proportion** discards that fraction of the worst correspondences each iteration, which matters when the two layers only partly overlap. The reported **Chamfer residual** is the mean one-way distance after alignment — useful for comparing runs. The result is written to the source layer's **matrix**; vertex coordinates are not touched. Implemented with TrueForm's `fit_icp_alignment`. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The layer that is moved. - **referenceMesh** (*mesh*, default: `@otherMeshIndex`) — The layer that stays put. - **metric** (*enum*, default: `point_to_plane`) — Point to plane converges faster on smooth surfaces; point to point is safer when the reference normals are unreliable. - **coarseInit** (*bool*, default: `True`) — Run a bounding-box alignment first. Leave on unless the layers are already roughly registered. - **maxIterations** (*int*, default: `50`) — Upper bound on ICP iterations. - **samples** (*int*, default: `1000`) — Source points sampled per iteration. 0 uses all of them, which is slower but deterministic. - **minImprovement** (*double*, default: `0.001`) — Stop once the error improves by less than this fraction between iterations. - **outlierProportion** (*double*, default: `0.0`) — Fraction of the worst correspondences rejected each iteration. Raise it when the two layers only partly overlap. ``` --- (filter-compute-matrix-by-mesh-global-alignment)= ## Align Meshes Globally **Categories:** `Geometry/Alignment` **Plugin:** qmeshlab.filter.icp Globally align overlapping mesh layers using pairwise ICP arcs. ```{py:function} ms.compute_matrix_by_mesh_global_alignment(**params) :module: _qmeshlab Build an overlap graph among the selected document layers, run ICP on sufficiently overlapping layer pairs, then solve a global alignment. The chosen base mesh remains fixed and the other layer transforms are updated without baking coordinates. **References:** - Kari Pulli. **Multiview Registration for Large Data Sets**. *Proceedings of the 2nd International Conference on 3-D Digital Imaging and Modeling (3DIM)* (1999). [Web](https://graphics.stanford.edu/papers/pulli-3dim99/3dim99.pdf) **Parameters:** - **BaseMesh** (*mesh*, default: `@currentMeshIndex`) — The layer that remains fixed while the other aligned layers are moved. - **OnlyVisibleMeshes** (*bool*, default: `False`) — If enabled, align only visible layers. The base mesh must be visible. - **OGSize** (*int*, default: `50000`) — Resolution budget used to detect overlapping mesh pairs. - **arcThreshold** (*double*, default: `0.3`) — Only mesh pairs with normalized overlap above this threshold become ICP arcs. - **recalcThreshold** (*double*, default: `0.1`) — Fraction of existing high-error arcs to recompute during iterative global alignment. This port computes arcs once, so the value is retained for MeshLab parameter compatibility. - **SampleNum** (*int*, default: `2000`) — Number of source samples used for each pairwise ICP arc. - **MinDistAbs** (*double*, default: `10.0`) — Initial maximum correspondence distance. - **TrgDistAbs** (*double*, default: `0.005`) — ICP stop distance for each pairwise arc. - **MaxIterNum** (*int*, default: `75`) — Maximum number of ICP iterations for each pairwise arc. - **SampleMode** (*bool*, default: `True`) — Distribute samples uniformly with respect to normal directions. - **ReduceFactorPerc** (*double*, default: `0.8`) — Percentile used to reduce correspondence distance. - **PassHiFilter** (*double*, default: `0.75`) — Discard samples farther than this percentile. - **MatchMode** (*bool*, default: `True`) — If enabled, pairwise and global alignment use rigid transforms. - **UseVertexOnly** (*bool*, default: `False`) — Use closest vertices instead of closest points on faces. - **MaxAngleDeg** (*double*, default: `45.0`) — Maximum accepted normal angle in degrees. - **MinPointNum** (*int*, default: `30`) — Minimum number of matched point pairs required for a valid pairwise ICP arc. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the sub-sampling of each aligned pair exactly reproducible. ``` --- (filter-compute-matrix-by-obb-alignment)= ## Align by Bounding Box (TrueForm) **Categories:** `Geometry/Alignment` **Plugin:** qmeshlab.filter.trueform Coarsely align one layer to another by matching their oriented bounding boxes. ```{py:function} ms.compute_matrix_by_obb_alignment(**params) :module: _qmeshlab Aligns the source layer to the reference by fitting their **oriented bounding boxes**. It needs no initial guess and no correspondences, and it is fast, which makes it the natural first step before ICP — *Align by ICP* can run it for you. An oriented bounding box is only defined up to 180-degree flips about its axes, so the fit is ambiguous in principle. TrueForm resolves this by testing the candidate orientations against a spatial index of the reference and keeping the best. The result is written to the source layer's **matrix**; vertex coordinates are not touched. Implemented with TrueForm's `fit_obb_alignment`. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The layer that is moved. - **referenceMesh** (*mesh*, default: `@otherMeshIndex`) — The layer that stays put. ``` --- (filter-apply-vertex-geometric-function)= ## Compute Vertex Coordinates by Expression **Categories:** `Geometry/Deformation` **Plugin:** qmeshlab.filter.expression Computes new per-vertex coordinates from expressions. ```{py:function} ms.apply_vertex_geometric_function(**params) :module: _qmeshlab Geometric function using muparser lib to generate new Coord
You can change x,y,z for every vertex according to the function specified.
**Parameters:** - **x** (*string*, default: `x`) — Expression for X output. - **y** (*string*, default: `y`) — Expression for Y output. - **z** (*string*, default: `sin(x+y)`) — Expression for Z output. - **a** (*string*, default: `1`) — Expression for alpha channel (ignored for geometry). - **onselected** (*bool*, default: `False`) — If enabled, the filter affects only selected elements. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-displace-by-fractal-brownian-motion)= ## Displace Vertices by Fractal Brownian Motion **Categories:** `Geometry/Deformation` **Plugin:** qmeshlab.filter.vertex_displacement Displace vertices along their normals using fractal Brownian motion. ```{py:function} ms.displace_by_fractal_brownian_motion(**params) :module: _qmeshlab Evaluates fractal Brownian motion (fBM) in normalized object space and displaces each vertex along a smoothed normal. The noise is the weighted sum $$N(\mathbf{x})=\sum_{i=0}^{n-1} L^{-Hi}\,P(L^i\mathbf{x}),$$ where $P$ is VCGLib's three-dimensional Perlin noise, $n$ is the octave count, $L$ is lacunarity, and $H$ is the fractal increment. Lower $H$ retains more high-frequency detail. **Upstream:** [MeshLab Fractal Filter](https://github.com/cnr-isti-vclab/meshlab/tree/main/src/meshlabplugins/filter_fractal) **License:** GPL-2.0-or-later **References:** - David S. Ebert, F. Kenton Musgrave, Darwyn Peachey, Ken Perlin, Steven Worley. **Texturing and Modeling: A Procedural Approach** (2002). **Parameters:** - **maxHeight** (*absperc*, default: `@bboxDiag01`) — Maximum positive displacement, relative to the mesh bounding-box diagonal. - **scale** (*absperc*, default: `@bboxDiag`) — Spatial size of the base noise features; smaller values produce finer detail. - **octaves** (*int*, default: `10`) — Number of Perlin-noise frequency bands. - **lacunarity** (*double*, default: `2.0`) — Frequency multiplier between consecutive octaves. - **fractalIncrement** (*double*, default: `1.2`) — Exponent controlling the spectral weight of higher frequencies. - **seed** (*double*, default: `1.0`) — Translation of the noise domain; changing it produces another morphology. - **normalSmoothingSteps** (*int*, default: `5`) — Laplacian smoothing iterations applied to normals before displacement. ``` --- (filter-displace-by-heterogeneous-multifractal-noise)= ## Displace Vertices by Heterogeneous Multifractal Noise **Categories:** `Geometry/Deformation` **Plugin:** qmeshlab.filter.vertex_displacement Displace vertices using elevation-dependent heterogeneous multifractal noise. ```{py:function} ms.displace_by_heterogeneous_multifractal_noise(**params) :module: _qmeshlab Evaluates a heterogeneous multifractal whose successive increments are modulated by the accumulated signal. This makes high-frequency detail depend on the local elevation already produced by lower octaves, yielding spatially varying roughness rather than a stationary noise field. **Upstream:** [MeshLab Fractal Filter](https://github.com/cnr-isti-vclab/meshlab/tree/main/src/meshlabplugins/filter_fractal) **License:** GPL-2.0-or-later **References:** - David S. Ebert, F. Kenton Musgrave, Darwyn Peachey, Ken Perlin, Steven Worley. **Texturing and Modeling: A Procedural Approach** (2002). **Parameters:** - **maxHeight** (*absperc*, default: `@bboxDiag01`) — Maximum positive displacement, relative to the mesh bounding-box diagonal. - **scale** (*absperc*, default: `@bboxDiag`) — Spatial size of the base noise features; smaller values produce finer detail. - **octaves** (*int*, default: `8`) — Number of Perlin-noise frequency bands. - **lacunarity** (*double*, default: `3.0`) — Frequency multiplier between consecutive octaves. - **fractalIncrement** (*double*, default: `0.9`) — Exponent controlling the spectral weight of higher frequencies. - **offset** (*double*, default: `0.4`) — Bias controlling the strength of multifractal modulation. - **seed** (*double*, default: `1.0`) — Translation of the noise domain; changing it produces another morphology. - **normalSmoothingSteps** (*int*, default: `5`) — Laplacian smoothing iterations applied to normals before displacement. ``` --- (filter-displace-by-hybrid-multifractal-noise)= ## Displace Vertices by Hybrid Multifractal Noise **Categories:** `Geometry/Deformation` **Plugin:** qmeshlab.filter.vertex_displacement Displace vertices using signal-weighted hybrid multifractal noise. ```{py:function} ms.displace_by_hybrid_multifractal_noise(**params) :module: _qmeshlab Evaluates hybrid multifractal noise, where each octave controls how strongly the following octave contributes. The feedback is clamped to avoid unbounded amplification, producing terrain-like regions with locally varying roughness. **Upstream:** [MeshLab Fractal Filter](https://github.com/cnr-isti-vclab/meshlab/tree/main/src/meshlabplugins/filter_fractal) **License:** GPL-2.0-or-later **References:** - David S. Ebert, F. Kenton Musgrave, Darwyn Peachey, Ken Perlin, Steven Worley. **Texturing and Modeling: A Procedural Approach** (2002). **Parameters:** - **maxHeight** (*absperc*, default: `@bboxDiag01`) — Maximum positive displacement, relative to the mesh bounding-box diagonal. - **scale** (*absperc*, default: `@bboxDiag`) — Spatial size of the base noise features; smaller values produce finer detail. - **octaves** (*int*, default: `8`) — Number of Perlin-noise frequency bands. - **lacunarity** (*double*, default: `4.0`) — Frequency multiplier between consecutive octaves. - **fractalIncrement** (*double*, default: `0.1`) — Exponent controlling the spectral weight of higher frequencies. - **offset** (*double*, default: `0.3`) — Bias controlling the initial signal and octave feedback. - **seed** (*double*, default: `1.0`) — Translation of the noise domain; changing it produces another morphology. - **normalSmoothingSteps** (*int*, default: `5`) — Laplacian smoothing iterations applied to normals before displacement. ``` --- (filter-displace-by-ridged-multifractal-noise)= ## Displace Vertices by Ridged Multifractal Noise **Categories:** `Geometry/Deformation` **Plugin:** qmeshlab.filter.vertex_displacement Displace vertices using ridged multifractal noise. ```{py:function} ms.displace_by_ridged_multifractal_noise(**params) :module: _qmeshlab Evaluates ridged multifractal noise by folding each Perlin signal around zero, subtracting it from the offset, and squaring it. Feedback controlled by the gain sharpens coherent ridges while suppressing detail away from them. **Upstream:** [MeshLab Fractal Filter](https://github.com/cnr-isti-vclab/meshlab/tree/main/src/meshlabplugins/filter_fractal) **License:** GPL-2.0-or-later **References:** - David S. Ebert, F. Kenton Musgrave, Darwyn Peachey, Ken Perlin, Steven Worley. **Texturing and Modeling: A Procedural Approach** (2002). **Parameters:** - **maxHeight** (*absperc*, default: `@bboxDiag01`) — Maximum positive displacement, relative to the mesh bounding-box diagonal. - **scale** (*absperc*, default: `@bboxDiag`) — Spatial size of the base noise features; smaller values produce finer detail. - **octaves** (*int*, default: `8`) — Number of Perlin-noise frequency bands. - **lacunarity** (*double*, default: `4.0`) — Frequency multiplier between consecutive octaves. - **fractalIncrement** (*double*, default: `0.5`) — Exponent controlling the spectral weight of higher frequencies. - **offset** (*double*, default: `0.9`) — Sets the ridge level before squaring the folded signal. - **gain** (*double*, default: `2.0`) — Controls feedback strength and ridge sharpness. - **seed** (*double*, default: `2.0`) — Translation of the noise domain; changing it produces another morphology. - **normalSmoothingSteps** (*int*, default: `5`) — Laplacian smoothing iterations applied to normals before displacement. ``` --- (filter-displace-by-standard-multifractal-noise)= ## Displace Vertices by Standard Multifractal Noise **Categories:** `Geometry/Deformation` **Plugin:** qmeshlab.filter.vertex_displacement Displace vertices using multiplicative standard multifractal noise. ```{py:function} ms.displace_by_standard_multifractal_noise(**params) :module: _qmeshlab Evaluates standard multifractal noise in normalized object space and displaces vertices along smoothed normals. Unlike additive fBM, its octave contributions are multiplied: $$N(\mathbf{x})=\prod_{i=0}^{n-1}\left(O+L^{-Hi}P(L^i\mathbf{x})\right).$$ The offset $O$ controls multifractality and the fractal increment $H$ controls the contribution of high frequencies. **Upstream:** [MeshLab Fractal Filter](https://github.com/cnr-isti-vclab/meshlab/tree/main/src/meshlabplugins/filter_fractal) **License:** GPL-2.0-or-later **References:** - David S. Ebert, F. Kenton Musgrave, Darwyn Peachey, Ken Perlin, Steven Worley. **Texturing and Modeling: A Procedural Approach** (2002). **Parameters:** - **maxHeight** (*absperc*, default: `@bboxDiag01`) — Maximum positive displacement, relative to the mesh bounding-box diagonal. - **scale** (*absperc*, default: `@bboxDiag`) — Spatial size of the base noise features; smaller values produce finer detail. - **octaves** (*int*, default: `8`) — Number of Perlin-noise frequency bands. - **lacunarity** (*double*, default: `2.0`) — Frequency multiplier between consecutive octaves. - **fractalIncrement** (*double*, default: `0.9`) — Exponent controlling the spectral weight of higher frequencies. - **offset** (*double*, default: `0.9`) — Bias added to every octave before multiplication. - **seed** (*double*, default: `1.0`) — Translation of the noise domain; changing it produces another morphology. - **normalSmoothingSteps** (*int*, default: `5`) — Laplacian smoothing iterations applied to normals before displacement. ``` --- (filter-displace-vertices-randomly)= ## Displace Vertices Randomly **Categories:** `Geometry/Deformation` **Plugin:** qmeshlab.filter.vertex_displacement Move every vertex by an independently generated random vector. ```{py:function} ms.displace_vertices_randomly(**params) :module: _qmeshlab Adds an independent uniformly distributed displacement to each coordinate of every vertex. With maximum displacement $d$, each coordinate offset lies in $[-d,d]$. Set a nonzero random seed to obtain repeatable results. **Upstream:** [MeshLab Fractal Filter](https://github.com/cnr-isti-vclab/meshlab/tree/main/src/meshlabplugins/filter_fractal) **License:** GPL-2.0-or-later **Parameters:** - **maxDisplacement** (*absperc*, default: `@bboxDiag01`) — Maximum absolute displacement applied independently to each coordinate. - **recomputeNormals** (*bool*, default: `True`) — Recompute face and vertex normals after displacement. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the displacement exactly reproducible. ``` --- (filter-vertex-linear-morphing)= ## Displace Vertices toward Target Mesh **Categories:** `Geometry/Deformation` **Plugin:** qmeshlab.filter.unsharp Linearly morph the current mesh toward another mesh. ```{py:function} ms.vertex_linear_morphing(**params) :module: _qmeshlab Morphs the current mesh toward a target mesh that has the same number of vertices in the same order. Each source vertex moves along the straight line to its counterpart:\n\n$$p_i^{\mathrm{result}}=(1-\lambda)\,p_i^{\mathrm{source}}+\lambda\,p_i^{\mathrm{target}}.$$\n\n**Weight** is $\lambda$: 0 leaves the mesh alone, 1 lands exactly on the target, and values in between interpolate. Values outside $[0,1]$ extrapolate past either end. **Parameters:** - **TargetMesh** (*mesh*, default: `@otherMeshIndex`) — Mesh that acts as the morph target. - **PercentMorph** (*double*, default: `0.0`) — 0 keeps the current mesh, 100 reaches the target mesh, values outside [0,100] extrapolate. ``` --- (filter-apply-coord-laplacian-smoothing-surface-preserving)= ## Smooth Vertices by Surface-Preserving Laplacian (vcglib) **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.trioptimize Laplacian smooth while limiting normal deviation from the original surface. ```{py:function} ms.apply_coord_laplacian_smoothing_surface_preserving(**params) :module: _qmeshlab Laplacian smooth with limited surface modification: each vertex moves toward the average position of neighboring vertices only when the new position still almost lies on the original surface. **Parameters:** - **selection** (*bool*, default: `False`) — If enabled, smooth only selected faces. - **AngleDeg** (*double*, default: `0.5`) — Maximum mean normal angle displacement allowed from old to new faces. - **iterations** (*int*, default: `1`) — Number of smoothing iterations. ``` --- (filter-apply-laplacian-smoothing-trueform)= ## Smooth Vertices by Laplacian (TrueForm) **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.trueform Move each vertex towards the average of its neighbours. ```{py:function} ms.apply_laplacian_smoothing_trueform(**params) :module: _qmeshlab Moves each vertex towards the average position of its linked neighbours, repeatedly.\n\n**Lambda** is how far towards that average each step travels: 1.0 goes all the way, smaller values creep. **Iterations** is how many steps.\n\nLaplacian smoothing **shrinks**: every step pulls the surface towards its own average, so a closed shape loses volume and sharp features round off. That is the price of its simplicity, and the reason for its Taubin sibling, which alternates a shrinking step with an expanding one to compensate.\n\nEnable **Selected Only** to restrict movement to the current vertex selection.\n\nCompeting implementation: QMeshLab already has vcglib smoothing under *Geometry/Smoothing*. TrueForm's is parallelised through oneTBB, which shows on large meshes. Results should agree closely; where they differ the difference is in the boundary handling. **Parameters:** - **iterations** (*int*, default: `10`) — How many smoothing steps to take. - **lambda** (*double*, default: `0.5`) — How far each step moves towards the neighbour average, 0 to 1. - **selectedOnly** (*bool*, default: `False`) — Move only the selected vertices. ``` --- (filter-apply-mls-apss)= ## Project Vertices onto MLS Surface (APSS) **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.mls Project a mesh or point set onto an Algebraic Point Set Surface. ```{py:function} ms.apply_mls_apss(**params) :module: _qmeshlab Projects a mesh, or a bare point set, onto the MLS surface defined by itself or by another point set.\n\nThis is the **algebraic point set surfaces** (APSS) variant: the local approximation fitted at each point is an algebraic sphere rather than a plane, which keeps curved regions from flattening out. It needs points carrying oriented normals. **References:** - Gaël Guennebaud, Markus Gross. **Algebraic point set surfaces**. *ACM Transactions on Graphics (SIGGRAPH 2007)* (2007). [DOI](https://doi.org/10.1145/1276377.1276406) - Gaël Guennebaud, Marcel Germann, Markus Gross. **Dynamic Sampling and Rendering of Algebraic Point Set Surfaces**. *Computer Graphics Forum (Eurographics 2008)* (2008). [DOI](https://doi.org/10.1111/j.1467-8659.2008.01163.x) **Parameters:** - **ControlMesh** (*mesh*, default: `@currentMeshIndex`) — The point set (or mesh) which defines the MLS surface. - **ProxyMesh** (*mesh*, default: `@currentMeshIndex`) — The mesh that will be projected/resampled onto the MLS surface. - **SelectionOnly** (*bool*, default: `False`) — If checked, only selected vertices will be projected. - **FilterScale** (*double*, default: `2.0`) — Scale of the spatial low pass filter. It is relative to the radius (local point spacing) of the vertices. - **SphericalParameter** (*double*, default: `1.0`) — Control the curvature of the fitted spheres: 0 is equivalent to a pure plane fit, 1 to a pure spherical fit, values between 0 and 1 give intermediate results, while other real values might give interesting results, but take care with extreme settings. - **AccurateNormal** (*bool*, default: `True`) — If checked, use the accurate MLS gradient instead of the local approximation to compute the normals. - **MaxSubdivisions** (*int*, default: `0`) — Max number of subdivisions. - **ThAngleInDegree** (*double*, default: `2.0`) — Threshold angle between two faces controlling the refinement. - **ProjectionAccuracy** (*double*, default: `0.0001`) — Threshold value used to stop the projections. This value is scaled by the mean point spacing to get the actual threshold. - **MaxProjectionIters** (*int*, default: `15`) — Max number of iterations for the projection. ``` --- (filter-apply-mls-rimls)= ## Project Vertices onto MLS Surface (RIMLS) **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.mls Project a mesh or point set onto a Robust Implicit MLS surface. ```{py:function} ms.apply_mls_rimls(**params) :module: _qmeshlab Projects a mesh, or a bare point set, onto the MLS surface defined by itself or by another point set.\n\nThis is the **robust implicit MLS** (RIMLS) variant: it extends implicit MLS with non-linear kernel regression, so sharp edges survive instead of being rounded away with the noise. It needs points carrying oriented normals. **References:** - A. Cengiz Öztireli, Gaël Guennebaud, Markus Gross. **Feature Preserving Point Set Surfaces based on Non-Linear Kernel Regression**. *Computer Graphics Forum (Eurographics 2009)* (2009). [DOI](https://doi.org/10.1111/j.1467-8659.2009.01388.x) **Parameters:** - **ControlMesh** (*mesh*, default: `@currentMeshIndex`) — The point set (or mesh) which defines the MLS surface. - **ProxyMesh** (*mesh*, default: `@currentMeshIndex`) — The mesh that will be projected/resampled onto the MLS surface. - **SelectionOnly** (*bool*, default: `False`) — If checked, only selected vertices will be projected. - **FilterScale** (*double*, default: `2.0`) — Scale of the spatial low pass filter. It is relative to the radius (local point spacing) of the vertices. - **SigmaN** (*double*, default: `0.75`) — Width of the filter used by the normal refitting weight. This weight function is a Gaussian on the distance between two unit vectors: the current gradient and the input normal. Typical values range between 0.5 (sharp) and 2 (smooth). - **MaxRefittingIters** (*int*, default: `3`) — Max number of fitting iterations. (0 or 1 is equivalent to the standard IMLS). - **MaxSubdivisions** (*int*, default: `0`) — Max number of subdivisions. - **ThAngleInDegree** (*double*, default: `2.0`) — Threshold angle between two faces controlling the refinement. - **ProjectionAccuracy** (*double*, default: `0.0001`) — Threshold value used to stop the projections. This value is scaled by the mean point spacing to get the actual threshold. - **MaxProjectionIters** (*int*, default: `15`) — Max number of iterations for the projection. ``` --- (filter-apply-taubin-smoothing-trueform)= ## Smooth Vertices by Taubin (TrueForm) **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.trueform Smooth without the shrinkage that Laplacian smoothing causes. ```{py:function} ms.apply_taubin_smoothing_trueform(**params) :module: _qmeshlab Alternates a Laplacian shrinking step with a slightly larger expanding one, so noise is removed while the overall volume is preserved. This is the smoothing to reach for by default; plain Laplacian is the one to reach for when you *want* the shape to contract.\n\n**Lambda** is the shrinking step and **Kpb** sets the expanding one — larger Kpb pushes back harder against shrinkage. The defaults are the values from Taubin's paper and are a reasonable starting point.\n\nEnable **Selected Only** to restrict movement to the current vertex selection.\n\nCompeting implementation: QMeshLab already has vcglib smoothing under *Geometry/Smoothing*. TrueForm's is parallelised through oneTBB, which shows on large meshes. Results should agree closely; where they differ the difference is in the boundary handling. **References:** - Gabriel Taubin. **A signal processing approach to fair surface design**. *Proceedings of the 22nd Annual Conference on Computer Graphics and Interactive Techniques (SIGGRAPH '95)* (1995). [DOI](https://doi.org/10.1145/218380.218473) **Parameters:** - **iterations** (*int*, default: `10`) — How many smoothing steps to take. - **lambda** (*double*, default: `0.5`) — The shrinking step size, 0 to 1. - **kpb** (*double*, default: `0.1`) — Controls the compensating expansion. Larger values resist shrinkage more. - **selectedOnly** (*bool*, default: `False`) — Move only the selected vertices. ``` --- (filter-smooth-depth)= ## Smooth Vertices along One Direction **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.unsharp Smooth vertices only along a given depth direction. ```{py:function} ms.smooth_depth(**params) :module: _qmeshlab A laplacian smooth that is constrained to move vertices only in one given direction (usually the viewer direction). **Parameters:** - **stepSmoothNum** (*int*, default: `3`) — Number of smoothing iterations. - **viewPoint** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Position of the viewpoint that defines the allowed displacement direction. - **delta** (*double*, default: `1.0`) — How much smoothing is applied: 0 means no smoothing, 1 means full smoothing. - **Selected** (*bool*, default: `@hasSelectedFaces`) — If enabled, apply the filter only to the selected area. ``` --- (filter-smooth-directional)= ## Project Vertices onto the Line of Sight **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.unsharp Snap vertices back onto the sight line through their stored position. ```{py:function} ms.smooth_directional(**params) :module: _qmeshlab Projects every vertex back onto the line joining **Viewpoint** to the position stored for it in a per-vertex custom point attribute, keeping only the part of its displacement that lies along that line and discarding the part across it. Writing $o$ for the stored position, $p$ for the current one and $d$ for the unit vector from the viewpoint to $o$: $$p_{\mathrm{new}} = o + d\,\big((p-o)\cdot d\big).$$ Run it after a smoothing filter to confine that filter's effect to depth. Time-of-flight scanners resolve *x,y* well but carry much larger depth error, so smoothing is worth trusting along the line of sight and worth undoing across it. Store the original coordinates first, in the custom attribute named here. Note that this is a projection, not a blend: there is no mixing factor, and every vertex moves. **Parameters:** - **attr_name** (*string*, default: ``) — Name of the per-vertex custom point attribute containing the original geometry. - **viewPoint** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Position of the viewpoint whose sight lines the vertices are projected onto. ``` --- (filter-smooth-hc-laplacian)= ## Smooth Vertices by HC Laplacian **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.unsharp Improved Laplacian smoothing with better shape preservation. ```{py:function} ms.smooth_hc_laplacian(**params) :module: _qmeshlab HC Laplacian smoothing: an extended Laplacian smoothing that pushes each vertex back toward its original position after every averaging step, which removes most of the shrinkage plain Laplacian smoothing causes. **References:** - J. Vollmer, R. Mencl, H. Müller. **Improved Laplacian Smoothing of Noisy Surface Meshes**. *Computer Graphics Forum* (1999). [DOI](https://doi.org/10.1111/1467-8659.00334) [Web](https://onlinelibrary.wiley.com/doi/abs/10.1111/1467-8659.00334) This filter has no parameters. ``` --- (filter-smooth-laplacian)= ## Smooth Vertices by Laplacian (vcglib) **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.unsharp Average vertex positions with their neighbors. ```{py:function} ms.smooth_laplacian(**params) :module: _qmeshlab Laplacian smoothing: each vertex moves toward the average position of its neighbours. The simplest and fastest of the smoothing filters, and the one that shrinks the mesh most -- repeated passes pull the surface inward. Use Taubin or HC Laplacian where that matters. **Parameters:** - **stepSmoothNum** (*int*, default: `3`) — Number of smoothing iterations. - **Boundary** (*bool*, default: `True`) — Smooth boundary edges only by themselves instead of shrinking them into the surface. - **cotangentWeight** (*bool*, default: `True`) — Use cotangent weights instead of umbrella weights for the position average. - **Selected** (*bool*, default: `@hasSelectedFaces`) — If enabled, apply the filter only to the selected area. ``` --- (filter-smooth-scale-dependent-laplacian)= ## Smooth Vertices by Scale-Dependent Laplacian **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.unsharp Fujiwara-style scale-dependent Laplacian smoothing. ```{py:function} ms.smooth_scale_dependent_laplacian(**params) :module: _qmeshlab Scale-dependent Laplacian smoothing, using the Fujiwara extended umbrella operator. Weighting each neighbour by the inverse of its edge length makes the smoothing step independent of how unevenly the mesh is tessellated, so dense and sparse regions are faired at the same rate rather than the dense ones collapsing first. **References:** - Mathieu Desbrun, Mark Meyer, Peter Schröder, Alan H. Barr. **Implicit fairing of irregular meshes using diffusion and curvature flow**. *Proceedings of the 26th Annual Conference on Computer Graphics and Interactive Techniques (SIGGRAPH '99)* (1999). [DOI](https://doi.org/10.1145/311535.311576) **Parameters:** - **stepSmoothNum** (*int*, default: `3`) — Number of smoothing iterations. - **delta** (*absperc*, default: `@bboxDiag001`) — Maximum displacement scale used by the Fujiwara operator. - **Selected** (*bool*, default: `@hasSelectedFaces`) — If enabled, apply the filter only to the selected area. ``` --- (filter-smooth-taubin)= ## Smooth Vertices by Taubin (vcglib) **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.unsharp Lambda-mu smoothing with reduced shrinkage. ```{py:function} ms.smooth_taubin(**params) :module: _qmeshlab The $\lambda$-$\mu$ Taubin smoothing. Each iteration combines two low-pass filtering steps -- a positive $\lambda$ pass followed by a negative $\mu$ pass -- so that noise is attenuated without the volume loss of repeated Laplacian smoothing. **References:** - Gabriel Taubin. **A signal processing approach to fair surface design**. *Proceedings of the 22nd Annual Conference on Computer Graphics and Interactive Techniques (SIGGRAPH '95)* (1995). [DOI](https://doi.org/10.1145/218380.218473) **Parameters:** - **lambda** (*double*, default: `0.5`) — Lambda parameter of Taubin smoothing. - **mu** (*double*, default: `-0.53`) — Mu parameter of Taubin smoothing. - **stepSmoothNum** (*int*, default: `10`) — Number of Taubin smoothing iterations. - **Selected** (*bool*, default: `@hasSelectedFaces`) — If enabled, apply the filter only to the selected area. ``` --- (filter-smooth-two-step)= ## Smooth Vertices by Two-Step Normal Fitting **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.unsharp Feature-preserving smoothing through normal smoothing and vertex fitting. ```{py:function} ms.smooth_two_step(**params) :module: _qmeshlab A feature-preserving fairing filter that runs in two stages:\n\n1. **Normal smoothing** -- face normals that already point in similar directions are averaged together, while normals that differ sharply are left alone, so creases survive.\n2. **Vertex repositioning** -- vertices are then moved to fit the smoothed normals.\n\nSmoothing the normals first and the positions second is what separates this from plain Laplacian smoothing: noise is removed without rounding off the edges that carry the shape. **References:** - Alexander Belyaev, Yutaka Ohtake. **A comparison of mesh smoothing methods**. *Israel-Korea Bi-National Conference on Geometric Modeling and Computer Graphics* (2003). [Web](https://www.researchgate.net/publication/47861030_A_comparison_of_mesh_smoothing_methods) **Parameters:** - **stepSmoothNum** (*int*, default: `3`) — Number of full algorithm iterations. - **normalThr** (*double*, default: `60.0`) — Features forming angles larger than this threshold are preserved. - **stepNormalNum** (*int*, default: `20`) — Number of normal smoothing iterations per step. - **stepFitNum** (*int*, default: `20`) — Number of vertex fitting iterations per step. - **Selected** (*bool*, default: `@hasSelectedFaces`) — If enabled, perform the filter only on selected faces. ``` --- (filter-unsharp-mask-geometry)= ## Sharpen Vertices by Unsharp Mask **Categories:** `Geometry/Smoothing` **Plugin:** qmeshlab.filter.unsharp Enhance geometric ridges and valleys with an unsharp mask. ```{py:function} ms.unsharp_mask_geometry(**params) :module: _qmeshlab Sharpens the **vertex positions**, deepening ridges and valleys in the surface itself. Unlike the normal variant this really moves geometry, so the effect survives export.\n\nUnsharp masking exaggerates local variation by adding back the difference between the signal and a smoothed copy of it: $$s' = s + \lambda\,(s - \mathrm{smooth}(s)).$$ **Weight** is $\lambda$; larger values sharpen harder and amplify noise along with the features. **Smoothing steps** sets how blurred the subtracted copy is, which fixes the scale of the detail being enhanced.\n\n **References:** - Paolo Cignoni, Roberto Scopigno, Marco Tarini. **A simple normal enhancement technique for interactive non-photorealistic renderings**. *Computers & Graphics* (2005). [DOI](https://doi.org/10.1016/j.cag.2004.11.012) [Web](https://www.sciencedirect.com/science/article/pii/S0097849304001980) **Parameters:** - **weight** (*double*, default: `0.3`) — Unsharp weight applied to the high-frequency geometric component. - **weightOrig** (*double*, default: `1.0`) — Weight of the original geometry signal. - **iterations** (*int*, default: `5`) — Number of Laplacian smoothing iterations used to build the low-pass geometry. ``` --- (filter-matrix-freeze)= ## Freeze Matrix **Categories:** `Geometry/Transform` **Plugin:** qmeshlab.filter.meshing Bake the layer matrix into the vertex coordinates. ```{py:function} ms.matrix_freeze(**params) :module: _qmeshlab Freeze the current transformation matrix into the coordinates of the vertices of the mesh (and set this matrix to the identity). In other words it applies in a definetive way the current matrix to the vertex coordinates. This filter has no parameters. ``` --- (filter-matrix-invert)= ## Invert Matrix **Categories:** `Geometry/Transform` **Plugin:** qmeshlab.filter.meshing Invert current transformation matrix. ```{py:function} ms.matrix_invert(**params) :module: _qmeshlab Invert the current transformation matrix. The current transformation is reversed, becoming its opposite. **Parameters:** - **Freeze** (*bool*, default: `True`) — Transformation is explicitly applied to vertices. ``` --- (filter-matrix-reset)= ## Set Matrix to Identity **Categories:** `Geometry/Transform` **Plugin:** qmeshlab.filter.meshing Reset transform matrix to identity. ```{py:function} ms.matrix_reset(**params) :module: _qmeshlab Set the current transformation matrix to the Identity. This filter has no parameters. ``` --- (filter-matrix-set-copy)= ## Set Matrix from Values or Layer **Categories:** `Geometry/Transform` **Plugin:** qmeshlab.filter.meshing Set transformation matrix values. ```{py:function} ms.matrix_set_copy(**params) :module: _qmeshlab Set the current transformation matrix by filling it, or copying from another layer. **Parameters:** - **m00** (*double*, default: `1.0`) — Matrix coefficient. - **m01** (*double*, default: `0.0`) — Matrix coefficient. - **m02** (*double*, default: `0.0`) — Matrix coefficient. - **m03** (*double*, default: `0.0`) — Matrix coefficient. - **m10** (*double*, default: `0.0`) — Matrix coefficient. - **m11** (*double*, default: `1.0`) — Matrix coefficient. - **m12** (*double*, default: `0.0`) — Matrix coefficient. - **m13** (*double*, default: `0.0`) — Matrix coefficient. - **m20** (*double*, default: `0.0`) — Matrix coefficient. - **m21** (*double*, default: `0.0`) — Matrix coefficient. - **m22** (*double*, default: `1.0`) — Matrix coefficient. - **m23** (*double*, default: `0.0`) — Matrix coefficient. - **m30** (*double*, default: `0.0`) — Matrix coefficient. - **m31** (*double*, default: `0.0`) — Matrix coefficient. - **m32** (*double*, default: `0.0`) — Matrix coefficient. - **m33** (*double*, default: `1.0`) — Matrix coefficient. - **compose** (*bool*, default: `False`) — Compose with current matrix. - **Freeze** (*bool*, default: `True`) — Transformation is explicitly applied to vertices. ``` --- (filter-matrix-set-from-trs)= ## Set Matrix from Translation/Rotation/Scale **Categories:** `Geometry/Transform` **Plugin:** qmeshlab.filter.meshing Build transformation from T/R/S parameters. ```{py:function} ms.matrix_set_from_trs(**params) :module: _qmeshlab Set the current transformation matrix starting from parameters: [XYZ] translation, [XYZ] Euler angles rotation and [XYZ] scaling. **Parameters:** - **translationX** (*double*, default: `0.0`) — Translation X. - **translationY** (*double*, default: `0.0`) — Translation Y. - **translationZ** (*double*, default: `0.0`) — Translation Z. - **rotationX** (*double*, default: `0.0`) — Euler rotation X (deg). - **rotationY** (*double*, default: `0.0`) — Euler rotation Y (deg). - **rotationZ** (*double*, default: `0.0`) — Euler rotation Z (deg). - **scaleX** (*double*, default: `1.0`) — Scale X. - **scaleY** (*double*, default: `1.0`) — Scale Y. - **scaleZ** (*double*, default: `1.0`) — Scale Z. - **compose** (*bool*, default: `False`) — Compose with current matrix. - **Freeze** (*bool*, default: `True`) — Transformation is explicitly applied to vertices. ``` --- (filter-normalize-reference-frame)= ## Normalize Reference Frame **Categories:** `Geometry/Transform` **Plugin:** qmeshlab.filter.meshing Bring the mesh into a canonical position, orientation and scale. ```{py:function} ms.normalize_reference_frame(**params) :module: _qmeshlab Places the mesh in a canonical reference frame, so that two copies of the same shape end up superimposed however they were positioned, oriented or scaled beforehand. Each of the three controls can be left at **Unchanged**, so a partial canonicalization is fine. The three are independent by construction. A centre $C$ is derived from **Position**, the rotation and the scale are both taken about that centre, and the result is composed in a fixed order: $$M = T_{\mathrm{target}}\cdot S\cdot R\cdot T_{-C}.$$ When **Position** is *Unchanged*, $C$ is still used as the pivot and the object is put back where it started, so changing **Scale** or **Rotation** never moves it. **Position** picks the point that lands on the origin. *Bounding Box Center* is cheap but follows the extremes, so a single stray vertex moves it. *Vertex Average* is biased by tessellation density. *Shell Barycenter* weights by triangle area and is the robust choice for a surface. *Mesh Barycenter* is the centre of mass of the enclosed solid and needs a watertight mesh. **Rotation** aligns the principal axes with X, Y and Z, most spread first. *On Vertices* is biased wherever the tessellation is dense; *Area Weighted* integrates over the surface and is usually what you want. Principal axes are only defined up to sign, so the axis directions are fixed by the sign of the third moment along each one, and the third axis is set to the cross product of the first two. Without that step the same shape canonicalizes to any of four different frames depending on how it happened to be oriented on input. **Minimum Axis Separation** guards the ill-conditioned cases. A sphere has three equal eigenvalues and a cylinder two, so their principal axes are arbitrary; when the relative gap between consecutive eigenvalues falls below this value the rotation is skipped and the reason is logged. Zero always rotates. **Scale** is always uniform, and is measured *after* rotation, in the canonical frame. Note that applying this to several layers at once gives each layer its own frame, which will pull apart layers that were registered to each other. **Parameters:** - **position** (*enum*, default: `bbox_center`) — Which point of the mesh is moved onto the origin. - **rotation** (*enum*, default: `pca_area_weighted`) — Align the principal axes to X, Y and Z, widest spread first. - **scale** (*enum*, default: `unit_longest_side`) — Uniform scale, measured after rotation. - **minAxisSeparation** (*double*, default: `0.0`) — Skip the rotation when consecutive principal eigenvalues are closer than this relative gap, as they are for a sphere or a cylinder. Zero always rotates. - **Freeze** (*bool*, default: `True`) — Transformation is explicitly applied to vertices. ``` --- (filter-transform-flip-axis)= ## Mirror or Swap Axes **Categories:** `Geometry/Transform` **Plugin:** qmeshlab.filter.meshing Flip or swap axes. ```{py:function} ms.transform_flip_axis(**params) :module: _qmeshlab Generate a matrix transformation that flips each one of the axis or swaps a couple of axis. The listed transformations are applied in that order. This kind of transformation cannot be applied to set of Raster! **Parameters:** - **flipX** (*bool*, default: `False`) — Mirror along YZ plane. - **flipY** (*bool*, default: `False`) — Mirror along XZ plane. - **flipZ** (*bool*, default: `False`) — Mirror along XY plane. - **swapXY** (*bool*, default: `False`) — Swap X and Y. - **swapXZ** (*bool*, default: `False`) — Swap X and Z. - **swapYZ** (*bool*, default: `False`) — Swap Y and Z. - **Freeze** (*bool*, default: `True`) — Transformation is explicitly applied to vertices. ``` --- (filter-transform-rotate)= ## Rotate **Categories:** `Geometry/Transform` **Plugin:** qmeshlab.filter.meshing Rotate mesh. ```{py:function} ms.transform_rotate(**params) :module: _qmeshlab Generate a matrix transformation that rotates the mesh. The mesh can be rotated around one of the axis or a given axis and w.r.t. to the origin or the baricenter, or a given point. **Parameters:** - **rotAxis** (*enum*, default: `x`) — Choose rotation axis. - **rotCenter** (*enum*, default: `origin`) — Choose center of rotation. - **angle** (*double*, default: `0.0`) — Angle in degrees. - **customAxis** (*point3f*, default: `[0.0, 0.0, 1.0]`) — Custom rotation axis direction. - **customCenter** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Custom rotation center point. - **snapFlag** (*bool*, default: `False`) — Snap angle according to snap value. - **snapAngle** (*double*, default: `30.0`) — Snap step in degrees. - **Freeze** (*bool*, default: `True`) — Transformation is explicitly applied to vertices. ``` --- (filter-transform-rotate-to-fit-plane)= ## Rotate to Fitted Plane **Categories:** `Geometry/Transform` **Plugin:** qmeshlab.filter.meshing Rotate selection to fit a reference plane. ```{py:function} ms.transform_rotate_to_fit_plane(**params) :module: _qmeshlab Generate a matrix transformation that rotates the mesh so that the selection fits one of the main planes XY YZ ZX. May also translate such that the selection centroid rest on the origin. It reports on the log the average error of the fitting (in mesh units). **Parameters:** - **targetPlane** (*enum*, default: `xy`) — Target plane. - **rotAxis** (*enum*, default: `any`) — Rotation axis constraint. - **ToOrigin** (*bool*, default: `True`) — Translate so selection centroid rests on origin. - **Freeze** (*bool*, default: `True`) — Transformation is explicitly applied to vertices. ``` --- (filter-transform-scale)= ## Scale **Categories:** `Geometry/Transform` **Plugin:** qmeshlab.filter.meshing Scale mesh. ```{py:function} ms.transform_scale(**params) :module: _qmeshlab Generate a matrix transformation that scale the mesh. The mesh can be also automatically scaled to a unit side box. **Parameters:** - **axisX** (*double*, default: `1.0`) — Scale X. - **axisY** (*double*, default: `1.0`) — Scale Y. - **axisZ** (*double*, default: `1.0`) — Scale Z. - **uniformFlag** (*bool*, default: `True`) — Use same scale for all axes (axisX value). - **scaleCenter** (*enum*, default: `origin`) — Scaling center. - **customCenter** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Custom scaling center point. - **Freeze** (*bool*, default: `True`) — Transformation is explicitly applied to vertices. ``` --- (filter-transform-translate)= ## Translate **Categories:** `Geometry/Transform` **Plugin:** qmeshlab.filter.meshing Translate mesh. ```{py:function} ms.transform_translate(**params) :module: _qmeshlab Generate a matrix transformation that translate the mesh. The mesh can be translated around one of the axis or a given axis and w.r.t. to the origin or the baricenter, or a given point. **Parameters:** - **traslMethod** (*enum*, default: `xyz`) — Translation strategy. - **axis** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Custom translation vector. - **newOrigin** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Custom new origin point. - **Freeze** (*bool*, default: `True`) — Transformation is explicitly applied to vertices. ``` --- (filter-compute-chamfer-distance)= ## Measure Chamfer Distance (TrueForm) **Categories:** `Measurement/Geometric` **Plugin:** qmeshlab.filter.trueform Report the mean nearest-point distance between two layers. ```{py:function} ms.compute_chamfer_distance(**params) :module: _qmeshlab Reports the **mean** distance from each vertex of one layer to the nearest vertex of the other.\n\nWhere the *Measure Hausdorff Distance* reports the single worst correspondence — and so is dominated by one stray vertex — the chamfer distance averages over all of them. That makes it the more useful number for scoring an overall fit: comparing simplification settings, judging whether a registration improved, or tracking a reconstruction against ground truth. Use Hausdorff when the worst case is what matters, and this when the typical case is.\n\nThe measure is **not symmetric**: the mean distance from A to B differs from B to A, and a subset of a surface can sit very close to it while the surface as a whole sits far from the subset. **Symmetric** measures both directions and also reports the larger, which is the honest single number.\n\n**Outlier Proportion** discards that fraction of the worst correspondences before averaging, for partial overlaps.\n\nThis measures vertex to vertex, so it is sensitive to how densely each layer is sampled. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The layer being measured. - **referenceMesh** (*mesh*, default: `@otherMeshIndex`) — The layer measured against. - **symmetric** (*bool*, default: `True`) — Measure both directions and report the larger. - **outlierProportion** (*double*, default: `0.0`) — Fraction of the worst correspondences discarded before averaging. ``` --- (filter-compute-distance-from-reference)= ## Compute Distance from Reference Mesh **Categories:** `Measurement/Geometric`, `Attribute/Scalar` **Plugin:** qmeshlab.filter.sampling Compute per-vertex distance from another mesh or point cloud. ```{py:function} ms.compute_distance_from_reference(**params) :module: _qmeshlab Compute the signed/unsigned (per vertex) distance between a mesh/pointcloud and a reference mesh/pointcloud. Distance is stored in vertex quality; after the filter runs QMeshLab switches the measured mesh to vertex-quality color visualization without baking colors. **Parameters:** - **MeasureMesh** (*mesh*, default: `@currentMeshIndex`) — The mesh that will receive the computed distances in vertex quality. - **RefMesh** (*mesh*, default: `@otherMeshIndex`) — The mesh or point cloud used as the reference. - **SignedDist** (*bool*, default: `True`) — If enabled, compute a signed distance instead of the absolute value. - **MaxDist** (*absperc*, default: `@bboxDiag`) — Search is interrupted when nothing is found within this range. ``` --- (filter-compute-geometric-measures)= ## Measure Geometric Properties **Categories:** `Measurement/Geometric` **Plugin:** qmeshlab.filter.measure Compute a set of geometric measures of a mesh or point cloud. ```{py:function} ms.compute_geometric_measures(**params) :module: _qmeshlab Compute a set of geometric measures of a mesh/pointcloud. Bounding box extents and diagonal, principal axis, thin shell barycenter (mesh only), vertex barycenter and quality-weighted barycenter (pointcloud only), surface area (mesh only), volume (closed mesh) and inertia tensor matrix (closed mesh). This filter has no parameters. ``` --- (filter-compute-hausdorff-distance)= ## Measure Hausdorff Distance **Categories:** `Measurement/Geometric`, `Attribute/Scalar` **Plugin:** qmeshlab.filter.sampling Compute directional Hausdorff distance statistics between two meshes. ```{py:function} ms.compute_hausdorff_distance(**params) :module: _qmeshlab Compute the Measure Hausdorff Distance between two layers, sampling one of the two and finding for each sample the closest point over the other mesh. If sample layers are saved, distances are stored in vertex quality and QMeshLab switches those layers to vertex-quality color visualization without baking colors. **Parameters:** - **SampledMesh** (*mesh*, default: `@currentMeshIndex`) — The mesh whose surface is sampled. - **TargetMesh** (*mesh*, default: `@otherMeshIndex`) — The reference mesh searched for closest points. - **SaveSample** (*bool*, default: `False`) — Create two new layers with the used sample points and closest points. - **SampleVert** (*bool*, default: `True`) — Sample vertices of the sampled mesh. - **SampleEdge** (*bool*, default: `False`) — Sample edges of the sampled mesh. - **SampleFauxEdge** (*bool*, default: `False`) — Include faux edges when edge sampling is enabled. - **SampleFace** (*bool*, default: `False`) — Sample faces of the sampled mesh by Montecarlo sampling. - **SampleNum** (*int*, default: `1000`) — Desired number of samples for each enabled sampling strategy. - **MaxDist** (*absperc*, default: `@bboxDiagHalf`) — Discard sample points whose closest point is farther than this threshold. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the measured sample set exactly reproducible. ``` --- (filter-compute-selection-area-perimeter)= ## Measure Selection Area and Perimeter **Categories:** `Measurement/Geometric` **Plugin:** qmeshlab.filter.measure Compute area and perimeter of the face selection. ```{py:function} ms.compute_selection_area_perimeter(**params) :module: _qmeshlab Compute area and perimeter of the FACE selection. This filter has no parameters. ``` --- (filter-get-overlapping-meshes-graph)= ## Measure Layer Overlap **Categories:** `Measurement/Geometric` **Plugin:** qmeshlab.filter.icp Report which mesh layers overlap in an occupancy grid. ```{py:function} ms.get_overlapping_meshes_graph(**params) :module: _qmeshlab Voxelize all mesh layers into an occupancy grid and report the pairs that occupy common cells. This is an information filter and does not modify the document. **Parameters:** - **OGSize** (*int*, default: `50000`) — Resolution budget used by the occupancy grid. ``` --- (filter-compute-face-quality-histogram)= ## Measure Face Scalar Histogram **Categories:** `Measurement/Statistics` **Plugin:** qmeshlab.filter.measure Compute a histogram of per-face quality values. ```{py:function} ms.compute_face_quality_histogram(**params) :module: _qmeshlab Compute an histogram of the values of the per-face quality. **Parameters:** - **HistMin** (*double*, default: `@qualityFMin`) — Lower bound of the histogram range. - **HistMax** (*double*, default: `@qualityFMax`) — Upper bound of the histogram range. - **areaWeighted** (*bool*, default: `False`) — If false, each bin reports the number of faces in the range. If true, each bin reports the approximate area in that range. - **binNum** (*int*, default: `20`) — The number of bins of the histogram. ``` --- (filter-compute-face-quality-stat)= ## Measure Face Scalar Statistics **Categories:** `Measurement/Statistics` **Plugin:** qmeshlab.filter.measure Compute aggregate statistics over per-face quality. ```{py:function} ms.compute_face_quality_stat(**params) :module: _qmeshlab Compute some aggregate statistics over the per face quality, like Min, Max, Average, StdDev and Variance. This filter has no parameters. ``` --- (filter-compute-vertex-quality-histogram)= ## Measure Vertex Scalar Histogram **Categories:** `Measurement/Statistics` **Plugin:** qmeshlab.filter.measure Compute a histogram of per-vertex quality values. ```{py:function} ms.compute_vertex_quality_histogram(**params) :module: _qmeshlab Compute an histogram of the values of the per-vertex quality. It can be useful to evaluate the distribution of the quality value over the surface. It can be discrete (e.g. based on vertex count or area weighted). **Parameters:** - **HistMin** (*double*, default: `@qualityVMin`) — Lower bound of the histogram range. - **HistMax** (*double*, default: `@qualityVMax`) — Upper bound of the histogram range. - **areaWeighted** (*bool*, default: `False`) — If false, each bin reports the number of vertices in the range. If true, each bin reports the approximate mesh area associated with those values. - **binNum** (*int*, default: `20`) — The number of bins of the histogram. ``` --- (filter-compute-vertex-quality-stat)= ## Measure Vertex Scalar Statistics **Categories:** `Measurement/Statistics` **Plugin:** qmeshlab.filter.measure Compute aggregate statistics over per-vertex quality. ```{py:function} ms.compute_vertex_quality_stat(**params) :module: _qmeshlab Compute some aggregate statistics over the per vertex quality, like Min, Max, Average, StdDev and Variance. This filter has no parameters. ``` --- (filter-estimate-radius-from-density)= ## Estimate Radius from Density **Categories:** `Measurement/Statistics` **Plugin:** qmeshlab.filter.mls Estimate local point spacing for each vertex. ```{py:function} ms.estimate_radius_from_density(**params) :module: _qmeshlab Estimate the local point spacing (aka radius) around each vertex using a basic estimate of the local density. **Parameters:** - **NbNeighbors** (*int*, default: `16`) — Number of neighbors used to estimate the local density. Larger values lead to smoother variations. ``` --- (filter-compute-topological-measures)= ## Measure Topological Properties **Categories:** `Measurement/Topological` **Plugin:** qmeshlab.filter.measure Compute a set of topological measures over a mesh. ```{py:function} ms.compute_topological_measures(**params) :module: _qmeshlab This filter has no parameters. ``` --- (filter-compute-topological-measures-quad)= ## Measure Topological Properties for Quad Mesh **Categories:** `Measurement/Topological` **Plugin:** qmeshlab.filter.measure Compute a set of topological measures over a quad mesh. ```{py:function} ms.compute_topological_measures_quad(**params) :module: _qmeshlab This filter has no parameters. ``` --- (filter-get-info)= ## Measure Mesh Summary **Categories:** `Measurement/Topological` **Plugin:** qmeshlab.filter.basic Prints a compact summary for the current mesh. ```{py:function} ms.get_info(**params) :module: _qmeshlab Outputs vertex/edge/face counts and bounding-box metrics for the current mesh. **Parameters:** - **precision** (*int*, default: `3`) — Number of decimals used when formatting bounding-box metrics. ``` --- (filter-generate-boolean-difference)= ## Mesh Difference (libigl) **Categories:** `Meshing/Boolean` **Plugin:** qmeshlab.filter.igl Create the exact difference of two mesh layers using libigl and CGAL. ```{py:function} ms.generate_boolean_difference(**params) :module: _qmeshlab Executes an exact boolean difference between two mesh layers and creates the result as a new layer. The computation uses libigl's CGAL-backed mesh boolean implementation. The result is `First Mesh - Second Mesh`. Both operands should be watertight and consistently oriented. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) **Parameters:** - **first_mesh** (*mesh*, default: `@currentMeshIndex`) — First operand of the boolean operation. - **second_mesh** (*mesh*, default: `@otherMeshIndex`) — Second operand of the boolean operation. - **transfer_face_color** (*bool*, default: `False`) — Copy the birth face color to the result faces when available. - **transfer_face_quality** (*bool*, default: `False`) — Copy the birth face quality to the result faces when available. - **transfer_vert_color** (*bool*, default: `False`) — Copy birth vertex colors where possible and average neighboring source colors for newly created vertices. - **transfer_vert_quality** (*bool*, default: `False`) — Copy birth vertex qualities where possible and average neighboring source qualities for newly created vertices. ``` --- (filter-generate-boolean-difference-trueform)= ## Mesh Difference (TrueForm) **Categories:** `Meshing/Boolean` **Plugin:** qmeshlab.filter.trueform Exact boolean difference of two layers. ```{py:function} ms.generate_boolean_difference_trueform(**params) :module: _qmeshlab The first solid with the second removed from it. Order matters: swap the two layers to get the opposite difference.\n\nTrueForm evaluates booleans with **exact predicates**, so coplanar faces and near-degenerate intersections are decided consistently rather than by a tolerance. Both layers are taken in **world space**, so their layer matrices are applied first, and the result is added as a new layer with an identity matrix.\n\nThe libigl implementation of the same operation is also available and worth comparing on difficult input. **Parameters:** - **firstMesh** (*mesh*, default: `@currentMeshIndex`) — The first operand. - **secondMesh** (*mesh*, default: `@otherMeshIndex`) — The second operand. ``` --- (filter-generate-boolean-intersection)= ## Mesh Intersection (libigl) **Categories:** `Meshing/Boolean` **Plugin:** qmeshlab.filter.igl Create the exact intersection of two mesh layers using libigl and CGAL. ```{py:function} ms.generate_boolean_intersection(**params) :module: _qmeshlab Executes an exact boolean intersection between two mesh layers and creates the result as a new layer. The computation uses libigl's CGAL-backed mesh boolean implementation. Both operands should be watertight and consistently oriented. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) **Parameters:** - **first_mesh** (*mesh*, default: `@currentMeshIndex`) — First operand of the boolean operation. - **second_mesh** (*mesh*, default: `@otherMeshIndex`) — Second operand of the boolean operation. - **transfer_face_color** (*bool*, default: `False`) — Copy the birth face color to the result faces when available. - **transfer_face_quality** (*bool*, default: `False`) — Copy the birth face quality to the result faces when available. - **transfer_vert_color** (*bool*, default: `False`) — Copy birth vertex colors where possible and average neighboring source colors for newly created vertices. - **transfer_vert_quality** (*bool*, default: `False`) — Copy birth vertex qualities where possible and average neighboring source qualities for newly created vertices. ``` --- (filter-generate-boolean-intersection-trueform)= ## Mesh Intersection (TrueForm) **Categories:** `Meshing/Boolean` **Plugin:** qmeshlab.filter.trueform Exact boolean intersection of two layers. ```{py:function} ms.generate_boolean_intersection_trueform(**params) :module: _qmeshlab The intersection of two closed solids: only what lies inside both.\n\nTrueForm evaluates booleans with **exact predicates**, so coplanar faces and near-degenerate intersections are decided consistently rather than by a tolerance. Both layers are taken in **world space**, so their layer matrices are applied first, and the result is added as a new layer with an identity matrix.\n\nThe libigl implementation of the same operation is also available and worth comparing on difficult input. **Parameters:** - **firstMesh** (*mesh*, default: `@currentMeshIndex`) — The first operand. - **secondMesh** (*mesh*, default: `@otherMeshIndex`) — The second operand. ``` --- (filter-generate-boolean-union)= ## Mesh Union (libigl) **Categories:** `Meshing/Boolean` **Plugin:** qmeshlab.filter.igl Create the exact union of two mesh layers using libigl and CGAL. ```{py:function} ms.generate_boolean_union(**params) :module: _qmeshlab Executes an exact boolean union between two mesh layers and creates the result as a new layer. The computation uses libigl's CGAL-backed mesh boolean implementation. Both operands should be watertight and consistently oriented. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) **Parameters:** - **first_mesh** (*mesh*, default: `@currentMeshIndex`) — First operand of the boolean operation. - **second_mesh** (*mesh*, default: `@otherMeshIndex`) — Second operand of the boolean operation. - **transfer_face_color** (*bool*, default: `False`) — Copy the birth face color to the result faces when available. - **transfer_face_quality** (*bool*, default: `False`) — Copy the birth face quality to the result faces when available. - **transfer_vert_color** (*bool*, default: `False`) — Copy birth vertex colors where possible and average neighboring source colors for newly created vertices. - **transfer_vert_quality** (*bool*, default: `False`) — Copy birth vertex qualities where possible and average neighboring source qualities for newly created vertices. ``` --- (filter-generate-boolean-union-trueform)= ## Mesh Union (TrueForm) **Categories:** `Meshing/Boolean` **Plugin:** qmeshlab.filter.trueform Exact boolean union of two layers. ```{py:function} ms.generate_boolean_union_trueform(**params) :module: _qmeshlab The union of two closed solids: everything inside either one.\n\nTrueForm evaluates booleans with **exact predicates**, so coplanar faces and near-degenerate intersections are decided consistently rather than by a tolerance. Both layers are taken in **world space**, so their layer matrices are applied first, and the result is added as a new layer with an identity matrix.\n\nThe libigl implementation of the same operation is also available and worth comparing on difficult input. **Parameters:** - **firstMesh** (*mesh*, default: `@currentMeshIndex`) — The first operand. - **secondMesh** (*mesh*, default: `@otherMeshIndex`) — The second operand. ``` --- (filter-generate-boolean-xor)= ## Mesh Symmetric Difference (libigl) **Categories:** `Meshing/Boolean` **Plugin:** qmeshlab.filter.igl Create the exact symmetric difference of two mesh layers using libigl and CGAL. ```{py:function} ms.generate_boolean_xor(**params) :module: _qmeshlab Executes an exact boolean symmetric difference between two mesh layers and creates the result as a new layer. The computation uses libigl's CGAL-backed mesh boolean implementation. Both operands should be watertight and consistently oriented. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) **Parameters:** - **first_mesh** (*mesh*, default: `@currentMeshIndex`) — First operand of the boolean operation. - **second_mesh** (*mesh*, default: `@otherMeshIndex`) — Second operand of the boolean operation. - **transfer_face_color** (*bool*, default: `False`) — Copy the birth face color to the result faces when available. - **transfer_face_quality** (*bool*, default: `False`) — Copy the birth face quality to the result faces when available. - **transfer_vert_color** (*bool*, default: `False`) — Copy birth vertex colors where possible and average neighboring source colors for newly created vertices. - **transfer_vert_quality** (*bool*, default: `False`) — Copy birth vertex qualities where possible and average neighboring source qualities for newly created vertices. ``` --- (filter-generate-boolean-xor-trueform)= ## Mesh Symmetric Difference (TrueForm) **Categories:** `Meshing/Boolean` **Plugin:** qmeshlab.filter.trueform Exact boolean symmetric difference of two layers. ```{py:function} ms.generate_boolean_xor_trueform(**params) :module: _qmeshlab Everything inside exactly one of the two solids, and nothing inside both.\n\nTrueForm's boolean primitive offers union, intersection and difference but not this one, so it is evaluated through the CSG evaluator as `(A - B) | (B - A)`. The result is the same; only the route differs.\n\nTrueForm evaluates booleans with **exact predicates**, so coplanar faces and near-degenerate intersections are decided consistently rather than by a tolerance. Both layers are taken in **world space**, so their layer matrices are applied first, and the result is added as a new layer with an identity matrix.\n\nThe libigl implementation of the same operation is also available and worth comparing on difficult input. **Parameters:** - **firstMesh** (*mesh*, default: `@currentMeshIndex`) — The first operand. - **secondMesh** (*mesh*, default: `@otherMeshIndex`) — The second operand. ``` --- (filter-generate-csg-expression)= ## Mesh CSG Expression (TrueForm) **Categories:** `Meshing/Boolean` **Plugin:** qmeshlab.filter.trueform Evaluate a boolean expression over any number of layers in one exact pass. ```{py:function} ms.generate_csg_expression(**params) :module: _qmeshlab Evaluates an arbitrary constructive-solid-geometry expression over the document's layers, in a **single arrangement** rather than a chain of pairwise booleans. That matters for more than convenience: chaining booleans re-meshes and re-intersects at every step, accumulating error and cost, while one arrangement resolves all the surfaces together and classifies each region once.\n\n**Operands are layer numbers**, as shown in the layer panel. Operators, loosest-binding first:\n\n| Operator | Meaning |\n|---|---|\n| `\\|` | union |\n| `-` | difference |\n| `&` | intersection |\n| `~` | complement |\n\n`|` and `-` share the lowest precedence and associate to the left; `&` binds tighter; `~` binds tightest. Parentheses group.\n\nExamples:\n\n- `0 | 1 | 2` — the union of three layers\n- `(0 | 1) - 2` — two layers joined, then a third drilled out of them\n- `0 & ~1` — the part of layer 0 outside layer 1, i.e. the difference\n\nA layer may appear more than once; it becomes a single operand. Every referenced layer is taken in world space. **Parameters:** - **expression** (*string*, default: `0 | 1`) — A boolean expression over layer numbers, e.g. (0 | 1) - 2. Operators: | union, - difference, & intersection, ~ complement. ``` --- (filter-delete-all-faces)= ## Remove All Faces **Categories:** `Meshing/Deletion` **Plugin:** qmeshlab.filter.select Delete all faces, turning mesh into point cloud. ```{py:function} ms.delete_all_faces(**params) :module: _qmeshlab Delete ALL faces, turning the mesh into a pointcloud. This filter has no parameters. ``` --- (filter-delete-selected-faces)= ## Remove Selected Faces **Categories:** `Meshing/Deletion` **Plugin:** qmeshlab.filter.select Delete selected faces; unreferenced vertices are not deleted. ```{py:function} ms.delete_selected_faces(**params) :module: _qmeshlab Delete the current set of selected faces, vertices that remains unreferenced are not deleted. This filter has no parameters. ``` --- (filter-delete-selected-faces-and-vertices)= ## Remove Selected Faces and Vertices **Categories:** `Meshing/Deletion` **Plugin:** qmeshlab.filter.select Delete selected faces and enclosed selected vertices. ```{py:function} ms.delete_selected_faces_and_vertices(**params) :module: _qmeshlab Delete the current set of selected faces and all the vertices surrounded by that faces. This filter has no parameters. ``` --- (filter-delete-selected-vertices)= ## Remove Selected Vertices **Categories:** `Meshing/Deletion` **Plugin:** qmeshlab.filter.select Delete selected vertices; incident faces are deleted too. ```{py:function} ms.delete_selected_vertices(**params) :module: _qmeshlab Delete the current set of selected vertices; faces that share one of the deleted vertices are deleted too. This filter has no parameters. ``` --- (filter-convert-to-quad-dominant)= ## Convert to Quad-Dominant Mesh **Categories:** `Meshing/Quad` **Plugin:** qmeshlab.filter.meshing Convert tri mesh to quad-dominant mesh. ```{py:function} ms.convert_to_quad_dominant(**params) :module: _qmeshlab Convert a tri-mesh into a quad-dominant mesh by pairing suitable triangles. **Parameters:** - **level** (*enum*, default: `fewest`) — Greedy strategy. ``` --- (filter-convert-to-triangular)= ## Convert to Pure Triangles **Categories:** `Meshing/Quad` **Plugin:** qmeshlab.filter.meshing Split any polygonal face into triangles. ```{py:function} ms.convert_to_triangular(**params) :module: _qmeshlab Convert into a tri-mesh by splitting any polygonal face. This filter has no parameters. ``` --- (filter-tri-to-quad-4-8-subdivision)= ## Convert to Quads by 4-8 Subdivision **Categories:** `Meshing/Quad` **Plugin:** qmeshlab.filter.meshing Convert tri mesh into quad mesh by 4-8 subdivision. ```{py:function} ms.tri_to_quad_4_8_subdivision(**params) :module: _qmeshlab Convert a tri mesh into a quad mesh by applying a 4-8 subdivision scheme.It introduces less overhead than the plain Catmull-Clark Subdivision Surfaces, and applying two step of this procedure generates the same connectivity of the Catmull-Clark subdivision approach.(it adds only a single vertex for each triangle instead of four).
See:
4-8 Subdivision
Luiz Velho, Denis Zorin
CAGD, volume 18, Issue 5, Pages 397-427. This filter has no parameters. ``` --- (filter-tri-to-quad-by-pairing)= ## Convert to Quads by Triangle Pairing **Categories:** `Meshing/Quad` **Plugin:** qmeshlab.filter.meshing Pair triangles into quads. ```{py:function} ms.tri_to_quad_by_pairing(**params) :module: _qmeshlab Converts a triangle mesh into a quad mesh by merging pairs of adjacent triangles. Pairs are chosen by **quad quality** -- how close to a square the merged pair would be -- so the diagonals that were introduced when a quad mesh was triangulated are the ones removed again. Triangles that no good partner leaves over are then resolved by edge flipping, which can reach a pure quad mesh at the cost of some quality; if any remain unpaired the result is quad dominant and the filter says so. An odd triangle count cannot become pure quads, so one triangle is split first to make the count even. This filter has no parameters. ``` --- (filter-cut-along-scalar-isocontour)= ## Cut Along Scalar Isocontour (TrueForm) **Categories:** `Meshing/Remeshing` **Plugin:** qmeshlab.filter.trueform Split the surface along contours of the vertex scalar field. ```{py:function} ms.cut_along_scalar_isocontour(**params) :module: _qmeshlab Cuts the surface along evenly spaced contours of the **per-vertex scalar field**, so the band between each pair of successive contour values becomes its own set of faces, with real edges along the boundaries.\n\nWhere *Create Polyline from Scalar Isocontour (TrueForm)* draws the contour lines, this one cuts the mesh at them: the bands are geometry, so they can be coloured separately, split into layers, exported, or measured. Contour a height field and you get terraces; contour a geodesic distance and you get rings you can separate.\n\nEvery band is kept, so the result is the whole surface cut up rather than a filtered part of it.\n\nCompute a scalar first — a constant field has nothing to cut along, and the filter says so. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The layer whose scalar field is cut along. - **contourCount** (*int*, default: `5`) — How many evenly spaced contours to cut at. N contours give N+1 bands. ``` --- (filter-cut-mesh-along-crease-edges)= ## Cut Along Crease Edges **Categories:** `Meshing/Remeshing` **Plugin:** qmeshlab.filter.unsharp Split the mesh along sharp edges. ```{py:function} ms.cut_mesh_along_crease_edges(**params) :module: _qmeshlab Cut the mesh along crease edges, duplicating the vertices as necessary. Crease (or sharp) edges are defined according to the variation of normal of the adjacent faces. **Parameters:** - **angleDeg** (*double*, default: `90.0`) — If the angle between adjacent face normals is larger than this threshold, the edge is treated as a crease and the mesh is cut along it. ``` --- (filter-improve-triangulation-trueform)= ## Remesh by Edge Flipping (TrueForm) **Categories:** `Meshing/Remeshing` **Plugin:** qmeshlab.filter.trueform Improve triangle shape by flipping edges and relaxing vertices, without changing the vertex count. ```{py:function} ms.improve_triangulation_trueform(**params) :module: _qmeshlab Alternates rounds of **edge flipping** and **tangential relaxation** to improve triangle quality. Connectivity and vertex positions both change, but no vertex is added or removed — so this refines a tessellation you want to keep the size of, where *Remesh Isotropically* would rebuild it.\n\nThe two steps depend on each other, which is why they interleave: a flip creates room for a vertex to move somewhere useful, and a moved vertex makes a different flip worthwhile.\n\n**Objective** decides which flips are taken:\n\n| Objective | Effect |\n|---|---|\n| Valence | evens out how many edges meet at each vertex, giving a regular-looking mesh |\n| Minimum angle | maximises the smallest angle, attacking slivers directly |\n\nUse *Valence* for a tidy mesh, *Minimum angle* when thin triangles are causing numerical trouble.\n\n**Relaxation** moves each vertex along the surface towards its neighbours' centroid; **Lambda** is how far. Set **Max Deviation** above zero to bound how far the surface may drift from its starting shape — worth doing when the geometry matters more than the triangles.\n\n**Check Normals** rejects any flip or move that would fold a triangle over. Leave it on unless you know the mesh is well behaved.\n\nCompeting implementations: *Flip Edges by Curvature* and *Flip Edges by Planarity* do the flipping half with vcglib, driven by different objectives; the vcglib *Smooth* filters do the relaxation half. This does both together. **Parameters:** - **objective** (*enum*, default: `valence`) — What the edge flips optimise for. - **iterations** (*int*, default: `3`) — How many flip-then-relax rounds to run. - **relaxationIterations** (*int*, default: `3`) — Relaxation passes inside each round. Zero flips without moving anything. - **lambda** (*double*, default: `0.5`) — How far relaxation moves a vertex towards its neighbours, 0 to 1. - **maxDeviation** (*absperc*, default: `0.0`) — Largest distance the surface may drift from its starting shape. Zero leaves relaxation unbounded. - **checkNormals** (*bool*, default: `True`) — Reject flips and moves that would fold a triangle over. ``` --- (filter-meshing-edge-flip-by-curvature-optimization)= ## Flip Edges by Curvature **Categories:** `Meshing/Remeshing` **Plugin:** qmeshlab.filter.trioptimize Optimize local triangulation by reducing discrete curvature. ```{py:function} ms.meshing_edge_flip_by_curvature_optimization(**params) :module: _qmeshlab Mesh optimization by edge flipping to improve local mesh curvature. The method evaluates edge flips with discrete curvature metrics and applies flips that reduce the local curvature measure. **Parameters:** - **selection** (*bool*, default: `@hasSelectedFaces`) — If enabled, optimize only selected faces. - **pthreshold** (*double*, default: `1.0`) — Only face pairs with a dihedral angle larger than this threshold are considered for curvature optimization. - **curvtype** (*enum*, default: `mean`) — Metric used to evaluate curvature reduction before and after a flip. ``` --- (filter-meshing-edge-flip-by-planar-optimization)= ## Flip Edges by Planarity **Categories:** `Meshing/Remeshing` **Plugin:** qmeshlab.filter.trioptimize Optimize local triangle quality by flipping nearly coplanar edges. ```{py:function} ms.meshing_edge_flip_by_planar_optimization(**params) :module: _qmeshlab Mesh optimization by edge flipping, improving local triangle quality for face pairs whose dihedral angle is below the planar threshold. A small surface-preserving Laplacian relaxation can be run after the flip pass. **Parameters:** - **selection** (*bool*, default: `@hasSelectedFaces`) — If enabled, optimize only selected faces. - **pthreshold** (*double*, default: `1.0`) — Only adjacent faces whose dihedral angle is below this threshold are considered for planar optimization. - **planartype** (*enum*, default: `area_max_side`) — Metric used to rank planar edge flips. - **iterations** (*int*, default: `1`) — Number of surface-preserving planar Laplacian smoothing iterations performed after the flip pass. ``` --- (filter-remesh-to-quads-instant-meshes)= ## Remesh to Quads (Instant Meshes) **Categories:** `Meshing/Remeshing` **Plugin:** qmeshlab.filter.instant_meshes Generate an isotropic, field-aligned quad or quad-dominant mesh with Instant Meshes. ```{py:function} ms.remesh_to_quads_instant_meshes(**params) :module: _qmeshlab Runs the original **Instant Field-Aligned Meshes** pipeline by Jakob et al. The method builds a multiresolution hierarchy, optimizes a four-fold rotational orientation field and a compatible position field, then extracts a new surface whose edges follow those fields. It is a local, parallel method designed to scale linearly with input size. The result is created as a new geometry-only layer. QMeshLab stores each generated quad as two triangles connected by a VCGLib faux edge, preserving polygonal rendering and saving. Vertex attributes, selections, materials and textures are not transferred. **Pure quads** subdivides irregular extracted faces to obtain only quads; **quad dominant** retains exceptional triangles. The target edge length is approximate because extraction is driven by the optimized fields. **Upstream:** [Instant Meshes](https://github.com/wjakob/instant-meshes) **License:** BSD-3-Clause **References:** - Wenzel Jakob, Marco Tarini, Daniele Panozzo, Olga Sorkine-Hornung. **Instant Field-Aligned Meshes**. *ACM Transactions on Graphics* (2015). [DOI](https://doi.org/10.1145/2816795.2818078) [Web](https://igl.ethz.ch/projects/instant-meshes/) **Parameters:** - **targetEdgeLength** (*absperc*, default: `@bboxDiag01`) — Approximate world-space edge length of the generated mesh. - **outputTopology** (*enum*, default: `pure_quads`) — Pure quads subdivides exceptional faces; quad dominant permits triangles around irregular regions. - **detectCreases** (*bool*, default: `False`) — Split normals at sufficiently sharp input edges so the generated field follows them. - **creaseAngle** (*double*, default: `30.0`) — Dihedral-angle threshold used when sharp-crease detection is enabled. - **alignBoundaries** (*bool*, default: `False`) — Constrain the orientation and position fields to open mesh boundaries. - **optimizationSpace** (*enum*, default: `extrinsic`) — Extrinsic optimization uses embedded 3D directions; intrinsic optimization transports directions over the surface. - **smoothingIterations** (*int*, default: `2`) — Post-extraction smoothing iterations with projection back to the input surface. Zero disables smoothing and BVH construction. - **deterministic** (*bool*, default: `False`) — Prefer reproducible graph construction and ordering at some performance cost. - **threads** (*int*, default: `0`) — Maximum oneTBB parallelism. Zero uses the runtime default. ``` --- (filter-remesh-to-quads-quadwild-bimdf)= ## Remesh to Quads (QuadWild-BiMDF) **Categories:** `Meshing/Remeshing` **Plugin:** qmeshlab.filter.quadwild Generate a feature-aligned pure-quad mesh with QuadWild and its open-source Bi-MDF quantizer. ```{py:function} ms.remesh_to_quads_quadwild_bimdf(**params) :module: _qmeshlab Runs the original **QuadWild** feature-line-driven remeshing pipeline, using the open-source **Bi-MDF** solver from the cgg-bern fork instead of the commercial Gurobi solver. The method computes a feature-aligned cross field, traces a coarse patch layout that may contain T-junctions and non-quadrilateral patches, and quantizes and tessellates that layout into a conforming pure-quad mesh. QMeshLab invokes the two unmodified upstream helper executables in an isolated temporary directory. Their crashes and process-level exits therefore cannot terminate QMeshLab. The result is imported through VCGLib: each quad becomes two triangles joined by a faux edge, preserving polygonal rendering and saving. Geometry is created in a new layer with the input layer transform; input attributes, selections, textures and materials are not transferred. **Feature-aware** detects creases above 35 degrees and is intended for mechanical or CAD-like surfaces. **Organic** disables automatic sharp-feature detection. **Output scale** is QuadWild's dimensionless `scaleFact`: larger values generate larger, fewer quads. This is an expensive global algorithm and can take substantial time on complex meshes. **Upstream:** [QuadWild-BiMDF](https://github.com/cgg-bern/quadwild-bimdf) **License:** GPL-3.0-or-later **References:** - Nico Pietroni, Stefano Nuvoli, Thomas Alderighi, Paolo Cignoni, Marco Tarini. **Reliable Feature-Line Driven Quad-Remeshing**. *ACM Transactions on Graphics* (2021). [DOI](https://doi.org/10.1145/3450626.3459941) [Web](https://www.quadmesh.cloud/) - Martin Heistermann, Jethro Warnett, David Bommes. **Min-Deviation-Flow in Bi-directed Graphs for T-Mesh Quantization**. *ACM Transactions on Graphics* (2023). [DOI](https://doi.org/10.1145/3592437) [Web](https://www.algohex.eu/publications/bimdf-quantization) **Parameters:** - **surfacePreset** (*enum*, default: `feature_aware`) — Feature-aware detects sharp creases; Organic treats the surface as smooth. - **outputScale** (*double*, default: `1.0`) — Dimensionless QuadWild scale factor. Larger values produce larger and fewer quads. - **alignSingularities** (*bool*, default: `True`) — Encourage irregular vertices to align across the patch layout. - **smoothOutput** (*bool*, default: `True`) — Import QuadWild's surface-projected smoothed result instead of the unsmoothed quadrangulation. ``` --- (filter-remeshing-isotropic)= ## Remesh Isotropically (vcglib) **Categories:** `Meshing/Remeshing` **Plugin:** qmeshlab.filter.meshing Explicit isotropic remeshing by local operations. ```{py:function} ms.remeshing_isotropic(**params) :module: _qmeshlab Perform a explicit remeshing of a triangular mesh, by repeatedly applying edge flip, collapse, relax and refine operations to regularize size and aspect ration of the triangular meshing. Loosely inspired to:
Hugues Hoppe, Tony DeRose, Tom Duchamp, John McDonald, and Werner Stuetzle.
Mesh optimization
(SIGGRAPH '93). ACM, New York, NY, USA, 19–26. DOI **Parameters:** - **Iterations** (*int*, default: `10`) — Number of remeshing iterations. - **Adaptive** (*bool*, default: `False`) — Toggle adaptive isotropic remeshing. - **SelectedOnly** (*bool*, default: `False`) — Apply remeshing only to selected faces. - **TargetLen** (*absperc*, default: `@bboxDiag01`) — Target length for remeshed edges. - **FeatureDeg** (*double*, default: `30.0`) — Minimum angle to treat an edge as feature. - **CheckSurfDist** (*bool*, default: `False`) — Each operation must satisfy max surface distance. - **MaxSurfDist** (*absperc*, default: `@bboxDiag01`) — Maximum allowed local surface deviation. - **ReferenceMesh** (*mesh*, default: `@currentMeshIndex`) — Mesh used for surface-distance checks and reprojection. The current mesh preserves the original behavior; choosing another layer checks/remeshes against that layer, respecting both mesh transforms. - **SplitFlag** (*bool*, default: `True`) — Include refine step. - **CollapseFlag** (*bool*, default: `True`) — Include collapse step. - **SwapFlag** (*bool*, default: `True`) — Include edge-swap step. - **SmoothFlag** (*bool*, default: `True`) — Include smoothing step. - **ReprojectFlag** (*bool*, default: `True`) — Include projection step. ``` --- (filter-remeshing-isotropic-trueform)= ## Remesh Isotropically (TrueForm) **Categories:** `Meshing/Remeshing` **Plugin:** qmeshlab.filter.trueform Rebuild the tessellation with triangles of a uniform target edge length. ```{py:function} ms.remeshing_isotropic_trueform(**params) :module: _qmeshlab Rebuilds the tessellation so triangles approach a uniform size and shape, by splitting long edges, collapsing short ones, flipping to improve valence and relaxing vertices along the surface.\n\n**Target Edge Length** is the size aimed for. **Iterations** is how many split/collapse/flip/relax rounds run; **Relaxation Iterations** the tangential smoothing passes inside each round.\n\n**Feature Angle** protects sharp edges: any dihedral angle above it is treated as a crease and preserved rather than smoothed away. It is off by default (negative), which is right for organic surfaces and wrong for anything with intended hard edges.\n\nCompeting implementation: *Remesh Isotropically* does the same with vcglib. TrueForm's is parallelised and has the explicit feature and boundary contracts above. **Parameters:** - **targetLength** (*absperc*, default: `@bboxDiag01`) — The edge length the remesher aims for. - **iterations** (*int*, default: `3`) — How many remeshing rounds to run. - **relaxationIterations** (*int*, default: `3`) — Tangential smoothing passes within each round. - **preserveBoundary** (*bool*, default: `True`) — Hold boundary edges fixed. Turn off only if the border is allowed to move. - **featureAngle** (*double*, default: `-1.0`) — Dihedral angle above which an edge counts as a sharp feature and is protected. Negative disables feature detection. ``` --- (filter-resample-uniform)= ## Remesh Uniformly by Volumetric Resampling **Categories:** `Meshing/Remeshing` **Plugin:** qmeshlab.filter.sampling Build an offset mesh from a signed distance field sampled on a regular grid. ```{py:function} ms.resample_uniform(**params) :module: _qmeshlab Create a new mesh that is a resampled version of the current one.
The resampling is done by building a uniform volumetric representation where each voxel contains the signed distance from the original surface. The resampled surface is reconstructed using the marching cube algorithm over this volume. **Parameters:** - **CellSize** (*absperc*, default: `@bboxDiag01`) — Sampling cell size. Smaller cells give more precise results at higher cost. - **Offset** (*absperc*, default: `0.0`) — Offset of the extracted surface relative to the original mesh. - **mergeCloseVert** (*bool*, default: `False`) — Merge nearly coincident vertices in the generated mesh. - **discretize** (*bool*, default: `False`) — Use fixed edge midpoints instead of linear interpolation for a stair-step appearance. - **multisample** (*bool*, default: `False`) — Compute the distance field more accurately by multisampling the volume. - **absDist** (*bool*, default: `False`) — Use an unsigned distance field to create an inner and outer shell around the input mesh. ``` --- (filter-meshing-decimation-edge-collapse-for-marching-cube-meshes)= ## Simplify Marching-Cubes Mesh by Edge Collapse **Categories:** `Meshing/Simplification` **Plugin:** qmeshlab.filter.plymc Simplify only meshes generated by Marching Cubes, preserving the grid structure. ```{py:function} ms.meshing_decimation_edge_collapse_for_marching_cube_meshes(**params) :module: _qmeshlab A simplification/cleaning algorithm that works only on meshes generated by Marching Cubes. It detects the grid spacing automatically and collapses redundant edges while preserving the bounding box. **Parameters:** - **cellError** (*double*, default: `0.25`) — Collapse error in MC cell units. 0.25 = 1/4 of a cell side (original default). 1.0 = 1 full cell side (more aggressive). 0.0 = auto (same as 0.25). - **preserveBB** (*bool*, default: `False`) — If true, vertices on the bounding box are not collapsed. - **flipThreshold** (*double*, default: `10.0`) — T-vertex removal aggressiveness. Higher = more removal. Default 10. A vertex within 1/threshold of the edge length is considered a T-vertex. ``` --- (filter-simplification-by-decimation-trueform)= ## Simplify by Decimation (TrueForm) **Categories:** `Meshing/Simplification` **Plugin:** qmeshlab.filter.trueform Reduce the triangle count to a target fraction of the original. ```{py:function} ms.simplification_by_decimation_trueform(**params) :module: _qmeshlab Collapses edges until the face count reaches the requested **fraction of the original**, choosing collapses by geometric error so detail is given up where it costs least.\n\nA proportion rather than an absolute count, so the filter behaves the same on any input and can be applied repeatedly: 0.5 halves the mesh each time.\n\nUse *Simplify by Error Bound (TrueForm)* when fidelity matters more than the resulting size.\n\nCompeting implementation: see also the quadric edge collapse filters under *Meshing/Simplification*. **Parameters:** - **targetProportion** (*double*, default: `0.5`) — Fraction of the original face count to keep. 0.5 halves the mesh. - **preserveBoundary** (*bool*, default: `True`) — Hold boundary edges fixed. Turn off only if the border is allowed to move. - **featureAngle** (*double*, default: `-1.0`) — Dihedral angle above which an edge counts as a sharp feature and is protected. Negative disables feature detection. ``` --- (filter-simplification-by-error-trueform)= ## Simplify by Error Bound (TrueForm) **Categories:** `Meshing/Simplification` **Plugin:** qmeshlab.filter.trueform Reduce triangle count as far as a geometric error bound allows. ```{py:function} ms.simplification_by_error_trueform(**params) :module: _qmeshlab Collapses edges for as long as the surface stays within an **error bound**, rather than towards a face count. That is the useful difference from the other simplifiers here: you state the fidelity you will accept and get however few triangles that permits, instead of stating a triangle count and discovering the error afterwards.\n\n**Error Bound** is a distance. Type it directly in model units when you know the tolerance you have to hold -- a measurement accuracy, a printing tolerance -- or switch the field to a percentage of the bounding-box diagonal when you want the same value to mean the same thing across models of different scales. The default is 0.1% of the diagonal, which is conservative.\n\nUse *Simplify by Decimation (TrueForm)* when you need a specific face count instead. **Parameters:** - **errorBound** (*absperc*, default: `@bboxDiag001`) — Largest geometric deviation allowed. Enter it directly in model units, or as a percentage of the bounding-box diagonal. - **iterations** (*int*, default: `1`) — How many simplification passes to run. - **preserveBoundary** (*bool*, default: `True`) — Hold boundary edges fixed. Turn off only if the border is allowed to move. - **featureAngle** (*double*, default: `-1.0`) — Dihedral angle above which an edge counts as a sharp feature and is protected. Negative disables feature detection. ``` --- (filter-simplification-clustering)= ## Simplify by Vertex Clustering **Categories:** `Meshing/Simplification` **Plugin:** qmeshlab.filter.meshing Simplify mesh by clustering vertices on a grid. ```{py:function} ms.simplification_clustering(**params) :module: _qmeshlab Simplify the mesh by clustering vertices; by using a uniform grid over the mesh, the algorithm merges all the vertices in a grid cell into a single vertex. By design this approach removes all small triangles, but also create a number of non-manifold situation.
See:

Jarek Rossignac, and Paul Borrel.
Multi-resolution 3D approximations for rendering complex scenes.
Modeling in computer graphics: methods and applications. Springer, 1993 **Parameters:** - **Threshold** (*absperc*, default: `@bboxDiag01`) — Cell size of clustering grid. ``` --- (filter-simplification-quadric-edge-collapse)= ## Simplify by Quadric Edge Collapse (vcglib) **Categories:** `Meshing/Simplification` **Plugin:** qmeshlab.filter.meshing Simplify using quadric-based edge-collapse. ```{py:function} ms.simplification_quadric_edge_collapse(**params) :module: _qmeshlab Simplifies a mesh with VCGLib's quadric edge-collapse implementation, a variant of the Garland–Heckbert algorithm with additional weighting schemes for poorly shaped faces and planar or degenerate regions. This filter uses VCGLib and remains distinct from the separately available **Original QSlim Quadric Edge Collapse** filter, which compiles Garland's original `MxEdgeQSlim` implementation. **References:** - Michael Garland, Paul S. Heckbert. **Surface Simplification Using Quadric Error Metrics**. *Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (SIGGRAPH '97)* (1997). [DOI](https://doi.org/10.1145/258734.258849) [Web](https://github.com/alecjacobson/qslim) **Parameters:** - **TargetFaceNum** (*int*, default: `@selOrFaceCountHalf`) — Desired final number of faces. - **TargetPerc** (*double*, default: `0.0`) — Desired final size as percentage of initial size. - **QualityThr** (*double*, default: `0.3`) — Quality threshold for penalizing bad shaped faces. - **PreserveBoundary** (*bool*, default: `False`) — Try to preserve mesh boundaries. - **BoundaryWeight** (*double*, default: `1.0`) — Boundary importance during simplification. - **PreserveNormal** (*bool*, default: `False`) — Try to avoid face flipping effects. - **PreserveTopology** (*bool*, default: `False`) — Avoid collapses causing topology changes. - **OptimalPlacement** (*bool*, default: `True`) — Place collapsed vertices minimizing quadric error. - **PlanarQuadric** (*bool*, default: `False`) — Additional constraints preserving planar areas. - **PlanarWeight** (*double*, default: `0.001`) — Weight for preserving planar regions. - **QualityWeight** (*bool*, default: `False`) — Use per-vertex quality as weighting factor. - **AutoClean** (*bool*, default: `True`) — Run cleaning after simplification. - **Selected** (*bool*, default: `@hasSelectedFaces`) — Apply simplification only to selected faces. ``` --- (filter-simplification-quadric-edge-collapse-qslim)= ## Simplify by Quadric Edge Collapse (QSlim) **Categories:** `Meshing/Simplification` **Plugin:** qmeshlab.filter.qslim Simplify a triangle mesh with Garland's original QSlim implementation. ```{py:function} ms.simplification_quadric_edge_collapse_qslim(**params) :module: _qmeshlab Runs the original `MxEdgeQSlim` edge-contraction implementation from Michael Garland's MixKit, preserved through the pinned [QSlim 2.1 repository](https://github.com/alecjacobson/qslim). This is a separate implementation from QMeshLab's VCGLib quadric decimator, allowing results and historical behavior to be compared directly. QSlim's placement and weighting policies, boundary constraint weight, compactness threshold, and meshing penalty are exposed using their original meanings. The result is created as a new geometry-only layer and preserves the input layer transform. Vertex and face attributes, materials, textures, selections, and polygonal edge markings are not transferred. The original core has no cancellation or fine-grained progress API, so only phase-level progress is available. **Upstream:** [QSlim 2.1 (original MixKit implementation)](https://github.com/alecjacobson/qslim) **License:** LGPL-2.0-or-later with MixKit static-linking exception **References:** - Michael Garland, Paul S. Heckbert. **Surface Simplification Using Quadric Error Metrics**. *Proceedings of the 24th Annual Conference on Computer Graphics and Interactive Techniques (SIGGRAPH '97)* (1997). [DOI](https://doi.org/10.1145/258734.258849) [Web](https://github.com/alecjacobson/qslim) **Parameters:** - **TargetFaceNum** (*int*, default: `@faceCountHalf`) — Desired final number of faces. - **PlacementPolicy** (*enum*, default: `optimal`) — Original QSlim placement policy for the vertex produced by an edge contraction. - **WeightingPolicy** (*enum*, default: `area`) — Original QSlim policy used to weight face quadrics. - **BoundaryWeight** (*double*, default: `1000.0`) — Weight of the original QSlim boundary-preserving constraint. Zero disables it. - **CompactnessRatio** (*double*, default: `0.0`) — Minimum local triangle compactness accepted by QSlim. Zero disables this penalty. - **MeshingPenalty** (*double*, default: `1.0`) — Scale applied to QSlim's local validity, compactness, inversion, and degree penalties. ``` --- (filter-simplification-quadric-edge-collapse-with-texture)= ## Simplify by Quadric Edge Collapse with Texture (vcglib) **Categories:** `Meshing/Simplification`, `Texture` **Plugin:** qmeshlab.filter.meshing Simplify textured meshes preserving UVs. ```{py:function} ms.simplification_quadric_edge_collapse_with_texture(**params) :module: _qmeshlab Simplifies a textured mesh with VCGLib's attribute-aware quadric edge-collapse implementation while preserving its UV parameterization. This follows the Garland–Heckbert extension of quadric error metrics to material attributes. **References:** - Michael Garland, Paul S. Heckbert. **Simplifying Surfaces with Color and Texture using Quadric Error Metrics**. *Proceedings of IEEE Visualization '98* (1998). [DOI](https://doi.org/10.1109/VISUAL.1998.745312) [Web](https://mgarland.org/papers/quadric2.pdf) **Parameters:** - **TargetFaceNum** (*int*, default: `@selOrFaceCountHalf`) — Desired final number of faces. - **TargetPerc** (*double*, default: `0.0`) — Desired final size as percentage of initial size. - **QualityThr** (*double*, default: `0.3`) — Quality threshold for penalizing bad shaped faces. - **Extratcoordw** (*double*, default: `1.0`) — Additional weight for extra texture coordinates. - **PreserveBoundary** (*bool*, default: `False`) — Try to preserve mesh boundaries. - **BoundaryWeight** (*double*, default: `1.0`) — Boundary importance during simplification. - **OptimalPlacement** (*bool*, default: `True`) — Place collapsed vertices minimizing quadric error. - **PreserveNormal** (*bool*, default: `False`) — Try to avoid face flipping effects. - **PlanarQuadric** (*bool*, default: `False`) — Additional constraints preserving planar areas. - **Selected** (*bool*, default: `@hasSelectedFaces`) — Apply simplification only to selected faces. ``` --- (filter-simplify-point-cloud)= ## Simplify Point Cloud **Categories:** `Meshing/Simplification` **Plugin:** qmeshlab.filter.sampling Simplify a point cloud with Poisson-disk pruning. ```{py:function} ms.simplify_point_cloud(**params) :module: _qmeshlab Create a new layer populated with a simplified version of the current point cloud. The simplification is performed by subsampling the original point cloud using a Poisson Disk strategy using the algorithm described in:
'Efficient and Flexible Sampling with Blue Noise Properties of Triangular Meshes'
Massimiliano Corsini, Paolo Cignoni, Roberto Scopigno
IEEE TVCG 2012 **Parameters:** - **SampleNum** (*int*, default: `1000`) — Desired number of samples. Ignored if an explicit radius is provided. - **Radius** (*absperc*, default: `0.0`) — If non-zero, overrides the sample number and uses this radius directly. - **BestSampleFlag** (*bool*, default: `True`) — Use a heuristic to improve the maximality of the chosen sample set. - **BestSamplePool** (*int*, default: `10`) — Number of candidate attempts used when the best-sample heuristic is enabled. - **ExactNumFlag** (*bool*, default: `False`) — Search for a radius that matches the requested number of samples within the given tolerance. - **ExactNumTolerance** (*double*, default: `0.005`) — Tolerance used by precise sample count search, expressed as a fraction of the requested sample count. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the surviving subset of points exactly reproducible. ``` --- (filter-refine-user-defined)= ## Refine by User Expression **Categories:** `Meshing/Subdivision` **Plugin:** qmeshlab.filter.expression Refines edges selected by an expression and places split points by expressions. ```{py:function} ms.refine_user_defined(**params) :module: _qmeshlab Refine current mesh with user defined parameters.
Specify a Boolean Function needed to select which edges will be cut for refinement purpose.
Each edge is identified with first and second vertex.
Arguments accepted are first and second vertex attributes:
**Parameters:** - **condSelect** (*string*, default: `(q0 >= 0 && q1 >= 0)`) — Boolean expression used to decide whether an edge is refined. - **x** (*string*, default: `(x0+x1)/2`) — Expression for X output. - **y** (*string*, default: `(y0+y1)/2`) — Expression for Y output. - **z** (*string*, default: `(z0+z1)/2`) — Expression for Z output. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-subdivision-butterfly)= ## Subdivide by Butterfly **Categories:** `Meshing/Subdivision` **Plugin:** qmeshlab.filter.meshing Apply Butterfly subdivision. ```{py:function} ms.subdivision_butterfly(**params) :module: _qmeshlab Apply Butterfly Subdivision Surface algorithm. It is an interpolated refinement method, defined on arbitrary triangular meshes. The scheme is known to be C1 but not C2 on regular meshes
**Parameters:** - **Iterations** (*int*, default: `3`) — Number of times the model is subdivided. - **Threshold** (*absperc*, default: `@bboxDiag01`) — All edges longer than this threshold are refined. - **Selected** (*bool*, default: `@hasSelectedFaces`) — If selected the filter affects only selected faces. ``` --- (filter-subdivision-catmull-clark)= ## Subdivide by Catmull-Clark **Categories:** `Meshing/Subdivision` **Plugin:** qmeshlab.filter.meshing Apply Catmull-Clark subdivision. ```{py:function} ms.subdivision_catmull_clark(**params) :module: _qmeshlab Apply a number of iteration of the classical Catmull-Clark Subdivision Surfaces. If the mesh is triangle based (no faux edges) it generates a quad mesh, otherwise it honores it the faux-edge bits **Parameters:** - **Iterations** (*int*, default: `2`) — Number of times model is subdivided. ``` --- (filter-subdivision-doo-sabin)= ## Subdivide by Doo-Sabin **Categories:** `Meshing/Subdivision` **Plugin:** qmeshlab.filter.meshing Apply Doo-Sabin subdivision. ```{py:function} ms.subdivision_doo_sabin(**params) :module: _qmeshlab Apply the DooSabin Subdivision Surfaces. It is a Dual approximating refinement scheme that creates a new face for each vertex, edge and face. On a pure quad mesh it will add non quad face for each extraordinarhy vertex in the mesh (e.g. in a cube it will add a triangular face for each corner. On the other hand after a refinement step all the vertices will have degree 4. **Parameters:** - **Iterations** (*int*, default: `2`) — Number of times model is subdivided. ``` --- (filter-subdivision-loop)= ## Subdivide by Loop **Categories:** `Meshing/Subdivision` **Plugin:** qmeshlab.filter.meshing Apply Loop subdivision. ```{py:function} ms.subdivision_loop(**params) :module: _qmeshlab Apply Loop's Subdivision Surface algorithm. It is an approximant refinement method and it works for every triangle and has rules for extraordinary vertices.
**Parameters:** - **LoopWeight** (*enum*, default: `loop`) — Change the weights used. Allows one to optimize some behaviors over others. - **Iterations** (*int*, default: `3`) — Number of times the model is subdivided. - **Threshold** (*absperc*, default: `@bboxDiag01`) — All edges longer than this threshold are refined. Zero means uniform refinement. - **Selected** (*bool*, default: `@hasSelectedFaces`) — If selected the filter affects only selected faces. ``` --- (filter-subdivision-ls3-loop)= ## Subdivide by LS3 Loop **Categories:** `Meshing/Subdivision` **Plugin:** qmeshlab.filter.meshing Apply LS3 Loop subdivision. ```{py:function} ms.subdivision_ls3_loop(**params) :module: _qmeshlab Apply LS3 Subdivision Surface algorithm using Loop's weights. This refinement method take normals into account.
See:Boye', S. Guennebaud, G. & Schlick, C.
Least squares subdivision surfaces
Computer Graphics Forum, 2010.

Alternatives weighting schemes are based on the paper: Barthe, L. & Kobbelt, L.
Subdivision scheme tuning around extraordinary vertices
Computer Aided Geometric Design, 2004, 21, 561-583.
The current implementation of these schemes don't handle vertices of valence > 12 **Parameters:** - **LoopWeight** (*enum*, default: `loop`) — Change the weights used. - **Iterations** (*int*, default: `3`) — Number of times the model is subdivided. - **Threshold** (*absperc*, default: `@bboxDiag01`) — All edges longer than this threshold are refined. - **Selected** (*bool*, default: `@hasSelectedFaces`) — If selected the filter affects only selected faces. ``` --- (filter-subdivision-midpoint)= ## Subdivide by Midpoint **Categories:** `Meshing/Subdivision` **Plugin:** qmeshlab.filter.meshing Apply midpoint subdivision. ```{py:function} ms.subdivision_midpoint(**params) :module: _qmeshlab Apply a plain subdivision scheme where every edge is split on its midpoint. Useful to uniformly refine a mesh substituting each triangle with four smaller triangles. **Parameters:** - **Iterations** (*int*, default: `3`) — Number of times the model is subdivided. - **Threshold** (*absperc*, default: `@bboxDiag01`) — All edges longer than this threshold are refined. - **Selected** (*bool*, default: `@hasSelectedFaces`) — If selected the filter affects only selected faces. ``` --- (filter-pack-uv-charts)= ## Pack UV Charts **Categories:** `Parametrization/Atlas Packing`, `Texture` **Plugin:** qmeshlab.filter.texture_defragmentation Lay the existing UV charts out again in a single atlas, using a choice of vcglib packing algorithms. ```{py:function} ms.pack_uv_charts(**params) :module: _qmeshlab Repacks the atlas without changing the charts themselves: no merging, no reparametrization, just a new layout for the islands the mesh already has. Four packers are offered, and they trade quality against time very differently: - **Rasterized, scaled to fit** rasterizes each chart outline and searches for the largest scale at which everything fits. The tightest packing, and the slowest. - **Rasterized, best effort** keeps the charts at their current scale and places as many as it can in the atlas you asked for. - **Axis-aligned rectangles** packs each chart's bounding box. Fast and loose. - **Object-oriented rectangles** packs each chart's minimum-area oriented box, rotating the chart to match. Usually tighter than axis-aligned for nothing like the cost of rasterizing. The *Try chart permutations* option is worth knowing about. The rasterized packers can retry the layout with reshuffled chart orders, which costs five packing passes per similarly sized chart -- on an atlas whose islands are all much of a muchness that is five passes per chart, and it dominates the run. It is off here by default. **Parameters:** - **algorithm** (*enum*, default: `rasterized_scaled`) — Which vcglib packer lays the charts out. - **textureSize** (*int*, default: `1024`) — Side of the square atlas the charts are packed into. - **gutterWidth** (*int*, default: `4`) — Padding kept around each chart, so bilinear filtering cannot bleed between neighbours. - **rotationNum** (*int*, default: `4`) — How many orientations each chart is tried at, rounded to the nearest multiple of four -- the packer derives four slots from every base rasterization, so only multiples of four are usable. Rasterized packers only. - **permutations** (*bool*, default: `False`) — Retry the layout with reshuffled chart orders. Costs five packing passes per similarly sized chart, so on a uniform atlas it is five per chart and it dominates the run. Rasterized packers only. - **resampleTextures** (*bool*, default: `True`) — Render the new atlas by resampling the original texture images. Turn it off to treat this as a parametrization-only filter: the layer comes back with the reorganized UV layout and no texture images, which is what you want when the texture is going to be baked again afterwards. The source images are still required either way -- the algorithm measures islands and distortion in texel space, so it needs their resolution before it can start. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the atlas packing exactly reproducible. ``` --- (filter-defragment-texture-map)= ## Defragment Texture Atlas **Categories:** `Parametrization/Defragmentation`, `Texture` **Plugin:** qmeshlab.filter.texture_defragmentation Reduce texture atlas fragmentation by merging compatible charts and resampling the texture map. ```{py:function} ms.defragment_texture_map(**params) :module: _qmeshlab Reduces texture fragmentation by merging compatible atlas charts, repacking the resulting charts, and resampling the associated texture images onto the optimized atlas. This QMeshLab port vendors the upstream TextureDefrag reference implementation from `https://github.com/maggio-a/texture-defrag` and adapts it to QMeshLab's mesh-owned texture model. The filter creates a new mesh layer named `texdefrag_` rather than overwriting the input mesh, preserving the original atlas for comparison. Implementation note: the original reference code used OpenGL to rasterize the new texture atlas. QMeshLab isolates that step behind the original `RenderTexture` boundary; this first integration uses an internal image renderer so the algorithm can run from the filter framework without requiring an OpenGL context. The renderer boundary is intentionally narrow so a QRhi backend can replace it cleanly. **References:** - Andrea Maggiordomo, Paolo Cignoni, Marco Tarini. **Texture Defragmentation for Photo-Reconstructed 3D Models**. *Computer Graphics Forum* (2021). [DOI](https://doi.org/10.1111/cgf.142615) [Web](https://diglib.eg.org/items/b3e092cd-5a96-4575-975d-af22795e870b) **Parameters:** - **matchingThreshold** (*double*, default: `2.0`) — Threshold on the seam alignment error. Higher values allow more seams to be considered compatible, which can reduce fragmentation, but may increase runtime and risk more distortion. MeshLab default: `2.0`. - **boundaryTolerance** (*double*, default: `0.2`) — Cutoff on the minimum fractional seam length relative to the chart perimeter. Seams with lower fractional length are not merged, helping keep chart borders compact. MeshLab default: `0.2`. - **distortionTolerance** (*double*, default: `0.5`) — Local UV optimization distortion tolerance when merging a seam. If local ARAP energy exceeds this value, the merge is reverted. Smaller values preserve the original parameterization more strictly; larger values can merge more charts. MeshLab default: `0.5`. - **globalDistortionTolerance** (*double*, default: `0.025`) — Global atlas ARAP distortion tolerance when accepting a seam merge. If the global atlas energy exceeds this value, the merge is reverted. This is usually kept much smaller than the local tolerance. MeshLab default: `0.025`. - **uvReductionLimit** (*double*, default: `0.0`) — Target UV boundary length reduction, expressed as a percentage of the input UV boundary length. The algorithm stops once this reduction has been reached, or when no further seams can be merged. `0` means no target reduction stop condition. MeshLab default: `0`. - **offsetFactor** (*double*, default: `5.0`) — Coefficient controlling the extension of the local UV optimization area. Larger values can make defragmentation more effective by giving the optimizer more room, but increase geometric optimization cost and runtime. MeshLab default: `5.0`. - **timelimit** (*double*, default: `0.0`) — Time limit for the defragmentation process. `0` means unlimited. This is useful for very large atlases where chart merging can be expensive. MeshLab default: `0`. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the atlas packing exactly reproducible. - **resampleTextures** (*bool*, default: `True`) — Render the new atlas by resampling the original texture images. Turn it off to treat this as a parametrization-only filter: the layer comes back with the reorganized UV layout and no texture images, which is what you want when the texture is going to be baked again afterwards. The source images are still required either way -- the algorithm measures islands and distortion in texel space, so it needs their resolution before it can start. ``` --- (filter-small-islands-remover)= ## Merge Small Texture Islands **Categories:** `Parametrization/Defragmentation`, `Texture` **Plugin:** qmeshlab.filter.texture_defragmentation Merge texture islands below a size threshold into neighbors sharing a seam, then repack and resample the atlas. ```{py:function} ms.small_islands_remover(**params) :module: _qmeshlab Attempts to reduce all texture islands within a given size by merging them with neighbors sharing a common seam. The procedure tries to avoid distortion and overlap introduced by the removal of islands. It shares the defragmentation pipeline, so it needs the texture images as well as the parametrization: UVs are scaled into pixel space before anything else runs, the surviving charts are repacked, and the new atlas is resampled from the originals. The layer therefore comes back with new texture images, not just moved UVs. **References:** - Andrea Maggiordomo, Paolo Cignoni, Marco Tarini. **Texture Defragmentation for Photo-Reconstructed 3D Models**. *Computer Graphics Forum* (2021). [DOI](https://doi.org/10.1111/cgf.142615) [Web](https://diglib.eg.org/items/b3e092cd-5a96-4575-975d-af22795e870b) **Parameters:** - **maxMultiplier** (*double*, default: `1.0`) — Islands whose UV boundary length is smaller than this factor times the median island boundary length are candidates for removal. A value of 1.0 targets all below-median islands; 0.2 targets only the absolute tiniest fragments; values above 1.0 also capture larger-than-median islands. Set to 0 to attempt removal of all islands. - **distortionMode** (*enum*, default: `STRICT`) — Specifies how aggressively the algorithm removes islands: **STRICT**: operations that introduce significant geometric distortion are immediately rejected. Prioritizes visual fidelity over compactness. **LOOSE**: distortion introduced by the removal of islands is ignored. Still, operations that introduce overlaps are rejected. Prioritizes layout compactness over quality. **UNSAFE**: ignores any distortion and intersection introduced by a merge operation. This mode leads to the most compact and fast result. Note that topologically incompatible merges are still skipped, as they cannot be parameterized. - **targetTexCount** (*int*, default: `0`) — Specifies the maximum number of output textures that can be generated by the filter. If set to zero the parameter is ignored and the algorithm employs the default packing strategy. - **timelimit** (*double*, default: `0.0`) — Time limit for the chart merging stage. `0` means unlimited. Note that it does not bound the atlas packing that follows, which on a heavily fragmented layout can be the slower half. - **quickRun** (*bool*, default: `False`) — Speeds up the running time of the filter by never attempting again any rejected merge operation.
Although fast, it could lead to worst results. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the atlas packing exactly reproducible. - **resampleTextures** (*bool*, default: `True`) — Render the new atlas by resampling the original texture images. Turn it off to treat this as a parametrization-only filter: the layer comes back with the reorganized UV layout and no texture images, which is what you want when the texture is going to be baked again afterwards. The source images are still required either way -- the algorithm measures islands and distortion in texel space, so it needs their resolution before it can start. ``` --- (filter-convert-vertex-uv-to-wedge-uv)= ## Convert Per-Vertex UV to Per-Wedge UV **Categories:** `Parametrization/UV Conversion` **Plugin:** qmeshlab.filter.texture Convert per-vertex texture coordinates into per-wedge texture coordinates. ```{py:function} ms.convert_vertex_uv_to_wedge_uv(**params) :module: _qmeshlab Converts per Vertex Texture Coordinates to per Wedge Texture Coordinates. It does not merge superfluous vertices... This filter has no parameters. ``` --- (filter-convert-wedge-uv-to-vertex-uv)= ## Convert Per-Wedge UV to Per-Vertex UV **Categories:** `Parametrization/UV Conversion` **Plugin:** qmeshlab.filter.texture Convert per-wedge texture coordinates into per-vertex texture coordinates, splitting vertices when needed. ```{py:function} ms.convert_wedge_uv_to_vertex_uv(**params) :module: _qmeshlab Converts per Wedge Texture Coordinates to per Vertex Texture Coordinates splitting vertices with not coherent Wedge coordinates. This filter has no parameters. ``` --- (filter-apply-vertex-texture-function)= ## Parametrize per Vertex by Expression **Categories:** `Parametrization/UV Creation` **Plugin:** qmeshlab.filter.expression Computes per-vertex texture coordinates from expressions. ```{py:function} ms.apply_vertex_texture_function(**params) :module: _qmeshlab Texture function using muparser to generate new texture coords for every vertex
**Parameters:** - **u** (*string*, default: `x`) — Expression for U texture coordinate. - **v** (*string*, default: `y`) — Expression for V texture coordinate. - **onselected** (*bool*, default: `False`) — If enabled, the filter affects only selected elements. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-apply-wedge-texture-function)= ## Parametrize per Wedge by Expression **Categories:** `Parametrization/UV Creation` **Plugin:** qmeshlab.filter.expression Computes per-wedge texture coordinates from expressions. ```{py:function} ms.apply_wedge_texture_function(**params) :module: _qmeshlab Texture function using muparser to generate new per wedge tex coords for every face
Insert six functions each u v for each one of the three vertex of a face
**Parameters:** - **u0** (*string*, default: `x0`) — Expression for wedge texture coordinate. - **v0** (*string*, default: `y0`) — Expression for wedge texture coordinate. - **u1** (*string*, default: `x1`) — Expression for wedge texture coordinate. - **v1** (*string*, default: `y1`) — Expression for wedge texture coordinate. - **u2** (*string*, default: `x2`) — Expression for wedge texture coordinate. - **v2** (*string*, default: `y2`) — Expression for wedge texture coordinate. - **onselected** (*bool*, default: `False`) — If enabled, the filter affects only selected elements. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-compute-texcoord-parametrization-and-texture-from-registered-rasters)= ## Parametrize from Registered Rasters with Texture **Categories:** `Parametrization/UV Creation`, `Texture`, `Transfer/Raster to Mesh` **Plugin:** qmeshlab.filter.img_patch_param The mesh is parameterized and textured by creating some patches that correspond to projection of portions of surfaces onto the set of registered rasters. ```{py:function} ms.compute_texcoord_parametrization_and_texture_from_registered_rasters(**params) :module: _qmeshlab The mesh is parameterized and textured by creating patches that correspond to projections of surface portions onto the set of registered rasters. After patch-based parameterization, a texture image is generated by painting each raster into the corresponding UV regions. Optionally, a color correction step ensures seamless transitions between adjacent patches. Requires at least one visible raster with a valid camera and a 2-manifold mesh. **Parameters:** - **textureSize** (*int*, default: `1024`) — Specifies the dimension of the generated texture. - **textureName** (*filesave*, default: `texture.png`) — Specifies the name of the file into which the texture image will be saved. - **colorCorrection** (*bool*, default: `True`) — If true, the final texture is corrected to ensure seamless transitions between adjacent patches. - **colorCorrectionFilterSize** (*int*, default: `1`) — Radius (in pixels) of the kernel used to compute the difference between corresponding texels in different rasters. Default of 1 generates a 3x3 kernel. Higher values increase robustness for strong misalignments. - **useDistanceWeight** (*bool*, default: `True`) — Includes a weight accounting for the distance to the camera during the computation of reference images. - **useImgBorderWeight** (*bool*, default: `True`) — Includes a weight accounting for the distance to the image border during the computation of reference images. - **useAlphaWeight** (*bool*, default: `False`) — If true, alpha channel of the image is used as additional weight. Makes it possible to mask-out parts of images that should not be projected on the mesh. - **cleanIsolatedTriangles** (*bool*, default: `True`) — Remove all patches composed of a single triangle by aggregating them to adjacent patches. - **stretchingAllowed** (*bool*, default: `False`) — If true, texture coordinates are stretched to cover the full [0,1] interval for both directions. - **textureGutter** (*int*, default: `4`) — Extra boundary to add to each patch before packing in texture space (in pixels). - **depthEpsilon** (*double*, default: `0.5`) — Tolerance for depth test when checking vertex visibility against the software depth buffer. Increasing this value merges similar-depth regions, reducing the number of patches. Use values of a few units for noisy or inaccurate camera registrations. - **maxPackingSize** (*int*, default: `0`) — Maximum dimension of the packing grid (in pixels). Set to 0 to auto-compute from the total patch area. Lower values speed up packing but may produce denser, lower-resolution layouts. ``` --- (filter-compute-texcoord-parametrization-as-rigid-as-possible-libigl)= ## Parametrize by As-Rigid-As-Possible (libigl) **Categories:** `Parametrization/UV Creation` **Plugin:** qmeshlab.filter.igl Optimize a harmonic UV map with libigl's ARAP local-global solver. ```{py:function} ms.compute_texcoord_parametrization_as_rigid_as_possible_libigl(**params) :module: _qmeshlab Computes an **as-rigid-as-possible (ARAP)** UV parametrization. A harmonic map with a circular boundary supplies the initial guess; libigl's local-global solver then reduces local metric distortion without fixing the boundary. The input must be a connected disk-like triangle surface with at least one interior vertex. **Iterations** limits the nonlinear optimization. More iterations generally improve convergence at additional cost. ARAP strongly favors locally rigid maps but does not guarantee a globally injective result; use SLIM when preventing flipped triangles is the primary goal. The result is stored as per-vertex texture coordinates and synchronized to existing per-wedge coordinates. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) - Olga Sorkine, Marc Alexa. **As-Rigid-As-Possible Surface Modeling**. *Geometry Processing* (2007). [DOI](https://doi.org/10.2312/SGP/SGP07/109-116) **Parameters:** - **iterations** (*int*, default: `50`) — Maximum number of ARAP local-global iterations. ``` --- (filter-compute-texcoord-parametrization-from-registered-rasters)= ## Parametrize from Registered Rasters **Categories:** `Parametrization/UV Creation`, `Transfer/Raster to Mesh` **Plugin:** qmeshlab.filter.img_patch_param The mesh is parameterized by creating some patches that correspond to projection of portions of surfaces onto the set of registered rasters. ```{py:function} ms.compute_texcoord_parametrization_from_registered_rasters(**params) :module: _qmeshlab The mesh is parameterized by creating patches that correspond to projections of surface portions onto the set of registered rasters. For each face, a reference raster is chosen based on visibility, viewing angle, and optional weights. Connected faces sharing the same reference raster form patches. UV coordinates are computed by projecting faces onto the reference raster's image plane. Patches are then packed into texture space using rectangle packing. Requires at least one visible raster with a valid camera and a 2-manifold mesh. **Parameters:** - **useDistanceWeight** (*bool*, default: `True`) — Includes a weight accounting for the distance to the camera during the computation of reference images. - **useImgBorderWeight** (*bool*, default: `True`) — Includes a weight accounting for the distance to the image border during the computation of reference images. - **useAlphaWeight** (*bool*, default: `False`) — If true, alpha channel of the image is used as additional weight. Makes it possible to mask-out parts of images that should not be projected on the mesh. - **cleanIsolatedTriangles** (*bool*, default: `True`) — Remove all patches composed of a single triangle by aggregating them to adjacent patches. - **stretchingAllowed** (*bool*, default: `False`) — If true, texture coordinates are stretched to cover the full [0,1] interval for both directions. - **textureGutter** (*int*, default: `4`) — Extra boundary to add to each patch before packing in texture space (in pixels). - **depthEpsilon** (*double*, default: `0.5`) — Tolerance for depth test when checking vertex visibility against the software depth buffer. Increasing this value merges similar-depth regions, reducing the number of patches. Use values of a few units for noisy or inaccurate camera registrations. - **maxPackingSize** (*int*, default: `0`) — Maximum dimension of the packing grid (in pixels). Set to 0 to auto-compute from the total patch area. Lower values speed up packing but may produce denser, lower-resolution layouts. ``` --- (filter-compute-texcoord-parametrization-harmonic)= ## Parametrize by Harmonic Map (libigl) **Categories:** `Parametrization/UV Creation` **Plugin:** qmeshlab.filter.igl Compute a single-patch fixed-boundary harmonic UV parametrization using libigl. ```{py:function} ms.compute_texcoord_parametrization_harmonic(**params) :module: _qmeshlab Computes a single-patch fixed-boundary harmonic parametrization of the current mesh and stores the result as per-vertex texture coordinates. The mesh must have a boundary. If the mesh already has per-wedge texture coordinates, they are synchronized from the new per-vertex coordinates so the result is immediately visible in texture and UV views. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) **Parameters:** - **harm_function** (*int*, default: `1`) — Order of the harmonic function. `1` is harmonic, `2` is biharmonic, `3` is triharmonic, and so on. ``` --- (filter-compute-texcoord-parametrization-least-squares-conformal-maps)= ## Parametrize by Least Squares Conformal Maps (libigl) **Categories:** `Parametrization/UV Creation` **Plugin:** qmeshlab.filter.igl Compute a Least Squares Conformal Maps UV parametrization using libigl. ```{py:function} ms.compute_texcoord_parametrization_least_squares_conformal_maps(**params) :module: _qmeshlab Computes a Least Squares Conformal Maps parametrization of the current mesh and stores the result as per-vertex texture coordinates. The mesh must have a boundary. If the mesh already has per-wedge texture coordinates, they are synchronized from the new per-vertex coordinates so the result is immediately visible in texture and UV views. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) This filter has no parameters. ``` --- (filter-compute-texcoord-parametrization-slim-libigl)= ## Parametrize by SLIM (libigl) **Categories:** `Parametrization/UV Creation` **Plugin:** qmeshlab.filter.igl Optimize a flip-preventing UV map with libigl's SLIM solver. ```{py:function} ms.compute_texcoord_parametrization_slim_libigl(**params) :module: _qmeshlab Computes a UV parametrization with **Scalable Locally Injective Mappings (SLIM)**. The filter starts from a circular-boundary harmonic map and minimizes the selected distortion energy through SLIM's flip-preventing local-global iterations. If the cotangent harmonic initializer contains flips, a uniform-weight harmonic map is tried instead. The input must be a connected disk-like triangle surface with at least one interior vertex. **Symmetric Dirichlet** balances angle and area distortion and is the recommended default. **ARAP** emphasizes local rigidity; **Conformal** emphasizes angle preservation. SLIM preserves injectivity when supplied with an injective initial map, but cannot repair an initializer that remains folded. The result is stored as per-vertex texture coordinates and synchronized to existing per-wedge coordinates. **Upstream:** [libigl](https://github.com/libigl/libigl) **License:** MPL-2.0 **References:** - Alec Jacobson, Daniele Panozzo. **libigl: A Simple C++ Geometry Processing Library** (2017). [Web](https://libigl.github.io/) - Michael Rabinovich, Roi Poranne, Daniele Panozzo, Olga Sorkine-Hornung. **Scalable Locally Injective Mappings**. *ACM Transactions on Graphics* (2017). [DOI](https://doi.org/10.1145/3072959.2983621) **Parameters:** - **energy** (*enum*, default: `symmetric_dirichlet`) — Distortion energy minimized by SLIM. - **iterations** (*int*, default: `10`) — Number of SLIM optimization iterations. ``` --- (filter-geometric-cylindrical-unwrapping)= ## Parametrize by Cylindrical Projection **Categories:** `Parametrization/UV Creation` **Plugin:** qmeshlab.filter.meshing Unwrap geometry along cylindrical projection. ```{py:function} ms.geometric_cylindrical_unwrapping(**params) :module: _qmeshlab Unwrap the geometry of current mesh along a clylindrical equatorial projection. The cylindrical projection axis is centered on the origin and directed along the vertical Y axis. **Parameters:** - **startAngle** (*double*, default: `0.0`) — Starting angle of unrolling. - **endAngle** (*double*, default: `360.0`) — Ending angle of unrolling. - **radius** (*double*, default: `0.0`) — Reference cylinder radius. 0 = auto. ``` --- (filter-parametrize-flat-plane)= ## Parametrize by Flat Plane **Categories:** `Parametrization/UV Creation` **Plugin:** qmeshlab.filter.texture Generate a trivial flat-plane parametrization. ```{py:function} ms.parametrize_flat_plane(**params) :module: _qmeshlab Builds a trivial flat-plane parametrization. **Parameters:** - **projectionPlane** (*enum*, default: `xy`) — Choose the projection plane. - **aspectRatio** (*bool*, default: `False`) — If checked the resulting parametrization will preserve the original apsect ratio of the model otherwise it will fill up the whole 0..1 uv space. - **sideGutter** (*double*, default: `0.0`) — Leave an empty space around the parametrization area of the specified size (in texture space); accepted range [0.0 - 0.5]. ``` --- (filter-parametrize-trivial-per-triangle)= ## Parametrize by Trivial Per-Triangle Layout **Categories:** `Parametrization/UV Creation` **Plugin:** qmeshlab.filter.texture Generate a triangle-by-triangle parametrization using either equal-size or space-optimizing layout. ```{py:function} ms.parametrize_trivial_per_triangle(**params) :module: _qmeshlab Builds a trivial triangle-by-triangle parametrization.
Two methods are provided, the first maps all triangles into equal sized triangles, while the second one adapt the size of the triangles in texture space to their original size. **Parameters:** - **sidedim** (*int*, default: `0`) — Indicates how many triangles have to be put on each line (every quad contains two triangles) Leave 0 for automatic calculation. - **textdim** (*int*, default: `1024`) — Gives an indication on how big the texture is. - **border** (*int*, default: `2`) — Specifies how many pixels to be left between triangles in parametrization domain. - **method** (*enum*, default: `space_optimizing`) — Choose space optimizing to map smaller faces into smaller triangles in parametrizazion domain. ``` --- (filter-parametrize-voronoi-atlas)= ## Parametrize by Voronoi Atlas (vcglib) **Categories:** `Parametrization/UV Creation` **Plugin:** qmeshlab.filter.texture Build an atlased parametrization using a geodesic Voronoi partition of the surface. ```{py:function} ms.parametrize_voronoi_atlas(**params) :module: _qmeshlab Build an atlased parametrization based on a geodesic voronoi partitioning of the surface and parametrizing each region using Harmonic Mapping. For the parametrization of the disk like voronoi regions the used method is:
Ulrich Pinkall, Konrad Polthier
Computing Discrete Minimal Surfaces and Their Conjugates
Experimental Mathematics, Vol 2 (1), 1993. **Parameters:** - **regionNum** (*int*, default: `10`) — An estimation of the number of regions that must be generated. Smaller regions could lead to parametrizations with smaller distortion. - **overlapFlag** (*bool*, default: `False`) — If checked the resulting parametrization will be composed by overlapping regions, e.g. the resulting mesh will have duplicated faces: each region will have a ring of ovelapping duplicate faces that will ensure that border regions will be parametrized in the atlas twice. This is quite useful for building mipmap robust atlases. - **randomSeed** (*int*, default: `0`) — Zero draws a fresh seed on every run, so repeated applications differ; any other value makes the atlas regions exactly reproducible. ``` --- (filter-parametrize-xatlas)= ## Parametrize by Atlas (xatlas) **Categories:** `Parametrization/UV Creation` **Plugin:** qmeshlab.filter.xatlas Generate a charted and packed UV atlas for the current triangular mesh using xatlas. ```{py:function} ms.parametrize_xatlas(**params) :module: _qmeshlab Generates a new UV atlas for the current triangular mesh using **xatlas**, the lightweight atlas-generation library by Jonathan Young, an independent fork of **thekla_atlas**. The resulting UVs are written back to the current mesh as per-wedge texture coordinates and are suitable for baking and texture painting workflows. This first QMeshLab integration currently targets **single-atlas output** on the current mesh. Practical tuning notes: - For **denser packing**, try enabling **Brute-force packing**, keep chart rotation enabled, and reduce **Padding** as far as your baking workflow tolerates. - For **less fragmented atlases** with fewer, larger charts, try increasing **Max cost**, lowering **Normal deviation weight** and **Normal seam weight**, and leaving **Max chart area** and **Max boundary length** at `0`. - These goals trade off against each other: fewer/larger charts usually mean more distortion, while tighter packing with less padding increases the risk of bleeding and mipmap artifacts. **Parameters:** - **padding** (*int*, default: `0`) — Number of texels of padding inserted around charts. Lower values give denser packing, but increase the risk of bleeding and mipmap artifacts. Higher values are safer for baking. Reasonable values are usually `0..8`; `1..4` is a common practical range. - **texelsPerUnit** (*double*, default: `0.0`) — Unit-to-texel scale. Leave `0` to let xatlas estimate a suitable value automatically. Higher values allocate more texture area to the mesh and can make it harder to stay within a single atlas. A practical range is highly model-dependent, but values around `1..256` are much more common than very large values. - **resolution** (*int*, default: `0`) — If `0`, xatlas chooses a single-atlas size automatically. If greater than `0`, xatlas tries to match this atlas resolution. Large requested resolutions, especially with high texels-per-unit or padding, can force xatlas to create multiple atlases. Common values are `512`, `1024`, `2048`, and `4096`. - **bruteForce** (*bool*, default: `False`) — Use the slower but higher-quality chart packing strategy. This is the main option to try when you want more aggressive packing and better atlas utilization. - **use_dummy_texture** (*bool*, default: `False`) — If enabled, also attach a generated dummy base-color texture to the mesh after the xatlas UVs are created, so the result is immediately visible in textured and UV views. - **dummy_img_size** (*int*, default: `1024`) — Size in pixels of the generated dummy texture. Common values are `512`, `1024`, and `2048`. - **dummy_check_size** (*int*, default: `32`) — Size of the check or grid cells in pixels. A practical range is usually `8..128` depending on texture resolution. - **dummy_type** (*enum*, default: `checkerboard`) — Choose between a checkerboard or a grid pattern for the generated dummy texture. - **bilinear** (*bool*, default: `True`) — Leave space around charts for texels that would be sampled by bilinear filtering. Keep this enabled for safer baked textures; disabling it can improve packing density slightly but increases artifact risk. - **blockAlign** (*bool*, default: `False`) — Align charts to 4x4 blocks. This can improve packing speed and can help block-compressed textures, but it is usually a little less aggressive in raw packing efficiency. - **maxChartSize** (*int*, default: `0`) — Charts larger than this are scaled down. Leave `0` for no limit. A small limit can make the atlas more fragmented by preventing large islands from remaining large. Practical values are typically `256..4096` when you want to constrain very large charts. - **rotateChartsToAxis** (*bool*, default: `True`) — Rotate charts to the axis of their convex hull before packing. Usually helps packing and gives a cleaner starting orientation for islands. - **rotateCharts** (*bool*, default: `True`) — Allow chart rotation during packing to improve utilization. This usually helps create a denser atlas. - **normalDeviationWeight** (*double*, default: `2.0`) — Weight of angle deviation between a face and the average chart normal during chart growth. Higher values resist bending a chart across changing normals and usually increase fragmentation. Lower values can allow larger charts. A good working range is usually about `0.5..8`, with the default `2` being a balanced start. - **roundnessWeight** (*double*, default: `0.01`) — Weight that encourages compact, rounder charts. Higher values can promote smaller, tidier islands, sometimes at the cost of more fragmentation. Practical values are often in the `0..1` range; the default `0.01` is already fairly gentle. - **straightnessWeight** (*double*, default: `6.0`) — Weight that encourages straighter chart boundaries. This mostly affects boundary shape, but can also influence how readily charts split. A useful tuning range is commonly `0..20`, with the default `6` as a solid starting point. - **normalSeamWeight** (*double*, default: `4.0`) — Weight applied to chart boundaries crossing normal seams. Very high values preserve such seams strongly and usually create more fragmented atlases. Lower values allow more merging across those seams. A practical range is often `0..16`; values above that become increasingly aggressive about preserving seams. - **maxCost** (*double*, default: `2.0`) — Maximum growth cost for charts. Lower values generally produce more charts. Raising this is the first thing to try if you want fewer, larger islands and a less fragmented atlas. A good exploration range is usually `0.5..10`, with the default `2` as a balanced value. - **maxIterations** (*int*, default: `1`) — Number of chart seeding and growth iterations. Higher values may improve chart quality and coherence, though they also cost more time. Practical values are typically `1..10`; going much higher is uncommon unless you are explicitly experimenting. - **maxChartArea** (*double*, default: `0.0`) — Upper bound on chart area during growth. Leave `0` for no limit. Setting this to a small value forces more splitting and therefore a more fragmented atlas. This is scene-scale dependent; when used at all, it is usually tuned relative to mesh size rather than by absolute universal values. - **maxBoundaryLength** (*double*, default: `0.0`) — Upper bound on chart boundary length during growth. Leave `0` for no limit. Setting this to a small value tends to force more chart splitting. Like max chart area, this is model-scale dependent and is usually left at `0` unless you have a specific reason to constrain chart growth. - **fixWinding** (*bool*, default: `False`) — Enforce consistent texture-coordinate winding in the generated charts. This is mainly a robustness option rather than a packing or fragmentation control. ``` --- (filter-remove-isolated-pieces-by-diameter)= ## Remove Isolated Components by Diameter **Categories:** `Repair/Degenerate` **Plugin:** qmeshlab.filter.clean Remove isolated connected components whose diameter is below a threshold. ```{py:function} ms.remove_isolated_pieces_by_diameter(**params) :module: _qmeshlab Remove isolated connected components whose diameter is smaller than the specified constant **Parameters:** - **min_component_diag** (*absperc*, default: `@bboxDiagTenth`) — Delete all connected components (floating pieces) with a diameter smaller than the specified one. - **remove_unref** (*bool*, default: `True`) — If true, the unreferenced vertices remaining after face deletion are removed. ``` --- (filter-remove-isolated-pieces-by-face-num)= ## Remove Isolated Components by Face Count **Categories:** `Repair/Degenerate` **Plugin:** qmeshlab.filter.clean Remove isolated connected components composed of few triangles. ```{py:function} ms.remove_isolated_pieces_by_face_num(**params) :module: _qmeshlab Remove isolated connected components composed of a limited number of triangles **Parameters:** - **min_component_size** (*int*, default: `25`) — Delete all the connected components (floating pieces) composed by a number of triangles smaller than the specified one. - **remove_unref** (*bool*, default: `True`) — If true, the unreferenced vertices remaining after face deletion are removed. ``` --- (filter-remove-vertices-wrt-quality)= ## Remove Vertices by Scalar **Categories:** `Repair/Degenerate` **Plugin:** qmeshlab.filter.clean Remove all vertices whose scalar is lower than a threshold. ```{py:function} ms.remove_vertices_wrt_quality(**params) :module: _qmeshlab Remove all the vertices whose scalar is smaller than the specified constant **Parameters:** - **max_quality_thr** (*double*, default: `@qualityVMax`) — Vertices with quality lower than this threshold are deleted. ``` --- (filter-remove-zero-area-faces)= ## Remove Zero-Area Faces **Categories:** `Repair/Degenerate` **Plugin:** qmeshlab.filter.clean Remove null faces with zero area. ```{py:function} ms.remove_zero_area_faces(**params) :module: _qmeshlab Remove null faces (the one with area equal to zero) This filter has no parameters. ``` --- (filter-merge-close-vertices)= ## Merge Close Vertices **Categories:** `Repair/Duplicates` **Plugin:** qmeshlab.filter.clean Merge vertices that are nearer than a threshold. ```{py:function} ms.merge_close_vertices(**params) :module: _qmeshlab Merge together all the vertices that are nearer than the specified threshold. Like a unify duplicated vertices but with some tolerance. **Parameters:** - **threshold** (*absperc*, default: `@bboxDiag0001`) — All vertices closer than this threshold are merged together. Use very small values; default is 1/10000 of bounding box diagonal. ``` --- (filter-merge-wedge-texture-coords)= ## Merge Close Wedge UVs **Categories:** `Repair/Duplicates` **Plugin:** qmeshlab.filter.clean Merge per-wedge UVs that are very close. ```{py:function} ms.merge_wedge_texture_coords(**params) :module: _qmeshlab Merge together per-wedge UVs that are very close. Used to correct apparent texture seams that can arise from numerical approximations when saving in ascii formats. **Parameters:** - **merge_thr** (*double*, default: `0.0001`) — All per-wedge texture coords that are on the same vertex and are distant less than the threshold are merged together. Distance is in texture space. ``` --- (filter-remove-duplicate-faces)= ## Remove Duplicate Faces **Categories:** `Repair/Duplicates` **Plugin:** qmeshlab.filter.clean Remove all duplicate faces. ```{py:function} ms.remove_duplicate_faces(**params) :module: _qmeshlab Remove all the duplicate faces. Two faces are considered equal if they are composed by the same set of vertices, regardless of the order of the vertices. This filter has no parameters. ``` --- (filter-remove-duplicate-vertices)= ## Remove Duplicate Vertices (vcglib) **Categories:** `Repair/Duplicates` **Plugin:** qmeshlab.filter.clean Merge vertices that have exactly the same coordinates. ```{py:function} ms.remove_duplicate_vertices(**params) :module: _qmeshlab Check for every vertex on the mesh: if there are two vertices with same coordinates they are merged into a single one. This filter has no parameters. ``` --- (filter-remove-duplicate-vertices-trueform)= ## Remove Duplicate Vertices (TrueForm) **Categories:** `Repair/Duplicates` **Plugin:** qmeshlab.filter.trueform Weld coincident vertices and drop the degeneracies that welding exposes. ```{py:function} ms.remove_duplicate_vertices_trueform(**params) :module: _qmeshlab Welds vertices at the same position into one and removes the degenerate faces that welding leaves behind.\n\nThis is the first thing to run on a triangle soup — an STL, or anything exported face by face — because until the vertices are shared the mesh has no connectivity at all: no edges, no adjacency, and so no boundary, no components and no topology for any other filter to work with.\n\n**Tolerance** of zero welds only exactly coincident vertices, which is the safe choice. A positive tolerance also merges vertices within that distance, which closes cracks left by finite precision but will collapse genuinely small features if set too large.\n\nNote that QMeshLab's own STL reader (*TrueForm OBJ/STL*) already welds on import, so this is mainly for geometry that arrived unwelded by another route.\n\nCompeting implementation: *Remove Duplicate Vertices* and *Merge Close Vertices* do the same with vcglib. **Parameters:** - **tolerance** (*absperc*, default: `0.0`) — Weld vertices within this distance. Zero welds only exactly coincident ones. ``` --- (filter-remove-unreferenced-vertices)= ## Remove Unreferenced Vertices **Categories:** `Repair/Duplicates` **Plugin:** qmeshlab.filter.clean Remove vertices that are not referenced by any face. ```{py:function} ms.remove_unreferenced_vertices(**params) :module: _qmeshlab Check for every vertex on the mesh: if it is NOT referenced by a face, removes it This filter has no parameters. ``` --- (filter-vertex-attribute-seam)= ## Split Vertices by Attribute Seam **Categories:** `Repair/Duplicates` **Plugin:** qmeshlab.filter.meshing Split vertices to make attributes seam-independent. ```{py:function} ms.vertex_attribute_seam(**params) :module: _qmeshlab Make all selected vertex attributes connectivity-independent:
vertices are duplicated whenever two or more selected wedge or face attributes do not match.
This is particularly useful for GPU-friendly mesh layout, where a single index must be used to access all required vertex attributes. **Parameters:** - **NormalMode** (*enum*, default: `none`) — Choose normal source. - **ColorMode** (*enum*, default: `none`) — Choose color source. - **TexcoordMode** (*enum*, default: `none`) — Choose texcoord source. ``` --- (filter-close-holes)= ## Close Holes **Categories:** `Repair/Holes and Borders` **Plugin:** qmeshlab.filter.meshing Close holes under a size threshold. ```{py:function} ms.close_holes(**params) :module: _qmeshlab Close holes whose boundary is composed by a number of edges smaller than a given threshold **Parameters:** - **MaxHoleSize** (*int*, default: `30`) — Hole size threshold in boundary-edge count. - **Selected** (*bool*, default: `False`) — Only holes with selected boundary faces are closed. - **NewFaceSelected** (*bool*, default: `True`) — Leave newly created faces selected. - **SelfIntersection** (*bool*, default: `True`) — Try to avoid creating self-intersecting faces. - **RefineHole** (*bool*, default: `False`) — Refine newly created hole triangles. - **RefineHoleEdgeLen** (*absperc*, default: `@bboxDiag003`) — Target edge length for hole refinement. ``` --- (filter-snap-mismatched-borders)= ## Repair Mismatched Borders **Categories:** `Repair/Holes and Borders` **Plugin:** qmeshlab.filter.clean Try to snap together slightly mismatched adjacent borders. ```{py:function} ms.snap_mismatched_borders(**params) :module: _qmeshlab Try to snap together adjacent borders that are slightly mismatched.
This situation can happen on badly triangulated adjacent patches defined by high order surfaces.
For each border vertex the filter snap it onto the closest boundary edge only if it is closest of edge_length*threshold. When vertex is snapped the corresponding face is split and a new vertex is created. **Parameters:** - **edge_dist_ratio** (*double*, default: `0.01`) — Collapse edge when the edge / distance ratio is greater than this value. Larger values enforce that only vertices very close to the line are removed. - **unify_vertices** (*bool*, default: `True`) — If true, snapped vertices are welded together. ``` --- (filter-generate-outer-shell)= ## Extract Outer Shell (TrueForm) **Categories:** `Repair/Topology` **Plugin:** qmeshlab.filter.trueform Keep only the outermost surface of a layer, discarding internal shells. ```{py:function} ms.generate_outer_shell(**params) :module: _qmeshlab Resolves the layer's self-intersections and keeps only the **outermost** boundary, dropping every internal shell and any surface enclosed by another.\n\nThis is the repair step for geometry assembled from overlapping parts — kitbashed models, scans merged from several pieces, or anything destined for 3D printing, where interior walls are invisible but still slow slicing and can confuse a slicer about what is solid.\n\nThe input should be solid rather than an open sheet: an open surface has no inside, so there is no outer shell to extract. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The layer to extract the outer shell from. ``` --- (filter-invert-faces-orientation)= ## Invert Face Orientation **Categories:** `Repair/Topology` **Plugin:** qmeshlab.filter.meshing Flip mesh face orientation. ```{py:function} ms.invert_faces_orientation(**params) :module: _qmeshlab Invert faces orientation, flipping the normals of the mesh.
If requested, it tries to guess the right orientation; mainly it decide to flip all the faces if the minimum/maximum vertices have not outward point normals for a few directions.
Works well for single component watertight objects. **Parameters:** - **forceFlip** (*bool*, default: `True`) — Always flip normals; otherwise try to set normals outside. - **onlySelected** (*bool*, default: `False`) — If selected, only selected faces are affected. ``` --- (filter-orient-faces-coherently-trueform)= ## Orient Faces Consistently (TrueForm) **Categories:** `Repair/Topology` **Plugin:** qmeshlab.filter.trueform Make neighboring faces wind the same way. ```{py:function} ms.orient_faces_coherently_trueform(**params) :module: _qmeshlab Propagates a consistent winding across each connected component, so neighboring faces agree about which side is front. Meshes assembled from several sources, or exported by tools that do not care, commonly arrive with patches wound both ways — which makes backface culling, shading and every boolean unreliable.\n\nThis makes the winding *consistent*; it does not decide which way is out. Use *Orient Faces Outward (TrueForm)* for that.\n\nCompeting implementation: *Orient Faces Consistently (vcglib)* does the same with vcglib. **Implementation note.** A single pass of the underlying routine only partly repairs a badly mixed winding, so this filter repeats it until the winding stops improving and reports how many passes were needed. If edges remain inconsistent afterwards the surface is probably non-orientable — a Möbius-like configuration has no consistent winding to find. For diagnosis prefer the vcglib *Orient Faces Consistently (vcglib)*: it detects and reports a **non-orientable** surface, which this routine cannot distinguish from an incomplete repair. This filter has no parameters. ``` --- (filter-orient-faces-outward-trueform)= ## Orient Faces Outward (TrueForm) **Categories:** `Repair/Topology` **Plugin:** qmeshlab.filter.trueform Make the winding consistent and pointing out of the solid. ```{py:function} ms.orient_faces_outward_trueform(**params) :module: _qmeshlab First makes the winding consistent, then checks the **signed volume** and flips the whole mesh if it came out negative — so normals point out of the solid rather than into it.\n\nThat second step is what distinguishes this from *Orient Faces Consistently (TrueForm)*: a consistently wound mesh can still be inside out, and nothing local can tell, because every face agrees with its neighbours either way. Only the sign of the enclosed volume settles it.\n\nThe input must therefore be **closed** for the answer to mean anything: an open sheet encloses no volume, so there is no outward. This filter has no parameters. ``` --- (filter-remove-isolated-folded-faces)= ## Remove Isolated Folded Faces by Edge Flip **Categories:** `Repair/Topology` **Plugin:** qmeshlab.filter.clean Repair isolated folded triangles by changing the local triangulation. ```{py:function} ms.remove_isolated_folded_faces(**params) :module: _qmeshlab Repair an isolated folded triangle whose normal is nearly opposite to all three adjacent faces. The filter flips one supporting edge only when the opposite vertex projects strictly inside the adjacent triangle and the flip reduces the number of near-opposite normal relations in the affected neighborhood. No vertices or faces are removed. The input must be a consistently oriented, 2-manifold triangle mesh. Polygonal faux-edge meshes and meshes with per-wedge UVs are rejected because an edge flip cannot preserve their polygon boundaries or UV seams unambiguously. **Parameters:** - **normal_threshold_deg** (*double*, default: `175.0`) — Minimum angle, in degrees, between the candidate face normal and each adjacent face normal. Values near 180 detect only nearly reversed triangles. ``` --- (filter-remove-t-vertices)= ## Remove T-Vertices **Categories:** `Repair/Topology` **Plugin:** qmeshlab.filter.clean Remove T-vertices using edge collapse or edge flip. ```{py:function} ms.remove_t_vertices(**params) :module: _qmeshlab Remove t-vertices from the mesh by edge collapse (collapsing the shortest of the incident edges) or edge flip (flipping the opposite edge on the degenerate face if the triangulation quality improves). **Parameters:** - **method** (*enum*, default: `edge_collapse`) — Selects whether to remove t-vertices by edge collapse or edge flip. - **threshold** (*double*, default: `40.0`) — Detects faces where the base/height ratio is lower than this value. - **repeat** (*bool*, default: `True`) — Iterates the algorithm until it reaches convergence. ``` --- (filter-reorient-all-faces)= ## Orient Faces Consistently (vcglib) **Categories:** `Repair/Topology` **Plugin:** qmeshlab.filter.meshing Orient faces consistently. ```{py:function} ms.reorient_all_faces(**params) :module: _qmeshlab Re-orient in a consistent way all the faces of the mesh.
The filter visits a mesh face to face, reorienting any unvisited face so that it is coherent to the already visited faces. If the surface is orientable it will end with a consistent orientation of all the faces. If the surface is not orientable (e.g. it is non manifold or non orientable like a moebius This filter has no parameters. ``` --- (filter-repair-non-manifold-edges)= ## Repair Non-Manifold Edges **Categories:** `Repair/Topology` **Plugin:** qmeshlab.filter.clean Repair non-manifold edges by removing faces or splitting vertices. ```{py:function} ms.repair_non_manifold_edges(**params) :module: _qmeshlab Remove non-manifold edges by removing faces (for each non-manifold edge it iteratively removes the smallest area face until it becomes 2-Manifold) or by splitting vertices (each non manifold edges chain will become a border). **Parameters:** - **method** (*enum*, default: `remove_faces`) — Selects whether to repair non manifold edges by removing faces or by splitting vertices. ``` --- (filter-repair-non-manifold-vertices)= ## Repair Non-Manifold Vertices by Splitting **Categories:** `Repair/Topology` **Plugin:** qmeshlab.filter.clean Split non-manifold vertices until the mesh becomes 2-manifold. ```{py:function} ms.repair_non_manifold_vertices(**params) :module: _qmeshlab Split non Manifold vertices until it becomes 2-Manifold. **Parameters:** - **vert_disp_ratio** (*double*, default: `0.0`) — This parameter denotes the displacement ratio α. When a vertex is split, it is moved towards the barycenter of the FF-connected faces sharing it by (v-barycenter)*α. Reasonable values are in [0..0.1]. ``` --- (filter-repair-self-intersections)= ## Repair Self-Intersections (TrueForm) **Categories:** `Repair/Topology` **Plugin:** qmeshlab.filter.trueform Resolve a mesh's self-intersections into real edges and split faces. ```{py:function} ms.repair_self_intersections(**params) :module: _qmeshlab Computes the **arrangement** of the layer against itself: every place the surface passes through itself becomes a real edge, and every crossed face is split along it.\n\nThis is the principled repair for self-intersecting geometry. Before it, the surface has no well-defined inside — a ray can cross the same sheet twice with nothing recording that they met — which is why self-intersections break booleans, offsetting, signed distance and printing. Afterwards the pieces are properly separated, and *Extract Outer Shell (TrueForm)* can keep the outermost one.\n\nUse *Create Polyline from Self-Intersections (TrueForm)* first to see where the problem is, and *Select Self Intersecting Faces* to see how much is affected.\n\nThe result is a new layer; nothing is removed, so all interior sheets survive as separate geometry. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The layer to resolve. ``` --- (filter-repair-watertight-mesh-meshfix)= ## Repair Watertight Mesh (MeshFix) **Categories:** `Repair/Topology` **Plugin:** qmeshlab.filter.meshfix Repair a raw digitized mesh into a single watertight triangle mesh using MeshFix. ```{py:function} ms.repair_watertight_mesh_meshfix(**params) :module: _qmeshlab Runs the standard MeshFix repair pipeline: keeps the connected component with the most triangles, fills all holes with refined patches, then repairs degeneracies and self-intersections. The result is created as a new geometry-only layer and preserves the input layer transform. This filter is intended for raw digitized surfaces representing one closed solid. Vertex and face attributes, materials, textures, and polygonal edge markings are not transferred. MeshFix has no cancellation or fine-grained progress API, so only phase-level progress is available. **Upstream:** [MeshFix 2.1](https://github.com/MarcoAttene/MeshFix-V2.1) **License:** GPL-3.0-or-later **References:** - Marco Attene. **A lightweight approach to repairing digitized polygon meshes**. *The Visual Computer* (2010). [DOI](https://doi.org/10.1007/s00371-010-0416-3) This filter has no parameters. ``` --- (filter-dilate-selection)= ## Dilate Selection **Categories:** `Selection/Set Operations` **Plugin:** qmeshlab.filter.select Dilate (expand) current selected faces. ```{py:function} ms.dilate_selection(**params) :module: _qmeshlab Dilate (expand) the current set of selected faces. This filter has no parameters. ``` --- (filter-erode-selection)= ## Erode Selection **Categories:** `Selection/Set Operations` **Plugin:** qmeshlab.filter.select Erode (reduce) current selected faces. ```{py:function} ms.erode_selection(**params) :module: _qmeshlab Erode (reduce) the current set of selected faces. This filter has no parameters. ``` --- (filter-invert-selection)= ## Invert Selection **Categories:** `Selection/Set Operations` **Plugin:** qmeshlab.filter.select Invert the current set of selected faces/vertices. ```{py:function} ms.invert_selection(**params) :module: _qmeshlab **Parameters:** - **InvFaces** (*bool*, default: `@hasSelectedFaces`) — If true the filter will invert the set of selected faces. - **InvVerts** (*bool*, default: `@hasSelectedVerts`) — If true the filter will invert the set of selected vertices. ``` --- (filter-select-all)= ## Select All **Categories:** `Selection/Set Operations` **Plugin:** qmeshlab.filter.select Select all the faces/vertices of the current mesh. ```{py:function} ms.select_all(**params) :module: _qmeshlab **Parameters:** - **allFaces** (*bool*, default: `True`) — If true the filter will select all the faces. - **allVerts** (*bool*, default: `True`) — If true the filter will select all the vertices. ``` --- (filter-select-none)= ## Select None **Categories:** `Selection/Set Operations` **Plugin:** qmeshlab.filter.select Clear the current set of selected faces/vertices. ```{py:function} ms.select_none(**params) :module: _qmeshlab **Parameters:** - **allFaces** (*bool*, default: `True`) — If true the filter will de-select all the faces. - **allVerts** (*bool*, default: `True`) — If true the filter will de-select all the vertices. ``` --- (filter-select-by-face-quality)= ## Select Faces by Scalar **Categories:** `Selection/by Attribute` **Plugin:** qmeshlab.filter.select Select elements using per-face quality range. ```{py:function} ms.select_by_face_quality(**params) :module: _qmeshlab Select all the faces/vertices with within the specified face quality range. **Parameters:** - **minQ** (*double*, default: `@qualityFMin`) — Minimum acceptable quality value. - **maxQ** (*double*, default: `@qualityFMax`) — Maximum acceptable quality value. - **Inclusive** (*bool*, default: `True`) — If true only vertices with all adjacent faces within range are selected. Otherwise any vertex with at least one face in range is selected. ``` --- (filter-select-by-vertex-quality)= ## Select Vertices by Scalar **Categories:** `Selection/by Attribute` **Plugin:** qmeshlab.filter.select Select elements using per-vertex quality range. ```{py:function} ms.select_by_vertex_quality(**params) :module: _qmeshlab Select all the faces/vertices within the specified vertex quality range. **Parameters:** - **minQ** (*double*, default: `@qualityVMin`) — Minimum acceptable quality value. - **maxQ** (*double*, default: `@qualityVMax`) — Maximum acceptable quality value. - **Inclusive** (*bool*, default: `True`) — If true only faces with all vertices within range are selected. Otherwise any face with at least one vertex in range is selected. ``` --- (filter-select-faces-by-color)= ## Select Faces by Color **Categories:** `Selection/by Attribute` **Plugin:** qmeshlab.filter.select Select part of the mesh based on vertex color. ```{py:function} ms.select_faces_by_color(**params) :module: _qmeshlab Select part of the mesh based on its color. **Parameters:** - **Color** (*color*, default: `#000000`) — Color that you want to be selected. - **ColorSpace** (*enum*, default: `hsv`) — The color space that the sliders will manipulate. - **Inclusive** (*bool*, default: `True`) — If true only faces with all vertices within range are selected. Otherwise any face with at least one vertex in range is selected. - **PercentRH** (*double*, default: `0.2`) — A float in [0,1] representing accepted variation from selected Red/Hue. - **PercentGS** (*double*, default: `0.2`) — A float in [0,1] representing accepted variation from selected Green/Saturation. - **PercentBV** (*double*, default: `0.2`) — A float in [0,1] representing accepted variation from selected Blue/Value. ``` --- (filter-select-faces-by-condition)= ## Select Faces by Expression **Categories:** `Selection/by Attribute` **Plugin:** qmeshlab.filter.expression Selects faces for which a boolean expression evaluates true. ```{py:function} ms.select_faces_by_condition(**params) :module: _qmeshlab Boolean function using muparser lib to perform faces selection over current mesh.
**Parameters:** - **condSelect** (*string*, default: `(fi == 0)`) — Boolean expression evaluated per face. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-select-faces-by-view-angle)= ## Select Faces by View Angle **Categories:** `Selection/by Attribute` **Plugin:** qmeshlab.filter.select Select faces according to angle with view direction. ```{py:function} ms.select_faces_by_view_angle(**params) :module: _qmeshlab Select faces according to the angle between their normal and the view direction. It is used in range map processing to select and delete steep faces parallel to viewdirection. **Parameters:** - **anglelimit** (*double*, default: `75.0`) — Faces with normals at higher angle w.r.t. the view direction are selected. - **usecamera** (*bool*, default: `False`) — Uses the ViewPoint from the camera associated to the current mesh. If there is no camera, an error occurs. - **viewpoint** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Viewpoint position (ignored when UseCamera is true). ``` --- (filter-select-faces-with-edges-longer-than)= ## Select Faces by Edge Length **Categories:** `Selection/by Attribute` **Plugin:** qmeshlab.filter.select Select all triangles having an edge longer than threshold. ```{py:function} ms.select_faces_with_edges_longer_than(**params) :module: _qmeshlab Select all triangles having an edge with length greater or equal than a given threshold. **Parameters:** - **Threshold** (*absperc*, default: `@bboxDiag0005`) — Faces with an edge longer than this threshold will be selected. ``` --- (filter-select-outliers)= ## Select Outliers **Categories:** `Selection/by Attribute` **Plugin:** qmeshlab.filter.select Select outlier vertices using LoOP. ```{py:function} ms.select_outliers(**params) :module: _qmeshlab Select the vertex classified as outlier using Local Outlier Propabilty measure described in:
'LoOP: Local Outlier Probabilities' Kriegel et al.
CIKM 2009 **Parameters:** - **PropThreshold** (*double*, default: `0.8`) — Threshold to select a vertex. Vertex is selected if LoOP value is above threshold. - **KNearest** (*int*, default: `32`) — Number of neighbors used to compute LoOP. ``` --- (filter-select-vertices-by-condition)= ## Select Vertices by Expression **Categories:** `Selection/by Attribute` **Plugin:** qmeshlab.filter.expression Selects vertices for which a boolean expression evaluates true. ```{py:function} ms.select_vertices_by_condition(**params) :module: _qmeshlab Boolean function using muparser lib to perform vertex selection over current mesh.
**Parameters:** - **condSelect** (*string*, default: `(q < 0)`) — Boolean expression evaluated per vertex. - **randomSeed** (*int*, default: `0`) — Seed for the `rnd()` and `randInt()` helpers, which only matter if your expression calls them. Zero draws a fresh seed on every run; any other value makes the expression exactly reproducible. ``` --- (filter-select-vertices-inside-mesh)= ## Select Vertices Inside Mesh (TrueForm) **Categories:** `Selection/by Attribute` **Plugin:** qmeshlab.filter.trueform Select the vertices enclosed by another layer. ```{py:function} ms.select_vertices_inside_mesh(**params) :module: _qmeshlab Selects every vertex that falls **inside** the enclosing layer's volume.\n\nThis is the spatial counterpart to selecting by an attribute: crop a scan to a region of interest by modelling a rough box or sphere around it, isolate the part of an assembly within a clearance envelope, or find geometry that has ended up inside a shell it should be outside of.\n\nContainment is decided by the **sign of the distance** to the enclosing surface rather than by counting ray crossings, so a vertex lying exactly on the surface is resolved consistently instead of depending on the direction a ray happens to be cast.\n\nThe enclosing layer must be **closed** for inside to be meaningful. Enable **Select Outside** to invert the test. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The layer whose vertices are selected. - **referenceMesh** (*mesh*, default: `@otherMeshIndex`) — The closed layer that defines inside. - **selectOutside** (*bool*, default: `False`) — Select the vertices outside the enclosing layer instead. - **mode** (*enum*, default: `replace`) — Replace the current selection, or add to and subtract from it. ``` --- (filter-select-border)= ## Select Border **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.select Select vertices and faces on mesh boundary. ```{py:function} ms.select_border(**params) :module: _qmeshlab Select vertices and faces on the boundary. This filter has no parameters. ``` --- (filter-select-connected-faces)= ## Select Connected Faces **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.select Expand selected faces to their connected components. ```{py:function} ms.select_connected_faces(**params) :module: _qmeshlab Expand the current face selection so that it includes all the faces in the connected components where there is at least a selected face. This filter has no parameters. ``` --- (filter-select-crease-edges)= ## Select Crease Edges (vcglib) **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.meshing Select crease edges from dihedral angles. ```{py:function} ms.select_crease_edges(**params) :module: _qmeshlab It select the crease edges of a mesh according to edge dihedral angle.
Angle between face normal is considered signed according to convexity/concavity.Convex angles are positive and concave are negative. **Parameters:** - **AngleDegNeg** (*double*, default: `-45.0`) — Concave dihedral threshold. - **AngleDegPos** (*double*, default: `45.0`) — Convex dihedral threshold. ``` --- (filter-select-crease-edges-trueform)= ## Select Crease Edges (TrueForm) **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.trueform Select edges whose dihedral angle exceeds a threshold. ```{py:function} ms.select_crease_edges_trueform(**params) :module: _qmeshlab Marks every edge where the two incident faces meet at more than the given angle — the sharp features of the model.\n\nThe selection lands on the **per-face edge flags**, which is the same place the other crease filters write, so the result feeds straight into *Create Polyline from Selected Edges*, *Cut Along Crease Edges*, or a feature-preserving remesh.\n\nCompeting implementation: *Select Crease Edges* does the same with vcglib, with separate thresholds for convex and concave angles; this one uses a single unsigned threshold. **Parameters:** - **angle** (*double*, default: `60.0`) — Dihedral angle above which an edge counts as a crease. - **replaceSelection** (*bool*, default: `True`) — Clear the existing edge selection first instead of adding to it. ``` --- (filter-select-faces-from-vertices)= ## Select Faces from Vertices **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.select Transfer selection from selected vertices to faces. ```{py:function} ms.select_faces_from_vertices(**params) :module: _qmeshlab Select faces from selected vertices. **Parameters:** - **Inclusive** (*bool*, default: `True`) — If true only faces with all selected vertices are selected. Otherwise any face with at least one selected vertex is selected. ``` --- (filter-select-non-manifold-edges)= ## Select Non-Manifold Edges (vcglib) **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.select Select faces and vertices incident on non manifold edges. ```{py:function} ms.select_non_manifold_edges(**params) :module: _qmeshlab Select the faces and the vertices incident on non manifold edges (e.g. edges where more than two faces are incident); note that this function select the components that This filter has no parameters. ``` --- (filter-select-non-manifold-edges-trueform)= ## Select Non-Manifold Edges (TrueForm) **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.trueform Select edges shared by more than two faces. ```{py:function} ms.select_non_manifold_edges_trueform(**params) :module: _qmeshlab Marks every edge with more than two incident faces. Such edges have no well-defined surface either side, which is why they break booleans, offsetting, orientation and most reconstruction — so finding them is usually the first step in diagnosing a mesh that misbehaves for no visible reason.\n\nThe selection lands on the per-face edge flags, so it can be turned into a polyline with *Create Polyline from Selected Edges* to see exactly where the trouble is.\n\nCompeting implementation: *Select non Manifold Edges* does the same with vcglib. **Parameters:** - **replaceSelection** (*bool*, default: `True`) — Clear the existing edge selection first instead of adding to it. ``` --- (filter-select-non-manifold-vertices)= ## Select Non-Manifold Vertices **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.select Select non manifold vertices. ```{py:function} ms.select_non_manifold_vertices(**params) :module: _qmeshlab Select the non manifold vertices that do not belong to non manifold edges. For example two cones connected by their apex. Vertices incident on non manifold edges are ignored. This filter has no parameters. ``` --- (filter-select-problematic-faces)= ## Select Ill-Shaped Faces **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.select Select problematic faces: elongated, flipped, or folded. ```{py:function} ms.select_problematic_faces(**params) :module: _qmeshlab Select faces with 'problems', like normal inverted w.r.t the surrounding areas, extremely elongated or folded. **Parameters:** - **useAR** (*bool*, default: `True`) — If true, faces with aspect ratio below the limit will be selected. - **ARatio** (*double*, default: `0.02`) — Triangle face aspect ratio [1 (equilateral) - 0 (line)]: face is selected if below this threshold. - **useNF** (*bool*, default: `False`) — If true, adjacent faces with normals forming an angle above the limit are selected. - **NFRatio** (*double*, default: `60.0`) — Angle between adjacent faces: face is selected if above this threshold. - **select_folded_faces** (*bool*, default: `False`) — If true, folded faces created by quadric edge-collapse decimation are selected. - **folded_faces_angle_threshold** (*double*, default: `160.0`) — Angle between face normal and best-fitting plane of neighboring vertices. If above threshold, face is selected. ``` --- (filter-select-self-intersecting-faces)= ## Select Self-Intersecting Faces **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.select Select only self intersecting faces. ```{py:function} ms.select_self_intersecting_faces(**params) :module: _qmeshlab This filter has no parameters. ``` --- (filter-select-small-disconnected-component)= ## Select Small Disconnected Components **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.mls Select the small disconnected components of a mesh. ```{py:function} ms.select_small_disconnected_component(**params) :module: _qmeshlab **Parameters:** - **NbFaceRatio** (*double*, default: `0.1`) — This ratio (between 0 and 1) defines the meaning of small as the threshold ratio between the number of faces of the largest component and the other ones. A larger value will select more components. - **NonClosedOnly** (*bool*, default: `False`) — If enabled, only non-closed connected components are selected. ``` --- (filter-select-vertex-texture-seams)= ## Select Vertex Texture Seams **Categories:** `Selection/by Topology`, `Parametrization` **Plugin:** qmeshlab.filter.select Select vertices on texture seams. ```{py:function} ms.select_vertex_texture_seams(**params) :module: _qmeshlab Colorize only border edges. This filter has no parameters. ``` --- (filter-select-vertices-from-faces)= ## Select Vertices from Faces **Categories:** `Selection/by Topology` **Plugin:** qmeshlab.filter.select Transfer selection from selected faces to vertices. ```{py:function} ms.select_vertices_from_faces(**params) :module: _qmeshlab Select vertices from selected faces. **Parameters:** - **Inclusive** (*bool*, default: `True`) — If true only vertices with all incident faces selected are selected. Otherwise any vertex with at least one incident selected face is selected. ``` --- (filter-select-by-rectangle)= ## Select by Screen Rectangle **Categories:** `Selection/by Visibility` **Plugin:** qmeshlab.filter.select Select vertices or faces whose screen projection falls inside a rectangle. ```{py:function} ms.select_by_rectangle(**params) :module: _qmeshlab Screen-space rubber-band selection. Given a camera and a rectangle in normalized viewport coordinates (origin bottom-left, y up, range 0..1), selects the vertices (or face centroids) of the current mesh that project inside the rectangle. This is the filter committed by the interactive rubber-band tool, and is equally usable from scripting. **Parameters:** - **camera_state** (*camerastate*) — Camera state (QMeshLab.CameraState JSON) defining the projection. - **aspect** (*double*, default: `1.0`) — Viewport width/height used to build the projection. - **space** (*enum*, default: `view3d`) — Whether the rectangle is in the 3D view or the UV/parametrization view. - **uv_pan_x** (*double*, default: `0.5`) — UV-view pan (X), used when space = uv. - **uv_pan_y** (*double*, default: `0.5`) — UV-view pan (Y), used when space = uv. - **uv_zoom** (*double*, default: `1.0`) — UV-view zoom, used when space = uv. - **rect_min_x** (*double*, default: `0.0`) — Left edge, normalized [0..1]. - **rect_min_y** (*double*, default: `0.0`) — Bottom edge, normalized [0..1], y up. - **rect_max_x** (*double*, default: `1.0`) — Right edge, normalized [0..1]. - **rect_max_y** (*double*, default: `1.0`) — Top edge, normalized [0..1], y up. - **element** (*enum*, default: `face`) — Whether to select vertices or faces (by centroid). - **mode** (*enum*, default: `replace`) — Replace the current selection, add to it, or subtract from it. - **visible_only** (*bool*, default: `False`) — When selecting faces in the 3D view, keep only faces not occluded from the current viewpoint (ray-traced visibility). ``` --- (filter-select-visible-faces)= ## Select Visible Faces **Categories:** `Selection/by Visibility` **Plugin:** qmeshlab.filter.embree Selects faces visible from a user-defined direction. ```{py:function} ms.select_visible_faces(**params) :module: _qmeshlab Select visible face
This filter displays all visible faces from a given direction, selecting the face is is visible from the point given.This filter utilizes the Embree3 library by INTEL. **Parameters:** - **direction** (*point3f*, default: `[1.0, 1.0, 0.0]`) — Visibility ray direction. ``` --- (filter-select-visible-vertices)= ## Select Visible Vertices **Categories:** `Selection/by Visibility` **Plugin:** qmeshlab.filter.select Select the vertices visible from a given viewpoint. ```{py:function} ms.select_visible_vertices(**params) :module: _qmeshlab Selects the vertices of the current layer that are **visible from a viewpoint**, using the *hidden point removal* operator: the points are inverted through a sphere centred on the viewpoint, and the ones landing on the convex hull of the inverted set are the visible ones. Only vertex positions are used, so this works on a raw point cloud with no faces and no normals — which is what it is for. It is the point-cloud counterpart of *Select Visible Faces*, which needs a surface to cast rays against. **Radius Threshold** sets the inversion sphere radius as `radius * 10^threshold`. Larger values mark more points visible: use a large threshold for dense clouds and a small one for sparse clouds. The selection is **added** to the current one; clear it first for an exact result. Reference: Sagi Katz, Ayellet Tal, Ronen Basri, **Direct Visibility of Point Sets**, ACM Transactions on Graphics 26(3), 2007. **Parameters:** - **radiusThreshold** (*double*, default: `0.0`) — Exponent of the inversion sphere radius (radius * 10^threshold). Larger values mark more points as visible; use a large value for dense clouds, a small one for sparse clouds. - **usecamera** (*bool*, default: `False`) — Uses the ViewPoint from the camera associated to the current mesh. If there is no camera, an error occurs. - **viewpoint** (*point3f*, default: `[0.0, 0.0, 0.0]`) — Viewpoint position (ignored when UseCamera is true). ``` --- (filter-set-texture)= ## Set Texture **Categories:** `Texture/Assignment` **Plugin:** qmeshlab.filter.texture Associate an image or generated dummy texture with the current mesh UV coordinates. ```{py:function} ms.set_texture(**params) :module: _qmeshlab Associates one texture with the current mesh UV parametrization, replacing its existing texture associations. By default, the filter generates a checkerboard that makes UV scale and distortion immediately visible. Disable **Use dummy texture** to select an existing image file instead. **Parameters:** - **use_dummy_texture** (*bool*, default: `True`) — If checked, generate a dummy texture instead of loading an image. Disable it to select an image using 'Texture file'. - **textName** (*fileopen*, default: ``) — Sets the given input image as unique texture of the mesh. - **dummy_img_size** (*int*, default: `512`) — Size in pixel of the square dummy texture. - **dummy_check_size** (*int*, default: `64`) — Size in pixel of the checkerboard or grid cell of the dummy texture. - **dummy_type** (*enum*, default: `checkerboard`) — Choose between a checkerboard and a line grid. ``` --- (filter-convert-normal-map-to-tangent-space)= ## Convert: Object-Space Normal Map to Tangent-Space **Categories:** `Texture/Conversion` **Plugin:** qmeshlab.filter.texture Convert an object-space normal map into a tangent-space normal map for the current mesh UV slot. ```{py:function} ms.convert_normal_map_to_tangent_space(**params) :module: _qmeshlab Converts an object-space normal map into a tangent-space normal map using the current mesh geometry, normals, and UV parametrization. The result is suitable for direct use in QMeshLab's PBR normal-texture channel. **Parameters:** - **targetTexture** (*textureref*, default: `1`) — Choose the mesh texture slot that owns the UV layout to process. Only faces whose per-wedge texture index uses this slot are converted, and this is also the material slot whose PBR normal channel can be updated. This is separate from the source image because the object-space normal map may be stored as another associated texture. - **sourceNormalMap** (*textureref*, default: `1`) — Choose the associated texture image to interpret as the object-space normal map. Its pixels are sampled through the selected UV / Material Slot. - **targetNormalMap** (*textureoutputref*, default: `tangent_normal.png`) — Choose where the generated tangent-space normal map should go: overwrite an existing associated texture, or create a new texture file and add it to the mesh texture list. - **bindAsPbrNormal** (*bool*, default: `True`) — If enabled, the converted texture is added to the mesh associated texture list and assigned to the selected slot's PBR normal channel. - **invertX** (*bool*, default: `False`) — Invert the tangent-space X channel in the generated normal map. - **invertY** (*bool*, default: `False`) — Invert the tangent-space Y channel in the generated normal map. - **invertZ** (*bool*, default: `False`) — Invert the tangent-space Z channel in the generated normal map. - **normalScale** (*double*, default: `1.0`) — Normal intensity stored in the selected material slot when binding the converted map as a PBR normal texture. ``` --- (filter-pack-texture-per-mesh)= ## Pack Texture Images **Categories:** `Texture/Packing`, `Parametrization/Atlas Packing` **Plugin:** qmeshlab.filter.texture Combines complete texture images into fewer atlas images and remaps the mesh UVs. ```{py:function} ms.pack_texture_per_mesh(**params) :module: _qmeshlab Combines the complete texture images used by the current mesh into a smaller number of atlas images and creates a new mesh layer referencing the result. Each source image is kept intact, placed as a rectangular region in one output image, and copied without rescaling. The mesh's per-wedge texture indices and UV coordinates are then remapped so every triangle continues to sample the same source pixels from their new atlas location. The original mesh and its textures are left unchanged. This operation packs whole images, not individual UV islands or charts. Use **Defragment Texture Atlas** when the goal is to rearrange or optimize the UV charts themselves. Output image dimensions are determined automatically from the source image sizes and their packed arrangement, so they are not necessarily square or powers of two. **Target textures** specifies the desired number of output atlas images and must be smaller than the number of texture groups actually used by mesh faces. Source images are distributed between those outputs before rectangular packing. **Gutter** reserves the requested number of pixels around every source image. Border pixels are extruded into this area, reducing color bleeding when the atlas is displayed with bilinear filtering. Every face must reference one valid texture consistently across its three wedges, and all UV coordinates must lie inside `[0,1]`. Repeated or tiled texture coordinates cannot be represented safely after whole-image atlas packing, so such meshes are rejected rather than producing altered texture mapping. **Parameters:** - **containerNum** (*int*, default: `1`) — Number of output images. It must be smaller than the number of texture groups actually used by the mesh. - **gutter** (*int*, default: `4`) — Border pixels reserved around every source image. The source image edges are extruded into this area to prevent bilinear-filtering bleed. ``` --- (filter-transfer-texture-to-vertex-color)= ## Transfer: Texture to Vertex Color **Categories:** `Transfer/Attribute to Texture`, `Attribute/Color` **Plugin:** qmeshlab.filter.texture Generate vertex colors by sampling texture colors from the same mesh or another mesh. ```{py:function} ms.transfer_texture_to_vertex_color(**params) :module: _qmeshlab Generates Vertex Color values picking color from a texture (same mesh or another mesh). **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The mesh with associated texture that we want to sample from. - **targetMesh** (*mesh*, default: `@otherMeshIndex`) — The mesh whose vertex color will be filled according to source mesh texture. - **upperBound** (*absperc*, default: `@bboxDiag002`) — Sample points for which we do not find anything within this distance are rejected and not considered for recovering color. - **sourceTexture** (*textureref*, default: `0`) — Choose which associated source texture to sample. Automatic uses the source mesh per-face texture slot assignment. ``` --- (filter-transfer-vertex-attributes-to-texture)= ## Transfer: Vertex Attributes to Texture **Categories:** `Transfer/Attribute to Texture`, `Texture` **Plugin:** qmeshlab.filter.texture Transfer texture color, vertex color, normals, or quality from one mesh into another mesh texture. ```{py:function} ms.transfer_vertex_attributes_to_texture(**params) :module: _qmeshlab Transfer texture color, vertex color or normal from one mesh the texture of another mesh. This may be useful to restore detail lost in simplification, or resample a texture in a different parametrization. **Parameters:** - **sourceMesh** (*mesh*, default: `@currentMeshIndex`) — The mesh that contains the source data that we want to transfer. - **targetMesh** (*mesh*, default: `@otherMeshIndex`) — The mesh whose texture will be filled according to source mesh data. - **AttributeEnum** (*enum*, default: `vertex_color`) — Choose what attribute has to be transferred onto the target texture. You can choose between per-vertex attributes or transfer color information from source mesh texture. - **upperBound** (*absperc*, default: `@bboxDiag002`) — Sample points for which we do not find anything within this distance are rejected and not considered for recovering data. - **textName** (*filesave*, default: `texture.png`) — Base path of the texture image to be created. If more than one target texture slot is used, numeric suffixes are added automatically. - **textW** (*int*, default: `1024`) — The texture width. - **textH** (*int*, default: `1024`) — The texture height. - **overwrite** (*bool*, default: `False`) — If target mesh has associated textures, overwrite them instead of creating new files. - **pullpush** (*bool*, default: `True`) — If enabled the unmapped texture space is colored using a pull-push filling algorithm, otherwise it is left black. - **sourceTexture** (*textureref*, default: `0`) — When Texture Color is selected, choose which associated source texture to sample. Automatic uses the source mesh per-face texture slot assignment. ``` --- (filter-transfer-vertex-color-to-texture)= ## Transfer: Vertex Color to Texture **Categories:** `Transfer/Attribute to Texture`, `Texture` **Plugin:** qmeshlab.filter.texture Bake per-vertex color into texture image(s) using the current UV parametrization. ```{py:function} ms.transfer_vertex_color_to_texture(**params) :module: _qmeshlab Fills the specified texture using per-vertex color data of the mesh. **Parameters:** - **textName** (*filesave*, default: `texture.png`) — Base path of the texture image to be created. If more than one texture slot is used, numeric suffixes are added automatically. - **textW** (*int*, default: `1024`) — The texture width. - **textH** (*int*, default: `1024`) — The texture height. - **overwrite** (*bool*, default: `False`) — If current mesh has associated textures, overwrite them instead of creating new files. - **pullpush** (*bool*, default: `True`) — If enabled the unmapped texture space is colored using a pull-push filling algorithm, otherwise it is left black. ``` --- (filter-transfer-color-face-to-vertex)= ## Transfer Color: Face to Vertex **Categories:** `Transfer/Mesh to Mesh`, `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Transfer face colors to vertex colors. ```{py:function} ms.transfer_color_face_to_vertex(**params) :module: _qmeshlab Face to Vertex color transfer This filter has no parameters. ``` --- (filter-transfer-color-mesh-to-face)= ## Transfer Color: Mesh to Face **Categories:** `Transfer/Mesh to Mesh`, `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Transfer the per-mesh color to face colors. ```{py:function} ms.transfer_color_mesh_to_face(**params) :module: _qmeshlab Mesh to Face color transfer This filter has no parameters. ``` --- (filter-transfer-color-texture-to-vertex)= ## Transfer Color: Texture to Vertex **Categories:** `Transfer/Mesh to Mesh`, `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Sample associated textures into vertex colors. ```{py:function} ms.transfer_color_texture_to_vertex(**params) :module: _qmeshlab Texture to Vertex color transfer **Parameters:** - **sourceTexture** (*textureref*, default: `0`) — Choose which associated texture to sample. Automatic uses each face's per-wedge texture slot assignment, matching MeshLab's multi-texture behavior. ``` --- (filter-transfer-color-vertex-to-face)= ## Transfer Color: Vertex to Face **Categories:** `Transfer/Mesh to Mesh`, `Attribute/Color` **Plugin:** qmeshlab.filter.colorproc Transfer vertex colors to face colors. ```{py:function} ms.transfer_color_vertex_to_face(**params) :module: _qmeshlab Vertex to Face color transfer This filter has no parameters. ``` --- (filter-transfer-quality-face-to-vertex)= ## Transfer Quality: Face to Vertex **Categories:** `Transfer/Mesh to Mesh`, `Attribute/Scalar` **Plugin:** qmeshlab.filter.colorproc Transfer face quality to vertex quality. ```{py:function} ms.transfer_quality_face_to_vertex(**params) :module: _qmeshlab Face to Vertex quality transfer **Parameters:** - **areaWeight** (*bool*, default: `True`) — If true the vertex quality is computed according to the surface of the involved faces. ``` --- (filter-transfer-quality-vertex-to-face)= ## Transfer Quality: Vertex to Face **Categories:** `Transfer/Mesh to Mesh`, `Attribute/Scalar` **Plugin:** qmeshlab.filter.colorproc Transfer vertex quality to face quality. ```{py:function} ms.transfer_quality_vertex_to_face(**params) :module: _qmeshlab Vertex to Face quality transfer This filter has no parameters. ``` --- (filter-transfer-vertex-attributes)= ## Vertex Attribute Transfer **Categories:** `Transfer/Mesh to Mesh` **Plugin:** qmeshlab.filter.sampling Transfer attributes from one mesh to another by closest-point projection. ```{py:function} ms.transfer_vertex_attributes(**params) :module: _qmeshlab Transfer the chosen per-vertex attributes from one layer to another. Useful to transfer attributes to different representations of a same object.
For each vertex of the target mesh the closest point (not vertex!) on the source mesh is computed, and the requested interpolated attributes from that source point are copied into the target vertex.
The algorithm assumes that the two meshes are reasonably similar and aligned. **Parameters:** - **SourceMesh** (*mesh*, default: `@currentMeshIndex`) — The mesh that provides the attributes to transfer. - **TargetMesh** (*mesh*, default: `@otherMeshIndex`) — The mesh whose vertices receive the transferred attributes. - **VertexSampling** (*bool*, default: `False`) — If enabled, transfer attributes from the closest source vertex instead of the closest point on the source surface. - **GeomTransfer** (*bool*, default: `False`) — Snap target vertices onto the corresponding closest point on the source. - **NormalTransfer** (*bool*, default: `False`) — Transfer interpolated normals from the source. - **ColorTransfer** (*bool*, default: `True`) — Transfer vertex colors from the source. - **QualityTransfer** (*bool*, default: `False`) — Transfer vertex quality from the source. - **SelectionTransfer** (*bool*, default: `False`) — Select target vertices whose corresponding closest point lies on selected source elements. - **QualityDistance** (*bool*, default: `False`) — Store the transfer distance in the target vertex quality. - **SaveBarycentric** (*bool*, default: `False`) — Store barycentric coordinates and nearest face or vertex indices as per-vertex attributes on the target mesh. - **UpperBound** (*absperc*, default: `@bboxDiag01`) — Closest-point searches farther than this threshold are rejected. - **onSelected** (*bool*, default: `False`) — If enabled, transfer only to selected target vertices. ``` --- (filter-compute-color-and-texture-from-active-rasters-projection)= ## Project Active Rasters Color to Current Mesh Texture **Categories:** `Transfer/Raster to Mesh`, `Texture` **Plugin:** qmeshlab.filter.color_projection Project color from all visible rasters onto a new mesh texture using wedge UV coordinates. ```{py:function} ms.compute_color_and_texture_from_active_rasters_projection(**params) :module: _qmeshlab Projects color information from all visible and valid rasters onto a new texture image, using the mesh's existing wedge UV coordinates. The result is saved as a texture image and associated with the mesh. **Parameters:** - **textName** (*filesave*, default: `projected_texture.png`) — Output texture image file path. - **texsize** (*int*, default: `1024`) — Square texture image size in pixels. Should be a power of 2. - **dorefill** (*bool*, default: `True`) — If true, unfilled areas of the texture atlas are interpolated using PullPush to avoid visible seams when mipmapping. - **deptheta** (*double*, default: `0.5`) — Tolerance value for depth buffer comparison (shadow buffer). - **useangle** (*bool*, default: `True`) — If true, color contribution is weighted by the angle between the surface normal and the view direction. - **usedistance** (*bool*, default: `True`) — If true, color contribution is weighted by the texel distance from the camera. - **useborders** (*bool*, default: `True`) — If true, color contribution is weighted by the pixel distance from the image boundaries. - **usesilhouettes** (*bool*, default: `True`) — If true, color contribution is weighted by the pixel distance from depth discontinuities (silhouettes). - **usealpha** (*bool*, default: `False`) — If true, the alpha channel of the raster image is used as an additional weight. ``` --- (filter-compute-color-from-active-rasters-projection)= ## Project Active Rasters Color to Current Mesh **Categories:** `Transfer/Raster to Mesh`, `Attribute/Color` **Plugin:** qmeshlab.filter.color_projection Project color from all visible rasters onto the mesh vertices with weighted blending. ```{py:function} ms.compute_color_from_active_rasters_projection(**params) :module: _qmeshlab Projects color information from all visible and valid rasters onto the mesh vertices using perspective projection and weighted blending. Weights can account for view angle, distance, image border proximity, depth discontinuities, and image alpha. **Parameters:** - **deptheta** (*double*, default: `0.5`) — Tolerance value for depth buffer comparison (shadow buffer). - **onselection** (*bool*, default: `False`) — If true, projection is only applied to selected vertices. - **useangle** (*bool*, default: `True`) — If true, color contribution is weighted by the angle between the surface normal and the view direction. - **usedistance** (*bool*, default: `True`) — If true, color contribution is weighted by the vertex distance from the camera. - **useborders** (*bool*, default: `True`) — If true, color contribution is weighted by the pixel distance from the image boundaries. - **usesilhouettes** (*bool*, default: `True`) — If true, color contribution is weighted by the pixel distance from depth discontinuities (silhouettes). - **usealpha** (*bool*, default: `False`) — If true, the alpha channel of the raster image is used as an additional weight. - **blankColor** (*color*, default: `#00000000`) — Areas with no valid projection will be filled with this color. If all channels are 0, the original color is preserved. - **preserveoccluded** (*bool*, default: `False`) — If true, depth-occluded vertices keep their original color instead of being assigned the blank color. ``` --- (filter-compute-color-from-current-raster-projection)= ## Project Current Raster Color to Current Mesh **Categories:** `Transfer/Raster to Mesh`, `Attribute/Color` **Plugin:** qmeshlab.filter.color_projection Project the current raster image color onto the mesh vertices. ```{py:function} ms.compute_color_from_current_raster_projection(**params) :module: _qmeshlab Projects color information from the current raster onto the mesh vertices using perspective projection. Optionally uses a software depth buffer to restrict projection to visible faces only. **Parameters:** - **usedepth** (*bool*, default: `True`) — If true, a depth buffer is used to restrict projection to visible faces only. - **deptheta** (*double*, default: `0.5`) — Tolerance value for depth buffer comparison (shadow buffer). - **onselection** (*bool*, default: `False`) — If true, projection is only applied to selected vertices. - **blankColor** (*color*, default: `#00000000`) — Areas that cannot be projected will be filled with this color. If all channels are 0, the original color is preserved. - **preserveoccluded** (*bool*, default: `False`) — If true, depth-occluded vertices keep their original color instead of being assigned the blank color. ```