00001
00002
00003
00004
00005
00006
00007 #include "CmdAddPointGraph.h"
00008 #include "CmdMediator.h"
00009 #include "ColorFilter.h"
00010 #include "CurveStyles.h"
00011 #include "DigitizeStateContext.h"
00012 #include "DigitizeStatePointMatch.h"
00013 #include "EngaugeAssert.h"
00014 #include "EnumsToQt.h"
00015 #include "GraphicsPoint.h"
00016 #include "GraphicsScene.h"
00017 #include "GraphicsView.h"
00018 #include "Logger.h"
00019 #include "MainWindow.h"
00020 #include "OrdinalGenerator.h"
00021 #include "PointMatchAlgorithm.h"
00022 #include "PointStyle.h"
00023 #include <QApplication>
00024 #include <QCursor>
00025 #include <QGraphicsEllipseItem>
00026 #include <QGraphicsScene>
00027 #include <QImage>
00028 #include <qmath.h>
00029 #include <QMessageBox>
00030 #include <QPen>
00031
00032 const double Z_VALUE = 200.0;
00033
00034 DigitizeStatePointMatch::DigitizeStatePointMatch (DigitizeStateContext &context) :
00035 DigitizeStateAbstractBase (context),
00036 m_outline (0),
00037 m_candidatePoint (0)
00038 {
00039 }
00040
00041 DigitizeStatePointMatch::~DigitizeStatePointMatch ()
00042 {
00043 }
00044
00045 QString DigitizeStatePointMatch::activeCurve () const
00046 {
00047 return context().mainWindow().selectedGraphCurve();
00048 }
00049
00050 void DigitizeStatePointMatch::begin (CmdMediator *cmdMediator,
00051 DigitizeState )
00052 {
00053 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::begin";
00054
00055 setCursor(cmdMediator);
00056 context().setDragMode(QGraphicsView::NoDrag);
00057 context().mainWindow().updateViewsOfSettings(activeCurve ());
00058
00059
00060 m_outline = new QGraphicsEllipseItem ();
00061 context().mainWindow().scene().addItem (m_outline);
00062 m_outline->setPen (QPen (Qt::black));
00063 m_outline->setVisible (true);
00064 m_outline->setZValue (Z_VALUE);
00065 }
00066
00067 void DigitizeStatePointMatch::createPermanentPoint (CmdMediator *cmdMediator,
00068 const QPointF &posScreen)
00069 {
00070
00071 OrdinalGenerator ordinalGenerator;
00072 Document &document = cmdMediator->document ();
00073 const Transformation &transformation = context ().mainWindow ().transformation();
00074 QUndoCommand *cmd = new CmdAddPointGraph (context ().mainWindow(),
00075 document,
00076 context ().mainWindow().selectedGraphCurve(),
00077 posScreen,
00078 ordinalGenerator.generateCurvePointOrdinal(document,
00079 transformation,
00080 posScreen,
00081 activeCurve ()));
00082 context().appendNewCmd(cmdMediator,
00083 cmd);
00084
00085 }
00086
00087 void DigitizeStatePointMatch::createTemporaryPoint (CmdMediator *cmdMediator,
00088 const QPoint &posScreen)
00089 {
00090 LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStatePointMatch::createTemporaryPoint";
00091
00092 GeometryWindow *NULL_GEOMETRY_WINDOW = 0;
00093
00094 const DocumentModelPointMatch &modelPointMatch = cmdMediator->document().modelPointMatch();
00095
00096
00097 const CurveStyles &curveStyles = cmdMediator->document().modelCurveStyles();
00098 PointStyle pointStyle = curveStyles.pointStyle (activeCurve());
00099 pointStyle.setPaletteColor (modelPointMatch.paletteColorCandidate());
00100
00101
00102 GraphicsPoint *point = context().mainWindow().scene().createPoint(Point::temporaryPointIdentifier (),
00103 pointStyle,
00104 posScreen,
00105 NULL_GEOMETRY_WINDOW);
00106
00107 context().mainWindow().scene().removeTemporaryPointIfExists();
00108
00109 context().mainWindow().scene().addTemporaryPoint (Point::temporaryPointIdentifier(),
00110 point);
00111 m_posCandidatePoint = posScreen;
00112 }
00113
00114 QCursor DigitizeStatePointMatch::cursor(CmdMediator * ) const
00115 {
00116 LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStatePointMatch::cursor";
00117
00118 return QCursor (Qt::ArrowCursor);
00119 }
00120
00121 void DigitizeStatePointMatch::end ()
00122 {
00123 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::end";
00124
00125
00126 context().mainWindow().scene().removeTemporaryPointIfExists();
00127
00128
00129 ENGAUGE_CHECK_PTR (m_outline);
00130 context().mainWindow().scene().removeItem (m_outline);
00131 m_outline = 0;
00132 }
00133
00134 QList<PointMatchPixel> DigitizeStatePointMatch::extractSamplePointPixels (const QImage &img,
00135 const DocumentModelPointMatch &modelPointMatch,
00136 const QPointF &posScreen) const
00137 {
00138 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::extractSamplePointPixels";
00139
00140
00141
00142
00143 QList<PointMatchPixel> samplePointPixels;
00144
00145 int radiusMax = modelPointMatch.maxPointSize() / 2;
00146
00147 ColorFilter colorFilter;
00148 for (int xOffset = -radiusMax; xOffset <= radiusMax; xOffset++) {
00149 for (int yOffset = -radiusMax; yOffset <= radiusMax; yOffset++) {
00150
00151 int x = posScreen.x() + xOffset;
00152 int y = posScreen.y() + yOffset;
00153 int radius = qSqrt (xOffset * xOffset + yOffset * yOffset);
00154
00155 if (radius <= radiusMax) {
00156
00157 bool pixelIsOn = colorFilter.pixelFilteredIsOn (img,
00158 x,
00159 y);
00160
00161 PointMatchPixel point (xOffset,
00162 yOffset,
00163 pixelIsOn);
00164
00165 samplePointPixels.push_back (point);
00166 }
00167 }
00168 }
00169
00170 return samplePointPixels;
00171 }
00172
00173 void DigitizeStatePointMatch::handleContextMenuEventAxis (CmdMediator * ,
00174 const QString &pointIdentifier)
00175 {
00176 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::handleContextMenuEventAxis "
00177 << " point=" << pointIdentifier.toLatin1 ().data ();
00178 }
00179
00180 void DigitizeStatePointMatch::handleContextMenuEventGraph (CmdMediator * ,
00181 const QStringList &pointIdentifiers)
00182 {
00183 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch ::handleContextMenuEventGraph "
00184 << "points=" << pointIdentifiers.join(",").toLatin1 ().data ();
00185 }
00186
00187 void DigitizeStatePointMatch::handleCurveChange(CmdMediator * )
00188 {
00189 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::handleCurveChange";
00190 }
00191
00192 void DigitizeStatePointMatch::handleKeyPress (CmdMediator *cmdMediator,
00193 Qt::Key key,
00194 bool )
00195 {
00196 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::handleKeyPress"
00197 << " key=" << QKeySequence (key).toString ().toLatin1 ().data ();
00198
00199
00200 if (key == Qt::Key_Right) {
00201
00202 promoteCandidatePointToPermanentPoint (cmdMediator);
00203
00204 popCandidatePoint(cmdMediator);
00205
00206 }
00207 }
00208
00209 void DigitizeStatePointMatch::handleMouseMove (CmdMediator *cmdMediator,
00210 QPointF posScreen)
00211 {
00212
00213
00214 const DocumentModelPointMatch &modelPointMatch = cmdMediator->document().modelPointMatch();
00215
00216 m_outline->setRect (posScreen.x() - modelPointMatch.maxPointSize() / 2.0,
00217 posScreen.y() - modelPointMatch.maxPointSize() / 2.0,
00218 modelPointMatch.maxPointSize(),
00219 modelPointMatch.maxPointSize());
00220
00221 const QImage &img = context().mainWindow().imageFiltered();
00222 int radiusLimit = cmdMediator->document().modelGeneral().cursorSize();
00223 bool pixelShouldBeOn = pixelIsOnInImage (img,
00224 posScreen.x(),
00225 posScreen.y(),
00226 radiusLimit);
00227
00228 QColor penColorIs = m_outline->pen().color();
00229 bool pixelIsOn = (penColorIs.red () != penColorIs.green());
00230 if (pixelShouldBeOn != pixelIsOn) {
00231 QColor penColorShouldBe (pixelShouldBeOn ? Qt::green : Qt::black);
00232 m_outline->setPen (QPen (penColorShouldBe));
00233 }
00234 }
00235
00236 void DigitizeStatePointMatch::handleMousePress (CmdMediator * ,
00237 QPointF )
00238 {
00239 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::handleMousePress";
00240 }
00241
00242 void DigitizeStatePointMatch::handleMouseRelease (CmdMediator *cmdMediator,
00243 QPointF posScreen)
00244 {
00245 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::handleMouseRelease";
00246
00247 createPermanentPoint (cmdMediator,
00248 posScreen);
00249
00250 findPointsAndShowFirstCandidate (cmdMediator,
00251 posScreen);
00252 }
00253
00254 void DigitizeStatePointMatch::findPointsAndShowFirstCandidate (CmdMediator *cmdMediator,
00255 const QPointF &posScreen)
00256 {
00257 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::findPointsAndShowFirstCandidate";
00258
00259 const DocumentModelPointMatch &modelPointMatch = cmdMediator->document().modelPointMatch();
00260 const QImage &img = context().mainWindow().imageFiltered();
00261
00262 QList<PointMatchPixel> samplePointPixels = extractSamplePointPixels (img,
00263 modelPointMatch,
00264 posScreen);
00265
00266 QString curveName = activeCurve();
00267 const Document &doc = cmdMediator->document();
00268 const Curve *curve = doc.curveForCurveName (curveName);
00269
00270
00271 QApplication::setOverrideCursor(Qt::WaitCursor);
00272
00273 PointMatchAlgorithm pointMatchAlgorithm (context().isGnuplot());
00274 m_candidatePoints = pointMatchAlgorithm.findPoints (samplePointPixels,
00275 img,
00276 modelPointMatch,
00277 curve->points());
00278
00279 QApplication::restoreOverrideCursor();
00280 context().mainWindow().showTemporaryMessage ("Right arrow adds next matched point");
00281
00282 popCandidatePoint (cmdMediator);
00283 }
00284
00285 bool DigitizeStatePointMatch::pixelIsOnInImage (const QImage &img,
00286 int x,
00287 int y,
00288 int radiusLimit) const
00289 {
00290 ColorFilter filter;
00291
00292
00293 bool pixelShouldBeOn = false;
00294 for (int xOffset = -radiusLimit; xOffset <= radiusLimit; xOffset++) {
00295 for (int yOffset = -radiusLimit; yOffset <= radiusLimit; yOffset++) {
00296
00297 int radius = qSqrt (xOffset * xOffset + yOffset * yOffset);
00298
00299 if (radius <= radiusLimit) {
00300
00301 int xNearby = x + xOffset;
00302 int yNearby = y + yOffset;
00303
00304 if ((0 <= xNearby) &&
00305 (0 <= yNearby) &&
00306 (xNearby < img.width()) &&
00307 (yNearby < img.height())) {
00308
00309 if (filter.pixelFilteredIsOn (img,
00310 xNearby,
00311 yNearby)) {
00312
00313 pixelShouldBeOn = true;
00314 break;
00315 }
00316 }
00317 }
00318 }
00319 }
00320
00321 return pixelShouldBeOn;
00322 }
00323
00324 void DigitizeStatePointMatch::popCandidatePoint (CmdMediator *cmdMediator)
00325 {
00326 LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStatePointMatch::popCandidatePoint";
00327
00328 if (m_candidatePoints.count() > 0) {
00329
00330
00331 QPoint posScreen = m_candidatePoints.first();
00332 m_candidatePoints.pop_front ();
00333
00334 createTemporaryPoint(cmdMediator,
00335 posScreen);
00336
00337 } else {
00338
00339
00340 QMessageBox::information (0,
00341 QObject::tr ("Point Match"),
00342 QObject::tr ("There are no more matching points"));
00343
00344 }
00345 }
00346
00347 void DigitizeStatePointMatch::promoteCandidatePointToPermanentPoint(CmdMediator *cmdMediator)
00348 {
00349 createPermanentPoint (cmdMediator,
00350 m_posCandidatePoint);
00351 }
00352
00353 QString DigitizeStatePointMatch::state() const
00354 {
00355 return "DigitizeStatePointMatch";
00356 }
00357
00358 void DigitizeStatePointMatch::updateAfterPointAddition ()
00359 {
00360 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::updateAfterPointAddition";
00361 }
00362
00363 void DigitizeStatePointMatch::updateModelDigitizeCurve (CmdMediator * ,
00364 const DocumentModelDigitizeCurve & )
00365 {
00366 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::updateModelDigitizeCurve";
00367 }
00368
00369 void DigitizeStatePointMatch::updateModelSegments(const DocumentModelSegments & )
00370 {
00371 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::updateModelSegments";
00372 }