7 #include "DocumentModelSegments.h"
8 #include "EngaugeAssert.h"
15 #include <QGraphicsScene>
17 #include <QTextStream>
18 #include "QtToString.h"
20 #include "SegmentLine.h"
28 m_isGnuplot (isGnuplot)
34 QList<SegmentLine*>::iterator itr;
35 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
38 m_scene.removeItem (segmentLine);
51 LOG4CPP_DEBUG_S ((*mainCat)) <<
"Segment::appendColumn"
52 <<
" segment=0x" << std::hex << static_cast<void*> (
this) << std::dec
54 << xOld <<
"," << yOld <<
") to ("
55 << xNew <<
"," << yNew <<
")";
60 ENGAUGE_CHECK_PTR(line);
61 line->setLine(QLineF (xOld,
71 m_length += qSqrt((1.0) * (1.0) + (y - m_yLast) * (y - m_yLast));
76 void Segment::createAcceptablePoint(
bool *pFirst,
83 int iOld = qFloor (*xPrev + 0.5);
84 int jOld = qFloor (*yPrev + 0.5);
85 int i = qFloor (x + 0.5);
86 int j = qFloor (y + 0.5);
88 if (*pFirst || (iOld != i) || (jOld != j)) {
92 ENGAUGE_CHECK_PTR(pList);
93 pList->append(QPoint(i, j));
99 void Segment::dumpToGnuplot (QTextStream &strDump,
106 if (mainCat->
getPriority() == log4cpp::Priority::DEBUG) {
110 QString label = QString (
"Old: (%1,%2) to (%3,%4), New: (%5,%6) to (%7,%8)")
111 .arg (lineOld->line().x1())
112 .arg (lineOld->line().y1())
113 .arg (lineOld->line().x2())
114 .arg (lineOld->line().y2())
115 .arg (lineNew->line().x1())
116 .arg (lineNew->line().y1())
117 .arg (lineNew->line().x2())
118 .arg (lineNew->line().y2());
120 strDump <<
"unset label\n";
121 strDump <<
"set label \"" << label <<
"\" at graph 0, graph 0.02\n";
122 strDump <<
"set grid xtics\n";
123 strDump <<
"set grid ytics\n";
126 int rows = 0, cols = 0;
127 QList<SegmentLine*>::const_iterator itr;
128 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
131 ENGAUGE_CHECK_PTR (line);
133 int x1 = qFloor (line->line().x1());
134 int y1 = qFloor (line->line().y1());
135 int x2 = qFloor (line->line().x2());
136 int y2 = qFloor (line->line().y2());
138 rows = qMax (rows, y1 + 1);
139 rows = qMax (rows, y2 + 1);
140 cols = qMax (cols, x1 + 1);
141 cols = qMax (cols, x2 + 1);
146 int halfWidthX = qFloor (1.5 * qMax (qAbs (lineOld->line().dx()),
147 qAbs (lineNew->line().dx())));
148 int halfWidthY = qFloor (1.5 * qMax (qAbs (lineOld->line().dy()),
149 qAbs (lineNew->line().dy())));
152 strDump <<
"set xrange [" << (xInt - halfWidthX - 1) <<
":" << (xInt + halfWidthX + 1) <<
"]\n";
153 strDump <<
"set yrange [" << (yInt - halfWidthY - 1) <<
":" << (yInt + halfWidthY + 1) <<
"]\n";
158 strDump <<
"plot \\\n"
159 <<
"\"-\" title \"\" with lines, \\\n"
160 <<
"\"-\" title \"\" with lines, \\\n"
161 <<
"\"-\" title \"Replacement\" with lines, \\\n"
162 <<
"\"-\" title \"Segment pixels Even\" with linespoints, \\\n"
163 <<
"\"-\" title \"Segment pixels Odd\" with linespoints\n"
164 << xInt <<
" " << (yInt - halfWidthY) <<
"\n"
165 << xInt <<
" " << (yInt + halfWidthY) <<
"\n"
167 << (xInt - halfWidthX) <<
" " << yInt <<
"\n"
168 << (xInt + halfWidthY) <<
" " << yInt <<
"\n"
170 << lineOld->line().x1() <<
" " << lineOld->line().y1() <<
"\n"
171 << lineNew->line().x2() <<
" " << lineNew->line().y2() <<
"\n"
176 QTextStream strEven (&even), strOdd (&odd);
177 for (
int index = 0; index < m_lines.count(); index++) {
180 int x1 = qFloor (line->line().x1());
181 int y1 = qFloor (line->line().y1());
182 int x2 = qFloor (line->line().x2());
183 int y2 = qFloor (line->line().y2());
185 if (index % 2 == 0) {
186 strEven << x1 <<
" " << y1 <<
"\n";
187 strEven << x2 <<
" " << y2 <<
"\n";
190 strOdd << x1 <<
" " << y1 <<
"\n";
191 strOdd << x2 <<
" " << y2 <<
"\n";
196 strDump << even <<
"\n";
198 strDump << odd <<
"\n";
200 strDump <<
"pause -1 \"Hit Enter to continue\"\n";
207 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::fillPoints";
210 return fillPointsFillingCorners(modelSegments);
212 return fillPointsWithoutFillingCorners(modelSegments);
220 if (m_lines.count() > 0) {
222 double xLast = m_lines.first()->line().x1();
223 double yLast = m_lines.first()->line().y1();
226 double distanceCompleted = 0.0;
230 double xPrev = m_lines.first()->line().x1();
231 double yPrev = m_lines.first()->line().y1();
233 QList<SegmentLine*>::iterator itr;
234 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
238 ENGAUGE_CHECK_PTR(line);
239 xNext = double (line->line().x2());
240 yNext = double (line->line().y2());
242 double xStart = double (line->line().x1());
243 double yStart = double (line->line().y1());
244 if (isCorner (yPrev, yStart, yNext)) {
247 createAcceptablePoint(&firstPoint, &list, &xPrev, &yPrev, xStart, yStart);
248 distanceCompleted = 0.0;
252 double segmentLength = sqrt((xNext - xLast) * (xNext - xLast) + (yNext - yLast) * (yNext - yLast));
253 if (segmentLength > 0.0) {
257 while (distanceCompleted <= segmentLength) {
259 double s = distanceCompleted / segmentLength;
262 x = (1.0 - s) * xLast + s * xNext;
263 y = (1.0 - s) * yLast + s * yNext;
265 createAcceptablePoint(&firstPoint, &list, &xPrev, &yPrev, x, y);
270 distanceCompleted -= segmentLength;
283 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::firstPoint"
284 <<
" lineCount=" << m_lines.count();
287 ENGAUGE_ASSERT (m_lines.count () > 0);
290 QPointF pos = line->line().p1();
292 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::firstPoint"
293 <<
" pos=" << QPointFToString (pos).toLatin1().data();
300 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::forwardMousePress"
301 <<
" segmentLines=" << m_lines.count();
306 bool Segment::isCorner (
double yLast,
311 double deltaYBefore = yPrev - yLast;
312 double deltaYAfter = yNext - yPrev;
313 bool upThenAcrossOrDown = (deltaYBefore > 0) && (deltaYAfter <= 0);
314 bool downThenAcrossOrUp = (deltaYBefore < 0) && (deltaYAfter >= 0);
316 return upThenAcrossOrDown || downThenAcrossOrUp;
323 if (m_lines.count() > 0) {
325 double xLast = m_lines.first()->line().x1();
326 double yLast = m_lines.first()->line().y1();
329 double distanceCompleted = 0.0;
332 bool firstPoint =
true;
333 double xPrev = m_lines.first()->line().x1();
334 double yPrev = m_lines.first()->line().y1();
336 QList<SegmentLine*>::iterator itr;
337 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
341 ENGAUGE_CHECK_PTR(line);
342 xNext = double (line->line().x2());
343 yNext = double (line->line().y2());
346 double segmentLength = sqrt((xNext - xLast) * (xNext - xLast) + (yNext - yLast) * (yNext - yLast));
347 if (segmentLength > 0.0) {
351 while (distanceCompleted <= segmentLength) {
353 double s = distanceCompleted / segmentLength;
356 x = (1.0 - s) * xLast + s * xNext;
357 y = (1.0 - s) * yLast + s * yNext;
359 createAcceptablePoint(&firstPoint, &list, &xPrev, &yPrev, x, y);
364 distanceCompleted -= segmentLength;
382 return m_lines.count();
385 bool Segment::pointIsCloseToLine(
double xLeft,
392 double xProj, yProj, projectedDistanceOutsideLine, distanceToLine;
393 projectPointOntoLine(xInt, yInt, xLeft, yLeft, xRight, yRight, &xProj, &yProj, &projectedDistanceOutsideLine, &distanceToLine);
396 (xInt - xProj) * (xInt - xProj) +
397 (yInt - yProj) * (yInt - yProj) < 0.5 * 0.5);
400 bool Segment::pointsAreCloseToLine(
double xLeft,
402 QList<QPoint> removedPoints,
406 QList<QPoint>::iterator itr;
407 for (itr = removedPoints.begin(); itr != removedPoints.end(); ++itr) {
408 if (!pointIsCloseToLine(xLeft,
423 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::removeUnneededLines";
425 QFile *fileDump =
nullptr;
426 QTextStream *strDump =
nullptr;
429 QString filename (
"segment.gnuplot");
431 std::cout << GNUPLOT_FILE_MESSAGE.toLatin1().data() << filename.toLatin1().data() <<
"\n";
433 fileDump =
new QFile (filename);
434 fileDump->open (QIODevice::WriteOnly | QIODevice::Text);
435 strDump =
new QTextStream (fileDump);
444 QList<SegmentLine*>::iterator itr, itrPrevious;
445 QList<QPoint> removedPoints;
446 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
449 ENGAUGE_CHECK_PTR(line);
451 if (linePrevious !=
nullptr) {
453 double xLeft = linePrevious->line().x1();
454 double yLeft = linePrevious->line().y1();
455 double xInt = linePrevious->line().x2();
456 double yInt = linePrevious->line().y2();
460 if (linePrevious->line().p2() == line->line().p1()) {
462 double xRight = line->line().x2();
463 double yRight = line->line().y2();
465 if (pointIsCloseToLine(xLeft, yLeft, xInt, yInt, xRight, yRight) &&
466 pointsAreCloseToLine(xLeft, yLeft, removedPoints, xRight, yRight)) {
471 dumpToGnuplot (*strDump,
481 LOG4CPP_DEBUG_S ((*mainCat)) <<
"Segment::removeUnneededLines"
482 <<
" segment=0x" << std::hex << static_cast<void*> (
this) << std::dec
484 << linePrevious->line().x1() <<
"," << linePrevious->line().y1() <<
") to ("
485 << linePrevious->line().x2() <<
"," << linePrevious->line().y2() <<
") "
486 <<
" and modifying ("
487 << line->line().x1() <<
"," << line->line().y1() <<
") to ("
488 << line->line().x2() <<
"," << line->line().y2() <<
") into ("
489 << xLeft <<
"," << yLeft <<
") to ("
490 << xRight <<
"," << yRight <<
")";
492 removedPoints.append(QPoint(qFloor (xInt),
494 m_lines.erase (itrPrevious);
498 line->setLine (xLeft, yLeft, xRight, yRight);
503 removedPoints.clear();
512 if (itr == m_lines.end()) {
517 if (strDump !=
nullptr) {
520 *strDump <<
"set terminal x11 persist\n";
530 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::slotHover";
532 QList<SegmentLine*>::iterator itr, itrPrevious;
533 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
542 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::updateModelSegment";
544 QList<SegmentLine*>::iterator itr;
545 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.
Priority::Value getPriority() const
Returns unused priority.
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.