Engauge Digitizer  2
Point.cpp
1 #include "DocumentSerialize.h"
2 #include "EngaugeAssert.h"
3 #include "Logger.h"
4 #include "Point.h"
5 #include <QStringList>
6 #include <QTextStream>
7 #include "QtToString.h"
8 #include <QXmlStreamReader>
9 #include <QXmlStreamWriter>
10 #include "Xml.h"
11 
12 unsigned int Point::m_identifierIndex = 0;
13 
14 extern const QString AXIS_CURVE_NAME;
15 const QString POINT_IDENTIFIER_DELIMITER ("_");
16 
17 const double MISSING_ORDINAL_VALUE = 0;
18 const double MISSING_POSGRAPH_VALUE = 0;
19 
21 {
22 }
23 
24 Point::Point(const QString &curveName,
25  const QPointF &posScreen) :
26  m_isAxisPoint (curveName == AXIS_CURVE_NAME),
27  m_identifier (uniqueIdentifierGenerator(curveName)),
28  m_posScreen (posScreen),
29  m_hasPosGraph (false),
30  m_posGraph (MISSING_POSGRAPH_VALUE, MISSING_POSGRAPH_VALUE),
31  m_hasOrdinal (false),
32  m_ordinal (MISSING_ORDINAL_VALUE)
33 {
34  LOG4CPP_INFO_S ((*mainCat)) << "Point::Point"
35  << " curveName=" << curveName.toLatin1().data()
36  << " identifierGenerated=" << m_identifier.toLatin1().data()
37  << " posScreen=" << QPointFToString (posScreen).toLatin1().data();
38 
39  ENGAUGE_ASSERT (!curveName.isEmpty ());
40 }
41 
42 Point::Point(const QString &curveName,
43  const QPointF &posScreen,
44  const QPointF &posGraph) :
45  m_isAxisPoint (true),
46  m_identifier (uniqueIdentifierGenerator(curveName)),
47  m_posScreen (posScreen),
48  m_hasPosGraph (true),
49  m_posGraph (posGraph),
50  m_hasOrdinal (false),
51  m_ordinal (MISSING_ORDINAL_VALUE)
52 {
53  ENGAUGE_ASSERT (curveName == AXIS_CURVE_NAME);
54 
55  LOG4CPP_INFO_S ((*mainCat)) << "Point::Point"
56  << " curveName=" << curveName.toLatin1().data()
57  << " identifierGenerated=" << m_identifier.toLatin1().data()
58  << " posScreen=" << QPointFToString (posScreen).toLatin1().data()
59  << " posGraph=" << QPointFToString (posGraph).toLatin1().data();
60 
61  ENGAUGE_ASSERT (!curveName.isEmpty ());
62 }
63 
64 Point::Point(const QString &curveName,
65  const QString &identifier,
66  const QPointF &posScreen,
67  const QPointF &posGraph,
68  double ordinal) :
69  m_isAxisPoint (true),
70  m_identifier (identifier),
71  m_posScreen (posScreen),
72  m_hasPosGraph (true),
73  m_posGraph (posGraph),
74  m_hasOrdinal (true),
75  m_ordinal (ordinal)
76 {
77  ENGAUGE_ASSERT (curveName == AXIS_CURVE_NAME);
78 
79  LOG4CPP_INFO_S ((*mainCat)) << "Point::Point"
80  << " curveName=" << curveName.toLatin1().data()
81  << " identifier=" << m_identifier.toLatin1().data()
82  << " posScreen=" << QPointFToString (posScreen).toLatin1().data()
83  << " posGraph=" << QPointFToString (posGraph).toLatin1().data()
84  << " ordinal=" << ordinal;
85 
86  ENGAUGE_ASSERT (!curveName.isEmpty ());
87 }
88 
89 Point::Point(const QString &curveName,
90  const QPointF &posScreen,
91  const QPointF &posGraph,
92  double ordinal) :
93  m_isAxisPoint (true),
94  m_identifier (uniqueIdentifierGenerator(curveName)),
95  m_posScreen (posScreen),
96  m_hasPosGraph (true),
97  m_posGraph (posGraph),
98  m_hasOrdinal (true),
99  m_ordinal (ordinal)
100 {
101  ENGAUGE_ASSERT (curveName == AXIS_CURVE_NAME);
102 
103  LOG4CPP_INFO_S ((*mainCat)) << "Point::Point"
104  << " curveName=" << curveName.toLatin1().data()
105  << " identifierGenerated=" << m_identifier.toLatin1().data()
106  << " posScreen=" << QPointFToString (posScreen).toLatin1().data()
107  << " posGraph=" << QPointFToString (posGraph).toLatin1().data()
108  << " ordinal=" << ordinal;
109 
110  ENGAUGE_ASSERT (!curveName.isEmpty ());
111 }
112 
113 Point::Point(const QString &curveName,
114  const QString &identifier,
115  const QPointF &posScreen,
116  double ordinal) :
117  m_isAxisPoint (false),
118  m_identifier (identifier),
119  m_posScreen (posScreen),
120  m_hasPosGraph (false),
121  m_posGraph (MISSING_POSGRAPH_VALUE, MISSING_POSGRAPH_VALUE),
122  m_hasOrdinal (true),
123  m_ordinal (ordinal)
124 {
125  ENGAUGE_ASSERT (curveName != AXIS_CURVE_NAME);
126 
127  LOG4CPP_INFO_S ((*mainCat)) << "Point::Point"
128  << " curveName=" << curveName.toLatin1().data()
129  << " identifier=" << identifier.toLatin1().data()
130  << " posScreen=" << QPointFToString (posScreen).toLatin1().data()
131  << " ordinal=" << ordinal;
132 
133  ENGAUGE_ASSERT (!curveName.isEmpty ());
134 }
135 
136 Point::Point (const QString &curveName,
137  const QPointF &posScreen,
138  double ordinal) :
139  m_isAxisPoint (false),
140  m_identifier (uniqueIdentifierGenerator(curveName)),
141  m_posScreen (posScreen),
142  m_hasPosGraph (false),
143  m_posGraph (MISSING_POSGRAPH_VALUE, MISSING_POSGRAPH_VALUE),
144  m_hasOrdinal (true),
145  m_ordinal (ordinal)
146 {
147  ENGAUGE_ASSERT (curveName != AXIS_CURVE_NAME);
148 
149  LOG4CPP_INFO_S ((*mainCat)) << "Point::Point(identifier,posScreen,posGraph,ordinal)"
150  << " identifierGenerated=" << m_identifier.toLatin1().data()
151  << " posScreen=" << QPointFToString (posScreen).toLatin1().data()
152  << " ordinal=" << ordinal;
153 }
154 
155 Point::Point (QXmlStreamReader &reader)
156 {
157  loadXml(reader);
158 }
159 
161 {
162  LOG4CPP_INFO_S ((*mainCat)) << "Point::operator="
163  << " isAxisPoint=" << (point.isAxisPoint() ? "true" : "false")
164  << " identifier=" << point.identifier ().toLatin1().data()
165  << " posScreen=" << QPointFToString (point.posScreen ()).toLatin1().data()
166  << " hasPosGraph=" << (point.hasPosGraph() ? "true" : "false")
167  << " posGraph=" << QPointFToString (point.posGraph (SKIP_HAS_CHECK)).toLatin1().data()
168  << " hasOrdinal=" << (point.hasOrdinal() ? "true" : "false")
169  << " ordinal=" << point.ordinal (SKIP_HAS_CHECK);
170 
171  m_isAxisPoint = point.isAxisPoint ();
172  m_identifier = point.identifier ();
173  m_posScreen = point.posScreen ();
174  m_hasPosGraph = point.hasPosGraph ();
175  m_posGraph = point.posGraph (SKIP_HAS_CHECK);
176  m_hasOrdinal = point.hasOrdinal ();
177  m_ordinal = point.ordinal (SKIP_HAS_CHECK);
178 
179  return *this;
180 }
181 
182 Point::Point (const Point &other)
183 {
184  LOG4CPP_INFO_S ((*mainCat)) << "Point::Point(const Point &other)"
185  << " isAxisPoint=" << (other.isAxisPoint() ? "true" : "false")
186  << " identifier=" << other.identifier ().toLatin1().data()
187  << " posScreen=" << QPointFToString (other.posScreen ()).toLatin1().data()
188  << " hasPosGraph=" << (other.hasPosGraph() ? "true" : "false")
189  << " posGraph=" << QPointFToString (other.posGraph (SKIP_HAS_CHECK)).toLatin1().data()
190  << " hasOrdinal=" << (other.hasOrdinal() ? "true" : "false")
191  << " ordinal=" << other.ordinal (SKIP_HAS_CHECK);
192 
193  m_isAxisPoint = other.isAxisPoint ();
194  m_identifier = other.identifier ();
195  m_posScreen = other.posScreen ();
196  m_hasPosGraph = other.hasPosGraph ();
197  m_posGraph = other.posGraph (SKIP_HAS_CHECK);
198  m_hasOrdinal = other.hasOrdinal ();
199  m_ordinal = other.ordinal (SKIP_HAS_CHECK);
200 }
201 
202 QString Point::curveNameFromPointIdentifier (const QString &pointIdentifier)
203 {
204  QStringList tokens = pointIdentifier.split (POINT_IDENTIFIER_DELIMITER);
205  return tokens.value (0);
206 }
207 
208 bool Point::hasOrdinal () const
209 {
210  return m_hasOrdinal;
211 }
212 
213 bool Point::hasPosGraph () const
214 {
215  return m_hasPosGraph;
216 }
217 
218 QString Point::identifier() const
219 {
220  return m_identifier;
221 }
222 
223 unsigned int Point::identifierIndex ()
224 {
225  LOG4CPP_INFO_S ((*mainCat)) << "Point::identifierIndex"
226  << " identifierIndex=" << m_identifierIndex;
227 
228  return m_identifierIndex;
229 }
230 
231 bool Point::isAxisPoint() const
232 {
233  return m_isAxisPoint;
234 }
235 
236 void Point::loadXml(QXmlStreamReader &reader)
237 {
238  LOG4CPP_INFO_S ((*mainCat)) << "Point::loadXml";
239 
240  bool success = true;
241 
242  QXmlStreamAttributes attributes = reader.attributes();
243 
244  if (attributes.hasAttribute(DOCUMENT_SERIALIZE_POINT_IDENTIFIER) &&
245  attributes.hasAttribute(DOCUMENT_SERIALIZE_POINT_IDENTIFIER_INDEX) &&
246  attributes.hasAttribute(DOCUMENT_SERIALIZE_POINT_IS_AXIS_POINT)) {
247 
248  m_hasOrdinal = attributes.hasAttribute(DOCUMENT_SERIALIZE_POINT_ORDINAL);
249  if (m_hasOrdinal) {
250  m_ordinal = attributes.value(DOCUMENT_SERIALIZE_POINT_ORDINAL).toDouble();
251  } else {
252  m_ordinal = MISSING_ORDINAL_VALUE;
253  }
254 
255  QString isAxisPoint = attributes.value(DOCUMENT_SERIALIZE_POINT_IS_AXIS_POINT).toString();
256 
257  m_identifier = attributes.value(DOCUMENT_SERIALIZE_POINT_IDENTIFIER).toString();
258  m_identifierIndex = attributes.value(DOCUMENT_SERIALIZE_POINT_IDENTIFIER_INDEX).toInt();
259  m_isAxisPoint = (isAxisPoint == DOCUMENT_SERIALIZE_BOOL_TRUE);
260  m_hasPosGraph = false;
261  m_posGraph.setX (MISSING_POSGRAPH_VALUE);
262  m_posGraph.setY (MISSING_POSGRAPH_VALUE);
263 
264  while ((reader.tokenType() != QXmlStreamReader::EndElement) ||
265  (reader.name () != DOCUMENT_SERIALIZE_POINT)) {
266 
267  loadNextFromReader(reader);
268  if (reader.atEnd()) {
269  success = false;
270  break;
271  }
272 
273  if (reader.tokenType () == QXmlStreamReader::StartElement) {
274 
275  if (reader.name() == DOCUMENT_SERIALIZE_POINT_POSITION_SCREEN) {
276 
277  attributes = reader.attributes();
278 
279  if (attributes.hasAttribute(DOCUMENT_SERIALIZE_POINT_X) &&
280  attributes.hasAttribute(DOCUMENT_SERIALIZE_POINT_Y)) {
281 
282  m_posScreen.setX (attributes.value(DOCUMENT_SERIALIZE_POINT_X).toDouble());
283  m_posScreen.setY (attributes.value(DOCUMENT_SERIALIZE_POINT_Y).toDouble());
284 
285  } else {
286  success = false;
287  break;
288  }
289  } else if (reader.name() == DOCUMENT_SERIALIZE_POINT_POSITION_GRAPH) {
290 
291  m_hasPosGraph = true;
292  attributes = reader.attributes();
293 
294  if (attributes.hasAttribute(DOCUMENT_SERIALIZE_POINT_X) &&
295  attributes.hasAttribute(DOCUMENT_SERIALIZE_POINT_Y)) {
296 
297  m_posGraph.setX (attributes.value(DOCUMENT_SERIALIZE_POINT_X).toDouble());
298  m_posGraph.setY (attributes.value(DOCUMENT_SERIALIZE_POINT_Y).toDouble());
299 
300  } else {
301  success = false;
302  break;
303  }
304  }
305  }
306  }
307 
308  LOG4CPP_INFO_S ((*mainCat)) << "Point::loadXml"
309  << " identifier=" << m_identifier.toLatin1().data()
310  << " identifierIndex=" << m_identifierIndex
311  << " posScreen=" << QPointFToString (m_posScreen).toLatin1().data()
312  << " posGraph=" << QPointFToString (m_posGraph).toLatin1().data()
313  << " ordinal=" << m_ordinal;
314 
315  } else {
316  success = false;
317  }
318 
319  if (!success) {
320  reader.raiseError("Cannot read point data");
321  }
322 }
323 
324 double Point::ordinal (ApplyHasCheck applyHasCheck) const
325 {
326  if (applyHasCheck == KEEP_HAS_CHECK) {
327  ENGAUGE_ASSERT (m_hasOrdinal);
328  }
329 
330  return m_ordinal;
331 }
332 
333 QPointF Point::posGraph (ApplyHasCheck applyHasCheck) const
334 {
335  if (applyHasCheck == KEEP_HAS_CHECK) {
336  ENGAUGE_ASSERT (m_hasPosGraph);
337  }
338 
339  return m_posGraph;
340 }
341 
342 QPointF Point::posScreen () const
343 {
344  return m_posScreen;
345 }
346 
347 void Point::printStream(QString indentation,
348  QTextStream &str) const
349 {
350  const QString UNDEFINED ("undefined");
351 
352  str << indentation << "Point\n";
353 
354  indentation += INDENTATION_DELTA;
355 
356  str << indentation << "identifier=" << m_identifier << "\n";
357  str << indentation << "posScreen=" << QPointFToString (m_posScreen) << "\n";
358  if (m_hasPosGraph) {
359  str << indentation << "posGraph=" << QPointFToString (m_posGraph) << "\n";
360  } else {
361  str << indentation << "posGraph=" << UNDEFINED << "\n";
362  }
363  if (m_hasOrdinal) {
364  str << indentation << "ordinal=" << m_ordinal << "\n";
365  } else {
366  str << indentation << "ordinal=" << UNDEFINED << "\n";
367  }
368 }
369 
370 void Point::saveXml(QXmlStreamWriter &writer) const
371 {
372  LOG4CPP_INFO_S ((*mainCat)) << "Point::saveXml";
373 
374  writer.writeStartElement(DOCUMENT_SERIALIZE_POINT);
375  writer.writeAttribute(DOCUMENT_SERIALIZE_POINT_IDENTIFIER, m_identifier);
376  if (m_hasOrdinal) {
377  writer.writeAttribute(DOCUMENT_SERIALIZE_POINT_ORDINAL, QString::number (m_ordinal));
378  }
379  writer.writeAttribute(DOCUMENT_SERIALIZE_POINT_IS_AXIS_POINT,
380  m_isAxisPoint ? DOCUMENT_SERIALIZE_BOOL_TRUE : DOCUMENT_SERIALIZE_BOOL_FALSE);
381 
382  // Variable m_identifierIndex is static, but for simplicity this is handled like other values. Those values are all
383  // the same, but simplicity wins over a few extra bytes of storage
384  writer.writeAttribute(DOCUMENT_SERIALIZE_POINT_IDENTIFIER_INDEX, QString::number (m_identifierIndex));
385 
386  writer.writeStartElement(DOCUMENT_SERIALIZE_POINT_POSITION_SCREEN);
387  writer.writeAttribute(DOCUMENT_SERIALIZE_POINT_X, QString::number (m_posScreen.x()));
388  writer.writeAttribute(DOCUMENT_SERIALIZE_POINT_Y, QString::number (m_posScreen.y()));
389  writer.writeEndElement();
390 
391  if (m_hasPosGraph) {
392  writer.writeStartElement(DOCUMENT_SERIALIZE_POINT_POSITION_GRAPH);
393  writer.writeAttribute(DOCUMENT_SERIALIZE_POINT_X, QString::number (m_posGraph.x()));
394  writer.writeAttribute(DOCUMENT_SERIALIZE_POINT_Y, QString::number (m_posGraph.y()));
395  writer.writeEndElement();
396  }
397 
398  writer.writeEndElement();
399 }
400 
401 void Point::setIdentifierIndex (unsigned int identifierIndex)
402 {
403  LOG4CPP_INFO_S ((*mainCat)) << "Point::setIdentifierIndex"
404  << " identifierIndex=" << identifierIndex;
405 
406  m_identifierIndex = identifierIndex;
407 }
408 
409 void Point::setOrdinal(double ordinal)
410 {
411  LOG4CPP_DEBUG_S ((*mainCat)) << "Point::setOrdinal"
412  << " identifier=" << m_identifier.toLatin1().data()
413  << " ordinal=" << ordinal;
414 
415  m_hasOrdinal = true;
416  m_ordinal = ordinal;
417 }
418 
419 void Point::setPosGraph (const QPointF &posGraph)
420 {
421  LOG4CPP_DEBUG_S ((*mainCat)) << "Point::setPosGraph"
422  << " identifier=" << m_identifier.toLatin1().data()
423  << " posGraph=" << QPointFToString(posGraph).toLatin1().data();
424 
425  // Curve point graph coordinates should always be computed on the fly versus stored in this class, to reduce the
426  // chances for stale information
427  ENGAUGE_ASSERT (m_isAxisPoint);
428 
429  m_hasPosGraph = true;
430  m_posGraph = posGraph;
431 }
432 
433 void Point::setPosScreen (const QPointF &posScreen)
434 {
435  LOG4CPP_DEBUG_S ((*mainCat)) << "Point::setPosScreen"
436  << " identifier=" << m_identifier.toLatin1().data()
437  << " posScreen=" << QPointFToString(posScreen).toLatin1().data();
438 
439  m_posScreen = posScreen;
440 }
441 
443 {
444  return QString ("%1%2%3")
445  .arg (AXIS_CURVE_NAME)
446  .arg (POINT_IDENTIFIER_DELIMITER)
447  .arg (0);
448 }
449 
450 QString Point::uniqueIdentifierGenerator (const QString &curveName)
451 {
452  LOG4CPP_INFO_S ((*mainCat)) << "Point::uniqueIdentifierGenerator"
453  << " curveName=" << curveName.toLatin1().data()
454  << " identifierIndex=" << m_identifierIndex;
455 
456  return QString ("%1%2point%3%4")
457  .arg (curveName)
458  .arg (POINT_IDENTIFIER_DELIMITER)
459  .arg (POINT_IDENTIFIER_DELIMITER)
460  .arg (m_identifierIndex++);
461 }
QPointF posGraph(ApplyHasCheck applyHasCheck=KEEP_HAS_CHECK) const
Accessor for graph position. Skip check if copying one instance to another.
Definition: Point.cpp:333
static QString curveNameFromPointIdentifier(const QString &pointIdentifier)
Parse the curve name from the specified point identifier. This does the opposite of uniqueIdentifierG...
Definition: Point.cpp:202
bool isAxisPoint() const
True if point is an axis point. This is used only for sanity checks.
Definition: Point.cpp:231
static void setIdentifierIndex(unsigned int identifierIndex)
Reset the current index while performing a Redo.
Definition: Point.cpp:401
static unsigned int identifierIndex()
Return the current index for storage in case we need to reset it later while performing a Redo...
Definition: Point.cpp:223
void saveXml(QXmlStreamWriter &writer) const
Serialize to stream.
Definition: Point.cpp:370
Class that represents one digitized point. The screen-to-graph coordinate transformation is always ex...
Definition: Point.h:17
QPointF posScreen() const
Accessor for screen position.
Definition: Point.cpp:342
Point & operator=(const Point &point)
Assignment constructor.
Definition: Point.cpp:160
void setPosGraph(const QPointF &posGraph)
Set method for position in graph coordinates.
Definition: Point.cpp:419
static QString temporaryPointIdentifier()
Point identifier for temporary point that is used by DigitzeStateAxis.
Definition: Point.cpp:442
QString identifier() const
Unique identifier for a specific Point.
Definition: Point.cpp:218
bool hasPosGraph() const
True if graph position is defined.
Definition: Point.cpp:213
void printStream(QString indentation, QTextStream &str) const
Debugging method that supports print method of this class and printStream method of some other class(...
Definition: Point.cpp:347
void setPosScreen(const QPointF &posScreen)
Set method for position in screen coordinates.
Definition: Point.cpp:433
Point()
Default constructor so this class can be used inside a container.
Definition: Point.cpp:20
bool hasOrdinal() const
True if ordinal is defined.
Definition: Point.cpp:208
double ordinal(ApplyHasCheck applyHasCheck=KEEP_HAS_CHECK) const
Get method for ordinal. Skip check if copying one instance to another.
Definition: Point.cpp:324
void setOrdinal(double ordinal)
Set the ordinal used for ordering Points.
Definition: Point.cpp:409