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
30 changes: 16 additions & 14 deletions clus/src/clustering_extend.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -858,41 +858,43 @@ static void clustering_extend(


std::vector<std::pair<geo_point_t, const Blob*>> WireCell::Clus::Facade::get_strategic_points(const Cluster& cluster) {
// Store unique points and their corresponding blobs.
// Use std::set for deduplication — avoids std::sort which requires strict weak ordering
// (D3Vector::operator< is NOT a strict weak ordering and causes UB with std::sort).
std::set<std::pair<geo_point_t, const Blob*>> unique_points;
// Collect candidate starting points; deduplicated by geo_point_t below.
std::vector<std::pair<geo_point_t, const Blob*>> points;

// 1. Get extreme points along main axes
{
// Y-axis (highest/lowest)
auto [high_y, low_y] = cluster.get_highest_lowest_points(1);
unique_points.emplace(high_y, cluster.blob_with_point(cluster.get_closest_point_index(high_y)));
unique_points.emplace(low_y, cluster.blob_with_point(cluster.get_closest_point_index(low_y)));
points.emplace_back(high_y, cluster.blob_with_point(cluster.get_closest_point_index(high_y)));
points.emplace_back(low_y, cluster.blob_with_point(cluster.get_closest_point_index(low_y)));

// Z-axis (front/back)
auto [front, back] = cluster.get_front_back_points();
unique_points.emplace(front, cluster.blob_with_point(cluster.get_closest_point_index(front)));
unique_points.emplace(back, cluster.blob_with_point(cluster.get_closest_point_index(back)));
points.emplace_back(front, cluster.blob_with_point(cluster.get_closest_point_index(front)));
points.emplace_back(back, cluster.blob_with_point(cluster.get_closest_point_index(back)));

// X-axis (earliest/latest)
auto [early, late] = cluster.get_earliest_latest_points();
unique_points.emplace(early, cluster.blob_with_point(cluster.get_closest_point_index(early)));
unique_points.emplace(late, cluster.blob_with_point(cluster.get_closest_point_index(late)));
points.emplace_back(early, cluster.blob_with_point(cluster.get_closest_point_index(early)));
points.emplace_back(late, cluster.blob_with_point(cluster.get_closest_point_index(late)));
}

// 4. Add points from convex hull vertices
{
auto hull_points = cluster.get_hull();
for (const auto& p : hull_points) {
auto [closest_p, blob] = cluster.get_closest_point_blob(p);
unique_points.emplace(closest_p, blob);
points.emplace_back(closest_p, blob);
}
}

// Convert set to vector for return
std::vector<std::pair<geo_point_t, const Blob*>> points;
points.insert(points.end(), unique_points.begin(), unique_points.end());
// Sort by geo_point_t only (deterministic, no pointer dependency) then deduplicate
std::sort(points.begin(), points.end(),
[](const auto& a, const auto& b) { return a.first < b.first; });
points.erase(std::unique(points.begin(), points.end(),
[](const auto& a, const auto& b) {
return !(a.first < b.first) && !(b.first < a.first);
}), points.end());

return points;
}
Expand Down
7 changes: 4 additions & 3 deletions util/inc/WireCellUtil/D3Vector.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,11 @@ namespace WireCell {

bool operator<(const D3Vector& rhs) const
{
if (z() < rhs.z()) return true;
if (y() < rhs.y()) return true;
if (x() < rhs.x()) return true;
return false;
else if (x() > rhs.x()) return false;
else if (y() < rhs.y()) return true;
else if (y() > rhs.y()) return false;
else return z() < rhs.z();
}

D3Vector& operator+=(const D3Vector& other)
Expand Down