@@ -14,9 +14,11 @@ ScalarQuantity<QuantityT>::ScalarQuantity(QuantityT& quantity_, const std::vecto
1414 vizRangeMax(quantity.uniquePrefix() + "vizRangeMax", -777.), // including clearing cache
1515 cMap(quantity.uniquePrefix() + "cmap", defaultColorMap(dataType)),
1616 isolinesEnabled(quantity.uniquePrefix() + "isolinesEnabled", false),
17- isolineWidth(quantity.uniquePrefix() + "isolineWidth",
18- absoluteValue((dataRange.second - dataRange.first) * 0.02)),
19- isolineDarkness(quantity.uniquePrefix() + "isolineDarkness", 0.7)
17+ isolineStyle(quantity.uniquePrefix() + "isolinesStyle", IsolineStyle::Stripe),
18+ isolinePeriod(quantity.uniquePrefix() + "isolinePeriod",
19+ absoluteValue((dataRange.second - dataRange.first) * 0.02)),
20+ isolineDarkness(quantity.uniquePrefix() + "isolineDarkness", 0.7),
21+ isolineContourThickness(quantity.uniquePrefix() + "isolineContourThickness", 0.3)
2022
2123{
2224 values.checkInvalidValues ();
@@ -144,22 +146,46 @@ void ScalarQuantity<QuantityT>::buildScalarUI() {
144146
145147 // Isolines
146148 if (isolinesEnabled.get ()) {
149+
147150 ImGui::PushItemWidth (100 );
148151
152+
153+ auto styleName = [](const IsolineStyle& m) -> std::string {
154+ switch (m) {
155+ case IsolineStyle::Stripe:
156+ return " Stripe" ;
157+ case IsolineStyle::Contour:
158+ return " Contour" ;
159+ }
160+ return " " ;
161+ };
162+
163+ ImGui::TextUnformatted (" Isoline style" );
164+ ImGui::SameLine ();
165+ if (ImGui::BeginCombo (" ##IsolineStyle" , styleName (getIsolineStyle ()).c_str ())) {
166+ for (IsolineStyle s : {IsolineStyle::Stripe, IsolineStyle::Contour}) {
167+ std::string sName = styleName (s);
168+ if (ImGui::Selectable (sName .c_str (), getIsolineStyle () == s)) {
169+ setIsolineStyle (s);
170+ }
171+ }
172+ ImGui::EndCombo ();
173+ }
174+
149175 // Isoline width
150- ImGui::TextUnformatted (" Isoline width " );
176+ ImGui::TextUnformatted (" Isoline period " );
151177 ImGui::SameLine ();
152- if (isolineWidth .get ().isRelative ()) {
153- if (ImGui::DragFloat (" ##Isoline width relative" , isolineWidth .get ().getValuePtr (), .001 , 0.0001 , 1.0 , " %.4f" ,
178+ if (isolinePeriod .get ().isRelative ()) {
179+ if (ImGui::DragFloat (" ##Isoline period relative" , isolinePeriod .get ().getValuePtr (), .001 , 0.0001 , 1.0 , " %.4f" ,
154180 ImGuiSliderFlags_Logarithmic | ImGuiSliderFlags_NoRoundToFormat)) {
155- isolineWidth .manuallyChanged ();
181+ isolinePeriod .manuallyChanged ();
156182 requestRedraw ();
157183 }
158184 } else {
159185 float scaleWidth = dataRange.second - dataRange.first ;
160- if (ImGui::DragFloat (" ##Isoline width absolute" , isolineWidth .get ().getValuePtr (), scaleWidth / 1000 , 0 .,
186+ if (ImGui::DragFloat (" ##Isoline period absolute" , isolinePeriod .get ().getValuePtr (), scaleWidth / 1000 , 0 .,
161187 scaleWidth, " %.4f" , ImGuiSliderFlags_Logarithmic | ImGuiSliderFlags_NoRoundToFormat)) {
162- isolineWidth .manuallyChanged ();
188+ isolinePeriod .manuallyChanged ();
163189 requestRedraw ();
164190 }
165191 }
@@ -172,6 +198,18 @@ void ScalarQuantity<QuantityT>::buildScalarUI() {
172198 requestRedraw ();
173199 }
174200
201+
202+ // Isoline Contour Thickness
203+ if (isolineStyle.get () == IsolineStyle::Contour) {
204+ ImGui::TextUnformatted (" Contour thickness" );
205+ ImGui::SameLine ();
206+ if (ImGui::DragFloat (" ##Contour thickness" , &isolineContourThickness.get (), .001 , 0.0001 , 1.0 , " %.4f" ,
207+ ImGuiSliderFlags_Logarithmic | ImGuiSliderFlags_NoRoundToFormat)) {
208+ isolineContourThickness.manuallyChanged ();
209+ requestRedraw ();
210+ }
211+ }
212+
175213 ImGui::PopItemWidth ();
176214 }
177215}
@@ -192,9 +230,18 @@ std::vector<std::string> ScalarQuantity<QuantityT>::addScalarRules(std::vector<s
192230 // common case
193231 rules.push_back (" SHADE_COLORMAP_VALUE" );
194232 }
233+
195234 if (isolinesEnabled.get ()) {
196- rules.push_back (" ISOLINE_STRIPE_VALUECOLOR" );
235+ switch (isolineStyle.get ()) {
236+ case IsolineStyle::Stripe:
237+ rules.push_back (" ISOLINE_STRIPE_VALUECOLOR" );
238+ break ;
239+ case IsolineStyle::Contour:
240+ rules.push_back (" CONTOUR_VALUECOLOR" );
241+ break ;
242+ }
197243 }
244+
198245 return rules;
199246}
200247
@@ -207,8 +254,17 @@ void ScalarQuantity<QuantityT>::setScalarUniforms(render::ShaderProgram& p) {
207254 }
208255
209256 if (isolinesEnabled.get ()) {
210- p.setUniform (" u_modLen" , getIsolineWidth ());
211- p.setUniform (" u_modDarkness" , getIsolineDarkness ());
257+ switch (isolineStyle.get ()) {
258+ case IsolineStyle::Stripe:
259+ p.setUniform (" u_modLen" , getIsolinePeriod ());
260+ p.setUniform (" u_modDarkness" , getIsolineDarkness ());
261+ break ;
262+ case IsolineStyle::Contour:
263+ p.setUniform (" u_modLen" , getIsolinePeriod ());
264+ p.setUniform (" u_modThickness" , getIsolineContourThickness ());
265+ p.setUniform (" u_modDarkness" , getIsolineDarkness ());
266+ break ;
267+ }
212268 }
213269}
214270
@@ -277,17 +333,26 @@ std::pair<double, double> ScalarQuantity<QuantityT>::getDataRange() {
277333}
278334
279335template <typename QuantityT>
280- QuantityT* ScalarQuantity<QuantityT>::setIsolineWidth (double size, bool isRelative) {
281- isolineWidth = ScaledValue<float >(size, isRelative);
336+ QuantityT* ScalarQuantity<QuantityT>::setIsolinePeriod (double size, bool isRelative) {
337+ isolinePeriod = ScaledValue<float >(size, isRelative);
282338 if (!isolinesEnabled.get ()) {
283339 setIsolinesEnabled (true );
284340 }
285341 requestRedraw ();
286342 return &quantity;
287343}
288344template <typename QuantityT>
345+ double ScalarQuantity<QuantityT>::getIsolinePeriod() {
346+ return isolinePeriod.get ().asAbsolute ();
347+ }
348+
349+ template <typename QuantityT>
350+ QuantityT* ScalarQuantity<QuantityT>::setIsolineWidth(double size, bool isRelative) {
351+ return setIsolinePeriod (size, isRelative);
352+ }
353+ template <typename QuantityT>
289354double ScalarQuantity<QuantityT>::getIsolineWidth() {
290- return isolineWidth. get (). asAbsolute ();
355+ return getIsolinePeriod ();
291356}
292357
293358template <typename QuantityT>
@@ -319,4 +384,31 @@ bool ScalarQuantity<QuantityT>::getIsolinesEnabled() {
319384 return isolinesEnabled.get ();
320385}
321386
387+ template <typename QuantityT>
388+ QuantityT* ScalarQuantity<QuantityT>::setIsolineStyle(IsolineStyle val) {
389+ isolineStyle = val;
390+ quantity.refresh ();
391+ requestRedraw ();
392+ return &quantity;
393+ }
394+ template <typename QuantityT>
395+ IsolineStyle ScalarQuantity<QuantityT>::getIsolineStyle() {
396+ return isolineStyle.get ();
397+ }
398+
399+
400+ template <typename QuantityT>
401+ QuantityT* ScalarQuantity<QuantityT>::setIsolineContourThickness(double val) {
402+ isolineContourThickness = val;
403+ if (!isolinesEnabled.get ()) {
404+ setIsolinesEnabled (true );
405+ }
406+ requestRedraw ();
407+ return &quantity;
408+ }
409+ template <typename QuantityT>
410+ double ScalarQuantity<QuantityT>::getIsolineContourThickness() {
411+ return isolineContourThickness.get ();
412+ }
413+
322414} // namespace polyscope
0 commit comments