Engauge Digitizer  2
GridRemoval.cpp
1 #include "EngaugeAssert.h"
2 #include "GridRemoval.h"
3 #include "Logger.h"
4 #include <qdebug.h>
5 #include <QImage>
6 #include <qmath.h>
7 #include "Transformation.h"
8 
9 const double EPSILON = 0.000001;
10 
12 {
13 }
14 
15 QPointF GridRemoval::clipX (const QPointF &posUnprojected,
16  double xBoundary,
17  const QPointF &posOther) const
18 {
19  double s = (xBoundary - posUnprojected.x()) / (posOther.x() - posUnprojected.x());
20  ENGAUGE_ASSERT ((-1.0 * EPSILON < s) && (s < 1.0 + EPSILON));
21 
22  return QPointF ((1.0 - s) * posUnprojected.x() + s * posOther.x(),
23  (1.0 - s) * posUnprojected.y() + s * posOther.y());
24 }
25 
26 QPointF GridRemoval::clipY (const QPointF &posUnprojected,
27  double yBoundary,
28  const QPointF &posOther) const
29 {
30  double s = (yBoundary - posUnprojected.y()) / (posOther.y() - posUnprojected.y());
31  ENGAUGE_ASSERT ((-1.0 * EPSILON < s) && (s < 1.0 + EPSILON));
32 
33  return QPointF ((1.0 - s) * posUnprojected.x() + s * posOther.x(),
34  (1.0 - s) * posUnprojected.y() + s * posOther.y());
35 }
36 
37 QPixmap GridRemoval::remove (const Transformation &transformation,
38  const DocumentModelGridRemoval &modelGridRemoval,
39  const QImage &imageBefore)
40 {
41  LOG4CPP_INFO_S ((*mainCat)) << "GridRemoval::remove"
42  << " transformationIsDefined=" << (transformation.transformIsDefined() ? "true" : "false")
43  << " removeDefinedGridLines=" << (modelGridRemoval.removeDefinedGridLines() ? "true" : "false");
44 
45  QImage image = imageBefore;
46 
47  // Make sure grid line removal is wanted, and possible. Otherwise all processing is skipped
48  if (modelGridRemoval.removeDefinedGridLines() &&
49  transformation.transformIsDefined()) {
50 
51  double yGraphMin = modelGridRemoval.startY();
52  double yGraphMax = modelGridRemoval.stopY();
53  for (int i = 0; i < modelGridRemoval.countX(); i++) {
54  double xGraph = modelGridRemoval.startX() + i * modelGridRemoval.stepX();
55 
56  // Convert line between graph coordinates (xGraph,yGraphMin) and (xGraph,yGraphMax) to screen coordinates
57  QPointF posScreenMin, posScreenMax;
58  transformation.transformRawGraphToScreen (QPointF (xGraph,
59  yGraphMin),
60  posScreenMin);
61  transformation.transformRawGraphToScreen (QPointF (xGraph,
62  yGraphMax),
63  posScreenMax);
64 
65  removeLine (posScreenMin,
66  posScreenMax,
67  image);
68  }
69 
70  double xGraphMin = modelGridRemoval.startX();
71  double xGraphMax = modelGridRemoval.stopX();
72  for (int j = 0; j < modelGridRemoval.countY(); j++) {
73  double yGraph = modelGridRemoval.startY() + j * modelGridRemoval.stepY();
74 
75  // Convert line between graph coordinates (xGraphMin,yGraph) and (xGraphMax,yGraph) to screen coordinates
76  QPointF posScreenMin, posScreenMax;
77  transformation.transformRawGraphToScreen (QPointF (xGraphMin,
78  yGraph),
79  posScreenMin);
80  transformation.transformRawGraphToScreen (QPointF (xGraphMax,
81  yGraph),
82  posScreenMax);
83 
84  removeLine (posScreenMin,
85  posScreenMax,
86  image);
87  }
88  }
89 
90  return QPixmap::fromImage (image);
91 }
92 
93 void GridRemoval::removeLine (const QPointF &posMin,
94  const QPointF &posMax,
95  QImage &image)
96 {
97  double w = image.width() - 1; // Inclusive width = exclusive width - 1
98  double h = image.height() - 1; // Inclusive height = exclusive height - 1
99 
100  QPointF pos1 = posMin;
101  QPointF pos2 = posMax;
102 
103  // Throw away all lines that are entirely above or below or left or right to the screen, since
104  // they cannot intersect the screen
105  bool onLeft = (pos1.x() < 0 && pos2.x () < 0);
106  bool onTop = (pos1.y() < 0 && pos2.y () < 0);
107  bool onRight = (pos1.x() > w && pos2.x () > w);
108  bool onBottom = (pos1.y() > h && pos2.y () > h);
109  if (!onLeft && !onTop && !onRight && !onBottom) {
110 
111  // Clip to within the four sides
112  if (pos1.x() < 0) { pos1 = clipX (pos1, 0, pos2); }
113  if (pos2.x() < 0) { pos2 = clipX (pos2, 0, pos1); }
114  if (pos1.y() < 0) { pos1 = clipY (pos1, 0, pos2); }
115  if (pos2.y() < 0) { pos2 = clipY (pos2, 0, pos1); }
116  if (pos1.x() > w) { pos1 = clipX (pos1, w, pos2); }
117  if (pos2.x() > w) { pos2 = clipX (pos2, w, pos1); }
118  if (pos1.y() > h) { pos1 = clipY (pos1, h, pos2); }
119  if (pos2.y() > h) { pos2 = clipY (pos2, h, pos1); }
120 
121  // Is line more horizontal or vertical?
122  double deltaX = qAbs (pos1.x() - pos2.x());
123  double deltaY = qAbs (pos1.y() - pos2.y());
124  if (deltaX > deltaY) {
125 
126  // More horizontal
127  int xMin = qMin (pos1.x(), pos2.x());
128  int xMax = qMax (pos1.x(), pos2.x());
129  int yAtXMin = (pos1.x() < pos2.x() ? pos1.y() : pos2.y());
130  int yAtXMax = (pos1.x() < pos2.x() ? pos2.y() : pos1.y());
131  for (int x = xMin; x <= xMax; x++) {
132  double s = (double) (x - xMin) / (double) (xMax - xMin);
133  double yLine = (1.0 - s) * yAtXMin + s * yAtXMax;
134  for (int yOffset = -1; yOffset <= 1; yOffset++) {
135  int y = (int) (0.5 + yLine + yOffset);
136  image.setPixel (x, y, QColor(Qt::white).rgb());
137  }
138  }
139  } else {
140 
141  // More vertical
142  int yMin = qMin (pos1.y(), pos2.y());
143  int yMax = qMax (pos1.y(), pos2.y());
144  int xAtYMin = (pos1.y() < pos2.y() ? pos1.x() : pos2.x());
145  int xAtYMax = (pos1.y() < pos2.y() ? pos2.x() : pos1.x());
146  for (int y = yMin; y <= yMax; y++) {
147  double s = (double) (y - yMin) / (double) (yMax - yMin);
148  double xLine = (1.0 - s) * xAtYMin + s * xAtYMax;
149  for (int xOffset = -1; xOffset <= 1; xOffset++) {
150  int x = (int) (0.5 + xLine + xOffset);
151  image.setPixel (x, y, QColor(Qt::white).rgb());
152  }
153  }
154  }
155  }
156 }
157 
bool removeDefinedGridLines() const
Get method for removing defined grid lines.
double startY() const
Get method for y start.
double stepY() const
Get method for y step.
Affine transformation between screen and graph coordinates, based on digitized axis points...
double stopX() const
Get method for x stop.
QPixmap remove(const Transformation &transformation, const DocumentModelGridRemoval &modelGridRemoval, const QImage &imageBefore)
Process QImage into QPixmap, removing the grid lines.
Definition: GridRemoval.cpp:37
double startX() const
Get method for x start.
double stopY() const
Get method for y stop.
int countX() const
Get method for x count.
int countY() const
Get method for y count.
bool transformIsDefined() const
Transform is defined when at least three axis points have been digitized.
double stepX() const
Get method for x step.
void transformRawGraphToScreen(const QPointF &pointRaw, QPointF &pointScreen) const
Transform from raw graph coordinates to linear cartesian graph coordinates, then to screen coordinate...
Model for DlgSettingsGridRemoval and CmdSettingsGridRemoval. The settings are unstable until the user...
GridRemoval()
Single constructor.
Definition: GridRemoval.cpp:11