1 /*************************************************************************** 2 * Copyright (C) 2003 by Tim Sutton * 3 * tim@linfiniti.com * 4 * * 5 * This program is free software; you can redistribute it and/or modify * 6 * it under the terms of the GNU General Public License as published by * 7 * the Free Software Foundation; either version 2 of the License, or * 8 * (at your option) any later version. * 9 ***************************************************************************/ 10 11 #ifndef QGSGEOREFMAINWINDOW_H 12 #define QGSGEOREFMAINWINDOW_H 13 14 #include "ui_qgsgeorefpluginguibase.h" 15 #include "qgsgeoreftransform.h" 16 17 #include "qgsgcplist.h" 18 #include "qgsmapcoordsdialog.h" 19 #include "qgsimagewarper.h" 20 #include "qgscoordinatereferencesystem.h" 21 22 #include <memory> 23 24 #include <QPointer> 25 26 class QAction; 27 class QActionGroup; 28 class QIcon; 29 class QPlainTextEdit; 30 class QLabel; 31 32 class QgisInterface; 33 class QgsDoubleSpinBox; 34 class QgsGeorefDataPoint; 35 class QgsGCPListWidget; 36 class QgsMapTool; 37 class QgsMapCanvas; 38 class QgsMapCoordsDialog; 39 class QgsPointXY; 40 class QgsRasterLayer; 41 class QgsRectangle; 42 class QgsMessageBar; 43 class QgsGeorefToolAddPoint; 44 class QgsGeorefToolDeletePoint; 45 class QgsGeorefToolMovePoint; 46 class QgsGeorefToolMovePoint; 47 class QgsGCPCanvasItem; 48 49 class QgsGeorefDockWidget : public QgsDockWidget 50 { 51 Q_OBJECT 52 public: 53 QgsGeorefDockWidget( const QString &title, QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags() ); 54 }; 55 56 class QgsGeoreferencerMainWindow : public QMainWindow, private Ui::QgsGeorefPluginGuiBase 57 { 58 Q_OBJECT 59 60 public: 61 QgsGeoreferencerMainWindow( QWidget *parent = nullptr, Qt::WindowFlags fl = Qt::WindowFlags() ); 62 ~QgsGeoreferencerMainWindow() override; 63 64 protected: 65 void closeEvent( QCloseEvent * ) override; 66 void dropEvent( QDropEvent *event ) override; 67 void dragEnterEvent( QDragEnterEvent *event ) override; 68 69 private slots: 70 // file 71 void reset(); 72 void openRaster( const QString &fileName = QString() ); 73 void doGeoreference(); 74 void generateGDALScript(); 75 bool getTransformSettings(); 76 77 // edit 78 void setAddPointTool(); 79 void setDeletePointTool(); 80 void setMovePointTool(); 81 82 // view 83 void setZoomInTool(); 84 void setZoomOutTool(); 85 void zoomToLayerTool(); 86 void zoomToLast(); 87 void zoomToNext(); 88 void setPanTool(); 89 void linkGeorefToQgis( bool link ); 90 void linkQGisToGeoref( bool link ); 91 92 // gcps 93 void addPoint( const QgsPointXY &pixelCoords, const QgsPointXY &mapCoords, 94 const QgsCoordinateReferenceSystem &crs, bool enable = true, bool finalize = true ); 95 void deleteDataPoint( QPoint pixelCoords ); 96 void deleteDataPoint( int index ); 97 void showCoordDialog( const QgsPointXY &pixelCoords ); 98 99 void selectPoint( QPoint ); 100 void movePoint( QPoint ); 101 void releasePoint( QPoint ); 102 103 void loadGCPsDialog(); 104 void saveGCPsDialog(); 105 106 // settings 107 void showRasterPropertiesDialog(); 108 void showGeorefConfigDialog(); 109 110 // comfort 111 void jumpToGCP( uint theGCPIndex ); 112 void extentsChangedGeorefCanvas(); 113 void extentsChangedQGisCanvas(); 114 void updateCanvasRotation(); 115 116 // canvas info 117 void showMouseCoords( const QgsPointXY &pt ); 118 void updateMouseCoordinatePrecision(); 119 120 // Histogram stretch 121 void localHistogramStretch(); 122 void fullHistogramStretch(); 123 124 bool updateGeorefTransform(); 125 void invalidateCanvasCoords(); 126 127 private: 128 enum SaveGCPs 129 { 130 GCPSAVE, 131 GCPSILENTSAVE, 132 GCPDISCARD, 133 GCPCANCEL 134 }; 135 136 // gui 137 void createActions(); 138 void createActionGroups(); 139 void createMapCanvas(); 140 void createMenus(); 141 void createDockWidgets(); 142 QLabel *createBaseLabelStatus(); 143 void createStatusBar(); 144 void setupConnections(); 145 void removeOldLayer(); 146 147 // Mapcanvas Plugin 148 void addRaster( const QString &file ); 149 150 // settings 151 void readSettings(); 152 void writeSettings(); 153 154 // gcp points 155 bool loadGCPs( /*bool verbose = true*/ ); 156 void saveGCPs(); 157 QgsGeoreferencerMainWindow::SaveGCPs checkNeedGCPSave(); 158 159 // georeference 160 bool georeference(); 161 bool writeWorldFile( const QgsPointXY &origin, double pixelXSize, double pixelYSize, double rotation ); 162 bool writePDFReportFile( const QString &fileName, const QgsGeorefTransform &transform ); 163 bool writePDFMapFile( const QString &fileName, const QgsGeorefTransform &transform ); 164 void updateTransformParamLabel(); 165 166 // gdal script 167 void showGDALScript( const QStringList &commands ); 168 QString generateGDALtranslateCommand( bool generateTFW = true ); 169 170 /** 171 * Generate command-line for gdalwarp based on current GCPs and given parameters. 172 * For values in the range 1 to 3, the parameter "order" prescribes the degree of the interpolating polynomials to use, 173 * a value of -1 indicates that thin plate spline interpolation should be used for warping. 174 */ 175 QString generateGDALwarpCommand( const QString &resampling, const QString &compress, bool useZeroForTrans, int order, 176 double targetResX, double targetResY ); 177 178 // utils 179 bool checkReadyGeoref(); 180 QgsRectangle transformViewportBoundingBox( const QgsRectangle &canvasExtent, QgsGeorefTransform &t, 181 bool rasterToWorld = true, uint numSamples = 4 ); 182 QString convertResamplingEnumToString( QgsImageWarper::ResamplingMethod resampling ); 183 int polynomialOrder( QgsGeorefTransform::TransformMethod transform ); 184 QString guessWorldFileName( const QString &rasterFileName ); 185 bool checkFileExisting( const QString &fileName, const QString &title, const QString &question ); 186 bool equalGCPlists( const QgsGCPList &list1, const QgsGCPList &list2 ); 187 void logTransformOptions(); 188 void logRequaredGCPs(); 189 void clearGCPData(); 190 191 /** 192 * Calculates root mean squared error for the currently active 193 * ground control points and transform method. 194 * Note that the RMSE measure is adjusted for the degrees of freedom of the 195 * used polynomial transform. 196 * \param error out: the mean error 197 * \returns TRUE in case of success 198 */ 199 bool calculateMeanError( double &error ) const; 200 201 //! Docks / undocks this window 202 void dockThisWindow( bool dock ); 203 204 QGridLayout *mCentralLayout = nullptr; 205 206 QgsMessageBar *mMessageBar = nullptr; 207 QMenu *mPanelMenu = nullptr; 208 QMenu *mToolbarMenu = nullptr; 209 210 QgsGCPListWidget *mGCPListWidget = nullptr; 211 QLineEdit *mScaleEdit = nullptr; 212 QLabel *mScaleLabel = nullptr; 213 QLabel *mCoordsLabel = nullptr; 214 QLabel *mTransformParamLabel = nullptr; 215 QLabel *mEPSG = nullptr; 216 QLabel *mRotationLabel = nullptr; 217 QgsDoubleSpinBox *mRotationEdit = nullptr; 218 unsigned int mMousePrecisionDecimalPlaces = 0; 219 220 QString mRasterFileName; 221 QString mModifiedRasterFileName; 222 QString mWorldFileName; 223 QString mTranslatedRasterFileName; 224 QString mGCPpointsFileName; 225 QgsCoordinateReferenceSystem mProjection; 226 QgsCoordinateReferenceSystem mLastGCPProjection; 227 QString mPdfOutputFile; 228 QString mPdfOutputMapFile; 229 QString mSaveGcp; 230 double mUserResX, mUserResY; // User specified target scale 231 232 QgsGcpTransformerInterface::TransformMethod mTransformParam = QgsGcpTransformerInterface::TransformMethod::InvalidTransform; 233 QgsImageWarper::ResamplingMethod mResamplingMethod; 234 QgsGeorefTransform mGeorefTransform; 235 QString mCompressionMethod; 236 237 QgsGCPList mPoints; 238 QgsGCPList mInitialPoints; 239 QgsMapCanvas *mCanvas = nullptr; 240 std::unique_ptr< QgsRasterLayer > mLayer; 241 242 QgsMapTool *mToolZoomIn = nullptr; 243 QgsMapTool *mToolZoomOut = nullptr; 244 QgsMapTool *mToolPan = nullptr; 245 QgsMapTool *mPrevQgisMapTool = nullptr; 246 QgsGeorefToolAddPoint *mToolAddPoint = nullptr; 247 QgsGeorefToolDeletePoint *mToolDeletePoint = nullptr; 248 QgsGeorefToolMovePoint *mToolMovePoint = nullptr; 249 QgsGeorefToolMovePoint *mToolMovePointQgis = nullptr; 250 251 QgsGCPCanvasItem *mNewlyAddedPointItem = nullptr; 252 253 QgsGeorefDataPoint *mMovingPoint = nullptr; 254 QgsGeorefDataPoint *mMovingPointQgis = nullptr; 255 QPointer<QgsMapCoordsDialog> mMapCoordsDialog; 256 257 bool mUseZeroForTrans = false; 258 bool mExtentsChangedRecursionGuard; 259 bool mGCPsDirty; 260 bool mLoadInQgis = false; 261 262 263 QgsDockWidget *mDock = nullptr; 264 }; 265 266 #endif 267