7#include "DocumentModelSegments.h"
8#include "EngaugeAssert.h"
14#include <QGraphicsScene>
17#include "QtToString.h"
19#include "SegmentLine.h"
26 m_isGnuplot (isGnuplot)
28 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::Segment"
29 <<
" address=0x" << hex << (quintptr)
this;
34 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::~Segment"
35 <<
" address=0x" << hex << (quintptr)
this;
37 QList<SegmentLine*>::iterator itr;
38 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
41 m_scene.removeItem (segmentLine);
54 LOG4CPP_DEBUG_S ((*mainCat)) <<
"Segment::appendColumn"
55 <<
" segment=0x" << std::hex << (quintptr)
this << std::dec
57 << xOld <<
"," << yOld <<
") to ("
58 << xNew <<
"," << yNew <<
")";
63 ENGAUGE_CHECK_PTR(line);
64 line->setLine(QLineF (xOld,
74 m_length += qSqrt((1.0) * (1.0) + (y - m_yLast) * (y - m_yLast));
79void Segment::createAcceptablePoint(
bool *pFirst,
86 int iOld = (int) (*xPrev + 0.5);
87 int jOld = (int) (*yPrev + 0.5);
88 int i = (int) (x + 0.5);
89 int j = (int) (y + 0.5);
91 if (*pFirst || (iOld != i) || (jOld != j)) {
95 ENGAUGE_CHECK_PTR(pList);
96 pList->append(QPoint(i, j));
102void Segment::dumpToGnuplot (QTextStream &strDump,
109 if (mainCat->getPriority() == log4cpp::Priority::DEBUG) {
113 QString label = QString (
"Old: (%1,%2) to (%3,%4), New: (%5,%6) to (%7,%8)")
114 .arg (lineOld->line().x1())
115 .arg (lineOld->line().y1())
116 .arg (lineOld->line().x2())
117 .arg (lineOld->line().y2())
118 .arg (lineNew->line().x1())
119 .arg (lineNew->line().y1())
120 .arg (lineNew->line().x2())
121 .arg (lineNew->line().y2());
123 strDump <<
"unset label\n";
124 strDump <<
"set label \"" << label <<
"\" at graph 0, graph 0.02\n";
125 strDump <<
"set grid xtics\n";
126 strDump <<
"set grid ytics\n";
129 int rows = 0, cols = 0;
130 QList<SegmentLine*>::const_iterator itr;
131 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
134 ENGAUGE_CHECK_PTR (line);
136 int x1 = line->line().x1();
137 int y1 = line->line().y1();
138 int x2 = line->line().x2();
139 int y2 = line->line().y2();
141 rows = qMax (rows, y1 + 1);
142 rows = qMax (rows, y2 + 1);
143 cols = qMax (cols, x1 + 1);
144 cols = qMax (cols, x2 + 1);
149 int halfWidthX = 1.5 * qMax (qAbs (lineOld->line().dx()),
150 qAbs (lineNew->line().dx()));
151 int halfWidthY = 1.5 * qMax (qAbs (lineOld->line().dy()),
152 qAbs (lineNew->line().dy()));
155 strDump <<
"set xrange [" << (xInt - halfWidthX - 1) <<
":" << (xInt + halfWidthX + 1) <<
"]\n";
156 strDump <<
"set yrange [" << (yInt - halfWidthY - 1) <<
":" << (yInt + halfWidthY + 1) <<
"]\n";
161 strDump <<
"plot \\\n"
162 <<
"\"-\" title \"\" with lines, \\\n"
163 <<
"\"-\" title \"\" with lines, \\\n"
164 <<
"\"-\" title \"Replacement\" with lines, \\\n"
165 <<
"\"-\" title \"Segment pixels Even\" with linespoints, \\\n"
166 <<
"\"-\" title \"Segment pixels Odd\" with linespoints\n"
167 << xInt <<
" " << (yInt - halfWidthY) <<
"\n"
168 << xInt <<
" " << (yInt + halfWidthY) <<
"\n"
170 << (xInt - halfWidthX) <<
" " << yInt <<
"\n"
171 << (xInt + halfWidthY) <<
" " << yInt <<
"\n"
173 << lineOld->line().x1() <<
" " << lineOld->line().y1() <<
"\n"
174 << lineNew->line().x2() <<
" " << lineNew->line().y2() <<
"\n"
179 QTextStream strEven (&even), strOdd (&odd);
180 for (
int index = 0; index < m_lines.count(); index++) {
183 int x1 = line->line().x1();
184 int y1 = line->line().y1();
185 int x2 = line->line().x2();
186 int y2 = line->line().y2();
188 if (index % 2 == 0) {
189 strEven << x1 <<
" " << y1 <<
"\n";
190 strEven << x2 <<
" " << y2 <<
"\n";
193 strOdd << x1 <<
" " << y1 <<
"\n";
194 strOdd << x2 <<
" " << y2 <<
"\n";
199 strDump << even <<
"\n";
201 strDump << odd <<
"\n";
203 strDump <<
"pause -1 \"Hit Enter to continue\"\n";
210 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::fillPoints";
213 return fillPointsFillingCorners(modelSegments);
215 return fillPointsWithoutFillingCorners(modelSegments);
223 if (m_lines.count() > 0) {
225 double xLast = m_lines.first()->line().x1();
226 double yLast = m_lines.first()->line().y1();
229 double distanceCompleted = 0.0;
233 double xPrev = m_lines.first()->line().x1();
234 double yPrev = m_lines.first()->line().y1();
236 QList<SegmentLine*>::iterator itr;
237 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
241 ENGAUGE_CHECK_PTR(line);
242 xNext = (double) line->line().x2();
243 yNext = (double) line->line().y2();
245 double xStart = (double) line->line().x1();
246 double yStart = (double) line->line().y1();
247 if (isCorner (yPrev, yStart, yNext)) {
250 createAcceptablePoint(&
firstPoint, &list, &xPrev, &yPrev, xStart, yStart);
251 distanceCompleted = 0.0;
255 double segmentLength = sqrt((xNext - xLast) * (xNext - xLast) + (yNext - yLast) * (yNext - yLast));
256 if (segmentLength > 0.0) {
260 while (distanceCompleted <= segmentLength) {
262 double s = distanceCompleted / segmentLength;
265 x = (1.0 - s) * xLast + s * xNext;
266 y = (1.0 - s) * yLast + s * yNext;
268 createAcceptablePoint(&
firstPoint, &list, &xPrev, &yPrev, x, y);
273 distanceCompleted -= segmentLength;
286 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::firstPoint"
287 <<
" lineCount=" << m_lines.count();
290 ENGAUGE_ASSERT (m_lines.count () > 0);
293 QPointF pos = line->line().p1();
295 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::firstPoint"
296 <<
" pos=" << QPointFToString (pos).toLatin1().data();
303 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::forwardMousePress"
304 <<
" segmentLines=" << m_lines.count();
309bool Segment::isCorner (
double yLast,
314 double deltaYBefore = yPrev - yLast;
315 double deltaYAfter = yNext - yPrev;
316 bool upThenAcrossOrDown = (deltaYBefore > 0) && (deltaYAfter <= 0);
317 bool downThenAcrossOrUp = (deltaYBefore < 0) && (deltaYAfter >= 0);
319 return upThenAcrossOrDown || downThenAcrossOrUp;
326 if (m_lines.count() > 0) {
328 double xLast = m_lines.first()->line().x1();
329 double yLast = m_lines.first()->line().y1();
332 double distanceCompleted = 0.0;
336 double xPrev = m_lines.first()->line().x1();
337 double yPrev = m_lines.first()->line().y1();
339 QList<SegmentLine*>::iterator itr;
340 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
344 ENGAUGE_CHECK_PTR(line);
345 xNext = (double) line->line().x2();
346 yNext = (double) line->line().y2();
349 double segmentLength = sqrt((xNext - xLast) * (xNext - xLast) + (yNext - yLast) * (yNext - yLast));
350 if (segmentLength > 0.0) {
354 while (distanceCompleted <= segmentLength) {
356 double s = distanceCompleted / segmentLength;
359 x = (1.0 - s) * xLast + s * xNext;
360 y = (1.0 - s) * yLast + s * yNext;
362 createAcceptablePoint(&
firstPoint, &list, &xPrev, &yPrev, x, y);
367 distanceCompleted -= segmentLength;
385 return m_lines.count();
388bool Segment::pointIsCloseToLine(
double xLeft,
395 double xProj, yProj, projectedDistanceOutsideLine, distanceToLine;
396 projectPointOntoLine(xInt, yInt, xLeft, yLeft, xRight, yRight, &xProj, &yProj, &projectedDistanceOutsideLine, &distanceToLine);
399 (xInt - xProj) * (xInt - xProj) +
400 (yInt - yProj) * (yInt - yProj) < 0.5 * 0.5);
403bool Segment::pointsAreCloseToLine(
double xLeft,
405 QList<QPoint> removedPoints,
409 QList<QPoint>::iterator itr;
410 for (itr = removedPoints.begin(); itr != removedPoints.end(); ++itr) {
411 if (!pointIsCloseToLine(xLeft, yLeft, (
double) (*itr).x(), (
double) (*itr).y(), xRight, yRight)) {
421 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::removeUnneededLines";
424 QTextStream *strDump = 0;
427 QString filename (
"segment.gnuplot");
429 std::cout <<
"Writing gnuplot file: " << filename.toLatin1().data() <<
"\n";
431 fileDump =
new QFile (filename);
432 fileDump->open (QIODevice::WriteOnly | QIODevice::Text);
433 strDump =
new QTextStream (fileDump);
442 QList<SegmentLine*>::iterator itr, itrPrevious;
443 QList<QPoint> removedPoints;
444 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
447 ENGAUGE_CHECK_PTR(line);
449 if (linePrevious != 0) {
451 double xLeft = linePrevious->line().x1();
452 double yLeft = linePrevious->line().y1();
453 double xInt = linePrevious->line().x2();
454 double yInt = linePrevious->line().y2();
458 if (linePrevious->line().p2() == line->line().p1()) {
460 double xRight = line->line().x2();
461 double yRight = line->line().y2();
463 if (pointIsCloseToLine(xLeft, yLeft, xInt, yInt, xRight, yRight) &&
464 pointsAreCloseToLine(xLeft, yLeft, removedPoints, xRight, yRight)) {
469 dumpToGnuplot (*strDump,
479 LOG4CPP_DEBUG_S ((*mainCat)) <<
"Segment::removeUnneededLines"
480 <<
" segment=0x" << std::hex << (quintptr)
this << std::dec
482 << linePrevious->line().x1() <<
"," << linePrevious->line().y1() <<
") to ("
483 << linePrevious->line().x2() <<
"," << linePrevious->line().y2() <<
") "
484 <<
" and modifying ("
485 << line->line().x1() <<
"," << line->line().y1() <<
") to ("
486 << line->line().x2() <<
"," << line->line().y2() <<
") into ("
487 << xLeft <<
"," << yLeft <<
") to ("
488 << xRight <<
"," << yRight <<
")";
490 removedPoints.append(QPoint((
int) xInt, (
int) yInt));
491 m_lines.erase (itrPrevious);
495 line->setLine (xLeft, yLeft, xRight, yRight);
500 removedPoints.clear();
509 if (itr == m_lines.end()) {
517 *strDump <<
"set terminal x11 persist\n";
527 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::slotHover";
529 QList<SegmentLine*>::iterator itr, itrPrevious;
530 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
539 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::updateModelSegment";
541 QList<SegmentLine*>::iterator itr;
542 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
Model for DlgSettingsSegments and CmdSettingsSegments.
bool fillCorners() const
Get method for fill corners.
double pointSeparation() const
Get method for point separation.
This class is a special case of the standard QGraphicsLineItem for segments.
void setHover(bool hover)
Apply/remove highlighting triggered by hover enter/leave.
void updateModelSegment(const DocumentModelSegments &modelSegments)
Update this segment line with new settings.
void signalMouseClickOnSegment(QPointF posSegmentStart)
Pass mouse press event, with coordinates of first point in the Segment since that info uniquely ident...
double length() const
Get method for length in pixels.
int lineCount() const
Get method for number of lines.
QList< QPoint > fillPoints(const DocumentModelSegments &modelSegments)
Create evenly spaced points along the segment.
Segment(QGraphicsScene &scene, int yLast, bool isGnuplot)
Single constructor.
void forwardMousePress()
Forward mouse press event from a component SegmentLine that was just clicked on.
void slotHover(bool hover)
Slot for hover enter/leave events in the associated SegmentLines.
void updateModelSegment(const DocumentModelSegments &modelSegments)
Update this segment given the new settings.
void appendColumn(int x, int y, const DocumentModelSegments &modelSegments)
Add some more pixels in a new column to an active segment.
QPointF firstPoint() const
Coordinates of first point in Segment.
void removeUnneededLines(int *foldedLines)
Try to compress a segment that was just completed, by folding together line from point i to point i+1...