@@ -1183,6 +1183,8 @@ void Renderer::setSettings(const Renderer::Settings& settings)
11831183 }
11841184}
11851185
1186+ // ////////////////////////////////////////////////////////////////
1187+
11861188SpectrumGenerator::SpectrumGenerator (double max_value) : scale_(1.0 / max_value)
11871189{
11881190}
@@ -1209,6 +1211,40 @@ Painter::Color SpectrumGenerator::getColor(double value, int alpha) const
12091211void SpectrumGenerator::drawLegend (
12101212 Painter& painter,
12111213 const std::vector<std::pair<int , std::string>>& legend_key) const
1214+ {
1215+ const int color_count = getColorCount ();
1216+ std::vector<Painter::Color> colors;
1217+ colors.reserve (color_count);
1218+ for (int i = 0 ; i < color_count; i += kLegendColorIncrement ) {
1219+ const double color_idx = (color_count - 1 - i) / scale_;
1220+ colors.push_back (getColor (color_idx / color_count));
1221+ }
1222+ std::vector<std::pair<Painter::Color, std::string>> legend_key_colors;
1223+ for (const auto & [legend_value, legend_text] : legend_key) {
1224+ const int idx = std::clamp (legend_value / kLegendColorIncrement ,
1225+ 0 ,
1226+ static_cast <int >(colors.size ()) - 1 );
1227+ legend_key_colors.push_back ({colors[idx], legend_text});
1228+ }
1229+ LinearLegend legend (colors);
1230+ legend.setLegendKey (legend_key_colors);
1231+ legend.draw (painter);
1232+ }
1233+
1234+ // ///////////////////////////////////////////////
1235+
1236+ LinearLegend::LinearLegend (const std::vector<Painter::Color>& colors)
1237+ : colors_(colors)
1238+ {
1239+ }
1240+
1241+ void LinearLegend::setLegendKey (
1242+ const std::vector<std::pair<Painter::Color, std::string>>& legend_key)
1243+ {
1244+ legend_key_ = legend_key;
1245+ }
1246+
1247+ void LinearLegend::draw (Painter& painter) const
12121248{
12131249 const odb::Rect& bounds = painter.getBounds ();
12141250 const double pixel_per_dbu = painter.getPixelsPerDBU ();
@@ -1224,14 +1260,20 @@ void SpectrumGenerator::drawLegend(
12241260 odb::Rect legend_bounds (
12251261 legend_left, legend_top, legend_right + text_offset, legend_top);
12261262
1227- const int color_count = getColorCount ();
1228- const int color_incr = 2 ;
1263+ const int color_count = colors_.size ();
12291264
12301265 std::vector<std::pair<odb::Point, std::string>> legend_key_points;
1231- for (const auto & [legend_value, legend_text] : legend_key) {
1266+ for (const auto & [legend_color, legend_text] : legend_key_) {
1267+ const auto find_color = std::ranges::find (colors_, legend_color);
1268+ if (find_color == colors_.end ()) {
1269+ continue ;
1270+ }
1271+ const int legend_value
1272+ = std::distance (colors_.begin (), find_color); // index in colors_
1273+
12321274 const int text_right = legend_left - text_offset;
12331275 const int box_top
1234- = legend_top - ((color_count - legend_value) * box_height) / color_incr ;
1276+ = legend_top - ((color_count - legend_value) * box_height);
12351277
12361278 legend_key_points.push_back ({{text_right, box_top}, legend_text});
12371279 const odb::Rect text_bounds = painter.stringBoundaries (
@@ -1247,10 +1289,8 @@ void SpectrumGenerator::drawLegend(
12471289
12481290 // draw color map
12491291 double box_top = legend_top;
1250- for (int i = 0 ; i < color_count; i += color_incr) {
1251- const double color_idx = (color_count - 1 - i) / scale_;
1252-
1253- painter.setPen (getColor (color_idx / color_count), true );
1292+ for (int i = 0 ; i < color_count; i++) {
1293+ painter.setPen (colors_[i], true );
12541294 painter.drawLine (odb::Point (legend_left, box_top),
12551295 odb::Point (legend_right, box_top));
12561296 box_top -= box_height;
@@ -1265,6 +1305,71 @@ void SpectrumGenerator::drawLegend(
12651305 painter.drawRect (odb::Rect (legend_left, box_top, legend_right, legend_top));
12661306}
12671307
1308+ // ///////////////////////////////////////////////
1309+
1310+ void DiscreteLegend::addLegendKey (const Painter::Color& color,
1311+ const std::string& text)
1312+ {
1313+ color_key_.emplace_back (color, text);
1314+ }
1315+
1316+ void DiscreteLegend::draw (Painter& painter) const
1317+ {
1318+ const odb::Rect& bounds = painter.getBounds ();
1319+ const double pixel_per_dbu = painter.getPixelsPerDBU ();
1320+ const int legend_offset = 20 / pixel_per_dbu; // 20 pixels
1321+ const int legend_width = 20 / pixel_per_dbu; // 20 pixels
1322+ const int text_offset = 2 / pixel_per_dbu;
1323+ const int color_offset = 2 * text_offset;
1324+ const int legend_top = bounds.yMax () - legend_offset;
1325+ const int legend_right = bounds.xMax () - legend_offset;
1326+ const int legend_left = legend_right - legend_width;
1327+
1328+ odb::Rect legend_bounds (
1329+ legend_left, legend_top, legend_right + text_offset, legend_top);
1330+
1331+ std::vector<std::pair<odb::Rect, std::string>> legend_key_rects;
1332+ std::vector<std::pair<odb::Rect, Painter::Color>> legend_color_rects;
1333+ int last_text_top = legend_top;
1334+ for (const auto & [legend_color, legend_text] : color_key_) {
1335+ const int text_right = legend_left - text_offset;
1336+
1337+ const odb::Rect key_rect = painter.stringBoundaries (
1338+ text_right, last_text_top, Painter::Anchor::kTopRight , legend_text);
1339+
1340+ last_text_top = key_rect.yMin ();
1341+
1342+ legend_key_rects.push_back ({key_rect, legend_text});
1343+ legend_color_rects.push_back ({{legend_left + color_offset,
1344+ key_rect.yMin () + color_offset,
1345+ legend_right - color_offset,
1346+ key_rect.yMax () - color_offset},
1347+ legend_color});
1348+ legend_bounds.merge (key_rect);
1349+ }
1350+
1351+ // draw background
1352+ painter.setPen (Painter::kDarkGray , true );
1353+ painter.setBrush (Painter::kDarkGray );
1354+ painter.drawRect (legend_bounds, 10 , 10 );
1355+
1356+ // draw color map
1357+ painter.setPen (Painter::kBlack , true );
1358+ for (const auto & [rect, color] : legend_color_rects) {
1359+ painter.setBrush (color);
1360+ painter.drawRect (rect);
1361+ }
1362+
1363+ // draw key values
1364+ painter.setBrush (Painter::kTransparent );
1365+ for (const auto & [rect, text] : legend_key_rects) {
1366+ painter.drawString (
1367+ rect.xMax (), rect.yCenter (), Painter::Anchor::kRightCenter , text);
1368+ }
1369+ }
1370+
1371+ // ///////////////////////////////////////////////
1372+
12681373void Gui::fit ()
12691374{
12701375 main_window->fit ();
0 commit comments