diff --git a/rtengine/spot.cc b/rtengine/spot.cc index 6ef0ba5e0..f43eaa909 100644 --- a/rtengine/spot.cc +++ b/rtengine/spot.cc @@ -25,6 +25,40 @@ #include "rt_math.h" #include #include +#include + +namespace rtengine +{ + +class SpotBox; + +} + +namespace +{ + +using Boxes = std::vector>; + +/** + * Add the spot and its dependencies to a set of dependencies. + * + * @param spotNum The spot's index. + * @param dependencies A set to place the dependencies in. Spots that are + * already in the set must have all their dependencies included already. + * @param srcSpots Information on spot sources. + * @param dstSpots Information on spot destinations. + */ +void addSpotDependencies(int spotNum, std::unordered_set &dependencies, const Boxes &srcSpots, const Boxes &dstSpots); + +/** + * Returns the supplied spots and all their dependencies. + * + * @param visibleSpots The spots to get dependencies for. + * @param srcSpots Information on spot sources. + * @param dstSpots Information on spot destinations. + */ +std::unordered_set calcSpotDependencies(const std::set &visibleSpots, const Boxes &srcSpots, const Boxes &dstSpots); +} namespace rtengine { @@ -461,18 +495,10 @@ void ImProcFunctions::removeSpots (Imagefloat* img, ImageSource* imgsrc, const s // Construct list of upstream dependancies - std::set requiredSpots = visibleSpots; // starting point, visible spots are necessarilly required spots - for (auto i = requiredSpots.rbegin(); i != requiredSpots.rend(); i++) { - int spotNbr = *i; - requiredSpots.insert(spotNbr); - if (spotNbr > 0) { - for (int j = spotNbr - 1; j >= 0; --j) { - if ((srcSpotBoxs.at(spotNbr))->imageIntersects(*dstSpotBoxs.at(j))) { - requiredSpots.insert(spotNbr); - } - } - } - } + std::unordered_set requiredSpotsSet = calcSpotDependencies(visibleSpots, srcSpotBoxs, dstSpotBoxs); + std::vector requiredSpots(requiredSpotsSet.size()); + std::copy(requiredSpotsSet.begin(), requiredSpotsSet.end(), requiredSpots.begin()); + std::sort(requiredSpots.begin(), requiredSpots.end()); // Process spots and copy them downstream @@ -510,3 +536,45 @@ void ImProcFunctions::removeSpots (Imagefloat* img, ImageSource* imgsrc, const s } +namespace +{ + +void addSpotDependencies(int spotNum, std::unordered_set &dependencies, const Boxes &srcSpots, const Boxes &dstSpots) +{ + dependencies.insert(spotNum); + + // Our spot can depend on previous spots. + for (int i = spotNum - 1; i >= 0; --i) { + if (dependencies.find(i) != dependencies.end()) { + continue; // Spot already has its dependencies added. + } + + // Check if our spot depends on this previous spot. + if (srcSpots.at(spotNum)->imageIntersects(*dstSpots.at(i))) { + // If so, add it and its dependencies. + addSpotDependencies(i, dependencies, srcSpots, dstSpots); + } + } +} + +std::unordered_set calcSpotDependencies(const std::set &visibleSpots, const Boxes &srcSpots, const Boxes &dstSpots) +{ + std::unordered_set dependencies; + std::vector visibleSpotsOrdered(visibleSpots.size()); + + std::copy(visibleSpots.begin(), visibleSpots.end(), visibleSpotsOrdered.begin()); + std::sort(visibleSpotsOrdered.begin(), visibleSpotsOrdered.end()); + + // Add dependencies, starting with the last spot. + for (auto i = visibleSpotsOrdered.crbegin(); i != visibleSpotsOrdered.crend(); ++i) { + if (dependencies.find(*i) != dependencies.end()) { + continue; // Spot already has its dependencies added. + } + addSpotDependencies(*i, dependencies, srcSpots, dstSpots); + } + + return dependencies; +} + +} +