Path: blob/main/src/utils/gui/settings/GUIPropertyScheme.h
169685 views
/****************************************************************************/1// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.dev/sumo2// Copyright (C) 2001-2025 German Aerospace Center (DLR) and others.3// This program and the accompanying materials are made available under the4// terms of the Eclipse Public License 2.0 which is available at5// https://www.eclipse.org/legal/epl-2.0/6// This Source Code may also be made available under the following Secondary7// Licenses when the conditions for such availability set forth in the Eclipse8// Public License 2.0 are satisfied: GNU General Public License, version 29// or later which is available at10// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html11// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later12/****************************************************************************/13/// @file GUIPropertyScheme.h14/// @author Michael Behrisch15/// @author Daniel Krajzewicz16/// @author Jakob Erdmann17/// @date Mon, 20.07.200918///19//20/****************************************************************************/21#pragma once22#include <config.h>2324#include <cassert>25#include <vector>26#include <utils/common/RGBColor.h>27#include <utils/iodevices/OutputDevice.h>28#include <utils/gui/images/GUIIcons.h>293031// ===========================================================================32// class definitions33// ===========================================================================34/**35* @class GUIPropertyScheme36* This class provides a mapping from real values to properties (mainly colors).37* Each color is stored along with a threshold value.38* Color values between thresholds are obtained by interpolation39*/4041template<class T>42class GUIPropertyScheme {43public:44/// Constructor45GUIPropertyScheme(const std::string& name, const std::string& translatedName, const T& baseColor,46const std::string& colName = "", const bool isFixed = false, double baseValue = 0,47RGBColor bgColor = RGBColor::WHITE,48GUIIcon icon = GUIIcon::EMPTY) :49myName(name),50myTranslatedName(translatedName),51myIsInterpolated(!isFixed),52myIsFixed(isFixed),53myAllowNegativeValues(false),54myIcon(icon),55myBgColor(bgColor) {56addColor(baseColor, baseValue, colName);57}5859GUIPropertyScheme(const std::string& name, const T& baseColor,60const std::string& colName = "", const bool isFixed = false, double baseValue = 0,61RGBColor bgColor = RGBColor::WHITE,62GUIIcon icon = GUIIcon::EMPTY) :63myName(name),64myTranslatedName(name),65myIsInterpolated(!isFixed),66myIsFixed(isFixed),67myAllowNegativeValues(false),68myIcon(icon),69myBgColor(bgColor) {70addColor(baseColor, baseValue, colName);71}7273void setThreshold(const int pos, const double threshold) {74myThresholds[pos] = threshold;75}7677void setColor(const int pos, const T& color) {78myColors[pos] = color;79}8081bool setColor(const std::string& name, const T& color) {82std::vector<std::string>::iterator nameIt = myNames.begin();83typename std::vector<T>::iterator colIt = myColors.begin();84for (; nameIt != myNames.end(); ++nameIt, ++colIt) {85if (*nameIt == name) {86(*colIt) = color;87return true;88}89}90return false;91}9293int addColor(const T& color, const double threshold, const std::string& name = "") {94typename std::vector<T>::iterator colIt = myColors.begin();95std::vector<double>::iterator threshIt = myThresholds.begin();96std::vector<std::string>::iterator nameIt = myNames.begin();97int pos = 0;98while (threshIt != myThresholds.end() && (*threshIt) < threshold) {99++threshIt;100++colIt;101++nameIt;102pos++;103}104myColors.insert(colIt, color);105myThresholds.insert(threshIt, threshold);106myNames.insert(nameIt, name);107return pos;108}109110void removeColor(const int pos) {111assert(pos < (int)myColors.size());112myColors.erase(myColors.begin() + pos);113myThresholds.erase(myThresholds.begin() + pos);114myNames.erase(myNames.begin() + pos);115}116117void clear() {118myColors.clear();119myThresholds.clear();120myNames.clear();121}122123T getColor(const double value) const {124if (myColors.size() == 1 || value < myThresholds.front()) {125return myColors.front();126}127typename std::vector<T>::const_iterator colIt = myColors.begin() + 1;128std::vector<double>::const_iterator threshIt = myThresholds.begin() + 1;129while (threshIt != myThresholds.end() && (*threshIt) <= value) {130++threshIt;131++colIt;132}133if (threshIt == myThresholds.end()) {134return myColors.back();135}136if (!myIsInterpolated) {137return *(colIt - 1);138}139double lowVal = *(threshIt - 1);140return interpolate(*(colIt - 1), *colIt, (value - lowVal) / ((*threshIt) - lowVal));141}142143void setInterpolated(const bool interpolate, double interpolationStart = 0.f) {144myIsInterpolated = interpolate;145if (interpolate) {146myThresholds[0] = interpolationStart;147}148}149150const std::string& getName() const {151return myName;152}153154const std::string& getTranslatedName() const {155return myTranslatedName;156}157158const std::vector<T>& getColors() const {159return myColors;160}161162const std::vector<double>& getThresholds() const {163return myThresholds;164}165166bool isInterpolated() const {167return myIsInterpolated;168}169170const std::vector<std::string>& getNames() const {171return myNames;172}173174bool isFixed() const {175return myIsFixed;176}177178bool allowsNegativeValues() const {179return myAllowNegativeValues;180}181182void setAllowsNegativeValues(bool value) {183myAllowNegativeValues = value;184}185186GUIIcon getIcon() const {187return myIcon;188}189190const RGBColor& getBackgroundColor() const {191return myBgColor;192}193194void save(OutputDevice& dev, const std::string& prefix = "") const {195const int precision = dev.getPrecision();196const bool checkPrecision = precision <= 2; // 2 is default precision (see SystemFrame)197const std::string tag = getTagName(myColors);198199dev.openTag(tag);200dev.writeAttr(SUMO_ATTR_NAME, prefix + myName);201if (!myIsFixed) {202dev.writeAttr(SUMO_ATTR_INTERPOLATED, myIsInterpolated);203}204typename std::vector<T>::const_iterator colIt = myColors.begin();205std::vector<double>::const_iterator threshIt = myThresholds.begin();206std::vector<std::string>::const_iterator nameIt = myNames.begin();207while (threshIt != myThresholds.end()) {208dev.openTag(SUMO_TAG_ENTRY);209dev.writeAttr(SUMO_ATTR_COLOR, *colIt);210if (!myIsFixed && (*threshIt) != std::numeric_limits<double>::max()) {211const double t = *threshIt;212if (checkPrecision && t != 0 && fabs(t) < 0.01) {213dev.setPrecision(8);214}215dev.writeAttr(SUMO_ATTR_THRESHOLD, t);216dev.setPrecision(precision);217}218if ((*nameIt) != "") {219dev.writeAttr(SUMO_ATTR_NAME, *nameIt);220}221dev.closeTag();222++threshIt;223++colIt;224++nameIt;225}226dev.closeTag();227}228229bool operator==(const GUIPropertyScheme& c) const {230return myName == c.myName && myColors == c.myColors && myThresholds == c.myThresholds && myIsInterpolated == c.myIsInterpolated;231}232233234/// @brief specializations for GUIColorScheme235RGBColor interpolate(const RGBColor& min, const RGBColor& max, double weight) const {236return RGBColor::interpolate(min, max, weight);237}238239std::string getTagName(std::vector<RGBColor>) const {240return toString(SUMO_TAG_COLORSCHEME);241}242243244/// @brief specializations for GUIScaleScheme245double interpolate(const double& min, const double& max, double weight) const {246return min + (max - min) * weight;247}248249std::string getTagName(std::vector<double>) const {250return toString(SUMO_TAG_SCALINGSCHEME);251}252253254private:255std::string myName;256std::string myTranslatedName;257std::vector<T> myColors;258std::vector<double> myThresholds;259bool myIsInterpolated;260std::vector<std::string> myNames;261bool myIsFixed;262bool myAllowNegativeValues;263GUIIcon myIcon;264RGBColor myBgColor;265266};267268typedef GUIPropertyScheme<RGBColor> GUIColorScheme;269typedef GUIPropertyScheme<double> GUIScaleScheme;270271272