Skip to content

Commit 4338889

Browse files
committed
improve slice plane API, allow custom names
1 parent dc0c7c2 commit 4338889

7 files changed

Lines changed: 164 additions & 25 deletions

File tree

include/polyscope/slice_plane.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ class SlicePlane {
4242
const std::string postfix;
4343
std::string uniquePrefix();
4444

45+
// Remove the slice plane from the scene
46+
// (destroys this object, pointer is now invalid)
47+
void remove();
48+
4549
// Set the position and orientation of the plane
4650
// planePosition is any 3D position which the plane touches (the center of the plane)
4751
// planeNormal is a vector giving the normal direction of the plane, objects
@@ -109,10 +113,34 @@ class SlicePlane {
109113
void updateWidgetEnabled();
110114
};
111115

116+
// Manually specify a name for the slice plane
117+
SlicePlane* addSlicePlane(std::string name);
118+
119+
// Automatically generates a name for the plane like
120+
// "Scene Slice Plane 0", "Scene Slice Plane 1", etc.
121+
SlicePlane* addSlicePlane();
122+
123+
// DEPRECATED: there's on reason to offer this variant, it could be set manually
112124
SlicePlane* addSceneSlicePlane(bool initiallyVisible = false);
125+
126+
// Get a slice plane by name
127+
SlicePlane* getSlicePlane(std::string name);
128+
129+
// Remove a slice plane by name or pointer
130+
void removeSlicePlane(std::string name);
131+
void removeSlicePlane(SlicePlane* plane);
132+
133+
// Remove the last-added slice plane
113134
void removeLastSceneSlicePlane();
135+
136+
// Remove all slice planes
114137
void removeAllSlicePlanes();
138+
139+
140+
// === Internal helpers
141+
115142
void buildSlicePlaneGUI();
143+
void notifySlicePlanesChanged(); // call after adding/remove any slice plane
116144

117145
// flag to open the slice plane menu after adding a slice plane
118146
extern bool openSlicePlaneMenu;

src/slice_plane.cpp

Lines changed: 60 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,28 +13,64 @@ namespace polyscope {
1313
// Storage for global options
1414
bool openSlicePlaneMenu = false;
1515

16-
SlicePlane* addSceneSlicePlane(bool initiallyVisible) {
16+
SlicePlane* addSlicePlane(std::string name) {
17+
// check if the name is unique, throw an error if not
18+
for (const std::unique_ptr<SlicePlane>& s : state::slicePlanes) {
19+
if (s->name == name) {
20+
error("Slice plane with name " + name + " already exists");
21+
return nullptr;
22+
}
23+
}
24+
25+
state::slicePlanes.emplace_back(std::unique_ptr<SlicePlane>(new SlicePlane(name)));
26+
SlicePlane* newPlane = state::slicePlanes.back().get();
27+
notifySlicePlanesChanged();
28+
return newPlane;
29+
}
30+
31+
SlicePlane* addSlicePlane() {
1732
size_t nPlanes = state::slicePlanes.size();
1833
std::string newName = "Scene Slice Plane " + std::to_string(nPlanes);
19-
state::slicePlanes.emplace_back(std::unique_ptr<SlicePlane>(new SlicePlane(newName)));
20-
nPlanes++;
21-
SlicePlane* newPlane = state::slicePlanes.back().get();
34+
return addSlicePlane(newName);
35+
}
36+
37+
// DEPRECATED: there's on reason to offer this variant, it could be set manually
38+
SlicePlane* addSceneSlicePlane(bool initiallyVisible) {
39+
SlicePlane* newPlane = addSlicePlane();
2240
if (!initiallyVisible) {
2341
newPlane->setDrawPlane(false);
2442
newPlane->setDrawWidget(false);
2543
}
26-
for (std::unique_ptr<SlicePlane>& s : state::slicePlanes) {
27-
s->resetVolumeSliceProgram();
28-
}
2944
return newPlane;
3045
}
3146

47+
SlicePlane* getSlicePlane(std::string name) {
48+
for (const std::unique_ptr<SlicePlane>& s : state::slicePlanes) {
49+
if (s->name == name) {
50+
return s.get();
51+
}
52+
}
53+
error("No slice plane with name " + name + " exists");
54+
return nullptr;
55+
}
56+
57+
void removeSlicePlane(std::string name) {
58+
for (auto it = state::slicePlanes.begin(); it != state::slicePlanes.end(); it++) {
59+
if ((*it)->name == name) {
60+
state::slicePlanes.erase(it);
61+
notifySlicePlanesChanged();
62+
return;
63+
}
64+
}
65+
warning("No slice plane with name " + name + " exists, cannot remove");
66+
}
67+
68+
void removeSlicePlane(SlicePlane* plane) { removeSlicePlane(plane->name); }
69+
3270
void removeLastSceneSlicePlane() {
3371
if (state::slicePlanes.empty()) return;
3472
state::slicePlanes.pop_back();
35-
for (std::unique_ptr<SlicePlane>& s : state::slicePlanes) {
36-
s->resetVolumeSliceProgram();
37-
}
73+
notifySlicePlanesChanged();
3874
}
3975

4076
void removeAllSlicePlanes() {
@@ -43,6 +79,13 @@ void removeAllSlicePlanes() {
4379
}
4480
}
4581

82+
void notifySlicePlanesChanged() {
83+
// NSHARP: I've forgotten why this is needed. Perhaps it is not?
84+
for (std::unique_ptr<SlicePlane>& s : state::slicePlanes) {
85+
s->resetVolumeSliceProgram();
86+
}
87+
}
88+
4689
void buildSlicePlaneGUI() {
4790

4891

@@ -53,7 +96,7 @@ void buildSlicePlaneGUI() {
5396
}
5497
if (ImGui::TreeNode("Slice Planes")) {
5598
if (ImGui::Button("Add plane")) {
56-
addSceneSlicePlane(true);
99+
addSlicePlane();
57100
}
58101
ImGui::SameLine();
59102
if (ImGui::Button("Remove plane")) {
@@ -94,6 +137,11 @@ SlicePlane::~SlicePlane() {
94137
95138
std::string SlicePlane::uniquePrefix() { return "SlicePlane#" + name + "#"; }
96139
140+
void SlicePlane::remove() {
141+
removeSlicePlane(name);
142+
// now invalid! can't do anything else
143+
}
144+
97145
void SlicePlane::prepare() {
98146
99147
planeProgram = render::engine->requestShader("SLICE_PLANE", {}, render::ShaderReplacementDefaults::Process);
@@ -380,6 +428,7 @@ void SlicePlane::updateWidgetEnabled() {
380428
transformGizmo.enabled = enabled;
381429
}
382430
431+
383432
void SlicePlane::setPose(glm::vec3 planePosition, glm::vec3 planeNormal) {
384433
385434
// Choose the other axes to be most similar to the current ones, which will make animations look smoother

src/structure.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ void Structure::buildUI() {
9393
// if there are none, show a helpful message
9494
if (ImGui::Button("Add slice plane")) {
9595
openSlicePlaneMenu = true;
96-
addSceneSlicePlane(true);
96+
addSlicePlane();
9797
}
9898
} else {
9999
// otherwise, show toggles for each

test/src/combo_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ TEST_F(PolyscopeTest, SlicePlaneTest) {
111111
polyscope::show(3);
112112

113113
// render with one slice plane
114-
polyscope::addSceneSlicePlane();
114+
polyscope::addSlicePlane();
115115
polyscope::show(3);
116116

117117
// try a few variations of point cloud settings
@@ -126,7 +126,7 @@ TEST_F(PolyscopeTest, SlicePlaneTest) {
126126
polyscope::show(3);
127127

128128
// add another and rotate it
129-
polyscope::SlicePlane* p = polyscope::addSceneSlicePlane();
129+
polyscope::SlicePlane* p = polyscope::addSlicePlane();
130130
p->setTransform(glm::translate(p->getTransform(), glm::vec3{-1., 0., 0.}));
131131
polyscope::show(3);
132132

test/src/floating_test.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ TEST_F(PolyscopeTest, FloatingRenderImageTest) {
106106
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
107107

108108
// add a slice plane
109-
polyscope::addSceneSlicePlane();
109+
polyscope::addSlicePlane();
110110
polyscope::show(3);
111111
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
112112
polyscope::removeLastSceneSlicePlane();
@@ -120,7 +120,7 @@ TEST_F(PolyscopeTest, FloatingRenderImageTest) {
120120
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
121121

122122
// add a slice plane
123-
polyscope::addSceneSlicePlane();
123+
polyscope::addSlicePlane();
124124
polyscope::show(3);
125125
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
126126
polyscope::removeLastSceneSlicePlane();
@@ -135,7 +135,7 @@ TEST_F(PolyscopeTest, FloatingRenderImageTest) {
135135
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
136136

137137
// add a slice plane
138-
polyscope::addSceneSlicePlane();
138+
polyscope::addSlicePlane();
139139
polyscope::show(3);
140140
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
141141
polyscope::removeLastSceneSlicePlane();
@@ -149,7 +149,7 @@ TEST_F(PolyscopeTest, FloatingRenderImageTest) {
149149
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
150150

151151
// add a slice plane
152-
polyscope::addSceneSlicePlane();
152+
polyscope::addSlicePlane();
153153
polyscope::show(3);
154154
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
155155
polyscope::removeLastSceneSlicePlane();
@@ -164,7 +164,7 @@ TEST_F(PolyscopeTest, FloatingRenderImageTest) {
164164
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
165165

166166
// add a slice plane
167-
polyscope::addSceneSlicePlane();
167+
polyscope::addSlicePlane();
168168
polyscope::show(3);
169169
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
170170
polyscope::removeLastSceneSlicePlane();
@@ -178,7 +178,7 @@ TEST_F(PolyscopeTest, FloatingRenderImageTest) {
178178
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
179179

180180
// add a slice plane
181-
polyscope::addSceneSlicePlane();
181+
polyscope::addSlicePlane();
182182
polyscope::show(3);
183183
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
184184
polyscope::removeLastSceneSlicePlane();
@@ -194,7 +194,7 @@ TEST_F(PolyscopeTest, FloatingRenderImageTest) {
194194
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
195195

196196
// add a slice plane
197-
polyscope::addSceneSlicePlane();
197+
polyscope::addSlicePlane();
198198
polyscope::show(3);
199199
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
200200
polyscope::removeLastSceneSlicePlane();
@@ -209,7 +209,7 @@ TEST_F(PolyscopeTest, FloatingRenderImageTest) {
209209
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
210210

211211
// add a slice plane
212-
polyscope::addSceneSlicePlane();
212+
polyscope::addSlicePlane();
213213
polyscope::show(3);
214214
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
215215
polyscope::removeLastSceneSlicePlane();
@@ -226,7 +226,7 @@ TEST_F(PolyscopeTest, FloatingRenderImageTest) {
226226
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
227227

228228
// add a slice plane
229-
polyscope::addSceneSlicePlane();
229+
polyscope::addSlicePlane();
230230
polyscope::show(3);
231231
polyscope::pickAtScreenCoords(glm::vec2(0.3, 0.8));
232232

test/src/misc_test.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,65 @@ TEST_F(PolyscopeTest, FlatMaterialTest) {
6666

6767
polyscope::removeAllStructures();
6868
}
69+
70+
71+
// ============================================================
72+
// =============== Slice Plane Tests
73+
// ============================================================
74+
75+
// We test these on a point cloud because it is convenient, but really we are testing the scalar quantity
76+
77+
TEST_F(PolyscopeTest, TestSlicePlane) {
78+
79+
auto psPoints = registerPointCloud(); // add some structure to the scene
80+
81+
// Basic add
82+
polyscope::SlicePlane* sp1 = polyscope::addSlicePlane();
83+
polyscope::show(3);
84+
85+
// Set properties
86+
sp1->setColor(glm::vec3(1.0, 0.0, 0.0));
87+
EXPECT_EQ(sp1->getColor(), glm::vec3(1.0, 0.0, 0.0));
88+
89+
sp1->setTransparency(0.5);
90+
EXPECT_EQ(sp1->getTransparency(), 0.5);
91+
92+
sp1->setGridLineColor(glm::vec3(0.5, 0.5, 0.5));
93+
EXPECT_EQ(sp1->getGridLineColor(), glm::vec3(0.5, 0.5, 0.5));
94+
95+
polyscope::show(3);
96+
97+
// Transform stuff
98+
glm::mat4 transform = glm::mat4(1.0);
99+
transform[3][0] = 1.0;
100+
sp1->setTransform(transform);
101+
EXPECT_EQ(sp1->getTransform(), transform);
102+
103+
glm::vec3 center = sp1->getCenter();
104+
glm::vec3 normal = sp1->getNormal();
105+
106+
// Enable/disable drawing styles
107+
sp1->setDrawPlane(false);
108+
sp1->setDrawWidget(false);
109+
polyscope::show(3);
110+
111+
// Add/remove with custom names
112+
polyscope::SlicePlane* sp2 = polyscope::addSlicePlane("custom_name");
113+
EXPECT_EQ(sp2->name, "custom_name");
114+
polyscope::SlicePlane* sp3 = polyscope::addSlicePlane();
115+
polyscope::show(3);
116+
polyscope::removeSlicePlane("custom_name");
117+
polyscope::show(3);
118+
polyscope::removeLastSceneSlicePlane();
119+
polyscope::show(3);
120+
polyscope::removeSlicePlane(sp1);
121+
polyscope::show(3);
122+
polyscope::SlicePlane* sp4 = polyscope::addSlicePlane();
123+
sp4->remove();
124+
// for now, still test that the the old deprecated function works
125+
polyscope::SlicePlane* sp5 = polyscope::addSceneSlicePlane();
126+
polyscope::show(3);
127+
128+
polyscope::removeAllSlicePlanes();
129+
polyscope::removeAllStructures();
130+
}

test/src/volume_mesh_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -245,7 +245,7 @@ TEST_F(PolyscopeTest, VolumeMeshInspect) {
245245
polyscope::VolumeMesh* psVol = polyscope::registerVolumeMesh("vol", verts, cells);
246246

247247
// plain old inspecting
248-
polyscope::SlicePlane* p = polyscope::addSceneSlicePlane();
248+
polyscope::SlicePlane* p = polyscope::addSlicePlane();
249249
p->setVolumeMeshToInspect("vol");
250250
polyscope::show(3);
251251

@@ -280,7 +280,7 @@ TEST_F(PolyscopeTest, VolumeMeshInspectWithExtra) {
280280
polyscope::VolumeMesh* psVolExtra = polyscope::registerVolumeMesh("vol extra", verts, cells);
281281

282282
// plain old inspecting
283-
polyscope::SlicePlane* p = polyscope::addSceneSlicePlane();
283+
polyscope::SlicePlane* p = polyscope::addSlicePlane();
284284
p->setVolumeMeshToInspect("vol");
285285
polyscope::show(3);
286286

0 commit comments

Comments
 (0)