feat: add HighlightCorners mode to Prop3D and document Prop3D class functionality
This commit is contained in:
@@ -93,7 +93,8 @@ public:
|
||||
m_Selectable(true),
|
||||
m_Selected(false),
|
||||
m_Visibility(true),
|
||||
m_Dragable(true)
|
||||
m_Dragable(true),
|
||||
m_HighlightMode(Prop3D::HighlightPlain)
|
||||
{
|
||||
m_Color = Vector3d(-1, -1, -1);
|
||||
}
|
||||
@@ -125,6 +126,8 @@ public:
|
||||
bool m_Visibility;
|
||||
bool m_Dragable;
|
||||
|
||||
int m_HighlightMode; // 0: Plain, 1: Corners
|
||||
|
||||
//
|
||||
TRS m_Transform;
|
||||
|
||||
@@ -212,39 +215,71 @@ public:
|
||||
}
|
||||
|
||||
if (!m_HighlightActor) {
|
||||
m_HighlightActor = vtkSmartPointer<vtkActor>::New();
|
||||
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
||||
m_HighlightActor->SetMapper(mapper);
|
||||
m_HighlightActor->GetProperty()->SetRepresentationToWireframe();
|
||||
m_HighlightActor->GetProperty()->SetColor(1.0, 0.0, 0.0); // Red
|
||||
m_HighlightActor->GetProperty()->SetLineWidth(2.0);
|
||||
m_HighlightActor->GetProperty()->SetLighting(0);
|
||||
}
|
||||
|
||||
if (m_HighlightMode == Prop3D::HighlightPlain) {
|
||||
vtkSmartPointer<vtkCubeSource> cube = vtkSmartPointer<vtkCubeSource>::New();
|
||||
double bounds[6];
|
||||
polydata->GetBounds(bounds);
|
||||
// Add a small padding to prevent z-fighting
|
||||
double maxDim = std::max({bounds[1]-bounds[0], bounds[3]-bounds[2], bounds[5]-bounds[4]});
|
||||
double pad = maxDim * 0.02;
|
||||
if(pad < 1e-4) pad = 0.05;
|
||||
cube->SetBounds(bounds[0]-pad, bounds[1]+pad,
|
||||
bounds[2]-pad, bounds[3]+pad,
|
||||
bounds[4]-pad, bounds[5]+pad);
|
||||
|
||||
m_HighlightActor = vtkSmartPointer<vtkActor>::New();
|
||||
vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
||||
mapper->SetInputConnection(cube->GetOutputPort());
|
||||
m_HighlightActor->SetMapper(mapper);
|
||||
m_HighlightActor->GetProperty()->SetRepresentationToWireframe();
|
||||
m_HighlightActor->GetProperty()->SetColor(1.0, 0.0, 0.0); // Red
|
||||
m_HighlightActor->GetProperty()->SetLineWidth(2.0);
|
||||
m_HighlightActor->GetProperty()->SetLighting(0);
|
||||
cube->Update();
|
||||
m_HighlightActor->GetMapper()->SetInputConnection(cube->GetOutputPort());
|
||||
} else {
|
||||
if (auto* mapper = vtkPolyDataMapper::SafeDownCast(m_HighlightActor->GetMapper())) {
|
||||
if (auto* cube = vtkCubeSource::SafeDownCast(mapper->GetInputAlgorithm())) {
|
||||
double bounds[6];
|
||||
polydata->GetBounds(bounds);
|
||||
double maxDim = std::max({bounds[1]-bounds[0], bounds[3]-bounds[2], bounds[5]-bounds[4]});
|
||||
double pad = maxDim * 0.02;
|
||||
if(pad < 1e-4) pad = 0.05;
|
||||
cube->SetBounds(bounds[0]-pad, bounds[1]+pad,
|
||||
bounds[2]-pad, bounds[3]+pad,
|
||||
bounds[4]-pad, bounds[5]+pad);
|
||||
cube->Modified();
|
||||
// Corners mode logic
|
||||
double bounds[6];
|
||||
polydata->GetBounds(bounds);
|
||||
double maxDim = std::max({bounds[1]-bounds[0], bounds[3]-bounds[2], bounds[5]-bounds[4]});
|
||||
double pad = maxDim * 0.02;
|
||||
if(pad < 1e-4) pad = 0.05;
|
||||
|
||||
double b[6] = {bounds[0]-pad, bounds[1]+pad, bounds[2]-pad, bounds[3]+pad, bounds[4]-pad, bounds[5]+pad};
|
||||
|
||||
vtkNew<vtkPoints> points;
|
||||
vtkNew<vtkCellArray> lines;
|
||||
|
||||
float len[3] = {
|
||||
(float)(b[1] - b[0]) * 0.15f,
|
||||
(float)(b[3] - b[2]) * 0.15f,
|
||||
(float)(b[5] - b[4]) * 0.15f
|
||||
};
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
double p[3];
|
||||
p[0] = b[(i & 1) ? 1 : 0];
|
||||
p[1] = b[(i & 2) ? 1 : 0];
|
||||
p[2] = b[(i & 4) ? 1 : 0];
|
||||
|
||||
for (int axis = 0; axis < 3; ++axis) {
|
||||
double p2[3] = {p[0], p[1], p[2]};
|
||||
double delta = (i & (1 << axis)) ? -len[axis] : len[axis];
|
||||
p2[axis] += delta;
|
||||
|
||||
vtkIdType id1 = points->InsertNextPoint(p);
|
||||
vtkIdType id2 = points->InsertNextPoint(p2);
|
||||
lines->InsertNextCell(2);
|
||||
lines->InsertCellPoint(id1);
|
||||
lines->InsertCellPoint(id2);
|
||||
}
|
||||
}
|
||||
|
||||
vtkNew<vtkPolyData> cornerPoly;
|
||||
cornerPoly->SetPoints(points);
|
||||
cornerPoly->SetLines(lines);
|
||||
if (auto* mapper = vtkPolyDataMapper::SafeDownCast(m_HighlightActor->GetMapper())) {
|
||||
mapper->SetInputData(cornerPoly);
|
||||
}
|
||||
}
|
||||
|
||||
// Update highlight matrix from the model world matrix
|
||||
@@ -514,6 +549,12 @@ void Prop3D::SetRepresentation(const char *mode)
|
||||
else if (s == "slice") SetRepresentation(Slice);
|
||||
}
|
||||
|
||||
void Prop3D::SetHighlightMode(HighlightMode mode)
|
||||
{
|
||||
pd->m_HighlightMode = static_cast<int>(mode);
|
||||
pd->UpdateHighlight();
|
||||
}
|
||||
|
||||
void Prop3D::SetColor(double r, double g, double b)
|
||||
{
|
||||
pd->m_Color[0] = r;
|
||||
@@ -655,6 +696,8 @@ struct AppearanceProxy {
|
||||
ar & boost::serialization::make_hrp("Dragable", pd->m_Dragable);
|
||||
ar & boost::serialization::make_hrp("ShowBoundingBox", pd->m_ShowBoundingBox);
|
||||
ar & boost::serialization::make_hrp("ShowScaleMeasures", pd->m_ShowScaleMeasures);
|
||||
ar & boost::serialization::make_hrp_enum("HighlightMode",
|
||||
pd->m_HighlightMode, {"Plain", "Corners"});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user