diff --git a/plugins/tools/selectiontools/KisMagneticWorker.cc b/plugins/tools/selectiontools/KisMagneticWorker.cc index e1013a1b5f..17b14cb820 100644 --- a/plugins/tools/selectiontools/KisMagneticWorker.cc +++ b/plugins/tools/selectiontools/KisMagneticWorker.cc @@ -1,289 +1,284 @@ /* * Copyright (c) 2019 Kuntal Majumder * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "KisMagneticWorker.h" -#include -#include #include -#include #include -#include #include +#include +#include +#include +#include -#include -#include #include +#include +#include #include #include #include "KisMagneticGraph.h" -struct DistanceMap { +struct DistanceMap +{ typedef VertexDescriptor key_type; typedef double data_type; typedef std::pair value_type; - explicit DistanceMap(double const &dval) + explicit DistanceMap(double const& dval) : m_default(dval) - { } + {} - data_type &operator [] (key_type const &k) + data_type& operator[](key_type const& k) { if (m.find(k) == m.end()) m[k] = m_default; return m[k]; } -private: + private: std::map m; - data_type const m_default; + data_type const m_default; }; -struct PredecessorMap { +struct PredecessorMap +{ PredecessorMap() = default; - PredecessorMap(PredecessorMap const &that) = default; + PredecessorMap(PredecessorMap const& that) = default; typedef VertexDescriptor key_type; typedef VertexDescriptor value_type; typedef boost::read_write_property_map_tag category; - VertexDescriptor &operator [] (VertexDescriptor v) - { - return m_map[v]; - } + VertexDescriptor& operator[](VertexDescriptor v) { return m_map[v]; } std::map m_map; }; -VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v) +VertexDescriptor get(PredecessorMap const& m, VertexDescriptor v) { auto found = m.m_map.find(v); return found != m.m_map.end() ? found->second : v; } -void put(PredecessorMap &m, VertexDescriptor key, VertexDescriptor value) +void put(PredecessorMap& m, VertexDescriptor key, VertexDescriptor value) { m.m_map[key] = value; } double EuclideanDistance(VertexDescriptor p1, VertexDescriptor p2) { return std::sqrt(std::pow(p1.y - p2.y, 2) + std::pow(p1.x - p2.x, 2)); } class AStarHeuristic : public boost::astar_heuristic { -private: + private: VertexDescriptor m_goal; -public: - explicit AStarHeuristic(VertexDescriptor goal) : - m_goal(goal) - { } + public: + explicit AStarHeuristic(VertexDescriptor goal) + : m_goal(goal) + {} - double operator () (VertexDescriptor v) - { - return EuclideanDistance(v, m_goal); - } + double operator()(VertexDescriptor v) { return EuclideanDistance(v, m_goal); } }; -struct GoalFound { }; +struct GoalFound +{}; class AStarGoalVisitor : public boost::default_astar_visitor { -public: - explicit AStarGoalVisitor(VertexDescriptor goal) : m_goal(goal){ } + public: + explicit AStarGoalVisitor(VertexDescriptor goal) + : m_goal(goal) + {} - void examine_vertex(VertexDescriptor u, KisMagneticGraph const &g) + void examine_vertex(VertexDescriptor u, KisMagneticGraph const& g) { Q_UNUSED(g) if (u == m_goal) { throw GoalFound(); } } -private: + private: VertexDescriptor m_goal; }; -struct WeightMap { +struct WeightMap +{ typedef std::pair key_type; typedef double data_type; typedef std::pair value_type; WeightMap() = default; - explicit WeightMap(const KisMagneticGraph &g) : - m_graph(g) - { } + explicit WeightMap(const KisMagneticGraph& g) + : m_graph(g) + {} - data_type &operator [] (key_type const &k) + data_type& operator[](key_type const& k) { if (m_map.find(k) == m_map.end()) { double edge_gradient = (m_graph.getIntensity(k.first) + m_graph.getIntensity(k.second)) / 2; m_map[k] = EuclideanDistance(k.first, k.second) + 255.0 - edge_gradient; } return m_map[k]; } -private: + private: std::map m_map; - KisMagneticGraph m_graph; + KisMagneticGraph m_graph; }; KisMagneticLazyTiles::KisMagneticLazyTiles(KisPaintDeviceSP dev) { m_dev = KisPainter::convertToAlphaAsGray(dev); QSize s = dev->defaultBounds()->bounds().size(); - m_tileSize = KritaUtils::optimalPatchSize(); - m_tilesPerRow = (int) std::ceil((double) s.width() / (double) m_tileSize.width()); - int tilesPerColumn = (int) std::ceil((double) s.height() / (double) m_tileSize.height()); + m_tileSize = KritaUtils::optimalPatchSize(); + m_tilesPerRow = (int)std::ceil((double)s.width() / (double)m_tileSize.width()); + int tilesPerColumn = (int)std::ceil((double)s.height() / (double)m_tileSize.height()); m_dev->setDefaultBounds(dev->defaultBounds()); for (int i = 0; i < tilesPerColumn; i++) { for (int j = 0; j < m_tilesPerRow; j++) { - int width = std::min(s.width() - j * m_tileSize.width(), m_tileSize.width()); + int width = std::min(s.width() - j * m_tileSize.width(), m_tileSize.width()); int height = std::min(s.height() - i * m_tileSize.height(), m_tileSize.height()); - QRect temp(j *m_tileSize.width(), i *m_tileSize.height(), width, height); + QRect temp(j * m_tileSize.width(), i * m_tileSize.height(), width, height); m_tiles.push_back(temp); } } m_radiusRecord = QVector(m_tiles.size(), -1); } -void KisMagneticLazyTiles::filter(qreal radius, QRect &rect) +void KisMagneticLazyTiles::filter(qreal radius, QRect& rect) { - auto divide = [](QPoint p, QSize s){ - return QPoint(p.x() / s.width(), p.y() / s.height()); - }; + auto divide = [](QPoint p, QSize s) { return QPoint(p.x() / s.width(), p.y() / s.height()); }; QPoint firstTile = divide(rect.topLeft(), m_tileSize); - QPoint lastTile = divide(rect.bottomRight(), m_tileSize); + QPoint lastTile = divide(rect.bottomRight(), m_tileSize); for (int i = firstTile.y(); i <= lastTile.y(); i++) { for (int j = firstTile.x(); j <= lastTile.x(); j++) { int currentTile = i * m_tilesPerRow + j; if (radius != m_radiusRecord[currentTile]) { QRect bounds = m_tiles[currentTile]; - //KisGaussianKernel::applyTightLoG(m_dev, bounds, radius, -1.0, QBitArray(), nullptr); - KisFilterSP filter = KisFilterRegistry::instance()->value("edge detection"); - KisFilterConfigurationSP conf = filter->defaultConfiguration(); - conf->setProperty("type", "canny"); - filter->process(m_dev, bounds, conf); + KisGaussianKernel::applyTightLoG(m_dev, bounds, radius, -1.0, QBitArray(), nullptr); KisLazyFillTools::normalizeAlpha8Device(m_dev, bounds); m_radiusRecord[currentTile] = radius; } } } } -KisMagneticWorker::KisMagneticWorker(const KisPaintDeviceSP &dev) : - m_lazyTileFilter(dev) -{ } +KisMagneticWorker::KisMagneticWorker(const KisPaintDeviceSP& dev) + : m_lazyTileFilter(dev) +{} QVector KisMagneticWorker::computeEdge(int bounds, QPoint begin, QPoint end, qreal radius) { QRect rect; - KisAlgebra2D::accumulateBounds(QVector { begin, end }, &rect); + KisAlgebra2D::accumulateBounds(QVector{ begin, end }, &rect); rect = kisGrowRect(rect, bounds); m_lazyTileFilter.filter(radius, rect); VertexDescriptor goal(end); VertexDescriptor start(begin); m_graph = new KisMagneticGraph(m_lazyTileFilter.device(), rect); // How many maps does it require? - // Take a look here, if it doesn't make sense, https://www.boost.org/doc/libs/1_70_0/libs/graph/doc/astar_search.html + // Take a look here, if it doesn't make sense, + // https://www.boost.org/doc/libs/1_70_0/libs/graph/doc/astar_search.html PredecessorMap pmap; DistanceMap dmap(std::numeric_limits::max()); dmap[start] = 0; std::map rmap; std::map cmap; std::map imap; WeightMap wmap(*m_graph); AStarHeuristic heuristic(goal); QVector result; try { boost::astar_search_no_init( - *m_graph, start, heuristic, + *m_graph, + start, + heuristic, boost::visitor(AStarGoalVisitor(goal)) - .distance_map(boost::associative_property_map(dmap)) - .predecessor_map(boost::ref(pmap)) - .weight_map(boost::associative_property_map(wmap)) - .vertex_index_map(boost::associative_property_map >(imap)) - .rank_map(boost::associative_property_map >(rmap)) - .color_map(boost::associative_property_map > - (cmap)) - .distance_combine(std::plus()) - .distance_compare(std::less()) - ); - } catch (GoalFound const &) { + .distance_map(boost::associative_property_map(dmap)) + .predecessor_map(boost::ref(pmap)) + .weight_map(boost::associative_property_map(wmap)) + .vertex_index_map(boost::associative_property_map>(imap)) + .rank_map(boost::associative_property_map>(rmap)) + .color_map(boost::associative_property_map>(cmap)) + .distance_combine(std::plus()) + .distance_compare(std::less())); + } catch (GoalFound const&) { for (VertexDescriptor u = goal; u != start; u = pmap[u]) { result.push_front(QPointF(u.x, u.y)); } } result.push_front(QPoint(start.x, start.y)); return result; } // KisMagneticWorker::computeEdge qreal KisMagneticWorker::intensity(QPoint pt) { return m_graph->getIntensity(VertexDescriptor(pt)); } void KisMagneticWorker::saveTheImage(vQPointF points) { QImage img = m_lazyTileFilter.device()->convertToQImage(nullptr, m_lazyTileFilter.device()->exactBounds()); const QPointF offset = m_lazyTileFilter.device()->exactBounds().topLeft(); - for (QPointF &pt : points) { + for (QPointF& pt : points) { pt -= offset; } img = img.convertToFormat(QImage::Format_ARGB32); QPainter gc(&img); QPainterPath path; for (int i = 0; i < points.size(); i++) { if (i == 0) { path.moveTo(points[i]); } else { path.lineTo(points[i]); } } gc.setPen(Qt::blue); gc.drawPath(path); gc.setPen(Qt::green); gc.drawEllipse(points[0], 3, 3); gc.setPen(Qt::red); gc.drawEllipse(points[points.count() - 1], 2, 2); - for (QRect &r : m_lazyTileFilter.tiles() ) { + for (QRect& r : m_lazyTileFilter.tiles()) { gc.drawRect(r); } img.save("result.png"); } // KisMagneticWorker::saveTheImage