Skip to content

Libs/Mesh/Mesh.h

Namespaces

Name
shapeworks
User usage reporting (telemetry)

Classes

Name
class shapeworks::Mesh
class shapeworks::MeshReader
reads mesh (used only by one of the Mesh constructors)

Source code

```cpp

pragma once

include

include "Shapeworks.h"

class vtkStaticCellLocator; class vtkKdTreePointLocator;

namespace shapeworks {

class Mesh { public: enum FieldType { Point, Face }; enum AlignmentType { Rigid, Similarity, Affine }; enum DistanceMethod { PointToPoint, PointToCell }; enum CurvatureType { Principal, Gaussian, Mean }; enum SubdivisionType { Butterfly, Loop };

Mesh(const std::string& pathname);

void set_id(int id) { id_ = id; } int get_id() const { return id_; }

Mesh(vtkSmartPointer meshPtr) : poly_data_(meshPtr) { if (!poly_data_) throw std::invalid_argument("null meshPtr"); invalidateLocators(); }

Mesh(const Mesh& orig) : poly_data_(vtkSmartPointer::New()) { poly_data_->DeepCopy(orig.poly_data_); id_ = orig.id_; invalidateLocators(); }

Mesh(Mesh&& orig) : poly_data_(orig.poly_data_), id_{orig.id_} { orig.poly_data_ = nullptr; }

Mesh& operator=(const Mesh& orig) { poly_data_ = vtkSmartPointer::New(); poly_data_->DeepCopy(orig.poly_data_); id_ = orig.id_; invalidateLocators(); return *this; }

Mesh(const Eigen::MatrixXd& points, const Eigen::MatrixXi& faces);

Mesh& operator=(Mesh&& orig) { poly_data_ = orig.poly_data_; id_ = orig.id_; orig.poly_data_ = nullptr; orig.id_ = -1; return *this; }

Mesh& operator+=(const Mesh& otherMesh);

vtkSmartPointer getVTKMesh() const { return this->poly_data_; }

Mesh& write(const std::string& pathname, bool binaryFile = false);

Mesh& coverage(const Mesh& otherMesh, bool allowBackIntersections = true, double angleThreshold = 0, double backSearchRadius = 0);

Mesh& smooth(int iterations = 0, double relaxation = 0.0);

Mesh& smoothSinc(int iterations = 0, double passband = 0.0);

Mesh& remesh(int numVertices, double adaptivity = 1.0);

Mesh& remeshPercent(double percentage, double adaptivity = 1.0);

Mesh& invertNormals();

Mesh& reflect(const Axis& axis, const Vector3& origin = makeVector({0.0, 0.0, 0.0}));

MeshTransform createTransform(const Mesh& target, AlignmentType align = Similarity, unsigned iterations = 10);

Mesh& applyTransform(const MeshTransform transform);

Mesh& rotate(const double angle, const Axis axis);

Mesh& fillHoles(double hole_size = 1000.0);

Mesh& clean();

Mesh& probeVolume(const Image& image);

Mesh& clip(const Plane plane);

Mesh& translate(const Vector3& v);

Mesh& scale(const Vector3& v);

PhysicalRegion boundingBox() const;

Mesh& fixElement();

Mesh& fixNonManifold();

Mesh& extractLargestComponent();

bool detectNonManifold();

bool detectTriangular();

std::vector distance(const Mesh& target, const DistanceMethod method = PointToCell) const;

Mesh& clipClosedSurface(const Plane plane);

Mesh& computeNormals();

Point3 closestPoint(const Point3 point, double& distance, vtkIdType& face_id) const;

int closestPointId(const Point3 point) const;

bool isPointInside(const Point3 point) const;

double geodesicDistance(int source, int target) const;

Field geodesicDistance(const Point3 landmark) const;

Field geodesicDistance(const std::vector curve) const;

Field curvature(const CurvatureType type = Principal) const;

void computeFieldGradient(const std::string& field) const;

Eigen::Vector3d computeFieldGradientAtPoint(const std::string& field, const Point3& query) const;

double interpolateFieldAtPoint(const std::string& field, const Point3& query) const;

Mesh& applySubdivisionFilter(const SubdivisionType type = Butterfly, int subdivision = 1);

Image toImage(PhysicalRegion region = PhysicalRegion(), Point3 spacing = Point3({1., 1., 1.})) const;

Image toDistanceTransform(PhysicalRegion region = PhysicalRegion(), const Point3 spacing = Point3({1., 1., 1.}), const Dims padding = Dims({1, 1, 1})) const;

Mesh& computeThickness(Image& image, Image* dt = nullptr, double max_dist = 10000, double median_radius = 5.0, std::string distance_mesh = "");

Mesh& computeLandmarkGeodesics(const std::vector& landmarks);

// query functions //

Point3 center() const;

Point3 centerOfMass() const;

double getSurfaceArea() const;

int numPoints() const { return poly_data_->GetNumberOfPoints(); }

int numFaces() const { return poly_data_->GetNumberOfCells(); }

Eigen::MatrixXd points() const;

Eigen::MatrixXi faces() const;

Point3 getPoint(int id) const;

IPoint3 getFace(int id) const;

// fields of mesh points //

std::vector getFieldNames() const;

Mesh& setField(const std::string name, Array array, const FieldType type);

Field getField(const std::string& name, const FieldType type) const;

void setFieldValue(const std::string& name, int idx, double value);

double getFieldValue(const std::string& name, int idx) const;

Eigen::VectorXd getMultiFieldValue(const std::string& name, int idx) const;

// mesh comparison //

bool compareAllPoints(const Mesh& other_mesh) const;

bool compareAllFaces(const Mesh& other_mesh) const;

bool compareAllFields(const Mesh& other_mesh, const double eps = 1e4) const;

bool compareField(const Mesh& other_mesh, const std::string& name1, const std::string& name2 = "", const double eps = -1.0) const;

// todo: add support for comparison of fields of mesh faces (ex: their normals)

bool compare(const Mesh& other_mesh, const double eps = -1.0) const;

bool operator==(const Mesh& other) const { return compare(other); }

// public static functions //

static std::vector getSupportedTypes() { return {"vtk", "vtp", "ply", "stl", "obj"}; }

double getFFCValue(Eigen::Vector3d query) const;

Eigen::Vector3d getFFCGradient(Eigen::Vector3d query) const;

vtkSmartPointer getIGLMesh(Eigen::MatrixXd& V, Eigen::MatrixXi& F) const; // Copied directly from Surface. this->poly_data_ becomes this->mesh. // WARNING: Copied directly // from Surface. TODO: When refactoring, take this into account.

vtkSmartPointer clipByField(const std::string& name, double value);

vtkSmartPointer getCellLocator() const { updateCellLocator(); return cellLocator; }

int getClosestFace(const Point3& point) const;

Eigen::Vector3d computeBarycentricCoordinates(const Eigen::Vector3d& pt, int face) const; // // WARNING: Copied directly from Surface. TODO: When refactoring, take this into account.

void interpolate_scalars_to_mesh(std::string name, Eigen::VectorXd positions, Eigen::VectorXd scalar_values);

std::string checkIntegrity() const;

private: friend struct SharedCommandData; Mesh() : poly_data_(nullptr) {} // only for use by SharedCommandData since a Mesh should always be valid, never "empty"

MeshTransform createRegistrationTransform(const Mesh& target, AlignmentType align = Similarity, unsigned iterations = 10) const;

Mesh& setFieldForFaces(const std::string name, Array array);

Field getFieldForFaces(const std::string& name) const;

void invalidateLocators() const;

mutable vtkSmartPointer cellLocator; void updateCellLocator() const;

mutable vtkSmartPointer pointLocator; void updatePointLocator() const;

vtkSmartPointer poly_data_;

int id_{-1}; };

std::ostream& operator<<(std::ostream& os, const Mesh& mesh);

class MeshReader { static vtkSmartPointer read(const std::string& pathname); friend Mesh::Mesh(const std::string& pathname); };

} // namespace shapeworks ```


Updated on 2026-03-31 at 16:02:11 +0000