#include #include #include #include "Kml.hpp" Kml::Kml(const char *pDocRoot) : kml(nullptr) , m_pPlanePlaceMark(nullptr) , m_pPathPlaceMark(nullptr) , m_docRoot(pDocRoot) , m_altitudeModeString("absolute") , m_pathColorString("0xff00ffff") { memset(m_path, 0, sizeof(m_path)); } Kml::~Kml(void) { kml = nullptr; } const char* Kml::getPath() { return m_path; } void Kml::create() { time_t time_departure; struct tm *time_now; if (kml) destroy(); kml = new XmlElement("kml"); XmlElement *pDoc = kml->createNewChildElement("Document"); XmlElement *pFile = kml->getChildByName("Document")->createNewChildElement("filename"); XmlElement *pSnippet = kml->getChildByName("Document")->createNewChildElement("Snippet"); time(&time_departure); time_now = localtime(&time_departure); char time_str[256]; // Create an outer XML element.. kml->setAttribute("xmlns", "http://www.opengis.net/kml/2.2"); sprintf(m_path, "%s\\flight_%4.4d%2.2d%2.2d_%2.2d%2.2d%2.2d.kml", m_docRoot, 1900+time_now->tm_year, time_now->tm_mon+1, time_now->tm_mday, time_now->tm_hour, time_now->tm_min, time_now->tm_sec); pFile->addTextElement(m_path); pSnippet->setAttribute("maxLines", "2"); sprintf(time_str, "Created on %4.4d-%2.2d-%2.2d at %2.2d:%2.2d:%2.2d", 1900+time_now->tm_year, time_now->tm_mon+1, time_now->tm_mday, time_now->tm_hour, time_now->tm_min, time_now->tm_sec); pSnippet->addTextElement(time_str); } void Kml::destroy() { kml = nullptr; m_pPlanePlaceMark = nullptr; m_pPathPlaceMark = nullptr; } void Kml::setAltitudeMode(String const &modeString) { m_altitudeModeString = modeString; if (m_pPlanePlaceMark) { m_pPlanePlaceMark->getChildByName("Point")->getChildByName("altitudeMode")->getFirstChildElement()->setText(modeString); } if (m_pPathPlaceMark) { m_pPathPlaceMark->getChildByName("LineString")->getChildByName("altitudeMode")->getFirstChildElement()->setText(modeString); } } void Kml::setPathColor(String const &colorString) { const ScopedLock sl (m_lock); m_pathColorString = colorString; if (m_pPathPlaceMark) { m_pPathPlaceMark->getChildByName("Style")->getChildByName("LineStyle")->getChildByName("color")->getFirstChildElement()->setText(colorString); } } void Kml::update(FlightData const &flightData) { const ScopedLock sl (m_lock); updatePlane(flightData); updatePath(flightData); } void Kml::updatePlane(FlightData const &flightData) { char temp_str[1024]; XmlElement *pDoc = kml->getChildByName("Document"); XmlElement *pPlacemark = m_pPlanePlaceMark; XmlElement *pName; XmlElement *pStyle; XmlElement *pIconStyle; XmlElement *pIcon; XmlElement *pHref; XmlElement *pHeading; XmlElement *pY, *pW, *pH; XmlElement *pDescr; XmlElement *pPoint; XmlElement *pExtrude; XmlElement *pTesselate; XmlElement *pAltitudeMode; XmlElement *pCoords; if(pPlacemark == NULL) { // Placemark pPlacemark = pDoc->createNewChildElement("Placemark"); // Name sprintf(temp_str, "Unknown flight"); if (strlen(flightData.atcFlightIDStr)) { if (strlen(flightData.atcFlightNumStr) == 0) { sprintf(temp_str, "%s", flightData.atcFlightIDStr); } else { sprintf(temp_str, "%s/%s", flightData.atcFlightIDStr, flightData.atcFlightNumStr); } } pName = pPlacemark->createNewChildElement("name"); pName->addTextElement(temp_str); printf("%s\n", temp_str); // Description pDescr = pPlacemark->createNewChildElement("description"); sprintf(temp_str, "%s\nAltitude: %d ft, Speed: %d kts", flightData.atcFlightIDStr, (int)(flightData.alt_feet+0.5), (int)(flightData.gs_knots+0.5)); pDescr->addTextElement(temp_str); // Style pStyle = pPlacemark->createNewChildElement("Style"); // IconStyle pIconStyle = pStyle->createNewChildElement("IconStyle"); pHeading = pIconStyle->createNewChildElement("heading"); sprintf(temp_str, "%d", (int)flightData.hdgTrue_deg); pHeading->addTextElement(temp_str); // Icon pIcon = pIconStyle->createNewChildElement("Icon"); pHref = pIcon->createNewChildElement("href"); pHref->addTextElement("root://icons/palette-2.png"); pY = pIcon->createNewChildElement("y"); pY->addTextElement("0"); pW = pIcon->createNewChildElement("w"); pW->addTextElement("32"); pH = pIcon->createNewChildElement("h"); pH->addTextElement("32"); // Point pPoint = pPlacemark->createNewChildElement("Point"); pExtrude = pPoint->createNewChildElement("extrude"); pExtrude->addTextElement("1"); pTesselate = pPoint->createNewChildElement("tesselate"); pTesselate->addTextElement("1"); pAltitudeMode = pPoint->createNewChildElement("altitudeMode"); pAltitudeMode->addTextElement(m_altitudeModeString); pCoords = pPoint->createNewChildElement("coordinates"); sprintf(temp_str, "%9.6f,%9.6f,%9.6f", flightData.lon, flightData.lat, flightData.alt_meter); pCoords->addTextElement(temp_str); m_pPlanePlaceMark = pPlacemark; } else { // Description sprintf(temp_str, "%s\nAltitude: %d ft, Speed: %d kts", flightData.atcFlightIDStr, (int)(flightData.alt_feet+0.5), (int)(flightData.gs_knots+0.5)); pDescr = pPlacemark->getChildByName("description"); pDescr->getFirstChildElement()->setText(temp_str); // Heading sprintf(temp_str, "%d", (int)flightData.hdgTrue_deg); pHeading = pPlacemark->getChildByName("Style")->getChildByName("IconStyle")->getChildByName("heading"); pHeading->getFirstChildElement()->setText(temp_str); // Coordinates sprintf(temp_str, "%9.6f,%9.6f,%9.6f", flightData.lon, flightData.lat, flightData.alt_meter); pCoords = pPlacemark->getChildByName("Point")->getChildByName("coordinates"); pCoords->getFirstChildElement()->setText(temp_str); } } void Kml::updatePath(FlightData const &flightData) { char temp_str[1024]; XmlElement *pDoc = kml->getChildByName("Document"); XmlElement *pPlacemark = m_pPathPlaceMark; XmlElement *pName; XmlElement *pStyle; XmlElement *pLineStyle; XmlElement *pLineColor; XmlElement *pLineWidth; XmlElement *pPolyStyle; XmlElement *pPolyColor; XmlElement *pLineString; XmlElement *pExtrude; XmlElement *pTesselate; XmlElement *pAltitudeMode; XmlElement *pCoords; if(pPlacemark == NULL) { // Placemark pPlacemark = pDoc->createNewChildElement("Placemark"); // Name pName = pPlacemark->createNewChildElement("name"); pName->addTextElement("Track"); // Style pStyle = pPlacemark->createNewChildElement("Style"); // LineStyle pLineStyle = pStyle->createNewChildElement("LineStyle"); pLineColor = pLineStyle->createNewChildElement("color"); pLineColor->addTextElement(m_pathColorString); pLineWidth = pLineStyle->createNewChildElement("width"); pLineWidth->addTextElement("4"); // PolyStyle pPolyStyle = pStyle->createNewChildElement("PolyStyle"); pPolyColor = pPolyStyle->createNewChildElement("color"); sprintf(temp_str, "%4.4X", 0x7f00ff00); pPolyColor->addTextElement(temp_str); // LineString pLineString = pPlacemark->createNewChildElement("LineString"); pExtrude = pLineString->createNewChildElement("extrude"); pExtrude->addTextElement("1"); pTesselate = pLineString->createNewChildElement("tesselate"); pTesselate->addTextElement("1"); pAltitudeMode = pLineString->createNewChildElement("altitudeMode"); pAltitudeMode->addTextElement(m_altitudeModeString); pCoords = pLineString->createNewChildElement("coordinates"); sprintf(temp_str, "%9.6f,%9.6f,%9.6f", flightData.lon, flightData.lat, flightData.alt_meter); pCoords->addTextElement(temp_str); m_pPathPlaceMark = pPlacemark; } else { // Coordinates sprintf(temp_str, "\n%9.6f,%9.6f,%9.6f", flightData.lon, flightData.lat, flightData.alt_meter); pCoords = pPlacemark->getChildByName("LineString")->getChildByName("coordinates"); pCoords->addTextElement(temp_str); } } void Kml::exportKml(const char *pPath) { const ScopedLock sl (m_lock); if (pPath && kml) { File file(pPath); kml->writeToFile(file, StringRef("")); } } void Kml::exportKmz(const char *pPath) { // ToDo: add Compression if available in Juce const ScopedLock sl (m_lock); if (pPath && kml) { File file(pPath); file.deleteFile(); ScopedPointer pStream = file.createOutputStream(); kml->writeToStream(*pStream, StringRef("")); pStream = nullptr; } } void Kml::onUpdate(const char *pPath) { exportKmz(pPath); }