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 const DocumentModelPointMatch &modelPointMatch = cmdMediator->document().modelPointMatch();
00093
00094
00095 const CurveStyles &curveStyles = cmdMediator->document().modelCurveStyles();
00096 PointStyle pointStyle = curveStyles.pointStyle (activeCurve());
00097 pointStyle.setPaletteColor (modelPointMatch.paletteColorCandidate());
00098
00099
00100 GraphicsPoint *point = context().mainWindow().scene().createPoint(Point::temporaryPointIdentifier (),
00101 pointStyle,
00102 posScreen);
00103
00104 context().mainWindow().scene().removeTemporaryPointIfExists();
00105
00106 context().mainWindow().scene().addTemporaryPoint (Point::temporaryPointIdentifier(),
00107 point);
00108 m_posCandidatePoint = posScreen;
00109 }
00110
00111 QCursor DigitizeStatePointMatch::cursor(CmdMediator * ) const
00112 {
00113 LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStatePointMatch::cursor";
00114
00115 return QCursor (Qt::ArrowCursor);
00116 }
00117
00118 void DigitizeStatePointMatch::end ()
00119 {
00120 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::end";
00121
00122
00123 context().mainWindow().scene().removeTemporaryPointIfExists();
00124
00125
00126 ENGAUGE_CHECK_PTR (m_outline);
00127 context().mainWindow().scene().removeItem (m_outline);
00128 m_outline = 0;
00129 }
00130
00131 QList<PointMatchPixel> DigitizeStatePointMatch::extractSamplePointPixels (const QImage &img,
00132 const DocumentModelPointMatch &modelPointMatch,
00133 const QPointF &posScreen) const
00134 {
00135 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::extractSamplePointPixels";
00136
00137
00138
00139
00140 QList<PointMatchPixel> samplePointPixels;
00141
00142 int radiusMax = modelPointMatch.maxPointSize() / 2;
00143
00144 ColorFilter colorFilter;
00145 for (int xOffset = -radiusMax; xOffset <= radiusMax; xOffset++) {
00146 for (int yOffset = -radiusMax; yOffset <= radiusMax; yOffset++) {
00147
00148 int x = posScreen.x() + xOffset;
00149 int y = posScreen.y() + yOffset;
00150 int radius = qSqrt (xOffset * xOffset + yOffset * yOffset);
00151
00152 if (radius <= radiusMax) {
00153
00154 bool pixelIsOn = colorFilter.pixelFilteredIsOn (img,
00155 x,
00156 y);
00157
00158 PointMatchPixel point (xOffset,
00159 yOffset,
00160 pixelIsOn);
00161
00162 samplePointPixels.push_back (point);
00163 }
00164 }
00165 }
00166
00167 return samplePointPixels;
00168 }
00169
00170 void DigitizeStatePointMatch::handleCurveChange(CmdMediator * )
00171 {
00172 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::handleCurveChange";
00173 }
00174
00175 void DigitizeStatePointMatch::handleKeyPress (CmdMediator *cmdMediator,
00176 Qt::Key key,
00177 bool )
00178 {
00179 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::handleKeyPress"
00180 << " key=" << QKeySequence (key).toString ().toLatin1 ().data ();
00181
00182
00183 if (key == Qt::Key_Right) {
00184
00185 promoteCandidatePointToPermanentPoint (cmdMediator);
00186
00187 popCandidatePoint(cmdMediator);
00188
00189 }
00190 }
00191
00192 void DigitizeStatePointMatch::handleMouseMove (CmdMediator *cmdMediator,
00193 QPointF posScreen)
00194 {
00195
00196
00197 const DocumentModelPointMatch &modelPointMatch = cmdMediator->document().modelPointMatch();
00198
00199 m_outline->setRect (posScreen.x() - modelPointMatch.maxPointSize() / 2.0,
00200 posScreen.y() - modelPointMatch.maxPointSize() / 2.0,
00201 modelPointMatch.maxPointSize(),
00202 modelPointMatch.maxPointSize());
00203
00204 const QImage &img = context().mainWindow().imageFiltered();
00205 int radiusLimit = cmdMediator->document().modelGeneral().cursorSize();
00206 bool pixelShouldBeOn = pixelIsOnInImage (img,
00207 posScreen.x(),
00208 posScreen.y(),
00209 radiusLimit);
00210
00211 QColor penColorIs = m_outline->pen().color();
00212 bool pixelIsOn = (penColorIs.red () != penColorIs.green());
00213 if (pixelShouldBeOn != pixelIsOn) {
00214 QColor penColorShouldBe (pixelShouldBeOn ? Qt::green : Qt::black);
00215 m_outline->setPen (QPen (penColorShouldBe));
00216 }
00217 }
00218
00219 void DigitizeStatePointMatch::handleMousePress (CmdMediator * ,
00220 QPointF )
00221 {
00222 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::handleMousePress";
00223 }
00224
00225 void DigitizeStatePointMatch::handleMouseRelease (CmdMediator *cmdMediator,
00226 QPointF posScreen)
00227 {
00228 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::handleMouseRelease";
00229
00230 createPermanentPoint (cmdMediator,
00231 posScreen);
00232
00233 findPointsAndShowFirstCandidate (cmdMediator,
00234 posScreen);
00235 }
00236
00237 void DigitizeStatePointMatch::findPointsAndShowFirstCandidate (CmdMediator *cmdMediator,
00238 const QPointF &posScreen)
00239 {
00240 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::findPointsAndShowFirstCandidate";
00241
00242 const DocumentModelPointMatch &modelPointMatch = cmdMediator->document().modelPointMatch();
00243 const QImage &img = context().mainWindow().imageFiltered();
00244
00245 QList<PointMatchPixel> samplePointPixels = extractSamplePointPixels (img,
00246 modelPointMatch,
00247 posScreen);
00248
00249 QString curveName = activeCurve();
00250 const Document &doc = cmdMediator->document();
00251 const Curve *curve = doc.curveForCurveName (curveName);
00252
00253
00254 QApplication::setOverrideCursor(Qt::WaitCursor);
00255
00256 PointMatchAlgorithm pointMatchAlgorithm (context().isGnuplot());
00257 m_candidatePoints = pointMatchAlgorithm.findPoints (samplePointPixels,
00258 img,
00259 modelPointMatch,
00260 curve->points());
00261
00262 QApplication::restoreOverrideCursor();
00263 context().mainWindow().showTemporaryMessage ("Right arrow adds next matched point");
00264
00265 popCandidatePoint (cmdMediator);
00266 }
00267
00268 bool DigitizeStatePointMatch::pixelIsOnInImage (const QImage &img,
00269 int x,
00270 int y,
00271 int radiusLimit) const
00272 {
00273 ColorFilter filter;
00274
00275
00276 bool pixelShouldBeOn = false;
00277 for (int xOffset = -radiusLimit; xOffset <= radiusLimit; xOffset++) {
00278 for (int yOffset = -radiusLimit; yOffset <= radiusLimit; yOffset++) {
00279
00280 int radius = qSqrt (xOffset * xOffset + yOffset * yOffset);
00281
00282 if (radius <= radiusLimit) {
00283
00284 int xNearby = x + xOffset;
00285 int yNearby = y + yOffset;
00286
00287 if ((0 <= xNearby) &&
00288 (0 <= yNearby) &&
00289 (xNearby < img.width()) &&
00290 (yNearby < img.height())) {
00291
00292 if (filter.pixelFilteredIsOn (img,
00293 xNearby,
00294 yNearby)) {
00295
00296 pixelShouldBeOn = true;
00297 break;
00298 }
00299 }
00300 }
00301 }
00302 }
00303
00304 return pixelShouldBeOn;
00305 }
00306
00307 void DigitizeStatePointMatch::popCandidatePoint (CmdMediator *cmdMediator)
00308 {
00309 LOG4CPP_DEBUG_S ((*mainCat)) << "DigitizeStatePointMatch::popCandidatePoint";
00310
00311 if (m_candidatePoints.count() > 0) {
00312
00313
00314 QPoint posScreen = m_candidatePoints.first();
00315 m_candidatePoints.pop_front ();
00316
00317 createTemporaryPoint(cmdMediator,
00318 posScreen);
00319
00320 } else {
00321
00322
00323 QMessageBox::information (0,
00324 QObject::tr ("Point Match"),
00325 QObject::tr ("There are no more matching points"));
00326
00327 }
00328 }
00329
00330 void DigitizeStatePointMatch::promoteCandidatePointToPermanentPoint(CmdMediator *cmdMediator)
00331 {
00332 createPermanentPoint (cmdMediator,
00333 m_posCandidatePoint);
00334 }
00335
00336 QString DigitizeStatePointMatch::state() const
00337 {
00338 return "DigitizeStatePointMatch";
00339 }
00340
00341 void DigitizeStatePointMatch::updateModelDigitizeCurve (CmdMediator * ,
00342 const DocumentModelDigitizeCurve & )
00343 {
00344 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::updateModelDigitizeCurve";
00345 }
00346
00347 void DigitizeStatePointMatch::updateModelSegments(const DocumentModelSegments & )
00348 {
00349 LOG4CPP_INFO_S ((*mainCat)) << "DigitizeStatePointMatch::updateModelSegments";
00350 }