Krita Source Code Documentation
Loading...
Searching...
No Matches
GridIterationTools Namespace Reference

Namespaces

namespace  Private
 

Classes

struct  AlwaysCompletePolygonPolicy
 
struct  CellOp
 
struct  IncompletePolygonPolicy
 
struct  PaintDevicePolygonOp
 
struct  QImagePolygonOp
 
struct  RegularGridIndexesOp
 

Functions

void adjustAlignedPolygon (QPolygonF &polygon)
 
int calcGridDimension (int start, int end, const int pixelPrecision)
 
QSize calcGridSize (const QRect &srcBounds, const int pixelPrecision)
 
QVector< int > calculateCellIndexes (int col, int row, const QSize &gridSize)
 
QRect calculateCorrectSubGrid (QRect originalBoundsForGrid, int pixelPrecision, QRectF currentBounds, QSize gridSize)
 
template<class IndexesOp >
bool canProcessRectsInRandomOrder (IndexesOp &indexesOp, const QVector< QPointF > &transformedPoints, QRect subgrid)
 
template<class IndexesOp >
bool canProcessRectsInRandomOrder (IndexesOp &indexesOp, const QVector< QPointF > &transformedPoints, QSize grid)
 
QList< QRectF > cutOutSubgridFromBounds (QRect subGrid, QRect srcBounds, const QSize &gridSize, const QVector< QPointF > &originalPoints)
 
template<class IndexesOp >
bool getOrthogonalPointApproximation (const QPoint &cellPt, const QVector< QPointF > &originalPoints, const QVector< QPointF > &transformedPoints, IndexesOp indexesOp, QPointF *srcPoint, QPointF *dstPoint)
 
template<template< class PolygonOp, class IndexesOp > class IncompletePolygonPolicy, class PolygonOp , class IndexesOp >
void iterateThroughGrid (PolygonOp &polygonOp, IndexesOp &indexesOp, const QSize &gridSize, const QVector< QPointF > &originalPoints, const QVector< QPointF > &transformedPoints)
 
template<template< class PolygonOp, class IndexesOp > class IncompletePolygonPolicy, class PolygonOp , class IndexesOp >
void iterateThroughGrid (PolygonOp &polygonOp, IndexesOp &indexesOp, const QSize &gridSize, const QVector< QPointF > &originalPoints, const QVector< QPointF > &transformedPoints, const QRect subGrid)
 
int pointToIndex (const QPoint &cellPt, const QSize &gridSize)
 
template<class ProcessCell >
void processGrid (ProcessCell &cellOp, const QRect &srcBounds, const int pixelPrecision)
 
template<class ProcessPolygon , class ForwardTransform >
void processGrid (ProcessPolygon &polygonOp, ForwardTransform &transformOp, const QRect &srcBounds, const int pixelPrecision)
 

Function Documentation

◆ adjustAlignedPolygon()

void GridIterationTools::adjustAlignedPolygon ( QPolygonF & polygon)
inline

There is a weird problem in fetching correct bounds of the polygon. If the rightmost (bottommost) point of the polygon is integral, then QRectF() will end exactly on it, but when converting into QRect the last point will not be taken into account. It happens due to the difference between center-point/topleft-point point representation. In many cases the latter is expected, but we don't work with it in Qt/Krita.

Definition at line 874 of file kis_grid_interpolation_tools.h.

875{
876 static const qreal eps = 1e-5;
877 static const QPointF p1(eps, 0.0);
878 static const QPointF p2(eps, eps);
879 static const QPointF p3(0.0, eps);
880
881 polygon[1] += p1;
882 polygon[2] += p2;
883 polygon[3] += p3;
884}
QPointF p2
QPointF p3
QPointF p1
const qreal eps

References eps, p1, p2, and p3.

◆ calcGridDimension()

int GridIterationTools::calcGridDimension ( int start,
int end,
const int pixelPrecision )
inline

Definition at line 33 of file kis_grid_interpolation_tools.h.

34{
35 const int alignmentMask = ~(pixelPrecision - 1);
36
37 int alignedStart = (start + pixelPrecision - 1) & alignmentMask;
38 int alignedEnd = end & alignmentMask;
39
40 int size = 0;
41
42 if (alignedEnd > alignedStart) {
43 size = (alignedEnd - alignedStart) / pixelPrecision + 1;
44 size += alignedStart != start;
45 size += alignedEnd != end;
46 } else {
47 size = 2 + (end - start >= pixelPrecision);
48 }
49
50 return size;
51}
int size(const Forest< T > &forest)
Definition KisForest.h:1232

◆ calcGridSize()

QSize GridIterationTools::calcGridSize ( const QRect & srcBounds,
const int pixelPrecision )
inline

Definition at line 53 of file kis_grid_interpolation_tools.h.

53 {
54 return QSize(calcGridDimension(srcBounds.x(), srcBounds.right(), pixelPrecision),
55 calcGridDimension(srcBounds.y(), srcBounds.bottom(), pixelPrecision));
56}
int calcGridDimension(int start, int end, const int pixelPrecision)

References calcGridDimension().

◆ calculateCellIndexes()

QVector< int > GridIterationTools::calculateCellIndexes ( int col,
int row,
const QSize & gridSize )
inline

A--—B The polygons will be in the following order: | | | | polygon << A << B << D << C; C--—D

Definition at line 536 of file kis_grid_interpolation_tools.h.

537{
538 const int tl = col + row * gridSize.width();
539 const int tr = tl + 1;
540 const int bl = tl + gridSize.width();
541 const int br = bl + 1;
542
543 QVector<int> cellIndexes;
544 cellIndexes << tl;
545 cellIndexes << tr;
546 cellIndexes << br;
547 cellIndexes << bl;
548
549 return cellIndexes;
550}

◆ calculateCorrectSubGrid()

QRect GridIterationTools::calculateCorrectSubGrid ( QRect originalBoundsForGrid,
int pixelPrecision,
QRectF currentBounds,
QSize gridSize )
inline

Definition at line 578 of file kis_grid_interpolation_tools.h.

578 {
579
580 if (!QRectF(originalBoundsForGrid).intersects(currentBounds)) {
581 return QRect();
582 }
583
584 QPointF imaginaryGridStartF = QPoint(originalBoundsForGrid.x()/pixelPrecision, originalBoundsForGrid.y()/pixelPrecision)*pixelPrecision;
585
586 QPointF startPointB = currentBounds.topLeft() - imaginaryGridStartF;
587 QPoint startPointG = QPoint(startPointB.x()/pixelPrecision, startPointB.y()/pixelPrecision);
588 startPointG = QPoint(kisBoundFast(0, startPointG.x(), gridSize.width()), kisBoundFast(0, startPointG.y(), gridSize.height()));
589
590 QPointF endPointB = currentBounds.bottomRight() + QPoint(1, 1) - imaginaryGridStartF;
591 QPoint endPointG = QPoint(std::ceil(endPointB.x()/pixelPrecision), std::ceil(endPointB.y()/pixelPrecision)) + QPoint(1, 1);
592 QPoint endPointPotential = endPointG;
593
594 QPoint trueEndPoint = QPoint(kisBoundFast(0, endPointPotential.x(), gridSize.width()), kisBoundFast(0, endPointPotential.y(), gridSize.height()));
595
596 QPoint size = trueEndPoint - startPointG;
597
598 return QRect(startPointG, QSize(size.x(), size.y()));
599}
constexpr const T & kisBoundFast(const T &min, const T &val, const T &max)
Definition kis_global.h:37

References kisBoundFast().

◆ canProcessRectsInRandomOrder() [1/2]

template<class IndexesOp >
bool GridIterationTools::canProcessRectsInRandomOrder ( IndexesOp & indexesOp,
const QVector< QPointF > & transformedPoints,
QRect subgrid )

Definition at line 892 of file kis_grid_interpolation_tools.h.

892 {
893 QVector<int> polygonPoints(4);
894 QPoint startPoint = subgrid.topLeft();
895 QPoint endPoint = subgrid.bottomRight();
896
897 for (int row = startPoint.y(); row < endPoint.y(); row++) {
898 for (int col = startPoint.x(); col < endPoint.x(); col++) {
899 int numExistingPoints = 0;
900
901 polygonPoints = indexesOp.calculateMappedIndexes(col, row, &numExistingPoints);
902
903 QPolygonF dstPolygon;
904
905 for (int i = 0; i < polygonPoints.count(); i++) {
906 const int index = polygonPoints[i];
907 dstPolygon << transformedPoints[index];
908 }
909
910
911 adjustAlignedPolygon(dstPolygon);
912
913
914 if (!KisAlgebra2D::isPolygonTrulyConvex(dstPolygon)) {
915 return false;
916 }
917
918 }
919 }
920 return true;
921}
bool isPolygonTrulyConvex(const QVector< T > &polygon)

References adjustAlignedPolygon(), and KisAlgebra2D::isPolygonTrulyConvex().

◆ canProcessRectsInRandomOrder() [2/2]

template<class IndexesOp >
bool GridIterationTools::canProcessRectsInRandomOrder ( IndexesOp & indexesOp,
const QVector< QPointF > & transformedPoints,
QSize grid )

Definition at line 887 of file kis_grid_interpolation_tools.h.

887 {
888 return canProcessRectsInRandomOrder(indexesOp, transformedPoints, QRect(QPoint(0, 0), grid));
889}
bool canProcessRectsInRandomOrder(IndexesOp &indexesOp, const QVector< QPointF > &transformedPoints, QSize grid)

References canProcessRectsInRandomOrder().

◆ cutOutSubgridFromBounds()

QList< QRectF > GridIterationTools::cutOutSubgridFromBounds ( QRect subGrid,
QRect srcBounds,
const QSize & gridSize,
const QVector< QPointF > & originalPoints )
inline

Definition at line 601 of file kis_grid_interpolation_tools.h.

601 {
602 if (subGrid.width() == 0 || subGrid.height() == 0) {
603 return QList<QRectF> {srcBounds};
604 }
605 QPoint topLeft = subGrid.topLeft();
606 QPoint bottomRight = subGrid.topLeft() + QPoint(subGrid.width() - 1, subGrid.height() - 1);
607
608 int topLeftIndex = pointToIndex(topLeft, gridSize);
609 int bottomRightIndex = pointToIndex(bottomRight, gridSize);
610
611 topLeftIndex = qMax(0, qMin(topLeftIndex, originalPoints.length() - 1));
612 bottomRightIndex = qMax(0, qMin(bottomRightIndex, originalPoints.length() - 1));
613
614 QPointF topLeftReal = originalPoints[topLeftIndex];
615 QPointF bottomRightReal = originalPoints[bottomRightIndex];
616 QRectF cutOut = QRectF(topLeftReal, bottomRightReal);
617
618 QList<QRectF> response;
619 // *-----------*
620 // | top |
621 // |-----------|
622 // | l |xxx| r |
623 // | e |xxx| i |
624 // | f |xxx| g |
625 // | t |xxx| h |
626 // | |xxx| t |
627 // |-----------|
628 // | bottom |
629 // *-----------*
630
631
632 QRectF top = QRectF(srcBounds.topLeft(), QPointF(srcBounds.right() + 1, topLeftReal.y()));
633 QRectF bottom = QRectF(QPointF(srcBounds.left(), bottomRightReal.y() + 1), srcBounds.bottomRight() + QPointF(1, 1));
634 QRectF left = QRectF(QPointF(srcBounds.left(), cutOut.top()), QPointF(cutOut.left(), cutOut.bottom() + 1));
635 QRectF right = QRectF(QPointF(cutOut.right() + 1, cutOut.top()), QPointF(srcBounds.right() + 1, cutOut.bottom() + 1));
636 QList<QRectF> rects = {top, left, right, bottom};
637 for (int i = 0; i < rects.length(); i++) {
638 if (!rects[i].isEmpty()) {
639 response << rects[i];
640 }
641 }
642 return response;
643
644}
int pointToIndex(const QPoint &cellPt, const QSize &gridSize)

References pointToIndex().

◆ getOrthogonalPointApproximation()

template<class IndexesOp >
bool GridIterationTools::getOrthogonalPointApproximation ( const QPoint & cellPt,
const QVector< QPointF > & originalPoints,
const QVector< QPointF > & transformedPoints,
IndexesOp indexesOp,
QPointF * srcPoint,
QPointF * dstPoint )

Definition at line 650 of file kis_grid_interpolation_tools.h.

656{
657 QVector<Private::PointExtension> extensionPoints;
659
660 // left
661 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(-1, 0))) >= 0 &&
662 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(-2, 0))) >= 0) {
663
664 extensionPoints << ext;
665 }
666 // top
667 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(0, -1))) >= 0 &&
668 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(0, -2))) >= 0) {
669
670 extensionPoints << ext;
671 }
672 // right
673 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(1, 0))) >= 0 &&
674 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(2, 0))) >= 0) {
675
676 extensionPoints << ext;
677 }
678 // bottom
679 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(0, 1))) >= 0 &&
680 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(0, 2))) >= 0) {
681
682 extensionPoints << ext;
683 }
684
685 if (extensionPoints.isEmpty()) {
686 // top-left
687 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(-1, -1))) >= 0 &&
688 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(-2, -2))) >= 0) {
689
690 extensionPoints << ext;
691 }
692 // top-right
693 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(1, -1))) >= 0 &&
694 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(2, -2))) >= 0) {
695
696 extensionPoints << ext;
697 }
698 // bottom-right
699 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(1, 1))) >= 0 &&
700 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(2, 2))) >= 0) {
701
702 extensionPoints << ext;
703 }
704 // bottom-left
705 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(-1, 1))) >= 0 &&
706 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(-2, 2))) >= 0) {
707
708 extensionPoints << ext;
709 }
710 }
711
712 if (extensionPoints.isEmpty()) {
713 return false;
714 }
715
716 int numResultPoints = 0;
717 *srcPoint = indexesOp.getSrcPointForce(cellPt);
718 *dstPoint = QPointF();
719
720 Q_FOREACH (const Private::PointExtension &ext, extensionPoints) {
721 QPointF near = transformedPoints[ext.near];
722 QPointF far = transformedPoints[ext.far];
723
724 QPointF nearSrc = originalPoints[ext.near];
725 QPointF farSrc = originalPoints[ext.far];
726
727 QPointF base1 = nearSrc - farSrc;
728 QPointF base2 = near - far;
729
730 QPointF pt = near +
731 KisAlgebra2D::transformAsBase(*srcPoint - nearSrc, base1, base2);
732
733 *dstPoint += pt;
734 numResultPoints++;
735 }
736
737 *dstPoint /= numResultPoints;
738
739 return true;
740}
QPointF dstPoint
QPointF transformAsBase(const QPointF &pt, const QPointF &base1, const QPointF &base2)

References dstPoint, GridIterationTools::Private::PointExtension::far, GridIterationTools::Private::PointExtension::near, and KisAlgebra2D::transformAsBase().

◆ iterateThroughGrid() [1/2]

template<template< class PolygonOp, class IndexesOp > class IncompletePolygonPolicy, class PolygonOp , class IndexesOp >
void GridIterationTools::iterateThroughGrid ( PolygonOp & polygonOp,
IndexesOp & indexesOp,
const QSize & gridSize,
const QVector< QPointF > & originalPoints,
const QVector< QPointF > & transformedPoints )

Definition at line 928 of file kis_grid_interpolation_tools.h.

933{
934 iterateThroughGrid<IncompletePolygonPolicy, PolygonOp, IndexesOp>(polygonOp, indexesOp, gridSize, originalPoints, transformedPoints, QRect(QPoint(0, 0), gridSize));
935}

◆ iterateThroughGrid() [2/2]

template<template< class PolygonOp, class IndexesOp > class IncompletePolygonPolicy, class PolygonOp , class IndexesOp >
void GridIterationTools::iterateThroughGrid ( PolygonOp & polygonOp,
IndexesOp & indexesOp,
const QSize & gridSize,
const QVector< QPointF > & originalPoints,
const QVector< QPointF > & transformedPoints,
const QRect subGrid )

Definition at line 940 of file kis_grid_interpolation_tools.h.

946{
947 QVector<int> polygonPoints(4);
948 QPoint startPoint = subGrid.topLeft();
949 QPoint endPoint = subGrid.bottomRight(); // it's weird but bottomRight on QRect point does give us one unit of margin on both x and y
950 // when start is on (0, 0), and size is (500, 500), bottomRight is on (499, 499)
951 // but remember that it also only needs a top left corner of the polygon
952
953 KIS_SAFE_ASSERT_RECOVER(startPoint.x() >= 0 && startPoint.y() >= 0 && endPoint.x() <= gridSize.width() - 1 && endPoint.y() <= gridSize.height() - 1) {
954 startPoint = QPoint(qMax(startPoint.x(), 0), qMax(startPoint.y(), 0));
955 endPoint = QPoint(qMin(endPoint.x(), gridSize.width() - 1), qMin(startPoint.y(), gridSize.height() - 1));
956 }
957
958 for (int row = startPoint.y(); row < endPoint.y(); row++) {
959 for (int col = startPoint.x(); col < endPoint.x(); col++) {
960 int numExistingPoints = 0;
961
962 polygonPoints = indexesOp.calculateMappedIndexes(col, row, &numExistingPoints);
963
964 if (!IncompletePolygonPolicy<PolygonOp, IndexesOp>::
965 tryProcessPolygon(col, row,
966 numExistingPoints,
967 polygonOp,
968 indexesOp,
969 polygonPoints,
970 originalPoints,
971 transformedPoints)) {
972
973 QPolygonF srcPolygon;
974 QPolygonF dstPolygon;
975
976 for (int i = 0; i < 4; i++) {
977 const int index = polygonPoints[i];
978 srcPolygon << originalPoints[index];
979 dstPolygon << transformedPoints[index];
980 }
981
982 adjustAlignedPolygon(srcPolygon);
983 adjustAlignedPolygon(dstPolygon);
984
985 polygonOp(srcPolygon, dstPolygon);
986 }
987 }
988 }
989
990 polygonOp.finalize();
991}
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
void adjustAlignedPolygon(QPolygonF &polygon)

References adjustAlignedPolygon(), and KIS_SAFE_ASSERT_RECOVER.

◆ pointToIndex()

int GridIterationTools::pointToIndex ( const QPoint & cellPt,
const QSize & gridSize )
inline

Definition at line 552 of file kis_grid_interpolation_tools.h.

553{
554 return cellPt.x() +
555 cellPt.y() * gridSize.width();
556}

◆ processGrid() [1/2]

template<class ProcessCell >
void GridIterationTools::processGrid ( ProcessCell & cellOp,
const QRect & srcBounds,
const int pixelPrecision )

Definition at line 110 of file kis_grid_interpolation_tools.h.

113{
114 if (srcBounds.isEmpty()) return;
115
116 const int alignmentMask = ~(pixelPrecision - 1);
117
118 int prevRow = std::numeric_limits<int>::max();
119 int prevCol = std::numeric_limits<int>::max();
120
121 int rowIndex = 0;
122 int colIndex = 0;
123
124 for (int row = srcBounds.top(); row <= srcBounds.bottom();) {
125 for (int col = srcBounds.left(); col <= srcBounds.right();) {
126
127 cellOp.processPoint(col, row,
128 prevCol, prevRow,
129 colIndex, rowIndex);
130
131 prevCol = col;
132 col += pixelPrecision;
133 colIndex++;
134
135 if (col > srcBounds.right() &&
136 col <= srcBounds.right() + pixelPrecision - 1) {
137
138 col = srcBounds.right();
139 } else {
140 col &= alignmentMask;
141 }
142 }
143
144 cellOp.nextLine();
145 colIndex = 0;
146
147 prevRow = row;
148 row += pixelPrecision;
149 rowIndex++;
150
151 if (row > srcBounds.bottom() &&
152 row <= srcBounds.bottom() + pixelPrecision - 1) {
153
154 row = srcBounds.bottom();
155 } else {
156 row &= alignmentMask;
157 }
158 }
159}

◆ processGrid() [2/2]

template<class ProcessPolygon , class ForwardTransform >
void GridIterationTools::processGrid ( ProcessPolygon & polygonOp,
ForwardTransform & transformOp,
const QRect & srcBounds,
const int pixelPrecision )

Definition at line 162 of file kis_grid_interpolation_tools.h.

164{
165 CellOp<ProcessPolygon, ForwardTransform> cellOp(polygonOp, transformOp);
166 processGrid(cellOp, srcBounds, pixelPrecision);
167}
void processGrid(ProcessCell &cellOp, const QRect &srcBounds, const int pixelPrecision)

References processGrid().