Engauge Digitizer  2
CurvesGraphs.cpp
1 /******************************************************************************************************
2  * (C) 2014 markummitchell@github.com. This file is part of Engauge Digitizer, which is released *
3  * under GNU General Public License version 2 (GPLv2) or (at your option) any later version. See file *
4  * LICENSE or go to gnu.org/licenses for details. Distribution requires prior written permission. *
5  ******************************************************************************************************/
6 
7 #include "Curve.h"
8 #include "CurvesGraphs.h"
9 #include "CurveStyles.h"
10 #include "DocumentSerialize.h"
11 #include "EngaugeAssert.h"
12 #include "Logger.h"
13 #include "Point.h"
14 #include <qdebug.h>
15 #include <QTextStream>
16 #include <QXmlStreamWriter>
17 #include "Transformation.h"
18 #include "Xml.h"
19 
20 CurvesGraphs::CurvesGraphs()
21 {
22 }
23 
25 {
26  m_curvesGraphs.push_back (curve);
27 }
28 
29 void CurvesGraphs::addPoint (const Point &point)
30 {
31  QString curveName = Point::curveNameFromPointIdentifier (point.identifier());
32 
33  Curve *curve = curveForCurveName (curveName);
34  curve->addPoint (point);
35 }
36 
37 Curve *CurvesGraphs::curveForCurveName (const QString &curveName)
38 {
39  // Search for curve with matching name
40  CurveList::iterator itr;
41  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
42 
43  Curve &curve = *itr;
44  if (curveName == curve.curveName ()) {
45  return &curve;
46  }
47  }
48 
49  return 0;
50 }
51 
52 const Curve *CurvesGraphs::curveForCurveName (const QString &curveName) const
53 {
54  // Search for curve with matching name
55  CurveList::const_iterator itr;
56  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
57 
58  const Curve &curve = *itr;
59  if (curveName == curve.curveName ()) {
60  return &curve;
61  }
62  }
63 
64  return 0;
65 }
66 
67 QStringList CurvesGraphs::curvesGraphsNames () const
68 {
69  QStringList names;
70 
71  CurveList::const_iterator itr;
72  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
73 
74  const Curve &curve = *itr;
75  names << curve.curveName ();
76  }
77 
78  return names;
79 }
80 
81 int CurvesGraphs::curvesGraphsNumPoints (const QString &curveName) const
82 {
83  // Search for curve with matching name
84  CurveList::const_iterator itr;
85  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
86 
87  const Curve &curve = *itr;
88  if (curve.curveName () == curveName) {
89  return curve.numPoints ();
90  }
91  }
92 
93  return 0;
94 }
95 
97  bool isY,
98  double x,
99  double y,
100  const QStringList &identifiers,
101  const Transformation &transformation)
102 {
103  CurveList::iterator itr;
104  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
105 
106  Curve &curve = *itr;
107  curve.editPointGraph (isX,
108  isY,
109  x,
110  y,
111  identifiers,
112  transformation);
113  }
114 }
115 
116 void CurvesGraphs::iterateThroughCurvePoints (const QString &curveNameWanted,
117  const Functor2wRet<const QString &, const Point &, CallbackSearchReturn> &ftorWithCallback)
118 {
119  // Search for curve with matching name
120  CurveList::const_iterator itr;
121  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
122 
123  const Curve &curve = *itr;
124  if (curve.curveName () == curveNameWanted) {
125 
126  curve.iterateThroughCurvePoints (ftorWithCallback);
127  return;
128  }
129  }
130 
131  ENGAUGE_ASSERT (false);
132 }
133 
134 void CurvesGraphs::iterateThroughCurveSegments (const QString &curveNameWanted,
135  const Functor2wRet<const Point &, const Point &, CallbackSearchReturn> &ftorWithCallback) const
136 {
137  // Search for curve with matching name
138  CurveList::const_iterator itr;
139  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
140 
141  const Curve &curve = *itr;
142  if (curve.curveName () == curveNameWanted) {
143 
144  curve.iterateThroughCurveSegments (ftorWithCallback);
145  return;
146  }
147  }
148 
149  ENGAUGE_ASSERT (false);
150 }
151 
152 void CurvesGraphs::iterateThroughCurvesPoints (const Functor2wRet<const QString &, const Point &, CallbackSearchReturn> &ftorWithCallback)
153 {
154  CurveList::const_iterator itr;
155  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
156 
157  const Curve &curve = *itr;
158  curve.iterateThroughCurvePoints (ftorWithCallback);
159  }
160 }
161 
162 void CurvesGraphs::iterateThroughCurvesPoints (const Functor2wRet<const QString &, const Point &, CallbackSearchReturn> &ftorWithCallback) const
163 {
164  CurveList::const_iterator itr;
165  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
166 
167  const Curve &curve = *itr;
168  curve.iterateThroughCurvePoints (ftorWithCallback);
169  }
170 }
171 
172 void CurvesGraphs::loadPreVersion6(QDataStream &str)
173 {
174  LOG4CPP_INFO_S ((*mainCat)) << "CurvesGraphs::loadPreVersion6";
175 
176  int i;
177 
178  // Remove previous Curves. There is a DEFAULT_GRAPH_CURVE_NAME by default
179  m_curvesGraphs.clear();
180 
181  qint32 numberCurvesGraphs;
182  str >> numberCurvesGraphs;
183  for (i = 0; i < numberCurvesGraphs; i++) {
184  Curve curve (str);
185  m_curvesGraphs.append (curve);
186  }
187 
188  qint32 numberCurvesMeasures;
189  str >> numberCurvesMeasures;
190  for (i = 0; i < numberCurvesMeasures; i++) {
191  Curve curve (str);
192 
193  // Measures get dropped on the floor
194  }
195 }
196 
197 void CurvesGraphs::loadXml(QXmlStreamReader &reader)
198 {
199  LOG4CPP_INFO_S ((*mainCat)) << "CurvesGraphs::loadXml";
200 
201  bool success = true;
202 
203  // Remove previous Curves. There is a DEFAULT_GRAPH_CURVE_NAME by default
204  m_curvesGraphs.clear();
205 
206  // Read until end of this subtree
207  while ((reader.tokenType() != QXmlStreamReader::EndElement) ||
208  (reader.name() != DOCUMENT_SERIALIZE_CURVES_GRAPHS)){
209 
210  loadNextFromReader(reader);
211  if (reader.atEnd()) {
212  success = false;
213  break;
214  }
215 
216  if ((reader.tokenType() == QXmlStreamReader::StartElement) &&
217  (reader.name () == DOCUMENT_SERIALIZE_CURVE)) {
218 
219  Curve curve (reader);
220 
221  // Version 6 of Engauge let users create multiple curves with the same name. Reading a file with duplicate
222  // curve names can result in crashes and/or corruption, so we deconflict duplicate curve names here
223  QString DUPLICATE = QString ("-%1").arg (QObject::tr ("DUPLICATE"));
224  QString curveName = curve.curveName();
225  while (curvesGraphsNames().contains (curveName)) {
226  curveName += DUPLICATE;
227  }
228  curve.setCurveName (curveName); // No effect if curve name was not a duplicate
229 
230  // Add the curve
231  m_curvesGraphs.push_back (curve);
232 
233  }
234  }
235 
236  if (!success) {
237  reader.raiseError (QObject::tr ("Cannot read graph curves data"));
238  }
239 }
240 
242 {
243  return m_curvesGraphs.count ();
244 }
245 
246 void CurvesGraphs::printStream (QString indentation,
247  QTextStream &str) const
248 {
249  str << indentation << "CurvesGraphs\n";
250 
251  indentation += INDENTATION_DELTA;
252 
253  CurveList::const_iterator itr;
254  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
255 
256  const Curve &curve = *itr;
257  curve.printStream (indentation,
258  str);
259  }
260 }
261 
262 void CurvesGraphs::removePoint (const QString &pointIdentifier)
263 {
264  QString curveName = Point::curveNameFromPointIdentifier(pointIdentifier);
265 
266  Curve *curve = curveForCurveName (curveName);
267  curve->removePoint (pointIdentifier);
268 }
269 
270 void CurvesGraphs::saveXml(QXmlStreamWriter &writer) const
271 {
272  LOG4CPP_INFO_S ((*mainCat)) << "CurvesGraphs::saveXml";
273 
274  writer.writeStartElement(DOCUMENT_SERIALIZE_CURVES_GRAPHS);
275 
276  CurveList::const_iterator itr;
277  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
278 
279  const Curve &curve = *itr;
280  curve.saveXml (writer);
281  }
282 
283  writer.writeEndElement();
284 }
285 
287 {
288  LOG4CPP_INFO_S ((*mainCat)) << "CurvesGraphs::updatePointOrdinals";
289 
290  CurveList::iterator itr;
291  for (itr = m_curvesGraphs.begin (); itr != m_curvesGraphs.end (); itr++) {
292 
293  Curve &curve = *itr;
294  curve.updatePointOrdinals (transformation);
295  }
296 }
void removePoint(const QString &identifier)
Perform the opposite of addPointAtEnd.
Definition: Curve.cpp:510
static QString curveNameFromPointIdentifier(const QString &pointIdentifier)
Parse the curve name from the specified point identifier. This does the opposite of uniqueIdentifierG...
Definition: Point.cpp:227
int curvesGraphsNumPoints(const QString &curveName) const
Point count.
void loadXml(QXmlStreamReader &reader)
Load from serialized xml post-version 5 file.
void iterateThroughCurvePoints(const Functor2wRet< const QString &, const Point &, CallbackSearchReturn > &ftorWithCallback) const
Apply functor to Points on Curve.
Definition: Curve.cpp:301
Curve * curveForCurveName(const QString &curveName)
Return the axis or graph curve for the specified curve name.
void updatePointOrdinals(const Transformation &transformation)
See CurveGraphs::updatePointOrdinals.
Definition: Curve.cpp:568
void addGraphCurveAtEnd(Curve curve)
Append new graph Curve to end of Curve list.
void iterateThroughCurvesPoints(const Functor2wRet< const QString &, const Point &, CallbackSearchReturn > &ftorWithCallback)
Apply functor to Points on all of the Curves.
Class that represents one digitized point. The screen-to-graph coordinate transformation is always ex...
Definition: Point.h:23
int numPoints() const
Number of points.
Definition: Curve.cpp:432
void editPointGraph(bool isX, bool isY, double x, double y, const QStringList &identifiers, const Transformation &transformation)
Set the x and/or y coordinate values of the specified points.
void saveXml(QXmlStreamWriter &writer) const
Serialize curves.
QString identifier() const
Unique identifier for a specific Point.
Definition: Point.cpp:256
Affine transformation between screen and graph coordinates, based on digitized axis points...
void addPoint(const Point &point)
Append new Point to the specified Curve.
void printStream(QString indentation, QTextStream &str) const
Debugging method that supports print method of this class and printStream method of some other class(...
Definition: Curve.cpp:490
void iterateThroughCurvePoints(const QString &curveNameWanted, const Functor2wRet< const QString &, const Point &, CallbackSearchReturn > &ftorWithCallback)
Apply functor to Points in the specified axis or graph Curve.
void iterateThroughCurveSegments(const Functor2wRet< const Point &, const Point &, CallbackSearchReturn > &ftorWithCallback) const
Apply functor to successive Points, as line segments, on Curve. This could be a bit slow...
Definition: Curve.cpp:316
int numCurves() const
Current number of graphs curves.
void setCurveName(const QString &curveName)
Change the curve name.
Definition: Curve.cpp:551
QString curveName() const
Name of this Curve.
Definition: Curve.cpp:143
Container for one set of digitized Points.
Definition: Curve.h:33
void updatePointOrdinals(const Transformation &transformation)
Update point ordinals to be consistent with their CurveStyle and x/theta coordinate.
void iterateThroughCurveSegments(const QString &curveNameWanted, const Functor2wRet< const Point &, const Point &, CallbackSearchReturn > &ftorWithCallback) const
Apply functor to segments on the specified axis or graph Curve.
void editPointGraph(bool isX, bool isY, double x, double y, const QStringList &identifiers, const Transformation &transformation)
Edit the graph coordinates of one or more graph points. This method does not apply to an axis point...
Definition: Curve.cpp:170
QStringList curvesGraphsNames() const
List of graph curve names.
void loadPreVersion6(QDataStream &str)
Load from serialized binary pre-version 6 file.
void printStream(QString indentation, QTextStream &str) const
Debugging method that supports print method of this class and printStream method of some other class(...
void saveXml(QXmlStreamWriter &writer) const
Serialize curve.
Definition: Curve.cpp:523
void removePoint(const QString &pointIdentifier)
Remove the Point from its Curve.