@@ -64,21 +64,48 @@ CurveNetwork::CurveNetwork(std::string name, std::vector<glm::vec3> nodes_, std:
6464 updateObjectSpaceBounds();
6565}
6666
67- float CurveNetwork::computeRadiusMultiplierUniform() {
68- if (nodeRadiusQuantityName != " " && !nodeRadiusQuantityAutoscale) {
69- // special case: ignore radius uniform
70- return 1.;
71- } else {
72- // common case
67+ float CurveNetwork::computeNodeRadiusMultiplierUniform() {
68+ float scalarQScale = 1.;
69+ if (nodeRadiusQuantityName != " " ) {
70+ // node radius quantity only, or both
7371
74- float scalarQScale = 1.;
75- if (nodeRadiusQuantityName != " " ) {
76- CurveNetworkNodeScalarQuantity& radQ = resolveNodeRadiusQuantity();
77- scalarQScale = std::max(0., radQ.getDataRange().second);
78- }
72+ if (!nodeRadiusQuantityAutoscale) return 1.;
73+
74+ CurveNetworkNodeScalarQuantity& radQ = resolveNodeRadiusQuantity();
75+ scalarQScale = std::max(0., radQ.getDataRange().second);
76+
77+ } else if (edgeRadiusQuantityName != " " ) {
78+ // edge radius quantity
79+
80+ if (!edgeRadiusQuantityAutoscale) return 1.;
81+
82+ CurveNetworkEdgeScalarQuantity& radQ = resolveEdgeRadiusQuantity();
83+ scalarQScale = std::max(0., radQ.getDataRange().second);
84+ }
85+
86+ return getRadius() / scalarQScale;
87+ }
88+
89+ float CurveNetwork::computeEdgeRadiusMultiplierUniform() {
90+
91+ float scalarQScale = 1.;
92+ if (edgeRadiusQuantityName != " " ) {
93+ // edge radius quantity only, or both
94+
95+ if (!edgeRadiusQuantityAutoscale) return 1.;
7996
80- return getRadius() / scalarQScale;
97+ CurveNetworkEdgeScalarQuantity& radQ = resolveEdgeRadiusQuantity();
98+ scalarQScale = std::max(0., radQ.getDataRange().second);
99+ } else if (nodeRadiusQuantityName != " " ) {
100+ // node radius quantity only
101+
102+ if (!nodeRadiusQuantityAutoscale) return 1.;
103+
104+ CurveNetworkNodeScalarQuantity& radQ = resolveNodeRadiusQuantity();
105+ scalarQScale = std::max(0., radQ.getDataRange().second);
81106 }
107+
108+ return getRadius() / scalarQScale;
82109}
83110
84111// Helper to set uniforms
@@ -87,15 +114,15 @@ void CurveNetwork::setCurveNetworkNodeUniforms(render::ShaderProgram& p) {
87114 glm::mat4 Pinv = glm::inverse(P);
88115 p.setUniform(" u_invProjMatrix" , glm::value_ptr(Pinv));
89116 p.setUniform(" u_viewport" , render::engine->getCurrentViewport());
90- p.setUniform(" u_pointRadius" , computeRadiusMultiplierUniform ());
117+ p.setUniform(" u_pointRadius" , computeNodeRadiusMultiplierUniform ());
91118}
92119
93120void CurveNetwork::setCurveNetworkEdgeUniforms(render::ShaderProgram& p) {
94121 glm::mat4 P = view::getCameraPerspectiveMatrix();
95122 glm::mat4 Pinv = glm::inverse(P);
96123 p.setUniform(" u_invProjMatrix" , glm::value_ptr(Pinv));
97124 p.setUniform(" u_viewport" , render::engine->getCurrentViewport());
98- p.setUniform(" u_radius" , computeRadiusMultiplierUniform ());
125+ p.setUniform(" u_radius" , computeNodeRadiusMultiplierUniform ());
99126}
100127
101128void CurveNetwork::draw() {
@@ -175,7 +202,7 @@ void CurveNetwork::drawPick() {
175202std::vector<std::string> CurveNetwork::addCurveNetworkNodeRules(std::vector<std::string> initRules) {
176203 initRules = addStructureRules(initRules);
177204
178- if (nodeRadiusQuantityName != " " ) {
205+ if (nodeRadiusQuantityName != " " || edgeRadiusQuantityName != " " ) {
179206 initRules.push_back(" SPHERE_VARIABLE_SIZE" );
180207 }
181208 if (wantsCullPosition()) {
@@ -187,7 +214,7 @@ std::vector<std::string> CurveNetwork::addCurveNetworkEdgeRules(std::vector<std:
187214 initRules = addStructureRules(initRules);
188215
189216 // use node radius to blend cylinder radius
190- if (nodeRadiusQuantityName != " " ) {
217+ if (nodeRadiusQuantityName != " " || edgeRadiusQuantityName != " " ) {
191218 initRules.push_back(" CYLINDER_VARIABLE_SIZE" );
192219 }
193220
@@ -296,17 +323,35 @@ void CurveNetwork::preparePick() {
296323void CurveNetwork::fillNodeGeometryBuffers(render::ShaderProgram& program) {
297324 program.setAttribute(" a_position" , nodePositions.getRenderAttributeBuffer());
298325
299- if (nodeRadiusQuantityName != " " ) {
326+ bool haveNodeRadiusQuantity = (nodeRadiusQuantityName != " " );
327+ bool haveEdgeRadiusQuantity = (edgeRadiusQuantityName != " " );
328+
329+ if (haveNodeRadiusQuantity) {
330+ // have just node, or have both
300331 CurveNetworkNodeScalarQuantity& nodeRadQ = resolveNodeRadiusQuantity();
301332 program.setAttribute(" a_pointRadius" , nodeRadQ.values.getRenderAttributeBuffer());
333+ } else if (haveEdgeRadiusQuantity) {
334+ // have just edge
335+ CurveNetworkEdgeScalarQuantity& edgeRadQ = resolveEdgeRadiusQuantity();
336+ edgeRadQ.updateNodeAverageValues();
337+ program.setAttribute(" a_pointRadius" , edgeRadQ.nodeAverageValues.getRenderAttributeBuffer());
302338 }
303339}
304340
305341void CurveNetwork::fillEdgeGeometryBuffers(render::ShaderProgram& program) {
306342 program.setAttribute(" a_position_tail" , nodePositions.getIndexedRenderAttributeBuffer(edgeTailInds));
307343 program.setAttribute(" a_position_tip" , nodePositions.getIndexedRenderAttributeBuffer(edgeTipInds));
308344
309- if (nodeRadiusQuantityName != " " ) {
345+ bool haveNodeRadiusQuantity = (nodeRadiusQuantityName != " " );
346+ bool haveEdgeRadiusQuantity = (edgeRadiusQuantityName != " " );
347+
348+ if (haveEdgeRadiusQuantity) {
349+ // have just edge or have both
350+ CurveNetworkEdgeScalarQuantity& edgeRadQ = resolveEdgeRadiusQuantity();
351+ program.setAttribute(" a_tailRadius" , edgeRadQ.values.getRenderAttributeBuffer());
352+ program.setAttribute(" a_tipRadius" , edgeRadQ.values.getRenderAttributeBuffer());
353+ } else if (haveNodeRadiusQuantity) {
354+ // have just node
310355 CurveNetworkNodeScalarQuantity& nodeRadQ = resolveNodeRadiusQuantity();
311356 program.setAttribute(" a_tailRadius" , nodeRadQ.values.getIndexedRenderAttributeBuffer(edgeTailInds));
312357 program.setAttribute(" a_tipRadius" , nodeRadQ.values.getIndexedRenderAttributeBuffer(edgeTipInds));
@@ -422,7 +467,7 @@ void CurveNetwork::buildCustomUI() {
422467
423468void CurveNetwork::buildCustomOptionsUI() {
424469
425- if (ImGui::BeginMenu(" Variable Radius" )) {
470+ if (ImGui::BeginMenu(" Node Variable Radius" )) {
426471
427472 if (ImGui::MenuItem(" none" , nullptr, nodeRadiusQuantityName == " " )) clearNodeRadiusQuantity();
428473 ImGui::Separator();
@@ -438,6 +483,21 @@ void CurveNetwork::buildCustomOptionsUI() {
438483 ImGui::EndMenu();
439484 }
440485
486+ if (ImGui::BeginMenu(" Edge Variable Radius" )) {
487+
488+ if (ImGui::MenuItem(" none" , nullptr, edgeRadiusQuantityName == " " )) clearEdgeRadiusQuantity();
489+ ImGui::Separator();
490+
491+ for (auto& q : quantities) {
492+ CurveNetworkEdgeScalarQuantity* scalarQ = dynamic_cast<CurveNetworkEdgeScalarQuantity*>(q.second.get());
493+ if (scalarQ != nullptr) {
494+ if (ImGui::MenuItem(scalarQ->name.c_str(), nullptr, edgeRadiusQuantityName == scalarQ->name))
495+ setEdgeRadiusQuantity(scalarQ);
496+ }
497+ }
498+
499+ ImGui::EndMenu();
500+ }
441501
442502 if (render::buildMaterialOptionsGui(material.get())) {
443503 material.manuallyChanged();
@@ -521,6 +581,24 @@ void CurveNetwork::clearNodeRadiusQuantity() {
521581 refresh ();
522582};
523583
584+ void CurveNetwork::setEdgeRadiusQuantity (CurveNetworkEdgeScalarQuantity* quantity, bool autoScale) {
585+ setEdgeRadiusQuantity (quantity->name , autoScale);
586+ }
587+
588+ void CurveNetwork::setEdgeRadiusQuantity (std::string name, bool autoScale) {
589+ edgeRadiusQuantityName = name;
590+ edgeRadiusQuantityAutoscale = autoScale;
591+
592+ resolveEdgeRadiusQuantity (); // do it once, just so we fail fast if it doesn't exist
593+
594+ refresh ();
595+ }
596+
597+ void CurveNetwork::clearEdgeRadiusQuantity () {
598+ edgeRadiusQuantityName = " " ;
599+ refresh ();
600+ };
601+
524602CurveNetwork* CurveNetwork::setRadius (float newVal, bool isRelative) {
525603 radius = ScaledValue<float >(newVal, isRelative);
526604 polyscope::requestRedraw ();
@@ -607,10 +685,27 @@ CurveNetworkNodeScalarQuantity& CurveNetwork::resolveNodeRadiusQuantity() {
607685 if (sizeQ != nullptr ) {
608686 sizeScalarQ = dynamic_cast <CurveNetworkNodeScalarQuantity*>(sizeQ);
609687 if (sizeScalarQ == nullptr ) {
610- exception (" Cannot populate node size from quantity [" + name + " ], it is not a scalar quantity" );
688+ exception (" Cannot populate node size from quantity [" + nodeRadiusQuantityName +
689+ " ], it is not a scalar quantity" );
690+ }
691+ } else {
692+ exception (" Cannot populate node size from quantity [" + nodeRadiusQuantityName + " ], it does not exist" );
693+ }
694+
695+ return *sizeScalarQ;
696+ }
697+
698+ CurveNetworkEdgeScalarQuantity& CurveNetwork::resolveEdgeRadiusQuantity () {
699+ CurveNetworkEdgeScalarQuantity* sizeScalarQ = nullptr ;
700+ CurveNetworkQuantity* sizeQ = getQuantity (edgeRadiusQuantityName);
701+ if (sizeQ != nullptr ) {
702+ sizeScalarQ = dynamic_cast <CurveNetworkEdgeScalarQuantity*>(sizeQ);
703+ if (sizeScalarQ == nullptr ) {
704+ exception (" Cannot populate edge size from quantity [" + edgeRadiusQuantityName +
705+ " ], it is not a scalar quantity" );
611706 }
612707 } else {
613- exception (" Cannot populate node size from quantity [" + name + " ], it does not exist" );
708+ exception (" Cannot populate edge size from quantity [" + edgeRadiusQuantityName + " ], it does not exist" );
614709 }
615710
616711 return *sizeScalarQ;
0 commit comments