7 #include "DocumentModelSegments.h"
8 #include "EngaugeAssert.h"
14 #include <QGraphicsScene>
16 #include <QTextStream>
17 #include "QtToString.h"
19 #include "SegmentLine.h"
27 m_isGnuplot (isGnuplot)
29 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::Segment"
30 <<
" address=0x" << hex << (quintptr)
this;
35 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::~Segment"
36 <<
" address=0x" << hex << (quintptr)
this;
38 QList<SegmentLine*>::iterator itr;
39 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
42 m_scene.removeItem (segmentLine);
55 LOG4CPP_DEBUG_S ((*mainCat)) <<
"Segment::appendColumn"
56 <<
" segment=0x" << std::hex << (quintptr)
this << std::dec
58 << xOld <<
"," << yOld <<
") to ("
59 << xNew <<
"," << yNew <<
")";
64 ENGAUGE_CHECK_PTR(line);
65 line->setLine(QLineF (xOld,
75 m_length += qSqrt((1.0) * (1.0) + (y - m_yLast) * (y - m_yLast));
80 void Segment::createAcceptablePoint(
bool *pFirst,
87 int iOld = (int) (*xPrev + 0.5);
88 int jOld = (int) (*yPrev + 0.5);
89 int i = (int) (x + 0.5);
90 int j = (int) (y + 0.5);
92 if (*pFirst || (iOld != i) || (jOld != j)) {
96 ENGAUGE_CHECK_PTR(pList);
97 pList->append(QPoint(i, j));
103 void Segment::dumpToGnuplot (QTextStream &strDump,
110 if (mainCat->getPriority() == log4cpp::Priority::DEBUG) {
114 QString label = QString (
"Old: (%1,%2) to (%3,%4), New: (%5,%6) to (%7,%8)")
115 .arg (lineOld->line().x1())
116 .arg (lineOld->line().y1())
117 .arg (lineOld->line().x2())
118 .arg (lineOld->line().y2())
119 .arg (lineNew->line().x1())
120 .arg (lineNew->line().y1())
121 .arg (lineNew->line().x2())
122 .arg (lineNew->line().y2());
124 strDump <<
"unset label\n";
125 strDump <<
"set label \"" << label <<
"\" at graph 0, graph 0.02\n";
126 strDump <<
"set grid xtics\n";
127 strDump <<
"set grid ytics\n";
130 int rows = 0, cols = 0;
131 QList<SegmentLine*>::const_iterator itr;
132 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
135 ENGAUGE_CHECK_PTR (line);
137 int x1 = line->line().x1();
138 int y1 = line->line().y1();
139 int x2 = line->line().x2();
140 int y2 = line->line().y2();
142 rows = qMax (rows, y1 + 1);
143 rows = qMax (rows, y2 + 1);
144 cols = qMax (cols, x1 + 1);
145 cols = qMax (cols, x2 + 1);
150 int halfWidthX = 1.5 * qMax (qAbs (lineOld->line().dx()),
151 qAbs (lineNew->line().dx()));
152 int halfWidthY = 1.5 * qMax (qAbs (lineOld->line().dy()),
153 qAbs (lineNew->line().dy()));
156 strDump <<
"set xrange [" << (xInt - halfWidthX - 1) <<
":" << (xInt + halfWidthX + 1) <<
"]\n";
157 strDump <<
"set yrange [" << (yInt - halfWidthY - 1) <<
":" << (yInt + halfWidthY + 1) <<
"]\n";
162 strDump <<
"plot \\\n"
163 <<
"\"-\" title \"\" with lines, \\\n"
164 <<
"\"-\" title \"\" with lines, \\\n"
165 <<
"\"-\" title \"Replacement\" with lines, \\\n"
166 <<
"\"-\" title \"Segment pixels Even\" with linespoints, \\\n"
167 <<
"\"-\" title \"Segment pixels Odd\" with linespoints\n"
168 << xInt <<
" " << (yInt - halfWidthY) <<
"\n"
169 << xInt <<
" " << (yInt + halfWidthY) <<
"\n"
171 << (xInt - halfWidthX) <<
" " << yInt <<
"\n"
172 << (xInt + halfWidthY) <<
" " << yInt <<
"\n"
174 << lineOld->line().x1() <<
" " << lineOld->line().y1() <<
"\n"
175 << lineNew->line().x2() <<
" " << lineNew->line().y2() <<
"\n"
180 QTextStream strEven (&even), strOdd (&odd);
181 for (
int index = 0; index < m_lines.count(); index++) {
184 int x1 = line->line().x1();
185 int y1 = line->line().y1();
186 int x2 = line->line().x2();
187 int y2 = line->line().y2();
189 if (index % 2 == 0) {
190 strEven << x1 <<
" " << y1 <<
"\n";
191 strEven << x2 <<
" " << y2 <<
"\n";
194 strOdd << x1 <<
" " << y1 <<
"\n";
195 strOdd << x2 <<
" " << y2 <<
"\n";
200 strDump << even <<
"\n";
202 strDump << odd <<
"\n";
204 strDump <<
"pause -1 \"Hit Enter to continue\"\n";
211 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::fillPoints";
214 return fillPointsFillingCorners(modelSegments);
216 return fillPointsWithoutFillingCorners(modelSegments);
224 if (m_lines.count() > 0) {
226 double xLast = m_lines.first()->line().x1();
227 double yLast = m_lines.first()->line().y1();
230 double distanceCompleted = 0.0;
234 double xPrev = m_lines.first()->line().x1();
235 double yPrev = m_lines.first()->line().y1();
237 QList<SegmentLine*>::iterator itr;
238 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
242 ENGAUGE_CHECK_PTR(line);
243 xNext = (double) line->line().x2();
244 yNext = (double) line->line().y2();
246 double xStart = (double) line->line().x1();
247 double yStart = (double) line->line().y1();
248 if (isCorner (yPrev, yStart, yNext)) {
251 createAcceptablePoint(&firstPoint, &list, &xPrev, &yPrev, xStart, yStart);
252 distanceCompleted = 0.0;
256 double segmentLength = sqrt((xNext - xLast) * (xNext - xLast) + (yNext - yLast) * (yNext - yLast));
257 if (segmentLength > 0.0) {
261 while (distanceCompleted <= segmentLength) {
263 double s = distanceCompleted / segmentLength;
266 x = (1.0 - s) * xLast + s * xNext;
267 y = (1.0 - s) * yLast + s * yNext;
269 createAcceptablePoint(&firstPoint, &list, &xPrev, &yPrev, x, y);
274 distanceCompleted -= segmentLength;
287 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::firstPoint"
288 <<
" lineCount=" << m_lines.count();
291 ENGAUGE_ASSERT (m_lines.count () > 0);
294 QPointF pos = line->line().p1();
296 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::firstPoint"
297 <<
" pos=" << QPointFToString (pos).toLatin1().data();
304 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::forwardMousePress"
305 <<
" segmentLines=" << m_lines.count();
310 bool Segment::isCorner (
double yLast,
315 double deltaYBefore = yPrev - yLast;
316 double deltaYAfter = yNext - yPrev;
317 bool upThenAcrossOrDown = (deltaYBefore > 0) && (deltaYAfter <= 0);
318 bool downThenAcrossOrUp = (deltaYBefore < 0) && (deltaYAfter >= 0);
320 return upThenAcrossOrDown || downThenAcrossOrUp;
327 if (m_lines.count() > 0) {
329 double xLast = m_lines.first()->line().x1();
330 double yLast = m_lines.first()->line().y1();
333 double distanceCompleted = 0.0;
336 bool firstPoint =
true;
337 double xPrev = m_lines.first()->line().x1();
338 double yPrev = m_lines.first()->line().y1();
340 QList<SegmentLine*>::iterator itr;
341 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
345 ENGAUGE_CHECK_PTR(line);
346 xNext = (double) line->line().x2();
347 yNext = (double) line->line().y2();
350 double segmentLength = sqrt((xNext - xLast) * (xNext - xLast) + (yNext - yLast) * (yNext - yLast));
351 if (segmentLength > 0.0) {
355 while (distanceCompleted <= segmentLength) {
357 double s = distanceCompleted / segmentLength;
360 x = (1.0 - s) * xLast + s * xNext;
361 y = (1.0 - s) * yLast + s * yNext;
363 createAcceptablePoint(&firstPoint, &list, &xPrev, &yPrev, x, y);
368 distanceCompleted -= segmentLength;
386 return m_lines.count();
389 bool Segment::pointIsCloseToLine(
double xLeft,
396 double xProj, yProj, projectedDistanceOutsideLine, distanceToLine;
397 projectPointOntoLine(xInt, yInt, xLeft, yLeft, xRight, yRight, &xProj, &yProj, &projectedDistanceOutsideLine, &distanceToLine);
400 (xInt - xProj) * (xInt - xProj) +
401 (yInt - yProj) * (yInt - yProj) < 0.5 * 0.5);
404 bool Segment::pointsAreCloseToLine(
double xLeft,
406 QList<QPoint> removedPoints,
410 QList<QPoint>::iterator itr;
411 for (itr = removedPoints.begin(); itr != removedPoints.end(); ++itr) {
412 if (!pointIsCloseToLine(xLeft, yLeft, (
double) (*itr).x(), (double) (*itr).y(), xRight, yRight)) {
422 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::removeUnneededLines";
425 QTextStream *strDump = 0;
428 QString filename (
"segment.gnuplot");
430 std::cout <<
"Writing gnuplot file: " << filename.toLatin1().data() <<
"\n";
432 fileDump =
new QFile (filename);
433 fileDump->open (QIODevice::WriteOnly | QIODevice::Text);
434 strDump =
new QTextStream (fileDump);
443 QList<SegmentLine*>::iterator itr, itrPrevious;
444 QList<QPoint> removedPoints;
445 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
448 ENGAUGE_CHECK_PTR(line);
450 if (linePrevious != 0) {
452 double xLeft = linePrevious->line().x1();
453 double yLeft = linePrevious->line().y1();
454 double xInt = linePrevious->line().x2();
455 double yInt = linePrevious->line().y2();
459 if (linePrevious->line().p2() == line->line().p1()) {
461 double xRight = line->line().x2();
462 double yRight = line->line().y2();
464 if (pointIsCloseToLine(xLeft, yLeft, xInt, yInt, xRight, yRight) &&
465 pointsAreCloseToLine(xLeft, yLeft, removedPoints, xRight, yRight)) {
470 dumpToGnuplot (*strDump,
480 LOG4CPP_DEBUG_S ((*mainCat)) <<
"Segment::removeUnneededLines"
481 <<
" segment=0x" << std::hex << (quintptr)
this << std::dec
483 << linePrevious->line().x1() <<
"," << linePrevious->line().y1() <<
") to ("
484 << linePrevious->line().x2() <<
"," << linePrevious->line().y2() <<
") "
485 <<
" and modifying ("
486 << line->line().x1() <<
"," << line->line().y1() <<
") to ("
487 << line->line().x2() <<
"," << line->line().y2() <<
") into ("
488 << xLeft <<
"," << yLeft <<
") to ("
489 << xRight <<
"," << yRight <<
")";
491 removedPoints.append(QPoint((
int) xInt, (
int) yInt));
492 m_lines.erase (itrPrevious);
496 line->setLine (xLeft, yLeft, xRight, yRight);
501 removedPoints.clear();
510 if (itr == m_lines.end()) {
518 *strDump <<
"set terminal x11 persist\n";
528 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::slotHover";
530 QList<SegmentLine*>::iterator itr, itrPrevious;
531 for (itr = m_lines.begin(); itr != m_lines.end(); itr++) {
540 LOG4CPP_INFO_S ((*mainCat)) <<
"Segment::updateModelSegment";
542 QList<SegmentLine*>::iterator itr;
543 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.