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)
 
QPointF middlePoint (int x, int y)
 
QPointF middlePoint (QPoint p)
 
QPointF middlePoint (QPointF p)
 
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 893 of file kis_grid_interpolation_tools.h.

894{
895 static const qreal eps = 1e-5;
896 static const QPointF p1(eps, 0.0);
897 static const QPointF p2(eps, eps);
898 static const QPointF p3(0.0, eps);
899
900 polygon[1] += p1;
901 polygon[2] += p2;
902 polygon[3] += p3;
903}
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 555 of file kis_grid_interpolation_tools.h.

556{
557 const int tl = col + row * gridSize.width();
558 const int tr = tl + 1;
559 const int bl = tl + gridSize.width();
560 const int br = bl + 1;
561
562 QVector<int> cellIndexes;
563 cellIndexes << tl;
564 cellIndexes << tr;
565 cellIndexes << br;
566 cellIndexes << bl;
567
568 return cellIndexes;
569}

◆ calculateCorrectSubGrid()

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

Definition at line 597 of file kis_grid_interpolation_tools.h.

597 {
598
599 if (!QRectF(originalBoundsForGrid).intersects(currentBounds)) {
600 return QRect();
601 }
602
603 QPoint offsetB = originalBoundsForGrid.topLeft();
604
605 QPointF startPointB = currentBounds.topLeft() - offsetB;
606 QPoint startPointG = QPoint(startPointB.x()/pixelPrecision, startPointB.y()/pixelPrecision);
607 startPointG = QPoint(kisBoundFast(0, startPointG.x(), gridSize.width()), kisBoundFast(0, startPointG.y(), gridSize.height()));
608
609 QPointF endPointB = currentBounds.bottomRight() + QPoint(1, 1) - offsetB; // *true* bottomRight
610 QPoint endPointG = QPoint(std::ceil(endPointB.x()/pixelPrecision), std::ceil(endPointB.y()/pixelPrecision));
611 QPoint endPointPotential = endPointG;
612
613 QPoint trueEndPoint = QPoint(kisBoundFast(0, endPointPotential.x(), gridSize.width()), kisBoundFast(0, endPointPotential.y(), gridSize.height()));
614
615 QPoint size = trueEndPoint - startPointG;
616
617 return QRect(startPointG, QSize(size.x(), size.y()));
618}
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 911 of file kis_grid_interpolation_tools.h.

911 {
912 QVector<int> polygonPoints(4);
913 QPoint startPoint = subgrid.topLeft();
914 QPoint endPoint = subgrid.bottomRight();
915
916
917 int polygonsChecked = 0;
918
919 for (int row = startPoint.y(); row < endPoint.y(); row++) {
920 for (int col = startPoint.x(); col < endPoint.x(); col++) {
921 int numExistingPoints = 0;
922
923 polygonPoints = indexesOp.calculateMappedIndexes(col, row, &numExistingPoints);
924
925 QPolygonF dstPolygon;
926
927 for (int i = 0; i < polygonPoints.count(); i++) {
928 const int index = polygonPoints[i];
929 dstPolygon << transformedPoints[index];
930 }
931
932
933 adjustAlignedPolygon(dstPolygon);
934
935
936 if (!KisAlgebra2D::isPolygonTrulyConvex(dstPolygon)) {
937 return false;
938 }
939
940 }
941 }
942 return true;
943}
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 906 of file kis_grid_interpolation_tools.h.

906 {
907 return canProcessRectsInRandomOrder(indexesOp, transformedPoints, QRect(QPoint(0, 0), grid));
908}
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 620 of file kis_grid_interpolation_tools.h.

620 {
621 if (subGrid.width() == 0 || subGrid.height() == 0) {
622 return QList<QRectF> {srcBounds};
623 }
624 QPoint topLeft = subGrid.topLeft();
625 QPoint bottomRight = subGrid.topLeft() + QPoint(subGrid.width() - 1, subGrid.height() - 1);
626
627 int topLeftIndex = pointToIndex(topLeft, gridSize);
628 int bottomRightIndex = pointToIndex(bottomRight, gridSize);
629
630 topLeftIndex = qMax(0, qMin(topLeftIndex, originalPoints.length() - 1));
631 bottomRightIndex = qMax(0, qMin(bottomRightIndex, originalPoints.length() - 1));
632
633 QPointF topLeftReal = originalPoints[topLeftIndex];
634 QPointF bottomRightReal = originalPoints[bottomRightIndex];
635 QRectF cutOut = QRectF(topLeftReal, bottomRightReal);
636
637 QList<QRectF> response;
638 // *-----------*
639 // | top |
640 // |-----------|
641 // | l |xxx| r |
642 // | e |xxx| i |
643 // | f |xxx| g |
644 // | t |xxx| h |
645 // | |xxx| t |
646 // |-----------|
647 // | bottom |
648 // *-----------*
649
650
651 QRectF top = QRectF(srcBounds.topLeft(), QPointF(srcBounds.right() + 1, topLeftReal.y()));
652 QRectF bottom = QRectF(QPointF(srcBounds.left(), bottomRightReal.y()), srcBounds.bottomRight() + QPointF(1, 1));
653 QRectF left = QRectF(QPointF(srcBounds.left(), cutOut.top()), QPointF(cutOut.left(), cutOut.bottom()));
654 QRectF right = QRectF(QPointF(cutOut.right(), cutOut.top()), QPointF(srcBounds.right() + 1, cutOut.bottom()));
655 QList<QRectF> rects = {top, left, right, bottom};
656 for (int i = 0; i < rects.length(); i++) {
657 if (!rects[i].isEmpty()) {
658 response << rects[i];
659 }
660 }
661 return response;
662
663}
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 669 of file kis_grid_interpolation_tools.h.

675{
676 QVector<Private::PointExtension> extensionPoints;
678
679 // left
680 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(-1, 0))) >= 0 &&
681 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(-2, 0))) >= 0) {
682
683 extensionPoints << ext;
684 }
685 // top
686 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(0, -1))) >= 0 &&
687 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(0, -2))) >= 0) {
688
689 extensionPoints << ext;
690 }
691 // right
692 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(1, 0))) >= 0 &&
693 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(2, 0))) >= 0) {
694
695 extensionPoints << ext;
696 }
697 // bottom
698 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(0, 1))) >= 0 &&
699 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(0, 2))) >= 0) {
700
701 extensionPoints << ext;
702 }
703
704 if (extensionPoints.isEmpty()) {
705 // top-left
706 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(-1, -1))) >= 0 &&
707 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(-2, -2))) >= 0) {
708
709 extensionPoints << ext;
710 }
711 // top-right
712 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(1, -1))) >= 0 &&
713 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(2, -2))) >= 0) {
714
715 extensionPoints << ext;
716 }
717 // bottom-right
718 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(1, 1))) >= 0 &&
719 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(2, 2))) >= 0) {
720
721 extensionPoints << ext;
722 }
723 // bottom-left
724 if ((ext.near = indexesOp.tryGetValidIndex(cellPt + QPoint(-1, 1))) >= 0 &&
725 (ext.far = indexesOp.tryGetValidIndex(cellPt + QPoint(-2, 2))) >= 0) {
726
727 extensionPoints << ext;
728 }
729 }
730
731 if (extensionPoints.isEmpty()) {
732 return false;
733 }
734
735 int numResultPoints = 0;
736 *srcPoint = indexesOp.getSrcPointForce(cellPt);
737 *dstPoint = QPointF();
738
739 Q_FOREACH (const Private::PointExtension &ext, extensionPoints) {
740 QPointF near = transformedPoints[ext.near];
741 QPointF far = transformedPoints[ext.far];
742
743 QPointF nearSrc = originalPoints[ext.near];
744 QPointF farSrc = originalPoints[ext.far];
745
746 QPointF base1 = nearSrc - farSrc;
747 QPointF base2 = near - far;
748
749 QPointF pt = near +
750 KisAlgebra2D::transformAsBase(*srcPoint - nearSrc, base1, base2);
751
752 *dstPoint += pt;
753 numResultPoints++;
754 }
755
756 *dstPoint /= numResultPoints;
757
758 return true;
759}
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 950 of file kis_grid_interpolation_tools.h.

955{
956 iterateThroughGrid<IncompletePolygonPolicy, PolygonOp, IndexesOp>(polygonOp, indexesOp, gridSize, originalPoints, transformedPoints, QRect(QPoint(0, 0), gridSize));
957}

◆ 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 962 of file kis_grid_interpolation_tools.h.

968{
969 QVector<int> polygonPoints(4);
970 QPoint startPoint = subGrid.topLeft();
971 QPoint endPoint = subGrid.bottomRight(); // it's weird but bottomRight on QRect point does give us one unit of margin on both x and y
972 // when start is on (0, 0), and size is (500, 500), bottomRight is on (499, 499)
973 // but remember that it also only needs a top left corner of the polygon
974
975 KIS_SAFE_ASSERT_RECOVER(startPoint.x() >= 0 && startPoint.y() >= 0 && endPoint.x() <= gridSize.width() - 1 && endPoint.y() <= gridSize.height() - 1) {
976 startPoint = QPoint(qMax(startPoint.x(), 0), qMax(startPoint.y(), 0));
977 endPoint = QPoint(qMin(endPoint.x(), gridSize.width() - 1), qMin(startPoint.y(), gridSize.height() - 1));
978 }
979
980 for (int row = startPoint.y(); row < endPoint.y(); row++) {
981 for (int col = startPoint.x(); col < endPoint.x(); col++) {
982 int numExistingPoints = 0;
983
984 polygonPoints = indexesOp.calculateMappedIndexes(col, row, &numExistingPoints);
985
986 if (!IncompletePolygonPolicy<PolygonOp, IndexesOp>::
987 tryProcessPolygon(col, row,
988 numExistingPoints,
989 polygonOp,
990 indexesOp,
991 polygonPoints,
992 originalPoints,
993 transformedPoints)) {
994
995 QPolygonF srcPolygon;
996 QPolygonF dstPolygon;
997
998 for (int i = 0; i < 4; i++) {
999 const int index = polygonPoints[i];
1000 srcPolygon << originalPoints[index];
1001 dstPolygon << transformedPoints[index];
1002 }
1003
1004 adjustAlignedPolygon(srcPolygon);
1005 adjustAlignedPolygon(dstPolygon);
1006
1007 polygonOp(srcPolygon, dstPolygon);
1008 }
1009 }
1010 }
1011
1012 polygonOp.finalize();
1013}
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
void adjustAlignedPolygon(QPolygonF &polygon)

References adjustAlignedPolygon(), and KIS_SAFE_ASSERT_RECOVER.

◆ middlePoint() [1/3]

QPointF GridIterationTools::middlePoint ( int x,
int y )
inline

Definition at line 169 of file kis_grid_interpolation_tools.h.

169 {
170 return QPointF(x + 0.5, y + 0.5);
171}

◆ middlePoint() [2/3]

QPointF GridIterationTools::middlePoint ( QPoint p)
inline

Definition at line 173 of file kis_grid_interpolation_tools.h.

173 {
174 return QPointF(p.x() + 0.5, p.y() + 0.5);
175}
const Params2D p

References p.

◆ middlePoint() [3/3]

QPointF GridIterationTools::middlePoint ( QPointF p)
inline

Definition at line 177 of file kis_grid_interpolation_tools.h.

177 {
178 return QPointF(p.x() + 0.5, p.y() + 0.5);
179}

References p.

◆ pointToIndex()

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

Definition at line 571 of file kis_grid_interpolation_tools.h.

572{
573 return cellPt.x() +
574 cellPt.y() * gridSize.width();
575}

◆ 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().