diff --git a/src/blackmisc/aviation/livery.cpp b/src/blackmisc/aviation/livery.cpp index 7ad183ef6..2e05bcf91 100644 --- a/src/blackmisc/aviation/livery.cpp +++ b/src/blackmisc/aviation/livery.cpp @@ -103,6 +103,11 @@ namespace BlackMisc return c == this->m_combinedCode; } + bool CLivery::matchesColors(const CRgbColor &fuselage, const CRgbColor &tail) const + { + return this->getColorFuselage() == fuselage && this->getColorTail() == tail; + } + QString CLivery::convertToQString(bool i18n) const { QString s(i18n ? QCoreApplication::translate("Aviation", "Livery") : "Livery"); @@ -178,6 +183,23 @@ namespace BlackMisc return m_combinedCode.startsWith(colorLiveryMarker()); } + double CLivery::getColorDistance(const CRgbColor &fuselage, const CRgbColor &tail) const + { + if (!fuselage.isValid() || !tail.isValid()) { return 1.0; } + if (this->getColorFuselage().isValid() && this->getColorTail().isValid()) + { + if (this->matchesColors(fuselage, tail)) { return 0.0; } // avoid rounding + const double xDist = this->getColorFuselage().colorDistance(fuselage); + const double yDist = this->getColorTail().colorDistance(tail); + const double d = xDist * xDist + yDist * yDist; + return d / 2.0; // normalize to 0..1 + } + else + { + return 1.0; + } + } + CLivery CLivery::fromDatabaseJson(const QJsonObject &json, const QString &prefix) { if (!existsKey(json, prefix)) diff --git a/src/blackmisc/aviation/livery.h b/src/blackmisc/aviation/livery.h index e60482bed..2a8d2d4c9 100644 --- a/src/blackmisc/aviation/livery.h +++ b/src/blackmisc/aviation/livery.h @@ -122,6 +122,9 @@ namespace BlackMisc //! Matches combined code bool matchesCombinedCode(const QString &candidate) const; + //! Matches colors + bool matchesColors(const BlackMisc::CRgbColor &fuselage, const BlackMisc::CRgbColor &tail) const; + //! \copydoc BlackMisc::Mixin::Index::propertyByIndex CVariant propertyByIndex(const BlackMisc::CPropertyIndex &index) const; @@ -155,6 +158,9 @@ namespace BlackMisc //! Color livery bool isColorLivery() const; + //! Combined color distance (fuselage/tail): 0..1 + double getColorDistance(const BlackMisc::CRgbColor &fuselage, const BlackMisc::CRgbColor &tail) const; + //! Update missing parts void updateMissingParts(const CLivery &otherLivery); diff --git a/src/blackmisc/aviation/liverylist.cpp b/src/blackmisc/aviation/liverylist.cpp index 9491fe1b2..285a327d3 100644 --- a/src/blackmisc/aviation/liverylist.cpp +++ b/src/blackmisc/aviation/liverylist.cpp @@ -74,6 +74,34 @@ namespace BlackMisc return this->findStdLiveryByAirlineIcaoVDesignator(icao.getVDesignator()); } + CLivery CLiveryList::findColorLiveryOrDefault(const CRgbColor &fuselage, const CRgbColor &tail) const + { + if (!fuselage.isValid() || !tail.isValid()) { return CLivery(); } + return this->findFirstByOrDefault([&](const CLivery & livery) + { + if (!livery.isColorLivery()) { return false; } + return livery.matchesColors(fuselage, tail); + }); + } + + CLivery CLiveryList::findClosestColorLiveryOrDefault(const CRgbColor &fuselage, const CRgbColor &tail) const + { + if (!fuselage.isValid() || !tail.isValid()) { return CLivery(); } + CLivery bestMatch; + double bestDistance = 1.0; + for (const CLivery &livery : *this) + { + double d = livery.getColorDistance(fuselage, tail); + if (d == 0.0) { return livery; } // exact match + if (d < bestDistance) + { + bestMatch = livery; + bestDistance = d; + } + } + return bestMatch; + } + CLivery CLiveryList::findByCombinedCode(const QString &combinedCode) const { if (!CLivery::isValidCombinedCode(combinedCode)) { return CLivery(); } diff --git a/src/blackmisc/aviation/liverylist.h b/src/blackmisc/aviation/liverylist.h index 605ef95e1..3a6dffda1 100644 --- a/src/blackmisc/aviation/liverylist.h +++ b/src/blackmisc/aviation/liverylist.h @@ -52,6 +52,12 @@ namespace BlackMisc //! Find livery by airline CLivery findStdLiveryByAirlineIcaoVDesignator(const CAirlineIcaoCode &icao) const; + //! Search for colors + CLivery findColorLiveryOrDefault(const BlackMisc::CRgbColor &fuselage, const CRgbColor &tail) const; + + //! Search for colors + CLivery findClosestColorLiveryOrDefault(const BlackMisc::CRgbColor &fuselage, const CRgbColor &tail) const; + //! By simplified name CLiveryList findStdLiveriesBySimplifiedAirlineName(const QString &containedString) const;