Files
FsTrack/Source/Kml.cpp
T
2015-01-11 12:28:49 +00:00

307 lines
8.5 KiB
C++

#include <string.h>
#include <stdlib.h>
#include <time.h>
#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<OutputStream> pStream = file.createOutputStream();
kml->writeToStream(*pStream, StringRef(""));
pStream = nullptr;
}
}
void Kml::onUpdate(const char *pPath)
{
exportKmz(pPath);
}