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