00001
00002
00003
00004
00005
00006
00007 #include "Curve.h"
00008 #include "CurvesGraphs.h"
00009 #include "CurveStyle.h"
00010 #include "DocumentSerialize.h"
00011 #include "EngaugeAssert.h"
00012 #include "Logger.h"
00013 #include "MigrateToVersion6.h"
00014 #include "Point.h"
00015 #include "PointComparator.h"
00016 #include <QDataStream>
00017 #include <QDebug>
00018 #include <QMap>
00019 #include <QTextStream>
00020 #include <QXmlStreamReader>
00021 #include <QXmlStreamWriter>
00022 #include "Transformation.h"
00023 #include "Xml.h"
00024
00025 const QString AXIS_CURVE_NAME ("Axes");
00026 const QString DEFAULT_GRAPH_CURVE_NAME ("Curve1");
00027 const QString DUMMY_CURVE_NAME ("dummy");
00028 const QString TAB_DELIMITER ("\t");
00029
00030 typedef QMap<double, QString> XOrThetaToPointIdentifier;
00031
00032 Curve::Curve(const QString &curveName,
00033 const ColorFilterSettings &colorFilterSettings,
00034 const CurveStyle &curveStyle) :
00035 m_curveName (curveName),
00036 m_colorFilterSettings (colorFilterSettings),
00037 m_curveStyle (curveStyle)
00038 {
00039 }
00040
00041 Curve::Curve (const Curve &curve) :
00042 m_curveName (curve.curveName ()),
00043 m_points (curve.points ()),
00044 m_colorFilterSettings (curve.colorFilterSettings ()),
00045 m_curveStyle (curve.curveStyle ())
00046 {
00047 }
00048
00049 Curve::Curve (QDataStream &str)
00050 {
00051 const int CONVERT_ENUM_TO_RADIUS = 6;
00052 MigrateToVersion6 migrate;
00053
00054 qint32 int32, xScreen, yScreen;
00055 double xGraph, yGraph;
00056
00057 str >> m_curveName;
00058 str >> int32;
00059 m_curveStyle.setPointShape(migrate.pointShape (int32));
00060 str >> int32;
00061 m_curveStyle.setPointRadius(int32 + CONVERT_ENUM_TO_RADIUS);
00062 str >> int32;
00063 m_curveStyle.setPointLineWidth (int32);
00064 str >> int32;
00065 m_curveStyle.setPointColor(migrate.colorPalette (int32));
00066 str >> int32;
00067 str >> int32;
00068 m_curveStyle.setLineWidth(int32);
00069 str >> int32;
00070 if (m_curveName == AXIS_CURVE_NAME) {
00071 m_curveStyle.setLineColor(migrate.colorPalette (int32));
00072 } else {
00073 m_curveStyle.setLineColor(COLOR_PALETTE_TRANSPARENT);
00074 }
00075 str >> int32;
00076 m_curveStyle.setLineConnectAs(migrate.curveConnectAs (int32));
00077
00078 str >> int32;
00079 int count = int32;
00080 int ordinal = 0;
00081 for (int i = 0; i < count; i++) {
00082
00083 str >> xScreen;
00084 str >> yScreen;
00085 str >> xGraph;
00086 str >> yGraph;
00087 if (m_curveName == AXIS_CURVE_NAME) {
00088
00089
00090 Point point (m_curveName,
00091 QPointF (xScreen, yScreen),
00092 QPointF (xGraph, yGraph),
00093 ordinal++,
00094 false);
00095
00096 addPoint(point);
00097 } else {
00098
00099
00100 Point point (m_curveName,
00101 QPointF (xScreen, yScreen));
00102 point.setOrdinal (ordinal++);
00103
00104 addPoint(point);
00105 }
00106 }
00107 }
00108
00109 Curve::Curve (QXmlStreamReader &reader)
00110 {
00111 loadXml(reader);
00112 }
00113
00114 Curve &Curve::operator=(const Curve &curve)
00115 {
00116 m_curveName = curve.curveName ();
00117 m_points = curve.points ();
00118 m_colorFilterSettings = curve.colorFilterSettings ();
00119 m_curveStyle = curve.curveStyle ();
00120
00121 return *this;
00122 }
00123
00124 void Curve::addPoint (Point point)
00125 {
00126 m_points.push_back (point);
00127 }
00128
00129 ColorFilterSettings Curve::colorFilterSettings () const
00130 {
00131 return m_colorFilterSettings;
00132 }
00133
00134 QString Curve::curveName () const
00135 {
00136 return m_curveName;
00137 }
00138
00139 CurveStyle Curve::curveStyle() const
00140 {
00141 return m_curveStyle;
00142 }
00143
00144 void Curve::editPoint (const QPointF &posGraph,
00145 const QString &identifier)
00146 {
00147
00148 QList<Point>::iterator itr;
00149 for (itr = m_points.begin (); itr != m_points.end (); itr++) {
00150
00151 Point &point = *itr;
00152 if (point.identifier () == identifier) {
00153
00154 point.setPosGraph (posGraph);
00155 break;
00156
00157 }
00158 }
00159 }
00160
00161 void Curve::exportToClipboard (const QHash<QString, bool> &selectedHash,
00162 const Transformation &transformation,
00163 QTextStream &strCsv,
00164 QTextStream &strHtml,
00165 CurvesGraphs &curvesGraphs) const
00166 {
00167 LOG4CPP_INFO_S ((*mainCat)) << "Curve::exportToClipboard"
00168 << " hashCount=" << selectedHash.count();
00169
00170
00171
00172 bool isFirst = true;
00173 QList<Point>::const_iterator itr;
00174 for (itr = m_points.begin (); itr != m_points.end (); itr++) {
00175
00176 const Point &point = *itr;
00177 if (selectedHash.contains (point.identifier ())) {
00178
00179 if (isFirst) {
00180
00181
00182 isFirst = false;
00183 strCsv << "X" << TAB_DELIMITER << m_curveName << "\n";
00184 strHtml << "<table>\n"
00185 << "<tr><th>X</th><th>" << m_curveName << "</th></tr>\n";
00186 }
00187
00188
00189 CurveStyle curveStyleDefault;
00190 curveStyleDefault.setLineStyle(LineStyle::defaultAxesCurve());
00191 curveStyleDefault.setPointStyle(PointStyle::defaultGraphCurve (curvesGraphs.numCurves ()));
00192
00193
00194 if (curvesGraphs.curveForCurveName (m_curveName) == 0) {
00195 Curve curve(m_curveName,
00196 ColorFilterSettings::defaultFilter (),
00197 curveStyleDefault);
00198 curvesGraphs.addGraphCurveAtEnd(curve);
00199 }
00200
00201
00202 QPointF pos = point.posScreen();
00203 if (transformation.transformIsDefined()) {
00204
00205
00206 QPointF posGraph;
00207 transformation.transformScreenToRawGraph(pos,
00208 posGraph);
00209 pos = posGraph;
00210 }
00211
00212
00213 strCsv << pos.x() << TAB_DELIMITER << pos.y() << "\n";
00214 strHtml << "<tr><td>" << pos.x() << "</td><td>" << pos.y() << "</td></tr>\n";
00215
00216
00217 curvesGraphs.curveForCurveName (m_curveName)->addPoint (point);
00218 }
00219 }
00220
00221 if (!isFirst) {
00222 strHtml << "</table>\n";
00223 }
00224 }
00225
00226 bool Curve::isXOnly(const QString &pointIdentifier) const
00227 {
00228
00229 Points::const_iterator itr;
00230 for (itr = m_points.begin (); itr != m_points.end (); itr++) {
00231 const Point &point = *itr;
00232 if (pointIdentifier == point.identifier ()) {
00233 return point.isXOnly();
00234 break;
00235 }
00236 }
00237
00238 ENGAUGE_ASSERT (false);
00239
00240 return false;
00241 }
00242
00243 void Curve::iterateThroughCurvePoints (const Functor2wRet<const QString &, const Point&, CallbackSearchReturn> &ftorWithCallback) const
00244 {
00245 QList<Point>::const_iterator itr;
00246 for (itr = m_points.begin (); itr != m_points.end (); itr++) {
00247
00248 const Point &point = *itr;
00249
00250 CallbackSearchReturn rtn = ftorWithCallback (m_curveName, point);
00251
00252 if (rtn == CALLBACK_SEARCH_RETURN_INTERRUPT) {
00253 break;
00254 }
00255 }
00256 }
00257
00258 void Curve::iterateThroughCurveSegments (const Functor2wRet<const Point&, const Point&, CallbackSearchReturn> &ftorWithCallback) const
00259 {
00260
00261
00262 QList<Point>::const_iterator itr;
00263 const Point *pointBefore = 0;
00264 for (itr = m_points.begin(); itr != m_points.end(); itr++) {
00265
00266 const Point &point = *itr;
00267
00268 if (pointBefore != 0) {
00269
00270 CallbackSearchReturn rtn = ftorWithCallback (*pointBefore,
00271 point);
00272
00273 if (rtn == CALLBACK_SEARCH_RETURN_INTERRUPT) {
00274 break;
00275 }
00276
00277 }
00278 pointBefore = &point;
00279 }
00280 }
00281
00282 void Curve::loadCurvePoints(QXmlStreamReader &reader)
00283 {
00284 LOG4CPP_INFO_S ((*mainCat)) << "Curve::loadCurvePoints";
00285
00286 bool success = true;
00287
00288 while ((reader.tokenType() != QXmlStreamReader::EndElement) ||
00289 (reader.name() != DOCUMENT_SERIALIZE_CURVE_POINTS)) {
00290
00291 QXmlStreamReader::TokenType tokenType = loadNextFromReader(reader);
00292
00293 if (reader.atEnd()) {
00294 success = false;
00295 break;
00296 }
00297
00298 if (tokenType == QXmlStreamReader::StartElement) {
00299
00300 if (reader.name () == DOCUMENT_SERIALIZE_POINT) {
00301
00302 Point point (reader);
00303 m_points.push_back (point);
00304 }
00305 }
00306 }
00307
00308 if (!success) {
00309 reader.raiseError(QObject::tr ("Cannot read curve data"));
00310 }
00311 }
00312
00313 void Curve::loadXml(QXmlStreamReader &reader)
00314 {
00315 LOG4CPP_INFO_S ((*mainCat)) << "Curve::loadXml";
00316
00317 bool success = true;
00318
00319 QXmlStreamAttributes attributes = reader.attributes();
00320
00321 if (attributes.hasAttribute (DOCUMENT_SERIALIZE_CURVE_NAME)) {
00322
00323 setCurveName (attributes.value (DOCUMENT_SERIALIZE_CURVE_NAME).toString());
00324
00325
00326 while ((reader.tokenType() != QXmlStreamReader::EndElement) ||
00327 (reader.name() != DOCUMENT_SERIALIZE_CURVE)){
00328
00329 QXmlStreamReader::TokenType tokenType = loadNextFromReader(reader);
00330
00331 if (reader.atEnd()) {
00332 success = false;
00333 break;
00334 }
00335
00336 if (tokenType == QXmlStreamReader::StartElement) {
00337
00338 if (reader.name() == DOCUMENT_SERIALIZE_COLOR_FILTER) {
00339 m_colorFilterSettings.loadXml(reader);
00340 } else if (reader.name() == DOCUMENT_SERIALIZE_CURVE_POINTS) {
00341 loadCurvePoints(reader);
00342 } else if (reader.name() == DOCUMENT_SERIALIZE_CURVE_STYLE) {
00343 m_curveStyle.loadXml(reader);
00344 } else {
00345 success = false;
00346 break;
00347 }
00348 }
00349
00350 if (reader.hasError()) {
00351
00352
00353 break;
00354 }
00355 }
00356 } else {
00357 success = false;
00358 }
00359
00360 if (!success) {
00361 reader.raiseError (QObject::tr ("Cannot read curve data"));
00362 }
00363 }
00364
00365 void Curve::movePoint (const QString &pointIdentifier,
00366 const QPointF &deltaScreen)
00367 {
00368 Point *point = pointForPointIdentifier (pointIdentifier);
00369
00370 QPointF posScreen = deltaScreen + point->posScreen ();
00371 point->setPosScreen (posScreen);
00372 }
00373
00374 int Curve::numPoints () const
00375 {
00376 return m_points.count ();
00377 }
00378
00379 Point *Curve::pointForPointIdentifier (const QString pointIdentifier)
00380 {
00381 Points::iterator itr;
00382 for (itr = m_points.begin (); itr != m_points.end (); itr++) {
00383 Point &point = *itr;
00384 if (pointIdentifier == point.identifier ()) {
00385 return &point;
00386 }
00387 }
00388
00389 ENGAUGE_ASSERT (false);
00390 return 0;
00391 }
00392
00393 const Points Curve::points () const
00394 {
00395 return m_points;
00396 }
00397
00398 QPointF Curve::positionGraph (const QString &pointIdentifier) const
00399 {
00400 QPointF posGraph;
00401
00402
00403 Points::const_iterator itr;
00404 for (itr = m_points.begin (); itr != m_points.end (); itr++) {
00405 const Point &point = *itr;
00406 if (pointIdentifier == point.identifier ()) {
00407 posGraph = point.posGraph ();
00408 break;
00409 }
00410 }
00411
00412 return posGraph;
00413 }
00414
00415 QPointF Curve::positionScreen (const QString &pointIdentifier) const
00416 {
00417 QPointF posScreen;
00418
00419
00420 Points::const_iterator itr;
00421 for (itr = m_points.begin (); itr != m_points.end (); itr++) {
00422 const Point &point = *itr;
00423 if (pointIdentifier == point.identifier ()) {
00424 posScreen = point.posScreen ();
00425 break;
00426 }
00427 }
00428
00429 return posScreen;
00430 }
00431
00432 void Curve::printStream (QString indentation,
00433 QTextStream &str) const
00434 {
00435 str << indentation << "Curve=" << m_curveName << "\n";
00436
00437 indentation += INDENTATION_DELTA;
00438
00439 Points::const_iterator itr;
00440 for (itr = m_points.begin (); itr != m_points.end (); itr++) {
00441 const Point &point = *itr;
00442 point.printStream (indentation,
00443 str);
00444 }
00445
00446 m_colorFilterSettings.printStream (indentation,
00447 str);
00448 m_curveStyle.printStream (indentation,
00449 str);
00450 }
00451
00452 void Curve::removePoint (const QString &identifier)
00453 {
00454
00455 Points::iterator itr;
00456 for (itr = m_points.begin (); itr != m_points.end (); itr++) {
00457 Point point = *itr;
00458 if (point.identifier () == identifier) {
00459 m_points.erase (itr);
00460 break;
00461 }
00462 }
00463 }
00464
00465 void Curve::saveXml(QXmlStreamWriter &writer) const
00466 {
00467 LOG4CPP_INFO_S ((*mainCat)) << "Curve::saveXml";
00468
00469 writer.writeStartElement(DOCUMENT_SERIALIZE_CURVE);
00470 writer.writeAttribute(DOCUMENT_SERIALIZE_CURVE_NAME, m_curveName);
00471 m_colorFilterSettings.saveXml (writer,
00472 m_curveName);
00473 m_curveStyle.saveXml (writer,
00474 m_curveName);
00475
00476
00477 writer.writeStartElement(DOCUMENT_SERIALIZE_CURVE_POINTS);
00478 Points::const_iterator itr;
00479 for (itr = m_points.begin (); itr != m_points.end (); itr++) {
00480 const Point &point = *itr;
00481 point.saveXml (writer);
00482 }
00483 writer.writeEndElement();
00484
00485 writer.writeEndElement();
00486 }
00487
00488 void Curve::setColorFilterSettings (const ColorFilterSettings &colorFilterSettings)
00489 {
00490 m_colorFilterSettings = colorFilterSettings;
00491 }
00492
00493 void Curve::setCurveName (const QString &curveName)
00494 {
00495 m_curveName = curveName;
00496
00497
00498 QList<Point>::iterator itr;
00499 for (itr = m_points.begin(); itr != m_points.end(); itr++) {
00500 Point &point = *itr;
00501 point.setCurveName (curveName);
00502 }
00503 }
00504
00505 void Curve::setCurveStyle (const CurveStyle &curveStyle)
00506 {
00507 m_curveStyle = curveStyle;
00508 }
00509
00510 void Curve::updatePointOrdinals (const Transformation &transformation)
00511 {
00512 CurveConnectAs curveConnectAs = m_curveStyle.lineStyle().curveConnectAs();
00513
00514 LOG4CPP_INFO_S ((*mainCat)) << "Curve::updatePointOrdinals"
00515 << " curve=" << m_curveName.toLatin1().data()
00516 << " connectAs=" << curveConnectAsToString(curveConnectAs).toLatin1().data();
00517
00518
00519
00520 if (curveConnectAs == CONNECT_AS_FUNCTION_SMOOTH ||
00521 curveConnectAs == CONNECT_AS_FUNCTION_STRAIGHT) {
00522
00523 updatePointOrdinalsFunctions (transformation);
00524
00525 } else if (curveConnectAs == CONNECT_AS_RELATION_SMOOTH ||
00526 curveConnectAs == CONNECT_AS_RELATION_STRAIGHT) {
00527
00528 updatePointOrdinalsRelations ();
00529
00530 } else {
00531
00532 LOG4CPP_ERROR_S ((*mainCat)) << "Curve::updatePointOrdinals";
00533 ENGAUGE_ASSERT (false);
00534
00535 }
00536
00537 qSort (m_points.begin(),
00538 m_points.end(),
00539 PointComparator());
00540 }
00541
00542 void Curve::updatePointOrdinalsFunctions (const Transformation &transformation)
00543 {
00544 CurveConnectAs curveConnectAs = m_curveStyle.lineStyle().curveConnectAs();
00545
00546 LOG4CPP_INFO_S ((*mainCat)) << "Curve::updatePointOrdinalsFunctions"
00547 << " curve=" << m_curveName.toLatin1().data()
00548 << " connectAs=" << curveConnectAsToString(curveConnectAs).toLatin1().data();
00549
00550
00551 XOrThetaToPointIdentifier xOrThetaToPointIdentifier;
00552 Points::iterator itr;
00553 for (itr = m_points.begin (); itr != m_points.end (); itr++) {
00554 Point &point = *itr;
00555
00556 QPointF posGraph;
00557 if (transformation.transformIsDefined()) {
00558
00559
00560 transformation.transformScreenToRawGraph (point.posScreen (),
00561 posGraph);
00562 } else {
00563
00564
00565
00566 posGraph= point.posScreen();
00567 }
00568
00569 xOrThetaToPointIdentifier [posGraph.x()] = point.identifier();
00570 }
00571
00572
00573
00574 QMap<QString, double> pointIdentifierToOrdinal;
00575 int ordinal = 0;
00576 XOrThetaToPointIdentifier::const_iterator itrX;
00577 for (itrX = xOrThetaToPointIdentifier.begin(); itrX != xOrThetaToPointIdentifier.end(); itrX++) {
00578
00579 QString pointIdentifier = itrX.value();
00580 pointIdentifierToOrdinal [pointIdentifier] = ordinal++;
00581 }
00582
00583
00584 for (itr = m_points.begin(); itr != m_points.end(); itr++) {
00585 Point &point = *itr;
00586 int ordinalNew = pointIdentifierToOrdinal [point.identifier()];
00587 point.setOrdinal (ordinalNew);
00588 }
00589 }
00590
00591 void Curve::updatePointOrdinalsRelations ()
00592 {
00593 CurveConnectAs curveConnectAs = m_curveStyle.lineStyle().curveConnectAs();
00594
00595 LOG4CPP_INFO_S ((*mainCat)) << "Curve::updatePointOrdinalsRelations"
00596 << " curve=" << m_curveName.toLatin1().data()
00597 << " connectAs=" << curveConnectAsToString(curveConnectAs).toLatin1().data();
00598
00599
00600 Points::iterator itr;
00601 int ordinal = 0;
00602 for (itr = m_points.begin(); itr != m_points.end(); itr++) {
00603 Point &point = *itr;
00604 point.setOrdinal (ordinal++);
00605 }
00606 }