1 #include "DocumentModelSegments.h"
2 #include "EngaugeAssert.h"
8 #include <QGraphicsScene>
10 #include <QTextStream>
11 #include "QtToString.h"
13 #include "SegmentLine.h"
20 m_isGnuplot (isGnuplot)
22 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::Segment"
23 <<
" address=0x" << hex << (quintptr)
this;
28 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::~Segment"
29 <<
" address=0x" << hex << (quintptr)
this;
31 QList<SegmentLine*>::iterator itr;
32 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
35 m_scene.removeItem (segmentLine);
48 LOG4CPP_DEBUG_S ((*mainCat)) <<
"Segment::appendColumn"
49 <<
" segment=0x" << std::hex << (quintptr)
this << std::dec
51 << xOld <<
"," << yOld <<
") to ("
52 << xNew <<
"," << yNew <<
")";
57 ENGAUGE_CHECK_PTR(line);
58 line->setLine(QLineF (xOld,
68 m_length += qSqrt((1.0) * (1.0) + (y - m_yLast) * (y - m_yLast));
73 void Segment::createAcceptablePoint(
bool *pFirst,
80 int iOld = (int) (*xPrev + 0.5);
81 int jOld = (int) (*yPrev + 0.5);
82 int i = (int) (x + 0.5);
83 int j = (int) (y + 0.5);
85 if (*pFirst || (iOld != i) || (jOld != j)) {
89 ENGAUGE_CHECK_PTR(pList);
90 pList->append(QPoint(i, j));
96 void Segment::dumpToGnuplot (QTextStream &strDump,
103 if (mainCat->getPriority() == log4cpp::Priority::DEBUG) {
107 QString label = QString (
"Old: (%1,%2) to (%3,%4), New: (%5,%6) to (%7,%8)")
108 .arg (lineOld->line().x1())
109 .arg (lineOld->line().y1())
110 .arg (lineOld->line().x2())
111 .arg (lineOld->line().y2())
112 .arg (lineNew->line().x1())
113 .arg (lineNew->line().y1())
114 .arg (lineNew->line().x2())
115 .arg (lineNew->line().y2());
117 strDump <<
"unset label\n";
118 strDump <<
"set label \"" << label <<
"\" at graph 0, graph 0.02\n";
119 strDump <<
"set grid xtics\n";
120 strDump <<
"set grid ytics\n";
123 int rows = 0, cols = 0;
124 QList<SegmentLine*>::const_iterator itr;
125 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
128 ENGAUGE_CHECK_PTR (line);
130 int x1 = line->line().x1();
131 int y1 = line->line().y1();
132 int x2 = line->line().x2();
133 int y2 = line->line().y2();
135 rows = qMax (rows, y1 + 1);
136 rows = qMax (rows, y2 + 1);
137 cols = qMax (cols, x1 + 1);
138 cols = qMax (cols, x2 + 1);
143 int halfWidthX = 1.5 * qMax (qAbs (lineOld->line().dx()),
144 qAbs (lineNew->line().dx()));
145 int halfWidthY = 1.5 * qMax (qAbs (lineOld->line().dy()),
146 qAbs (lineNew->line().dy()));
149 strDump <<
"set xrange [" << (xInt - halfWidthX - 1) <<
":" << (xInt + halfWidthX + 1) <<
"]\n";
150 strDump <<
"set yrange [" << (yInt - halfWidthY - 1) <<
":" << (yInt + halfWidthY + 1) <<
"]\n";
155 strDump <<
"plot \\\n"
156 <<
"\"-\" title \"\" with lines, \\\n"
157 <<
"\"-\" title \"\" with lines, \\\n"
158 <<
"\"-\" title \"Replacement\" with lines, \\\n"
159 <<
"\"-\" title \"Segment pixels Even\" with linespoints, \\\n"
160 <<
"\"-\" title \"Segment pixels Odd\" with linespoints\n"
161 << xInt <<
" " << (yInt - halfWidthY) <<
"\n"
162 << xInt <<
" " << (yInt + halfWidthY) <<
"\n"
164 << (xInt - halfWidthX) <<
" " << yInt <<
"\n"
165 << (xInt + halfWidthY) <<
" " << yInt <<
"\n"
167 << lineOld->line().x1() <<
" " << lineOld->line().y1() <<
"\n"
168 << lineNew->line().x2() <<
" " << lineNew->line().y2() <<
"\n"
173 QTextStream strEven (&even), strOdd (&odd);
174 for (
int index = 0; index < m_lines.count(); index++) {
177 int x1 = line->line().x1();
178 int y1 = line->line().y1();
179 int x2 = line->line().x2();
180 int y2 = line->line().y2();
182 if (index % 2 == 0) {
183 strEven << x1 <<
" " << y1 <<
"\n";
184 strEven << x2 <<
" " << y2 <<
"\n";
187 strOdd << x1 <<
" " << y1 <<
"\n";
188 strOdd << x2 <<
" " << y2 <<
"\n";
193 strDump << even <<
"\n";
195 strDump << odd <<
"\n";
197 strDump <<
"pause -1 \"Hit Enter to continue\"\n";
204 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::fillPoints";
207 return fillPointsFillingCorners(modelSegments);
209 return fillPointsWithoutFillingCorners(modelSegments);
217 if (m_lines.count() > 0) {
219 double xLast = m_lines.first()->line().x1();
220 double yLast = m_lines.first()->line().y1();
223 double distanceCompleted = 0.0;
227 double xPrev = m_lines.first()->line().x1();
228 double yPrev = m_lines.first()->line().y1();
230 QList<SegmentLine*>::iterator itr;
231 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
235 ENGAUGE_CHECK_PTR(line);
236 xNext = (double) line->line().x2();
237 yNext = (double) line->line().y2();
239 double xStart = (double) line->line().x1();
240 double yStart = (double) line->line().y1();
241 if (isCorner (yPrev, yStart, yNext)) {
244 createAcceptablePoint(&firstPoint, &list, &xPrev, &yPrev, xStart, yStart);
245 distanceCompleted = 0.0;
249 double segmentLength = sqrt((xNext - xLast) * (xNext - xLast) + (yNext - yLast) * (yNext - yLast));
250 if (segmentLength > 0.0) {
254 while (distanceCompleted <= segmentLength) {
256 double s = distanceCompleted / segmentLength;
259 x = (1.0 - s) * xLast + s * xNext;
260 y = (1.0 - s) * yLast + s * yNext;
262 createAcceptablePoint(&firstPoint, &list, &xPrev, &yPrev, x, y);
267 distanceCompleted -= segmentLength;
280 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::firstPoint"
281 <<
" lineCount=" << m_lines.count();
284 ENGAUGE_ASSERT (m_lines.count () > 0);
287 QPointF pos = line->line().p1();
289 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::firstPoint"
290 <<
" pos=" << QPointFToString (pos).toLatin1().data();
297 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::forwardMousePress"
298 <<
" segmentLines=" << m_lines.count();
303 bool Segment::isCorner (
double yLast,
308 double deltaYBefore = yPrev - yLast;
309 double deltaYAfter = yNext - yPrev;
310 bool upThenAcrossOrDown = (deltaYBefore > 0) && (deltaYAfter <= 0);
311 bool downThenAcrossOrUp = (deltaYBefore < 0) && (deltaYAfter >= 0);
313 return upThenAcrossOrDown || downThenAcrossOrUp;
320 if (m_lines.count() > 0) {
322 double xLast = m_lines.first()->line().x1();
323 double yLast = m_lines.first()->line().y1();
326 double distanceCompleted = 0.0;
329 bool firstPoint =
true;
330 double xPrev = m_lines.first()->line().x1();
331 double yPrev = m_lines.first()->line().y1();
333 QList<SegmentLine*>::iterator itr;
334 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
338 ENGAUGE_CHECK_PTR(line);
339 xNext = (double) line->line().x2();
340 yNext = (double) line->line().y2();
343 double segmentLength = sqrt((xNext - xLast) * (xNext - xLast) + (yNext - yLast) * (yNext - yLast));
344 if (segmentLength > 0.0) {
348 while (distanceCompleted <= segmentLength) {
350 double s = distanceCompleted / segmentLength;
353 x = (1.0 - s) * xLast + s * xNext;
354 y = (1.0 - s) * yLast + s * yNext;
356 createAcceptablePoint(&firstPoint, &list, &xPrev, &yPrev, x, y);
361 distanceCompleted -= segmentLength;
379 return m_lines.count();
382 bool Segment::pointIsCloseToLine(
double xLeft,
389 double xProj, yProj, projectedDistanceOutsideLine, distanceToLine;
390 projectPointOntoLine(xInt, yInt, xLeft, yLeft, xRight, yRight, &xProj, &yProj, &projectedDistanceOutsideLine, &distanceToLine);
393 (xInt - xProj) * (xInt - xProj) +
394 (yInt - yProj) * (yInt - yProj) < 0.5 * 0.5);
397 bool Segment::pointsAreCloseToLine(
double xLeft,
399 QList<QPoint> removedPoints,
403 QList<QPoint>::iterator itr;
404 for (itr = removedPoints.begin(); itr != removedPoints.end(); ++itr) {
405 if (!pointIsCloseToLine(xLeft, yLeft, (
double) (*itr).x(), (double) (*itr).y(), xRight, yRight)) {
415 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::removeUnneededLines";
418 QTextStream *strDump = 0;
421 QString filename (
"segment.gnuplot");
423 std::cout <<
"Writing gnuplot file: " << filename.toLatin1().data() <<
"\n";
425 fileDump =
new QFile (filename);
426 fileDump->open (QIODevice::WriteOnly | QIODevice::Text);
427 strDump =
new QTextStream (fileDump);
436 QList<SegmentLine*>::iterator itr, itrPrevious;
437 QList<QPoint> removedPoints;
438 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
441 ENGAUGE_CHECK_PTR(line);
443 if (linePrevious != 0) {
445 double xLeft = linePrevious->line().x1();
446 double yLeft = linePrevious->line().y1();
447 double xInt = linePrevious->line().x2();
448 double yInt = linePrevious->line().y2();
452 if (linePrevious->line().p2() == line->line().p1()) {
454 double xRight = line->line().x2();
455 double yRight = line->line().y2();
457 if (pointIsCloseToLine(xLeft, yLeft, xInt, yInt, xRight, yRight) &&
458 pointsAreCloseToLine(xLeft, yLeft, removedPoints, xRight, yRight)) {
463 dumpToGnuplot (*strDump,
473 LOG4CPP_DEBUG_S ((*mainCat)) <<
"Segment::removeUnneededLines"
474 <<
" segment=0x" << std::hex << (quintptr)
this << std::dec
476 << linePrevious->line().x1() <<
"," << linePrevious->line().y1() <<
") to ("
477 << linePrevious->line().x2() <<
"," << linePrevious->line().y2() <<
") "
478 <<
" and modifying ("
479 << line->line().x1() <<
"," << line->line().y1() <<
") to ("
480 << line->line().x2() <<
"," << line->line().y2() <<
") into ("
481 << xLeft <<
"," << yLeft <<
") to ("
482 << xRight <<
"," << yRight <<
")";
484 removedPoints.append(QPoint((
int) xInt, (
int) yInt));
485 m_lines.erase (itrPrevious);
489 line->setLine (xLeft, yLeft, xRight, yRight);
494 removedPoints.clear();
503 if (itr == m_lines.end()) {
511 *strDump <<
"set terminal x11 persist\n";
521 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::slotHover";
523 QList<SegmentLine*>::iterator itr, itrPrevious;
524 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
533 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::updateModelSegment";
535 QList<SegmentLine*>::iterator itr;
536 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
int lineCount() const
Get method for number of lines.
void updateModelSegment(const DocumentModelSegments &modelSegments)
Update this segment line with new settings.
void removeUnneededLines(int *foldedLines)
Try to compress a segment that was just completed, by folding together line from point i to point i+1...
double pointSeparation() const
Get method for point separation.
void slotHover(bool hover)
Slot for hover enter/leave events in the associated SegmentLines.
void forwardMousePress()
Forward mouse press event from a component SegmentLine that was just clicked on.
void appendColumn(int x, int y, const DocumentModelSegments &modelSegments)
Add some more pixels in a new column to an active segment.
double length() const
Get method for length in pixels.
QList< QPoint > fillPoints(const DocumentModelSegments &modelSegments)
Create evenly spaced points along the segment.
void signalMouseClickOnSegment(QPointF posSegmentStart)
Pass mouse press event, with coordinates of first point in the Segment since that info uniquely ident...
void updateModelSegment(const DocumentModelSegments &modelSegments)
Update this segment given the new settings.
QPointF firstPoint() const
Coordinates of first point in Segment.
Model for DlgSettingsSegments and CmdSettingsSegments.
This class is a special case of the standard QGraphicsLineItem for segments.
void setHover(bool hover)
Apply/remove highlighting triggered by hover enter/leave.
Segment(QGraphicsScene &scene, int yLast, bool isGnuplot)
Single constructor.
bool fillCorners() const
Get method for fill corners.