Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Libs/Analyze/Shape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ MeshGroup Shape::get_original_meshes(bool wait) {
return original_meshes_;
}

if (!original_meshes_.valid() || original_meshes_.meshes().size() != subject_->get_number_of_domains()) {
if (!original_meshes_.valid() || original_meshes_.meshes().size() != subject_->get_original_filenames().size()) {
original_meshes_ = MeshGroup(subject_->get_number_of_domains());
generate_meshes(subject_->get_original_filenames(), original_meshes_, true, wait);
}
Expand Down
8 changes: 7 additions & 1 deletion Libs/Common/Logging.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,13 @@ void Logging::log_message(const std::string& message, const int line, const char
}

//-----------------------------------------------------------------------------
void Logging::log_only(const std::string& message, const int line, const char* file) const {
void Logging::log_only(const std::string& message, const int line, const char* file, const char* function) const {
if (spd::get_level() == spd::level::debug) {
// when in debug mode, treat this as a debug message
log_debug(message, line, file, function);
return;
}

spd::info(message);
if (log_open_) {
spd::get("file")->info(message);
Expand Down
4 changes: 2 additions & 2 deletions Libs/Common/Logging.h
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ class Logging {
void log_message(const std::string& message, const int line, const char* file) const;

//! Log a message, use SW_LOG_ONLY macro
void log_only(const std::string& message, const int line, const char* file) const;
void log_only(const std::string& message, const int line, const char* file, const char *function) const;

//! Log a stack trace message, use SW_LOG_STACK macro
void log_stack(const std::string& message) const;
Expand Down Expand Up @@ -176,7 +176,7 @@ class Logging {

//! Log only macro
#define SW_LOG_ONLY(message, ...) \
shapeworks::Logging::Instance().log_only(safe_format(message, ##__VA_ARGS__), __LINE__, __FILE__);
shapeworks::Logging::Instance().log_only(safe_format(message, ##__VA_ARGS__), __LINE__, __FILE__, __FUNCTION__);

//! Log warning macro
#define SW_WARN(message, ...) \
Expand Down
434 changes: 326 additions & 108 deletions Libs/Groom/Groom.cpp

Large diffs are not rendered by default.

8 changes: 7 additions & 1 deletion Libs/Groom/Groom.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ class Groom {
std::atomic<int> progress_counter_ = 0;

private:
enum class MeshSource { Original, Groomed };

//! Return the number of operations that will be performed
int get_total_ops();

Expand Down Expand Up @@ -66,6 +68,9 @@ class Groom {
//! Create shared boundary surface and contour if requested
bool run_shared_boundaries();

//! Remove all shared boundaries
void clear_unused_shared_boundaries();

void assign_transforms(std::vector<std::vector<double>> transforms, int domain, bool global = false);

static std::vector<std::vector<double>> get_icp_transforms(const std::vector<Mesh> meshes, Mesh reference);
Expand All @@ -80,7 +85,8 @@ class Groom {

std::vector<vtkSmartPointer<vtkPoints>> get_combined_points();

Mesh get_mesh(int subject, int domain, bool transformed = false);
Mesh get_mesh(int subject, int domain, bool transformed = false, MeshSource source = MeshSource::Original);


vtkSmartPointer<vtkPoints> get_landmarks(int subject, int domain);

Expand Down
209 changes: 147 additions & 62 deletions Libs/Groom/GroomParameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const std::string SHARED_BOUNDARY = "shared_boundary";
const std::string SHARED_BOUNDARY_FIRST_DOMAIN = "shared_boundary_first_domain";
const std::string SHARED_BOUNDARY_SECOND_DOMAIN = "shared_boundary_second_domain";
const std::string SHARED_BOUNDARY_TOLERANCE = "shared_boundary_tolerance";
const std::string SHARED_BOUNDARIES = "shared_boundaries";

} // namespace Keys

Expand Down Expand Up @@ -107,59 +108,90 @@ const bool shared_boundary = false;
const std::string shared_boundary_first_domain = "";
const std::string shared_boundary_second_domain = "";
const double shared_boundary_tolerance = 1e-1;
const std::string shared_boundaries = ""; // Empty string = no boundaries

} // namespace Defaults

// Helper methods for SharedBoundary struct
//---------------------------------------------------------------------------
std::string GroomParameters::SharedBoundary::to_string() const {
return first_domain + "|" + second_domain + "|" + std::to_string(tolerance);
}

//---------------------------------------------------------------------------
GroomParameters::SharedBoundary GroomParameters::SharedBoundary::from_string(const std::string& str) {
std::vector<std::string> parts;
std::stringstream ss(str);
std::string item;

while (std::getline(ss, item, '|')) {
parts.push_back(item);
}

if (parts.size() != 3) {
throw std::runtime_error("Invalid shared boundary string format");
}

SharedBoundary boundary;
boundary.first_domain = parts[0];
boundary.second_domain = parts[1];
boundary.tolerance = std::stod(parts[2]);
return boundary;
}

//---------------------------------------------------------------------------
GroomParameters::GroomParameters(ProjectHandle project, std::string domain_name)
: project_(project), domain_name_(domain_name) {
params_ = project_->get_parameters(Parameters::GROOM_PARAMS, domain_name_);

std::vector<std::string> all_params = {Keys::CROP,
Keys::REFLECT,
Keys::REFLECT_COLUMN,
Keys::REFLECT_CHOICE,
Keys::REFLECT_AXIS,
Keys::RESAMPLE,
Keys::ISOTROPIC,
Keys::ISO_SPACING,
Keys::SPACING,
Keys::CONVERT_MESH,
Keys::FILL_MESH_HOLES,
Keys::FILL_HOLES,
Keys::ISOLATE,
Keys::PAD,
Keys::PAD_VALUE,
Keys::ANTIALIAS,
Keys::ANTIALIAS_AMOUNT,
Keys::BLUR,
Keys::BLUR_SIGMA,
Keys::FASTMARCHING,
Keys::MESH_SMOOTH,
Keys::MESH_SMOOTHING_METHOD,
Keys::MESH_SMOOTHING_VTK_LAPLACIAN_ITERATIONS,
Keys::MESH_SMOOTHING_VTK_LAPLACIAN_RELAXATION,
Keys::MESH_SMOOTHING_VTK_WINDOWED_SINC_ITERATIONS,
Keys::MESH_SMOOTHING_VTK_WINDOWED_SINC_PASSBAND,
Keys::ALIGNMENT_METHOD,
Keys::ALIGNMENT_ENABLED,
Keys::ALIGNMENT_REFERENCE,
Keys::ALIGNMENT_REFERENCE_CHOSEN,
Keys::ALIGNMENT_SUBSET_SIZE,
Keys::GROOM_OUTPUT_PREFIX,
Keys::REMESH,
Keys::REMESH_PERCENT_MODE,
Keys::REMESH_PERCENT,
Keys::REMESH_NUM_VERTICES,
Keys::REMESH_GRADATION,
Keys::GROOM_ALL_DOMAINS_THE_SAME,
Keys::SKIP_GROOMING,
Keys::CENTER,
Keys::ICP,
Keys::SHARED_BOUNDARY,
Keys::SHARED_BOUNDARY_FIRST_DOMAIN,
Keys::SHARED_BOUNDARY_SECOND_DOMAIN,
Keys::SHARED_BOUNDARY_TOLERANCE};
std::vector<std::string> all_params = {
Keys::CROP,
Keys::REFLECT,
Keys::REFLECT_COLUMN,
Keys::REFLECT_CHOICE,
Keys::REFLECT_AXIS,
Keys::RESAMPLE,
Keys::ISOTROPIC,
Keys::ISO_SPACING,
Keys::SPACING,
Keys::CONVERT_MESH,
Keys::FILL_MESH_HOLES,
Keys::FILL_HOLES,
Keys::ISOLATE,
Keys::PAD,
Keys::PAD_VALUE,
Keys::ANTIALIAS,
Keys::ANTIALIAS_AMOUNT,
Keys::BLUR,
Keys::BLUR_SIGMA,
Keys::FASTMARCHING,
Keys::MESH_SMOOTH,
Keys::MESH_SMOOTHING_METHOD,
Keys::MESH_SMOOTHING_VTK_LAPLACIAN_ITERATIONS,
Keys::MESH_SMOOTHING_VTK_LAPLACIAN_RELAXATION,
Keys::MESH_SMOOTHING_VTK_WINDOWED_SINC_ITERATIONS,
Keys::MESH_SMOOTHING_VTK_WINDOWED_SINC_PASSBAND,
Keys::ALIGNMENT_METHOD,
Keys::ALIGNMENT_ENABLED,
Keys::ALIGNMENT_REFERENCE,
Keys::ALIGNMENT_REFERENCE_CHOSEN,
Keys::ALIGNMENT_SUBSET_SIZE,
Keys::GROOM_OUTPUT_PREFIX,
Keys::REMESH,
Keys::REMESH_PERCENT_MODE,
Keys::REMESH_PERCENT,
Keys::REMESH_NUM_VERTICES,
Keys::REMESH_GRADATION,
Keys::GROOM_ALL_DOMAINS_THE_SAME,
Keys::SKIP_GROOMING,
Keys::CENTER,
Keys::ICP,
Keys::SHARED_BOUNDARY,
Keys::SHARED_BOUNDARY_FIRST_DOMAIN,
Keys::SHARED_BOUNDARY_SECOND_DOMAIN,
Keys::SHARED_BOUNDARY_TOLERANCE,
Keys::SHARED_BOUNDARIES,
};

std::vector<std::string> to_remove;

Expand Down Expand Up @@ -497,40 +529,93 @@ bool GroomParameters::get_skip_grooming() { return params_.get(Keys::SKIP_GROOMI
void GroomParameters::set_skip_grooming(bool skip) { params_.set(Keys::SKIP_GROOMING, skip); }

//---------------------------------------------------------------------------
bool GroomParameters::get_shared_boundary() { return params_.get(Keys::SHARED_BOUNDARY, Defaults::shared_boundary); }
bool GroomParameters::get_shared_boundaries_enabled() {
return params_.get(Keys::SHARED_BOUNDARY, Defaults::shared_boundary);
}

//---------------------------------------------------------------------------
void GroomParameters::set_shared_boundary(bool shared_boundary) { params_.set(Keys::SHARED_BOUNDARY, shared_boundary); }
void GroomParameters::set_shared_boundaries_enabled(bool enabled) { params_.set(Keys::SHARED_BOUNDARY, enabled); }

//---------------------------------------------------------------------------
std::string GroomParameters::get_shared_boundary_first_domain() {
return params_.get(Keys::SHARED_BOUNDARY_FIRST_DOMAIN, Defaults::shared_boundary_first_domain);
}
std::vector<GroomParameters::SharedBoundary> GroomParameters::get_shared_boundaries() {
std::vector<SharedBoundary> boundaries;

//---------------------------------------------------------------------------
void GroomParameters::set_shared_boundary_first_domain(const std::string& domain_name) {
params_.set(Keys::SHARED_BOUNDARY_FIRST_DOMAIN, domain_name);
// Try new format first
if (params_.key_exists(Keys::SHARED_BOUNDARIES)) {
std::string boundaries_str = params_.get(Keys::SHARED_BOUNDARIES, Defaults::shared_boundaries);
if (!boundaries_str.empty()) {
std::stringstream ss(boundaries_str);
std::string boundary_str;

while (std::getline(ss, boundary_str, ';')) {
if (!boundary_str.empty()) {
try {
boundaries.push_back(SharedBoundary::from_string(boundary_str));
} catch (const std::exception& e) {
SW_WARN("Failed to parse shared boundary: " + boundary_str);
}
}
}
}
return boundaries;
}

// Migration: convert old single boundary format
if (params_.get(Keys::SHARED_BOUNDARY, Defaults::shared_boundary)) {
SharedBoundary boundary;
boundary.first_domain =
std::string(params_.get(Keys::SHARED_BOUNDARY_FIRST_DOMAIN, Defaults::shared_boundary_first_domain));
boundary.second_domain =
std::string(params_.get(Keys::SHARED_BOUNDARY_SECOND_DOMAIN, Defaults::shared_boundary_second_domain));
boundary.tolerance = params_.get(Keys::SHARED_BOUNDARY_TOLERANCE, Defaults::shared_boundary_tolerance);
boundaries.push_back(boundary);

// Migrate to new format
set_shared_boundaries(boundaries);
}

return boundaries;
}

//---------------------------------------------------------------------------
std::string GroomParameters::get_shared_boundary_second_domain() {
return params_.get(Keys::SHARED_BOUNDARY_SECOND_DOMAIN, Defaults::shared_boundary_second_domain);
void GroomParameters::set_shared_boundaries(const std::vector<SharedBoundary>& boundaries) {
if (boundaries.empty()) {
params_.set(Keys::SHARED_BOUNDARIES, "");
} else {
std::string boundaries_str;
for (size_t i = 0; i < boundaries.size(); ++i) {
if (i > 0) boundaries_str += ";";
boundaries_str += boundaries[i].to_string();
}
params_.set(Keys::SHARED_BOUNDARIES, boundaries_str);
}

// Clear old format keys to avoid confusion
params_.remove_entry(Keys::SHARED_BOUNDARY);
params_.remove_entry(Keys::SHARED_BOUNDARY_FIRST_DOMAIN);
params_.remove_entry(Keys::SHARED_BOUNDARY_SECOND_DOMAIN);
params_.remove_entry(Keys::SHARED_BOUNDARY_TOLERANCE);
}

//---------------------------------------------------------------------------
void GroomParameters::set_shared_boundary_second_domain(const std::string& domain_name) {
params_.set(Keys::SHARED_BOUNDARY_SECOND_DOMAIN, domain_name);
void GroomParameters::add_shared_boundary(const std::string& first_domain, const std::string& second_domain,
double tolerance) {
auto boundaries = get_shared_boundaries();
boundaries.push_back({first_domain, second_domain, tolerance});
set_shared_boundaries(boundaries);
}

//---------------------------------------------------------------------------
double GroomParameters::get_shared_boundary_tolerance() {
return params_.get(Keys::SHARED_BOUNDARY_TOLERANCE, Defaults::shared_boundary_tolerance);
void GroomParameters::remove_shared_boundary(size_t index) {
auto boundaries = get_shared_boundaries();
if (index < boundaries.size()) {
boundaries.erase(boundaries.begin() + index);
set_shared_boundaries(boundaries);
}
}

//---------------------------------------------------------------------------
void GroomParameters::set_shared_boundary_tolerance(double tolerance) {
params_.set(Keys::SHARED_BOUNDARY_TOLERANCE, tolerance);
}
void GroomParameters::clear_shared_boundaries() { set_shared_boundaries({}); }

//---------------------------------------------------------------------------
} // namespace shapeworks
Expand Down
28 changes: 18 additions & 10 deletions Libs/Groom/GroomParameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ namespace shapeworks {
* This class encapsulated processing of Groom parameters
*/
class GroomParameters {
public:
struct SharedBoundary {
std::string first_domain;
std::string second_domain;
double tolerance;

// Helper methods for serialization
std::string to_string() const;
static SharedBoundary from_string(const std::string& str);
};

enum class MeshSmoothingOption { laplacian, sinc };

enum class AlignmentOption { none, center, icp };
Expand Down Expand Up @@ -137,17 +148,14 @@ class GroomParameters {
bool get_skip_grooming();
void set_skip_grooming(bool skip);

bool get_shared_boundary();
void set_shared_boundary(bool shared_boundary);

std::string get_shared_boundary_first_domain();
void set_shared_boundary_first_domain(const std::string& domain_name);

std::string get_shared_boundary_second_domain();
void set_shared_boundary_second_domain(const std::string& domain_name);
bool get_shared_boundaries_enabled();
void set_shared_boundaries_enabled(bool enabled);

double get_shared_boundary_tolerance();
void set_shared_boundary_tolerance(double tolerance);
std::vector<SharedBoundary> get_shared_boundaries();
void set_shared_boundaries(const std::vector<SharedBoundary>& boundaries);
void add_shared_boundary(const std::string& first_domain, const std::string& second_domain, double tolerance);
void remove_shared_boundary(size_t index);
void clear_shared_boundaries();

void restore_defaults();

Expand Down
Loading
Loading