File indexing completed on 2024-12-01 12:27:07
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 }