File indexing completed on 2024-12-08 09:32:22

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2013 Dennis Nienhüser <nienhueser@kde.org>
0004 // Loosely based on MarblePhysics.cpp
0005 //
0006 
0007 /**
0008   * Animated jump from a source point to a destination point, recording
0009   * the result to a video.
0010   */
0011 
0012 #include <marble/MarbleWidget.h>
0013 #include <marble/GeoDataCoordinates.h>
0014 #include <marble/GeoDataLineString.h>
0015 #include <marble/RenderPlugin.h>
0016 #include <marble/Quaternion.h>
0017 
0018 #include <opencv2/highgui/highgui.hpp>
0019 #include <opencv2/imgproc/imgproc.hpp>
0020 
0021 #include <QTimeLine>
0022 #include <qmath.h>
0023 #include <QApplication>
0024 
0025 #include <cstdio>
0026 
0027 using namespace Marble;
0028 using namespace cv;
0029 
0030 namespace {
0031     // Some stuff you might want to change
0032 
0033     // The map theme in use
0034     QString const mapTheme = "earth/mapquest-open-aerial/mapquest-open-aerial.dgml";
0035 
0036     // Enabled plugins. Everything else will be disabled
0037     QStringList const features = QStringList() << "stars" << "atmosphere";
0038 
0039     // Camera starting point: Position and zoom level
0040     GeoDataCoordinates const source(   8.40314, 49.01302, 0.0, GeoDataCoordinates::Degree);
0041     double const sourceZoomLevel = 11;
0042 
0043     // Camera destination point: Position and zoom level
0044     GeoDataCoordinates const destination( -101.36631, 43.13718, 0.0, GeoDataCoordinates::Degree);
0045     double const destinationZoomLevel = 14;
0046 
0047     // Minimum zoom level (in the middle of the animation)
0048     double const jumpZoomLevel = 5.5;
0049 
0050     // Length of the video
0051     QTimeLine timeLine( 20 * 1000 );
0052 
0053     // Frames per second
0054     int const fps = 30;
0055 
0056     // Target video file name
0057     std::string const videoFile = "marble-animated-zoom.avi";
0058 
0059     // Video resolution
0060     Size frameSize( 1280, 720 );
0061 }
0062 
0063 void interpolate( MarbleWidget* widget, qreal value )
0064 {
0065     GeoDataCoordinates coordinates;
0066     qreal lon, lat;
0067     Quaternion::slerp( source.quaternion(), destination.quaternion(), value ).getSpherical( lon, lat );
0068     coordinates.setLongitude( lon );
0069     coordinates.setLatitude( lat );
0070     widget->centerOn( coordinates );
0071     widget->setRadius( exp(jumpZoomLevel) + (value < 0.5 ? exp(sourceZoomLevel*(1.0-2*value)) : exp(destinationZoomLevel*(2*value-1.0))) );
0072 }
0073 
0074 void animatedFlight( MarbleWidget *mapWidget )
0075 {
0076     mapWidget->resize( frameSize.width, frameSize.height );
0077     VideoWriter videoWriter( videoFile, cv::VideoWriter::fourcc('D','I','V','X'), fps, frameSize );
0078     Mat buffer;
0079     buffer.create(frameSize, CV_8UC3);
0080     timeLine.setCurveShape( QTimeLine::EaseInOutCurve );
0081     int const frameTime = qRound( 1000.0 / fps );
0082     for ( int i=1; i<=timeLine.duration(); i+=frameTime ) {
0083         printf("[%i%% done]\r", cvRound( (100.0*i)/timeLine.duration() ) );
0084         fflush(stdout);
0085         interpolate( mapWidget, timeLine.valueForTime( i ) );
0086         QImage screenshot = QPixmap::grabWidget( mapWidget ).toImage().convertToFormat( QImage::Format_RGB888 );
0087         Mat converter( frameSize, CV_8UC3 );
0088         converter.data = screenshot.bits();
0089         cvtColor( converter, buffer, COLOR_RGB2BGR );
0090         videoWriter.write( buffer );
0091     }
0092     for ( int i=0; i<fps; ++i ) {
0093         videoWriter.write( buffer ); // one second stand-still at end
0094     }
0095     printf("Wrote %s\n", videoFile.c_str());
0096 }
0097 
0098 int main(int argc, char** argv)
0099 {
0100     QApplication app(argc,argv);
0101     MarbleWidget *mapWidget = new MarbleWidget;
0102     mapWidget->setMapThemeId(mapTheme);
0103     foreach( RenderPlugin* plugin, mapWidget->renderPlugins() ) {
0104         if ( !features.contains( plugin->nameId() ) ) {
0105             plugin->setEnabled( false );
0106         }
0107     }
0108 
0109     animatedFlight( mapWidget );
0110     return 0;
0111 }