Browse Source

add colorbar

master
cflin 2 years ago
parent
commit
8ee61d63f9
  1. 1
      CMakeLists.txt
  2. 19
      src/static_sim/SimTargetOption.cpp
  3. 3
      src/static_sim/SimTargetOption.h
  4. 129
      src/viewer/ColorbarPlugin.cpp
  5. 36
      src/viewer/ColorbarPlugin.h
  6. 47
      src/viewer/StaticSimGUI.cpp
  7. 23
      src/viewer/StaticSimGUI.h
  8. 58
      src/viewer/StaticSimGUIMenu.cpp
  9. 35
      src/viewer/Util.h

1
CMakeLists.txt

@ -54,3 +54,4 @@ add_subdirectory(${CMAKE_SOURCE_DIR}/sim-test/rigid-test)
target_link_libraries(${PROJECT_NAME} PUBLIC StaticSim)
target_compile_definitions(${PROJECT_NAME} PUBLIC CMAKE_SOURCE_DIR="${CMAKE_SOURCE_DIR}")
#add_compile_definitions(DEBUG_SSIM) # for auto load json

19
src/static_sim/SimTargetOption.cpp

@ -0,0 +1,19 @@
//
// Created by cflin on 4/17/23.
//
#include <string>
#include "SimTargetOption.h"
namespace ssim{
const std::string SimTargetOption::TAEGET_NAME[SimTargetOption::ENUM_SIZE] = {
"位移范数",
"位移-X",
"位移-Y",
"位移-Z",
"应力范数",
"冯氏应力",
"应力-X",
"应力-Y",
"应力-Z",
"柔顺度"
};
};

3
src/static_sim/SimTargetOption.h

@ -4,7 +4,7 @@
#ifndef RIGIDIPC_SIMTARGETOPTION_H
#define RIGIDIPC_SIMTARGETOPTION_H
#include <climits>
namespace ssim {
class SimTargetOption {
@ -12,6 +12,7 @@ namespace ssim {
enum Target {
U_NORM = 0, UX, UY, UZ, S_NORM, S_VON_Mises,/*primary stress*/SX, SY, SZ, COMPLIANCE, ENUM_SIZE
};
static const std::string TAEGET_NAME[ENUM_SIZE];
SimTargetOption(int init_state = 1) : state(init_state) {}

129
src/viewer/ColorbarPlugin.cpp

@ -0,0 +1,129 @@
//
// Created by cflin on 4/17/23.
//
#include "ColorbarPlugin.h"
#include <igl/opengl/glfw/imgui/ImGuiPlugin.h>
namespace ssim {
void ColorbarPlugin::init_colormaps() {
auto texture_from_colormap = [](const Eigen::MatrixXd &rgb, GLuint &id) {
int width = 1;
int height = (int) rgb.rows();
Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> cmap;
if (rgb.maxCoeff() > 1.0) {
cmap = rgb.cast<unsigned char>();
} else {
cmap = (rgb.array() * 255.f).cast<unsigned char>();
}
assert(cmap.cols() == 3);
cmap.conservativeResize(cmap.rows(), 4);
cmap.col(3).setConstant(255);
if (id == 0) {
glGenTextures(1, &id);
}
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA,
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, cmap.data());
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
};
Eigen::MatrixXd rgb;
for (size_t i = 0; i < igl::NUM_COLOR_MAP_TYPES; ++i) {
GLuint id = 0;
colormap(static_cast<igl::ColorMapType>(i), Eigen::VectorXd::LinSpaced(100, 1, 0), false, rgb);
texture_from_colormap(rgb, id);
colormaps_[i] = id;
}
}
// Draws a combo box for selecting the colormap
int ColorbarPlugin::draw_colormap_combo() const {
const char *items[]{
"Inferno",
"Jet",
"Magma",
"Parula",
"Plasma",
"Viridis",
};
static int selected_index = 1;
static const char *current_item = items[selected_index];
ImVec2 combo_pos = ImGui::GetCursorScreenPos();
if (ImGui::BeginCombo("Colormap##combo", "")) {
for (int n = 0; n < IM_ARRAYSIZE(items); ++n) {
// You can store your selection however you want, outside or inside your objects
bool is_selected = (current_item == items[n]);
ImGui::PushID(n);
if (ImGui::Selectable("", is_selected)) {
current_item = items[n];
selected_index = n;
}
ImGui::SameLine(0, 0);
ImGui::Image(
reinterpret_cast<ImTextureID>(colormaps_[n]),
ImVec2(ImGui::GetTextLineHeight(), ImGui::GetTextLineHeight()),
ImVec2(0, 0), ImVec2(1, 1));
ImGui::SameLine();
ImGui::Text("%s", items[n]);
if (is_selected) {
ImGui::SetItemDefaultFocus();
}
ImGui::PopID();
}
ImGui::EndCombo();
}
ImVec2 backup_pos = ImGui::GetCursorScreenPos();
ImGuiStyle &style = ImGui::GetStyle();
ImGui::SetCursorScreenPos(ImVec2(combo_pos.x + style.FramePadding.x, combo_pos.y + style.FramePadding.y));
float h = ImGui::GetTextLineHeight();
ImGui::Image(
reinterpret_cast<ImTextureID>(colormaps_[selected_index]),
ImVec2(h, h));
ImGui::SameLine();
ImGui::Text("%s", current_item);
ImGui::SetCursorScreenPos(backup_pos);
return selected_index;
}
// Draws the actual colorbar with min/max values
void ColorbarPlugin::draw_colorbar(igl::ColorMapType cm, float xmin, float xmax,
const Eigen::Vector4f &background_color) const {
ImVec4 color(0, 0, 0, 1);
// auto rgb = background_color;
// // http://stackoverflow.com/a/3943023/112731
// if (rgb[0] * 0.299 + rgb[1] * 0.587 + rgb[2] * 0.114 > 186) {
color = ImVec4(1, 1, 1, 1);
// }
float w = 20;
float h = 200;
ImGui::BeginGroup();
ImGui::BeginGroup();
static const int num_interval=5;
static const float interval=(h - 1.0*(num_interval+1) * ImGui::GetTextLineHeightWithSpacing())/num_interval;
ImGui::TextColored(color, "%.3g", xmax);
for(int i=num_interval-1;i>=0;--i){
ImGui::Dummy(ImVec2(0, interval));
ImGui::TextColored(color, "%.3g", (xmax-xmin)/num_interval*i+xmin);
}
ImGui::EndGroup();
ImGui::SameLine();
ImGui::Image(reinterpret_cast<ImTextureID>(colormaps_[cm]), ImVec2(w, h));
ImGui::EndGroup();
}
} // ssim

36
src/viewer/ColorbarPlugin.h

@ -0,0 +1,36 @@
//
// Created by cflin on 4/17/23.
//
#ifndef EXAMPLE_COLORBARPLUGIN_H
#define EXAMPLE_COLORBARPLUGIN_H
#include <Eigen/Eigen>
#include <igl/opengl/glfw/Viewer.h>
namespace ssim {
class ColorbarPlugin {
public:
ColorbarPlugin(){
init_colormaps();
}
void draw_colorbar_jet(float xmin,float xmax){
draw_colorbar(igl::COLOR_MAP_TYPE_JET,xmin,xmax, Eigen::Vector4f(0.9f, 0.9f, 0.9f, 0.4f));
}
protected:
void init_colormaps();
int draw_colormap_combo() const;
void draw_colorbar(igl::ColorMapType cm, float xmin, float xmax,
const Eigen::Vector4f &background_color) const;
protected:
std::array <GLuint, igl::NUM_COLOR_MAP_TYPES> colormaps_;
igl::ColorMapType colormap_type_ = igl::COLOR_MAP_TYPE_JET;
};
} // ssim
#endif //EXAMPLE_COLORBARPLUGIN_H

47
src/viewer/StaticSimGUI.cpp

@ -2,8 +2,9 @@
// Created by cflin on 4/14/23.
//
#include "StaticSimGUI.h"
#include "ColorbarPlugin.h"
namespace ssim{
namespace ssim {
void StaticSimGUI::viewer_launch() {
auto config_viewer = [&] {
@ -30,8 +31,8 @@ namespace ssim{
return false;
};
menu_.callback_draw_viewer_window=[&](){
float menu_width = 250.f *plugin_.hidpi_scaling() / plugin_.pixel_ratio();
menu_.callback_draw_viewer_window = [&]() {
float menu_width = 250.f * plugin_.hidpi_scaling() / plugin_.pixel_ratio();
ImGui::SetNextWindowPos(ImVec2(0.0f, 0.0f), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(0.0f, 0.0f), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints(ImVec2(menu_width, -1.0f), ImVec2(menu_width, -1.0f));
@ -43,11 +44,42 @@ namespace ssim{
);
ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.4f);
// call menu here
menu_draw_viewer_menu();
draw_menu();
ImGui::PopItemWidth();
ImGui::End();
if (!gui_ctrl_.is_single_color) {
//--------------------------------window2: colorbar--------------------//
// float legends_width = 270.f * plugin_.hidpi_scaling();
//
// ImGui::SetNextWindowSizeConstraints(
// ImVec2(200.0f, 30.0f), ImVec2(legends_width, -1.0f));
float menu_width = 100.f * plugin_.hidpi_scaling() / plugin_.pixel_ratio();
ImGui::SetNextWindowPos(ImVec2(ImGui::GetIO().DisplaySize.x - menu_width,
ImGui::GetIO().DisplaySize.y - menu_width * 2),
ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSize(ImVec2(0.0f, 0.0f), ImGuiCond_FirstUseEver);
ImGui::SetNextWindowSizeConstraints(ImVec2(menu_width, -1.0f), ImVec2(menu_width, -1.0f));
bool _viewer_menu_visible = true;
ImGui::Begin(
SimTargetOption::TAEGET_NAME[gui_ctrl_.target_to_evaluate].c_str(),
&_viewer_menu_visible,
ImGuiWindowFlags_NoSavedSettings
| ImGuiWindowFlags_AlwaysAutoResize
);
ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.4f);
// call menu here
draw_colorbar();
ImGui::PopItemWidth();
ImGui::End();
}
};
viewer_.launch(
/*resizable=*/true, /*fullscreen=*/false,
/*name=*/"静力学仿真");
@ -103,6 +135,9 @@ namespace ssim{
C.row(NBC_vertex_idx(i_)) = Eigen::RowVector3d(1, 0, 0);
}
}
gui_ctrl_.colorbar_bd.xmin = target.minCoeff();
gui_ctrl_.colorbar_bd.xmax = target.maxCoeff();
viewer_.data_list[0].set_colors(C);
} else {
Eigen::MatrixXd color(V.rows(), 3);
@ -198,9 +233,9 @@ namespace ssim{
// size remain 1
viewer_.data_list.resize(1);
viewer_.data_list.front().clear();
viewer_.data_list.front().show_lines= true;
viewer_.data_list.front().show_lines = true;
// add boundary box
for (int i = 1; i <=sp_StaticSim_->DirichletBCs.size() + sp_StaticSim_->NeumannBCs.size(); ++i) {
for (int i = 1; i <= sp_StaticSim_->DirichletBCs.size() + sp_StaticSim_->NeumannBCs.size(); ++i) {
viewer_.append_mesh();
viewer_.data_list.back().show_lines = false;
}

23
src/viewer/StaticSimGUI.h

@ -19,6 +19,7 @@
#include <igl/colormap.h>
#include "../static_sim/StaticSim.h"
#include "StaticMenu.h"
#include "ColorbarPlugin.h"
namespace ssim {
@ -30,6 +31,10 @@ namespace ssim {
bool is_visible_BC = false;
bool is_visible_mesh = true;
bool is_single_color = true;
struct ColorbarBoundary{
float xmin;
float xmax;
}colorbar_bd;
ssim::SimTargetOption::Target target_to_evaluate = ssim::SimTargetOption::U_NORM;
void set_target(ssim::SimTargetOption::Target target_to_set) {
@ -46,7 +51,7 @@ namespace ssim {
void viewer_launch();
protected:
private:
void reload_json(std::string f_json="");
@ -56,7 +61,21 @@ namespace ssim {
void init_mesh();
void menu_draw_viewer_menu();
void draw_menu();
void draw_colorbar(){
auto colorbar_menu=[&](){
static ColorbarPlugin color_plugin;
color_plugin.draw_colorbar_jet(gui_ctrl_.colorbar_bd.xmin,gui_ctrl_.colorbar_bd.xmax);
};
if (!gui_ctrl_.is_initialized && gui_ctrl_.is_loaded_json) {
if (gui_ctrl_.is_solved) {
if(!gui_ctrl_.is_single_color){
colorbar_menu();
}
}
}
}
private:
bool pre_draw_loop();

58
src/viewer/StaticSimGUIMenu.cpp

@ -4,9 +4,11 @@
#include <igl/file_dialog_save.h>
#include "StaticSimGUI.h"
#include "Util.h"
namespace ssim{
#include "ColorbarPlugin.h"
void StaticSimGUI::menu_draw_viewer_menu() {
namespace ssim {
void StaticSimGUI::draw_menu() {
// Draw parent menu content
// menu_.draw_viewer_menu();
@ -14,19 +16,16 @@ namespace ssim{
if (ImGui::Button("加载文件##IO", ImVec2(-1, 0))) {
#ifndef DEBUG_SSIM
std::string f_json = igl::file_dialog_open();
if (f_json != "" ) {
if(f_json=="") return;
reload_json(f_json);
gui_ctrl_.is_initialized = true;
gui_ctrl_.is_loaded_json = true;
}
#else
load(CMAKE_SOURCE_DIR "/sim-test/rigid-test/rocker-arm/config.json");
reload_json(CMAKE_SOURCE_DIR "/sim-test/rigid-test/cube/config.json");
#endif
gui_ctrl_.is_initialized = true;
gui_ctrl_.is_loaded_json = true;
}
};
auto model_menu = [&]() {
@ -133,85 +132,84 @@ namespace ssim{
auto result_menu = [&]() {
ImGui::TextWrapped("柔顺度 (compliance): %.3e",
sp_StaticSim_->EvaluateTarget(ssim::SimTargetOption::COMPLIANCE)(0, 0));
static const ImVec2 button_size(200,40);
static bool arr_extract[SimTargetOption::Target::ENUM_SIZE]={false};
int idx=0;
if (ImGui::Button("位移范数",button_size)) {
static const ImVec2 button_size(200, 40);
static bool arr_extract[SimTargetOption::Target::ENUM_SIZE] = {false};
int idx = 0;
if (ImGui::Button("位移范数", button_size)) {
gui_ctrl_.set_target(ssim::SimTargetOption::Target::U_NORM);
}
ImGui::SameLine();
ImGui::Checkbox("导出位移范数",arr_extract+idx);
ImGui::Checkbox("导出位移范数", arr_extract + idx);
++idx;
if (ImGui::Button("位移-X", button_size)) {
gui_ctrl_.set_target(ssim::SimTargetOption::Target::UX);
}
ImGui::SameLine();
ImGui::Checkbox("导出位移-X",arr_extract+idx);
ImGui::Checkbox("导出位移-X", arr_extract + idx);
++idx;
if (ImGui::Button("位移-Y", button_size)) {
gui_ctrl_.set_target(ssim::SimTargetOption::Target::UY);
}
ImGui::SameLine();
ImGui::Checkbox("导出位移-Y",arr_extract+idx);
ImGui::Checkbox("导出位移-Y", arr_extract + idx);
++idx;
if (ImGui::Button("位移-Z", button_size)) {
gui_ctrl_.set_target(ssim::SimTargetOption::Target::UZ);
}
ImGui::SameLine();
ImGui::Checkbox("导出位移-Z",arr_extract+idx);
ImGui::Checkbox("导出位移-Z", arr_extract + idx);
++idx;
if (ImGui::Button("应力范数", button_size)) {
gui_ctrl_.set_target(ssim::SimTargetOption::Target::S_NORM);
}
ImGui::SameLine();
ImGui::Checkbox("导出应力范数",arr_extract+idx);
ImGui::Checkbox("导出应力范数", arr_extract + idx);
++idx;
if (ImGui::Button("冯氏应力", button_size)) {
gui_ctrl_.set_target(ssim::SimTargetOption::Target::S_VON_Mises);
}
ImGui::SameLine();
ImGui::Checkbox("导出冯氏应力",arr_extract+idx);
ImGui::Checkbox("导出冯氏应力", arr_extract + idx);
++idx;
if (ImGui::Button("应力-X", button_size)) {
gui_ctrl_.set_target(ssim::SimTargetOption::Target::SX);
}
ImGui::SameLine();
ImGui::Checkbox("导出应力-X",arr_extract+idx);
ImGui::Checkbox("导出应力-X", arr_extract + idx);
++idx;
if (ImGui::Button("应力-Y", button_size)) {
gui_ctrl_.set_target(ssim::SimTargetOption::Target::SY);
}
ImGui::SameLine();
ImGui::Checkbox("导出应力-Y",arr_extract+idx);
ImGui::Checkbox("导出应力-Y", arr_extract + idx);
++idx;
if (ImGui::Button("应力-Z", button_size)) {
gui_ctrl_.set_target(ssim::SimTargetOption::Target::SZ);
}
ImGui::SameLine();
ImGui::Checkbox("导出应力-Z",arr_extract+idx);
ImGui::Checkbox("导出应力-Z", arr_extract + idx);
++idx;
static bool is_extract_coord= false;
if(ImGui::Button("导出结果文件",button_size)){
std::string extract_dir=ssim::directory_dialog_save();
spdlog::info("extract to: {}",extract_dir);
std::vector<bool> v_is_extract(arr_extract,arr_extract+SimTargetOption::Target::ENUM_SIZE);
sp_StaticSim_->ExtractTarget(extract_dir,v_is_extract,is_extract_coord);
static bool is_extract_coord = false;
if (ImGui::Button("导出结果文件", button_size)) {
std::string extract_dir = ssim::directory_dialog_save();
spdlog::info("extract to: {}", extract_dir);
std::vector<bool> v_is_extract(arr_extract, arr_extract + SimTargetOption::Target::ENUM_SIZE);
sp_StaticSim_->ExtractTarget(extract_dir, v_is_extract, is_extract_coord);
}
ImGui::SameLine();
ImGui::Checkbox("导出坐标",&is_extract_coord);
ImGui::Checkbox("导出坐标", &is_extract_coord);
};
if (ImGui::CollapsingHeader("载入模型", ImGuiTreeNodeFlags_DefaultOpen)) {
io_menu();
}

35
src/viewer/Util.h

@ -7,7 +7,7 @@
#include <string>
#include <cstdio>
#include <cstring>
#include <Eigen/Eigen>
#ifdef _WIN32
#include <windows.h>
#include <Commdlg.h>
@ -111,6 +111,39 @@ namespace ssim {
return std::string(buffer);
}
void texture_from_colormap(const Eigen::MatrixXd &rgb, GLuint & id)
{
int width = 1;
int height = (int) rgb.rows();
Eigen::Matrix<unsigned char, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor> cmap;
if (rgb.maxCoeff() > 1.0) {
cmap = rgb.cast<unsigned char>();
} else {
cmap = (rgb.array() * 255.f).cast<unsigned char>();
}
assert(cmap.cols() == 3);
cmap.conservativeResize(cmap.rows(), 4);
cmap.col(3).setConstant(255);
if (id == 0) {
glGenTextures(1, &id);
}
glBindTexture(GL_TEXTURE_2D, id);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(
GL_TEXTURE_2D, 0, GL_RGBA,
width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, cmap.data());
glGenerateMipmap(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, 0);
}
} // ssim
#endif //EXAMPLE_UTIL_H

Loading…
Cancel
Save