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