00001
00002
00003
00004
00005
00006
00007 #include "DataKey.h"
00008 #include "EngaugeAssert.h"
00009 #include "EnumsToQt.h"
00010 #include "GraphicsItemType.h"
00011 #include "GraphicsLinesForCurve.h"
00012 #include "GraphicsPoint.h"
00013 #include "GraphicsScene.h"
00014 #include "LineStyle.h"
00015 #include "Logger.h"
00016 #include "Point.h"
00017 #include "PointStyle.h"
00018 #include <QGraphicsItem>
00019 #include <QMap>
00020 #include <QPen>
00021 #include <QTextStream>
00022 #include "QtToString.h"
00023 #include "Spline.h"
00024 #include "Transformation.h"
00025
00026 using namespace std;
00027
00028 typedef QMap<double, double> XOrThetaToOrdinal;
00029
00030 GraphicsLinesForCurve::GraphicsLinesForCurve(const QString &curveName) :
00031 m_curveName (curveName)
00032 {
00033 setData (DATA_KEY_GRAPHICS_ITEM_TYPE,
00034 GRAPHICS_ITEM_TYPE_LINE);
00035 setData (DATA_KEY_IDENTIFIER,
00036 QVariant (m_curveName));
00037 }
00038
00039 GraphicsLinesForCurve::~GraphicsLinesForCurve()
00040 {
00041 OrdinalToGraphicsPoint::iterator itr;
00042 for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
00043 GraphicsPoint *point = itr.value();
00044 delete point;
00045 }
00046
00047 m_graphicsPoints.clear();
00048 }
00049
00050 void GraphicsLinesForCurve::addPoint (const QString &pointIdentifier,
00051 double ordinal,
00052 GraphicsPoint &graphicsPoint)
00053 {
00054 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::addPoint"
00055 << " curve=" << m_curveName.toLatin1().data()
00056 << " identifier=" << pointIdentifier.toLatin1().data()
00057 << " ordinal=" << ordinal
00058 << " pos=" << QPointFToString (graphicsPoint.pos()).toLatin1().data()
00059 << " newPointCount=" << (m_graphicsPoints.count() + 1);
00060
00061 m_graphicsPoints [ordinal] = &graphicsPoint;
00062 }
00063
00064 QPainterPath GraphicsLinesForCurve::drawLinesSmooth ()
00065 {
00066 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::drawLinesSmooth"
00067 << " curve=" << m_curveName.toLatin1().data();
00068
00069 QPainterPath path;
00070
00071
00072 vector<double> t;
00073 vector<SplinePair> xy;
00074 OrdinalToGraphicsPoint::const_iterator itr;
00075 for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
00076
00077 double ordinal = itr.key();
00078 const GraphicsPoint *point = itr.value();
00079
00080 t.push_back (ordinal);
00081 xy.push_back (SplinePair (point->pos ().x(),
00082 point->pos ().y()));
00083 }
00084
00085
00086 Spline spline (t, xy);
00087
00088
00089 int segmentEndingAtPointI = 0;
00090
00091
00092 bool isFirst = true;
00093 for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
00094
00095 const GraphicsPoint *point = itr.value();
00096
00097 if (isFirst) {
00098 isFirst = false;
00099 path.moveTo (point->pos());
00100 } else {
00101
00102 QPointF p1 (spline.p1 (segmentEndingAtPointI).x(),
00103 spline.p1 (segmentEndingAtPointI).y());
00104 QPointF p2 (spline.p2 (segmentEndingAtPointI).x(),
00105 spline.p2 (segmentEndingAtPointI).y());
00106
00107 path.cubicTo (p1,
00108 p2,
00109 point->pos ());
00110
00111 ++segmentEndingAtPointI;
00112 }
00113 }
00114
00115 return path;
00116 }
00117
00118 QPainterPath GraphicsLinesForCurve::drawLinesStraight ()
00119 {
00120 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::drawLinesStraight"
00121 << " curve=" << m_curveName.toLatin1().data();
00122
00123 QPainterPath path;
00124
00125
00126 bool isFirst = true;
00127 OrdinalToGraphicsPoint::const_iterator itr;
00128 for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
00129
00130 const GraphicsPoint *point = itr.value();
00131
00132 if (isFirst) {
00133 isFirst = false;
00134 path.moveTo (point->pos ());
00135 } else {
00136 path.lineTo (point->pos ());
00137 }
00138 }
00139
00140 return path;
00141 }
00142
00143 double GraphicsLinesForCurve::identifierToOrdinal (const QString &identifier) const
00144 {
00145 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::identifierToOrdinal"
00146 << " identifier=" << identifier.toLatin1().data();
00147
00148 OrdinalToGraphicsPoint::const_iterator itr;
00149 for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
00150
00151 const GraphicsPoint *point = itr.value();
00152
00153 if (point->data (DATA_KEY_IDENTIFIER) == identifier) {
00154 return itr.key();
00155 }
00156 }
00157
00158 ENGAUGE_ASSERT (false);
00159
00160 return 0;
00161 }
00162
00163 void GraphicsLinesForCurve::lineMembershipPurge (const LineStyle &lineStyle)
00164 {
00165 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::lineMembershipPurge"
00166 << " curve=" << m_curveName.toLatin1().data();
00167
00168 OrdinalToGraphicsPoint::iterator itr, itrNext;
00169 for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr = itrNext) {
00170
00171 itrNext = itr;
00172 ++itrNext;
00173
00174 GraphicsPoint *point = *itr;
00175
00176 if (!point->wanted ()) {
00177
00178 double ordinal = itr.key ();
00179
00180 delete point;
00181 m_graphicsPoints.remove (ordinal);
00182 }
00183 }
00184
00185
00186 QPen pen;
00187 if (lineStyle.paletteColor() == COLOR_PALETTE_TRANSPARENT) {
00188
00189 pen = QPen (Qt::NoPen);
00190
00191 } else {
00192
00193 pen = QPen (QBrush (ColorPaletteToQColor (lineStyle.paletteColor())),
00194 lineStyle.width());
00195
00196 }
00197
00198 setPen (pen);
00199
00200 updateGraphicsLinesToMatchGraphicsPoints (lineStyle);
00201 }
00202
00203 void GraphicsLinesForCurve::lineMembershipReset ()
00204 {
00205 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::lineMembershipReset"
00206 << " curve=" << m_curveName.toLatin1().data();
00207
00208 OrdinalToGraphicsPoint::iterator itr;
00209 for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
00210
00211 GraphicsPoint *point = itr.value();
00212
00213 point->reset ();
00214 }
00215 }
00216
00217 bool GraphicsLinesForCurve::needOrdinalRenumbering () const
00218 {
00219
00220 bool needRenumbering = false;
00221 for (int ordinalKeyWanted = 0; ordinalKeyWanted < m_graphicsPoints.count(); ordinalKeyWanted++) {
00222
00223 double ordinalKeyGot = m_graphicsPoints.keys().at (ordinalKeyWanted);
00224
00225
00226 ENGAUGE_ASSERT (ordinalKeyGot != Point::UNDEFINED_ORDINAL ());
00227
00228 if (ordinalKeyWanted != ordinalKeyGot) {
00229 needRenumbering = true;
00230 break;
00231 }
00232 }
00233
00234 return needRenumbering;
00235 }
00236
00237 void GraphicsLinesForCurve::printStream (QString indentation,
00238 QTextStream &str) const
00239 {
00240 DataKey type = (DataKey) data (DATA_KEY_GRAPHICS_ITEM_TYPE).toInt();
00241
00242 str << indentation << "GraphicsLinesForCurve=" << m_curveName
00243 << " dataIdentifier=" << data (DATA_KEY_IDENTIFIER).toString().toLatin1().data()
00244 << " dataType=" << dataKeyToString (type).toLatin1().data() << "\n";
00245
00246 indentation += INDENTATION_DELTA;
00247
00248 OrdinalToGraphicsPoint::const_iterator itr;
00249 for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
00250
00251 double ordinalKey = itr.key();
00252 const GraphicsPoint *point = itr.value();
00253
00254 point->printStream (indentation,
00255 str,
00256 ordinalKey);
00257 }
00258 }
00259
00260 void GraphicsLinesForCurve::removePoint (double ordinal)
00261 {
00262 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::removePoint"
00263 << " point=" << ordinal
00264 << " pointCount=" << m_graphicsPoints.count();
00265
00266 ENGAUGE_ASSERT (m_graphicsPoints.contains (ordinal));
00267 GraphicsPoint *graphicsPoint = m_graphicsPoints [ordinal];
00268
00269 m_graphicsPoints.remove (ordinal);
00270
00271 delete graphicsPoint;
00272 }
00273
00274 void GraphicsLinesForCurve::removeTemporaryPointIfExists()
00275 {
00276 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::removeTemporaryPointIfExists";
00277
00278 OrdinalToGraphicsPoint::iterator itr;
00279 for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
00280
00281 GraphicsPoint *graphicsPoint = itr.value();
00282
00283 m_graphicsPoints.remove (itr.key());
00284
00285 delete graphicsPoint;
00286
00287 break;
00288 }
00289 }
00290
00291 void GraphicsLinesForCurve::renumberOrdinals ()
00292 {
00293 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::renumberOrdinals";
00294
00295 int ordinalKeyWanted;
00296
00297
00298
00299 QList<GraphicsPoint*> points;
00300 for (ordinalKeyWanted = 0; ordinalKeyWanted < m_graphicsPoints.count(); ordinalKeyWanted++) {
00301
00302 GraphicsPoint *graphicsPoint = m_graphicsPoints.values().at (ordinalKeyWanted);
00303 points << graphicsPoint;
00304 }
00305
00306 m_graphicsPoints.clear ();
00307
00308 for (ordinalKeyWanted = 0; ordinalKeyWanted < points.count(); ordinalKeyWanted++) {
00309
00310 GraphicsPoint *graphicsPoint = points.at (ordinalKeyWanted);
00311 m_graphicsPoints [ordinalKeyWanted] = graphicsPoint;
00312 }
00313 }
00314
00315 void GraphicsLinesForCurve::updateAfterCommand (GraphicsScene &scene,
00316 const PointStyle &pointStyle,
00317 const Point &point)
00318 {
00319 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsLinesForCurve::updateAfterCommand"
00320 << " curve=" << m_curveName.toLatin1().data()
00321 << " pointCount=" << m_graphicsPoints.count();
00322
00323 GraphicsPoint *graphicsPoint = 0;
00324 if (m_graphicsPoints.contains (point.ordinal())) {
00325
00326 graphicsPoint = m_graphicsPoints [point.ordinal()];
00327
00328
00329
00330
00331
00332 graphicsPoint->setPos (point.posScreen());
00333 graphicsPoint->setData (DATA_KEY_IDENTIFIER, point.identifier());
00334
00335 } else {
00336
00337
00338 graphicsPoint = scene.createPoint (point.identifier (),
00339 pointStyle,
00340 point.posScreen());
00341 m_graphicsPoints [point.ordinal ()] = graphicsPoint;
00342
00343 }
00344
00345
00346 ENGAUGE_CHECK_PTR (graphicsPoint);
00347 graphicsPoint->setWanted ();
00348 }
00349
00350 void GraphicsLinesForCurve::updateCurveStyle (const CurveStyle &curveStyle)
00351 {
00352 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::updateCurveStyle";
00353
00354 OrdinalToGraphicsPoint::const_iterator itr;
00355 for (itr = m_graphicsPoints.begin(); itr != m_graphicsPoints.end(); itr++) {
00356
00357 GraphicsPoint *point = itr.value();
00358 point->updateCurveStyle (curveStyle);
00359 }
00360 }
00361
00362 void GraphicsLinesForCurve::updateGraphicsLinesToMatchGraphicsPoints (const LineStyle &lineStyle)
00363 {
00364
00365
00366 bool needRenumbering = needOrdinalRenumbering ();
00367 if (needRenumbering) {
00368
00369 renumberOrdinals();
00370
00371 }
00372
00373 LOG4CPP_INFO_S ((*mainCat)) << "GraphicsLinesForCurve::updateGraphicsLinesToMatchGraphicsPoints"
00374 << " numberPoints=" << m_graphicsPoints.count()
00375 << " ordinalRenumbering=" << (needRenumbering ? "true" : "false");
00376
00377 if (lineStyle.curveConnectAs() != CONNECT_SKIP_FOR_AXIS_CURVE) {
00378
00379
00380
00381 QPainterPath path;
00382 if (lineStyle.curveConnectAs() == CONNECT_AS_FUNCTION_STRAIGHT ||
00383 lineStyle.curveConnectAs() == CONNECT_AS_RELATION_STRAIGHT ||
00384 m_graphicsPoints.count () < 3) {
00385
00386 path = drawLinesStraight ();
00387 } else {
00388 path = drawLinesSmooth ();
00389 }
00390
00391 setPath (path);
00392 }
00393 }
00394
00395 void GraphicsLinesForCurve::updatePointOrdinalsAfterDrag (const LineStyle &lineStyle,
00396 const Transformation &transformation)
00397 {
00398 CurveConnectAs curveConnectAs = lineStyle.curveConnectAs();
00399
00400 LOG4CPP_DEBUG_S ((*mainCat)) << "GraphicsLinesForCurve::updateGraphicsLinesToMatchGraphicsPoints"
00401 << " curve=" << m_curveName.toLatin1().data()
00402 << " curveConnectAs=" << curveConnectAsToString(curveConnectAs).toLatin1().data();
00403
00404 if (curveConnectAs == CONNECT_AS_FUNCTION_SMOOTH ||
00405 curveConnectAs == CONNECT_AS_FUNCTION_STRAIGHT) {
00406
00407
00408
00409
00410 XOrThetaToOrdinal xOrThetaToOrdinal;
00411 OrdinalToGraphicsPoint::iterator itrP;
00412 for (itrP = m_graphicsPoints.begin(); itrP != m_graphicsPoints.end(); itrP++) {
00413
00414 double ordinal = itrP.key();
00415 const GraphicsPoint *point = itrP.value();
00416
00417
00418 QPointF pointGraph;
00419 transformation.transformScreenToRawGraph(point->pos (),
00420 pointGraph);
00421
00422 xOrThetaToOrdinal [pointGraph.x()] = ordinal;
00423 }
00424
00425
00426 OrdinalToGraphicsPoint temporaryList;
00427 int ordinalNew = 0;
00428 XOrThetaToOrdinal::const_iterator itrX;
00429 for (itrX = xOrThetaToOrdinal.begin(); itrX != xOrThetaToOrdinal.end(); itrX++) {
00430
00431 double ordinalOld = *itrX;
00432 GraphicsPoint *point = m_graphicsPoints [ordinalOld];
00433
00434 temporaryList [ordinalNew++] = point;
00435 }
00436
00437
00438 m_graphicsPoints.clear();
00439 for (itrP = temporaryList.begin(); itrP != temporaryList.end(); itrP++) {
00440
00441 double ordinal = itrP.key();
00442 GraphicsPoint *point = itrP.value();
00443
00444 m_graphicsPoints [ordinal] = point;
00445 }
00446 }
00447 }