/** * @brief KmlExport::createTimespanPlacemark Creates a timespan placemark, which allows the * trajectory to be played forward in time. The placemark also contains pertinent data about * the vehicle's state at that timespan * @param timestampPoint * @param lastPlacemarkTime * @param newPlacemarkTime * @return Returns the placemark containing the timespan */ PlacemarkPtr KmlExport::createTimespanPlacemark(const LLAVCoordinates ×tampPoint, quint32 lastPlacemarkTime, quint32 newPlacemarkTime) { // Create coordinates CoordinatesPtr coordinates = factory->CreateCoordinates(); coordinates->add_latlngalt(timestampPoint.latitude, timestampPoint.longitude, timestampPoint.altitude); // Create point, using previous coordinates PointPtr point = factory->CreatePoint(); point->set_extrude(true); // Extrude to ground point->set_altitudemode(kmldom::ALTITUDEMODE_ABSOLUTE); point->set_coordinates(coordinates); // Create the timespan TimeSpanPtr timeSpan = factory->CreateTimeSpan(); QDateTime startTime = QDateTime::currentDateTimeUtc().addMSecs(lastPlacemarkTime); // FIXME: Make it a function of the realtime preferably gotten from the GPS QDateTime endTime = QDateTime::currentDateTimeUtc().addMSecs(newPlacemarkTime); timeSpan->set_begin(startTime.toString(dateTimeFormat).toStdString()); timeSpan->set_end(endTime.toString(dateTimeFormat).toStdString()); // Create an icon style. This arrow icon will be rotated and colored to represent velocity AttitudeActual::DataFields attitudeActualData = attitudeActual->getData(); AirspeedActual::DataFields airspeedActualData = airspeedActual->getData(); IconStylePtr iconStyle = factory->CreateIconStyle(); iconStyle->set_color(mapVelocity2Color(airspeedActualData.CalibratedAirspeed)); iconStyle->set_heading(attitudeActualData.Yaw + 180); //Adding 180 degrees because the arrow art points down, i.e. south. // Create a line style. This defines the style for the "legs" connecting the points to the ground. LineStylePtr lineStyle = factory->CreateLineStyle(); lineStyle->set_color(mapVelocity2Color(timestampPoint.groundspeed)); // Link the style to the icon StylePtr style = factory->CreateStyle(); style->set_linestyle(lineStyle); style->set_iconstyle(iconStyle); // Generate the placemark with all above attributes PlacemarkPtr placemark = factory->CreatePlacemark(); placemark->set_geometry(point); placemark->set_timeprimitive(timeSpan); placemark->set_name(QString("%1").arg(timeStamp / 1000.0).toStdString()); placemark->set_visibility(true); // Set the placemark to use the custom rotated arrow style placemark->set_styleurl("#directiveArrowStyle"); placemark->set_styleselector(style); // Add a nice description to the placemark placemark->set_description(informationString.toStdString()); return placemark; }
/** * @brief KmlExport::exportToKML Triggers logfile export to KML. */ bool KmlExport::exportToKML() { bool ret = open(); if (!ret) { qDebug () << "Logfile failed to open during KML export"; return false; } // Parses logfile and generates KML document ret = preparseLogFile(); if (!ret) { qDebug () << "Logfile preparsing failed"; return false; } // Call parser. parseLogFile(); // Add track to <Document> document->add_feature(trackFolder); // Add timespans to <Document> document->add_feature(timestampFolder); // Add ground track to <Document> { LineStringPtr linestring = factory->CreateLineString(); linestring->set_extrude(false); // Do not extrude to ground linestring->set_altitudemode(kmldom::ALTITUDEMODE_CLAMPTOGROUND); linestring->set_coordinates(wallAxes[0]); MultiGeometryPtr multiGeometry = factory->CreateMultiGeometry(); multiGeometry->add_geometry(linestring); PlacemarkPtr placemark = factory->CreatePlacemark(); placemark->set_geometry(multiGeometry); placemark->set_styleurl("#ts_2_tb"); placemark->set_name("Ground track"); document->add_feature(placemark); } // Add wall axes to <Document> FolderPtr folder = factory->CreateFolder(); for (int i=0; i<numberOfWallAxes; i++) { LineStringPtr linestring = factory->CreateLineString(); linestring->set_extrude(false); // Do not extrude to ground linestring->set_altitudemode(kmldom::ALTITUDEMODE_ABSOLUTE); linestring->set_coordinates(wallAxes[i]); MultiGeometryPtr multiGeometry = factory->CreateMultiGeometry(); multiGeometry->add_geometry(linestring); PlacemarkPtr placemark = factory->CreatePlacemark(); placemark->set_geometry(multiGeometry); placemark->set_styleurl("#ts_1_tb"); folder->add_feature(placemark); folder->set_name("Wall axes"); } document->add_feature(folder); // Create <kml> and give it <Document>. KmlPtr kml = factory->CreateKml(); kml->set_feature(document); // kml takes ownership. // Serialize to XML std::string kml_data = kmldom::SerializePretty(kml); // Save to file if (QFileInfo(outputFileName).suffix().toLower() == "kmz") { if (!kmlengine::KmzFile::WriteKmz(outputFileName.toStdString().c_str(), kml_data)) { qDebug() << "KMZ write failed: " << outputFileName; QMessageBox::critical(new QWidget(),"KMZ write failed", "Failed to write KMZ file."); return false; } } else if (QFileInfo(outputFileName).suffix().toLower() == "kml") { if (!kmlbase::File::WriteStringToFile(kml_data, outputFileName.toStdString())) { qDebug() << "KML write failed: " << outputFileName; QMessageBox::critical(new QWidget(),"KML write failed", "Failed to write KML file."); return false; } } else { qDebug() << "Write failed. Invalid file name:" << outputFileName; QMessageBox::critical(new QWidget(),"Write failed", "Failed to write file. Invalid filename"); return false; } return true; }