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
3 changes: 2 additions & 1 deletion examples/demo-app/demo_app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@ void processFileOBJ(std::string filename) {
randColor[iV] = {{polyscope::randomUnit(), polyscope::randomUnit(), polyscope::randomUnit()}};
}
polyscope::getSurfaceMesh(niceName)->addVertexScalarQuantity("cX_really_really_stupid_long_name_how_dumb", valX);
polyscope::getSurfaceMesh(niceName)->addVertexScalarQuantity("cY", valY);
auto q = polyscope::getSurfaceMesh(niceName)->addVertexScalarQuantity("cY", valY);
q->setOnscreenColorbarEnabled(true); // set the onscreen colormap for this one
polyscope::getSurfaceMesh(niceName)->addVertexScalarQuantity("cZ", valZ);
polyscope::getSurfaceMesh(niceName)->addVertexColorQuantity("vColor", randColor);
polyscope::getSurfaceMesh(niceName)->addVertexScalarQuantity("cY_sym", valY, polyscope::DataType::SYMMETRIC);
Expand Down
90 changes: 90 additions & 0 deletions include/polyscope/color_bar.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// Copyright 2017-2023, Nicholas Sharp and the Polyscope contributors. https://polyscope.run

#pragma once

#include "polyscope/quantity.h"
#include "polyscope/render/color_maps.h"
#include "polyscope/render/engine.h"
#include "polyscope/widget.h"

#include <vector>


namespace polyscope {

// A histogram that shows up in ImGUI window
// ONEDAY: we could definitely make a better histogram widget for categorical data...

class OncreenColorBarWidget;

class ColorBar {
public:
friend class OnscreenColorBarWidget;
ColorBar(Quantity& parent_); // must call buildHistogram() with data after
~ColorBar();

void buildHistogram(const std::vector<float>& values, DataType datatype);
void updateColormap(const std::string& newColormap);

// Width = -1 means set automatically
void buildUI(float width = -1.0);

Quantity& parent;
std::pair<double, double> colormapRange; // in DATA values, not [0,1]

void exportColorbarToSVG(const std::string& filename);

// Getters and setters

void setOnscreenColorbarEnabled(bool newEnabled);
bool getOnscreenColorbarEnabled();

// Location in screen coords. (-1,-1), means "place automatically" (default)
void setOnscreenColorbarLocation(glm::vec2 newScreenCoords);
glm::vec2 getOnscreenColorbarLocation();

private:
// Basic data defining the color map
DataType dataType = DataType::STANDARD;
std::pair<double, double> dataRange;

// == The inline horizontal histogram visualization in the structures bar

// Manage histogram counts
void fillHistogramBuffers();
size_t rawHistBinCount = 51;
std::vector<float> rawHistCurveY;
std::vector<std::array<float, 2>> rawHistCurveX;

// Render to a texture for the inline histogram visualization in the structures bar
void renderInlineHistogramToTexture();
void prepareInlineHistogram();
unsigned int texDim = 600;
std::shared_ptr<render::TextureBuffer> inlineHistogramTexture = nullptr;
std::shared_ptr<render::FrameBuffer> inlineHistogramFramebuffer = nullptr;
std::shared_ptr<render::ShaderProgram> inlineHistogramProgram = nullptr;
std::string colormap = "viridis";

// A few parameters which control appearance
float bottomBarHeight = 0.35;
float bottomBarGap = 0.1;

// == The optional vertical colorbar which floats ont he main display
PersistentValue<bool> onscreenColorbarEnabled;
PersistentValue<glm::vec2> onscreenColorbarLocation;
std::shared_ptr<render::TextureBuffer> cmapTexture; // this is just the plain colormap rgb
void prepareOnscreenColorBar();
std::unique_ptr<Widget> onscreenColorBarWidget = nullptr;
};

class OnscreenColorBarWidget : public Widget {
public:
OnscreenColorBarWidget(ColorBar& parent_);
virtual void draw() override;

private:
ColorBar& parent;
};


} // namespace polyscope
1 change: 0 additions & 1 deletion include/polyscope/curve_network_scalar_quantity.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include "polyscope/affine_remapper.h"
#include "polyscope/curve_network.h"
#include "polyscope/histogram.h"
#include "polyscope/render/color_maps.h"
#include "polyscope/scalar_quantity.h"

Expand Down
59 changes: 0 additions & 59 deletions include/polyscope/histogram.h

This file was deleted.

10 changes: 10 additions & 0 deletions include/polyscope/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,15 @@ extern bool& pointCloudEfficiencyWarningReported;
// global members
extern FloatingQuantityStructure*& globalFloatingQuantityStructure;


// == UI and layout related
extern float imguiStackMargin;
extern float lastWindowHeightPolyscope;
extern float lastWindowHeightUser;
extern float lastRightSideFreeX;
extern float lastRightSideFreeY;
extern float leftWindowsWidth;
extern float rightWindowsWidth;

} // namespace internal
} // namespace polyscope
2 changes: 2 additions & 0 deletions include/polyscope/persistent_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ extern PersistentCache<double> persistentCache_double;
extern PersistentCache<float> persistentCache_float;
extern PersistentCache<bool> persistentCache_bool;
extern PersistentCache<std::string> persistentCache_string;
extern PersistentCache<glm::vec2> persistentCache_glmvec2;
extern PersistentCache<glm::vec3> persistentCache_glmvec3;
extern PersistentCache<glm::mat4> persistentCache_glmmat4;
extern PersistentCache<ScaledValue<double>> persistentCache_scaleddouble;
Expand All @@ -150,6 +151,7 @@ template<> inline PersistentCache<double>& getPersistentCacheR
template<> inline PersistentCache<float>& getPersistentCacheRef<float>() { return persistentCache_float; }
template<> inline PersistentCache<bool>& getPersistentCacheRef<bool>() { return persistentCache_bool; }
template<> inline PersistentCache<std::string>& getPersistentCacheRef<std::string>() { return persistentCache_string; }
template<> inline PersistentCache<glm::vec2>& getPersistentCacheRef<glm::vec2>() { return persistentCache_glmvec2; }
template<> inline PersistentCache<glm::vec3>& getPersistentCacheRef<glm::vec3>() { return persistentCache_glmvec3; }
template<> inline PersistentCache<glm::mat4>& getPersistentCacheRef<glm::mat4>() { return persistentCache_glmmat4; }
template<> inline PersistentCache<ScaledValue<double>>& getPersistentCacheRef<ScaledValue<double>>() { return persistentCache_scaleddouble; }
Expand Down
1 change: 0 additions & 1 deletion include/polyscope/point_cloud_color_quantity.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

#include "polyscope/affine_remapper.h"
#include "polyscope/color_quantity.h"
#include "polyscope/histogram.h"
#include "polyscope/point_cloud.h"
#include "polyscope/point_cloud_quantity.h"

Expand Down
1 change: 0 additions & 1 deletion include/polyscope/point_cloud_scalar_quantity.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#pragma once

#include "polyscope/affine_remapper.h"
#include "polyscope/histogram.h"
#include "polyscope/point_cloud.h"
#include "polyscope/render/color_maps.h"
#include "polyscope/scalar_quantity.h"
Expand Down
7 changes: 5 additions & 2 deletions include/polyscope/render/color_maps.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,11 @@ struct ValueColorMap {
double scaledVal = val * (values.size() - 1);
double lowerVal = std::floor(scaledVal);
double upperBlendVal = scaledVal - lowerVal;
unsigned int lowerInd = static_cast<unsigned int>(lowerVal);
unsigned int upperInd = lowerInd + 1;
int lowerInd = static_cast<unsigned int>(lowerVal);
int upperInd = lowerInd + 1;

lowerInd = std::min(std::max(0, lowerInd), (int)values.size() - 1);
upperInd = std::min(std::max(0, upperInd), (int)values.size() - 1);

return (float)(1.0 - upperBlendVal) * values[lowerInd] + (float)upperBlendVal * values[upperInd];
}
Expand Down
1 change: 1 addition & 0 deletions include/polyscope/render/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -614,6 +614,7 @@ class Engine {
std::vector<std::unique_ptr<ValueColorMap>> colorMaps;
const ValueColorMap& getColorMap(const std::string& name);
void loadColorMap(std::string cmapName, std::string filename);
std::shared_ptr<TextureBuffer> getColorMapTexture2d(const std::string& cmapName);

// Helpers
std::vector<glm::vec3> screenTrianglesCoords(); // two triangles which cover the screen
Expand Down
17 changes: 15 additions & 2 deletions include/polyscope/scalar_quantity.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#pragma once

#include "polyscope/affine_remapper.h"
#include "polyscope/histogram.h"
#include "polyscope/color_bar.h"
#include "polyscope/persistent_value.h"
#include "polyscope/polyscope.h"
#include "polyscope/render/engine.h"
Expand Down Expand Up @@ -33,6 +33,9 @@ class ScalarQuantity {
template <class V>
void updateData(const V& newValues);

// Export the current colorbar as an SVG file
void exportColorbarToSVG(const std::string& filename);

// === Members
QuantityT& quantity;

Expand All @@ -51,6 +54,15 @@ class ScalarQuantity {
std::pair<double, double> getMapRange();
QuantityT* resetMapRange(); // reset to full range
std::pair<double, double> getDataRange();

// Color bar options (it is always displayed inline in the structures panel)
QuantityT* setOnscreenColorbarEnabled(bool newEnabled);
bool getOnscreenColorbarEnabled();

// Location in screen coords. (-1,-1), means "place automatically" (default)
QuantityT* setOnscreenColorbarLocation(glm::vec2 newScreenCoords);
glm::vec2 getOnscreenColorbarLocation();


// Isolines
// NOTE there's a name typo, errant `s` in isolinesEnabled (leaving to avoid breaking change)
Expand Down Expand Up @@ -79,7 +91,8 @@ class ScalarQuantity {
std::pair<double, double> dataRange;
PersistentValue<float> vizRangeMin;
PersistentValue<float> vizRangeMax;
Histogram hist;

ColorBar colorBar;

// Parameters
PersistentValue<std::string> cMap;
Expand Down
51 changes: 44 additions & 7 deletions include/polyscope/scalar_quantity.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ ScalarQuantity<QuantityT>::ScalarQuantity(QuantityT& quantity_, const std::vecto
dataType(dataType_), dataRange(robustMinMax(values.data, 1e-5)),
vizRangeMin(quantity.uniquePrefix() + "vizRangeMin", -777.), // set later,
vizRangeMax(quantity.uniquePrefix() + "vizRangeMax", -777.), // including clearing cache
cMap(quantity.uniquePrefix() + "cmap", defaultColorMap(dataType)),
colorBar(quantity), cMap(quantity.uniquePrefix() + "cmap", defaultColorMap(dataType)),
isolinesEnabled(quantity.uniquePrefix() + "isolinesEnabled", false),
isolineStyle(quantity.uniquePrefix() + "isolinesStyle", IsolineStyle::Stripe),
isolinePeriod(quantity.uniquePrefix() + "isolinePeriod",
Expand All @@ -22,8 +22,8 @@ ScalarQuantity<QuantityT>::ScalarQuantity(QuantityT& quantity_, const std::vecto

{
values.checkInvalidValues();
hist.updateColormap(cMap.get());
hist.buildHistogram(values.data, dataType);
colorBar.updateColormap(cMap.get());
colorBar.buildHistogram(values.data, dataType);
// TODO: I think we might be building the histogram ^^^ twice for many quantities

if (vizRangeMin.holdsDefaultValue()) { // min and max should always have same cache state
Expand All @@ -38,7 +38,7 @@ void ScalarQuantity<QuantityT>::buildScalarUI() {

if (render::buildColormapSelector(cMap.get())) {
quantity.refresh();
hist.updateColormap(cMap.get());
colorBar.updateColormap(cMap.get());
setColorMap(getColorMap());
}

Expand Down Expand Up @@ -82,10 +82,10 @@ void ScalarQuantity<QuantityT>::buildScalarUI() {


// Draw the histogram of values
hist.colormapRange = std::pair<float, float>(vizRangeMin.get(), vizRangeMax.get());
colorBar.colormapRange = std::pair<float, float>(vizRangeMin.get(), vizRangeMax.get());
float windowWidth = ImGui::GetWindowWidth();
float histWidth = 0.75 * windowWidth;
hist.buildUI(histWidth);
colorBar.buildUI(histWidth);

// Data range
// Note: %g specifiers are generally nicer than %e, but here we don't acutally have a choice. ImGui (for somewhat
Expand Down Expand Up @@ -220,6 +220,14 @@ void ScalarQuantity<QuantityT>::buildScalarOptionsUI() {
if (dataType != DataType::CATEGORICAL) {
if (ImGui::MenuItem("Enable isolines", NULL, isolinesEnabled.get())) setIsolinesEnabled(!isolinesEnabled.get());
}
if (ImGui::MenuItem("Onscreen Colorbar", NULL, colorBar.getOnscreenColorbarEnabled())) {
colorBar.setOnscreenColorbarEnabled(!colorBar.getOnscreenColorbarEnabled());
}
if (ImGui::MenuItem("Export Colorbar")) {
std::string filename = quantity.parent.name + "_" + quantity.name + "_colorbar.svg";
colorBar.exportColorbarToSVG(filename);
polyscope::info("Exported colorbar to " + filename);
}
}

template <typename QuantityT>
Expand Down Expand Up @@ -294,6 +302,12 @@ QuantityT* ScalarQuantity<QuantityT>::resetMapRange() {
return &quantity;
}


template <typename QuantityT>
void ScalarQuantity<QuantityT>::exportColorbarToSVG(const std::string& filename) {
colorBar.exportColorbarToSVG(filename);
}

template <typename QuantityT>
template <class V>
void ScalarQuantity<QuantityT>::updateData(const V& newValues) {
Expand All @@ -306,7 +320,7 @@ void ScalarQuantity<QuantityT>::updateData(const V& newValues) {
template <typename QuantityT>
QuantityT* ScalarQuantity<QuantityT>::setColorMap(std::string val) {
cMap = val;
hist.updateColormap(cMap.get());
colorBar.updateColormap(cMap.get());
quantity.refresh();
requestRedraw();
return &quantity;
Expand All @@ -316,6 +330,29 @@ std::string ScalarQuantity<QuantityT>::getColorMap() {
return cMap.get();
}


template <typename QuantityT>
QuantityT* ScalarQuantity<QuantityT>::setOnscreenColorbarEnabled(bool newEnabled) {
colorBar.setOnscreenColorbarEnabled(newEnabled);
requestRedraw();
return &quantity;
}
template <typename QuantityT>
bool ScalarQuantity<QuantityT>::getOnscreenColorbarEnabled() {
return colorBar.getOnscreenColorbarEnabled();
}

template <typename QuantityT>
QuantityT* ScalarQuantity<QuantityT>::setOnscreenColorbarLocation(glm::vec2 newScreenCoords) {
colorBar.setOnscreenColorbarLocation(newScreenCoords);
requestRedraw();
return &quantity;
}
template <typename QuantityT>
glm::vec2 ScalarQuantity<QuantityT>::getOnscreenColorbarLocation() {
return colorBar.getOnscreenColorbarLocation();
}

template <typename QuantityT>
QuantityT* ScalarQuantity<QuantityT>::setMapRange(std::pair<double, double> val) {
vizRangeMin = val.first;
Expand Down
Loading