WIP: GPX Support #4067
12 changed files with 504 additions and 3 deletions
|
@ -588,6 +588,18 @@
|
|||
<data android:mimeType="application/vnd.google-earth.kmz"/>
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<data android:scheme="content"/>
|
||||
<data android:scheme="file"/>
|
||||
<data android:scheme="data"/>
|
||||
<data android:host="*"/>
|
||||
<data android:mimeType="*/*"/>
|
||||
<data android:pathPattern=".*\\.gpx" />
|
||||
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.DEFAULT"/>
|
||||
|
|
|
@ -1083,7 +1083,7 @@ Java_app_organicmaps_Framework_nativeGetMovableFilesExts(JNIEnv * env, jclass)
|
|||
JNIEXPORT jobjectArray JNICALL
|
||||
Java_app_organicmaps_Framework_nativeGetBookmarksFilesExts(JNIEnv * env, jclass)
|
||||
{
|
||||
const vector<string> exts = { kKmzExtension, kKmlExtension, kKmbExtension };
|
||||
const vector<string> exts = { kKmzExtension, kKmlExtension, kKmbExtension, kGpxExtension };
|
||||
return jni::ToJavaStringArray(env, exts);
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,18 @@
|
|||
<string>${PRODUCT_NAME}</string>
|
||||
<key>CFBundleDocumentTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeIconFiles</key>
|
||||
<array/>
|
||||
<key>CFBundleTypeName</key>
|
||||
<string>GPS Exchange Format (GPX)</string>
|
||||
<key>LSHandlerRank</key>
|
||||
<string>Default</string>
|
||||
<key>LSItemContentTypes</key>
|
||||
<array>
|
||||
<string>com.topografix.gpx</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeIconFiles</key>
|
||||
<array>
|
||||
|
|
|
@ -7,6 +7,8 @@ set(SRC
|
|||
serdes.hpp
|
||||
serdes_binary.cpp
|
||||
serdes_binary.hpp
|
||||
serdes_gpx.cpp
|
||||
serdes_gpx.hpp
|
||||
type_utils.cpp
|
||||
type_utils.hpp
|
||||
types.cpp
|
||||
|
|
|
@ -4,6 +4,7 @@ set(SRC
|
|||
serdes_tests.cpp
|
||||
tests_data.hpp
|
||||
minzoom_quadtree_tests.cpp
|
||||
gpx_tests.cpp
|
||||
)
|
||||
|
||||
omim_add_test(${PROJECT_NAME} ${SRC})
|
||||
|
|
43
kml/kml_tests/gpx_tests.cpp
Normal file
43
kml/kml_tests/gpx_tests.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
#include "testing/testing.hpp"
|
||||
|
||||
#include "kml/serdes_gpx.hpp"
|
||||
|
||||
#include "coding/string_utf8_multilang.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
|
||||
char const * kTextGpx =
|
||||
R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gpx version="1.0">
|
||||
<wpt lat="42.81025" lon="-1.65727">
|
||||
<time>2022-09-05T08:39:39.3700Z</time>
|
||||
<name>Waypoint 1</name>
|
||||
</wpt>
|
||||
)";
|
||||
|
||||
auto const kDefaultLang = StringUtf8Multilang::kDefaultCode;
|
||||
|
||||
UNIT_TEST(Gpx_Test)
|
||||
{
|
||||
|
||||
kml::FileData dataFromText;
|
||||
try
|
||||
{
|
||||
kml::DeserializerGpx des(dataFromText);
|
||||
MemReader reader(kTextGpx, strlen(kTextGpx));
|
||||
des.Deserialize(reader);
|
||||
}
|
||||
catch (kml::DeserializerGpx::DeserializeException const & exc)
|
||||
{
|
||||
TEST(false, ("Exception raised", exc.what()));
|
||||
}
|
||||
|
||||
kml::FileData data;
|
||||
kml::BookmarkData bookmarkData;
|
||||
bookmarkData.m_name[kDefaultLang] = "Waypoint 1";
|
||||
bookmarkData.m_point = mercator::FromLatLon(42.81025, -1.65727);
|
||||
data.m_bookmarksData.emplace_back(std::move(bookmarkData));
|
||||
|
||||
TEST_EQUAL(dataFromText, data, ());
|
||||
}
|
||||
|
273
kml/serdes_gpx.cpp
Normal file
273
kml/serdes_gpx.cpp
Normal file
|
@ -0,0 +1,273 @@
|
|||
#include "kml/serdes_gpx.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
|
||||
#include "coding/hex.hpp"
|
||||
#include "coding/point_coding.hpp"
|
||||
#include "coding/string_utf8_multilang.hpp"
|
||||
|
||||
#include "geometry/mercator.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
#include "base/stl_helpers.hpp"
|
||||
#include "base/string_utils.hpp"
|
||||
#include "base/timer.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
using namespace std::string_literals;
|
||||
|
||||
namespace kml
|
||||
{
|
||||
namespace gpx
|
||||
{
|
||||
auto const kDefaultLang = StringUtf8Multilang::kDefaultCode;
|
||||
|
||||
auto const kDefaultTrackWidth = 5.0;
|
||||
|
||||
std::string PointToString(m2::PointD const & org)
|
||||
{
|
||||
double const lon = mercator::XToLon(org.x);
|
||||
double const lat = mercator::YToLat(org.y);
|
||||
|
||||
std::ostringstream ss;
|
||||
ss.precision(8);
|
||||
|
||||
ss << lon << "," << lat;
|
||||
return ss.str();
|
||||
}
|
||||
}
|
||||
|
||||
GpxParser::GpxParser(FileData & data)
|
||||
: m_data(data)
|
||||
, m_categoryData(&m_data.m_categoryData)
|
||||
, m_attrCode(StringUtf8Multilang::kUnsupportedLanguageCode)
|
||||
{
|
||||
ResetPoint();
|
||||
}
|
||||
|
||||
void GpxParser::ResetPoint()
|
||||
{
|
||||
m_name.clear();
|
||||
m_description.clear();
|
||||
m_org = {};
|
||||
m_predefinedColor = PredefinedColor::None;
|
||||
m_viewportScale = 0;
|
||||
m_timestamp = {};
|
||||
|
||||
m_color = 0;
|
||||
m_styleId.clear();
|
||||
m_mapStyleId.clear();
|
||||
m_styleUrlKey.clear();
|
||||
|
||||
m_featureTypes.clear();
|
||||
m_customName.clear();
|
||||
m_boundTracks.clear();
|
||||
m_visible = true;
|
||||
m_nearestToponym.clear();
|
||||
m_nearestToponyms.clear();
|
||||
m_properties.clear();
|
||||
m_localId = 0;
|
||||
m_trackLayers.clear();
|
||||
m_trackWidth = gpx::kDefaultTrackWidth;
|
||||
m_icon = BookmarkIcon::None;
|
||||
|
||||
m_geometry.Clear();
|
||||
m_geometryType = GEOMETRY_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
bool GpxParser::MakeValid()
|
||||
{
|
||||
if (GEOMETRY_TYPE_POINT == m_geometryType)
|
||||
{
|
||||
if (mercator::ValidX(m_org.x) && mercator::ValidY(m_org.y))
|
||||
{
|
||||
// Set default name.
|
||||
if (m_name.empty() && m_featureTypes.empty())
|
||||
m_name[gpx::kDefaultLang] = gpx::PointToString(m_org);
|
||||
|
||||
// Set default pin.
|
||||
if (m_predefinedColor == PredefinedColor::None)
|
||||
m_predefinedColor = PredefinedColor::Red;
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
else if (GEOMETRY_TYPE_LINE == m_geometryType)
|
||||
{
|
||||
return m_geometry.IsValid();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GpxParser::Push(std::string const & tag)
|
||||
{
|
||||
m_tags.push_back(tag);
|
||||
if (GetTagFromEnd(0) == "wpt")
|
||||
{
|
||||
m_geometryType = GEOMETRY_TYPE_POINT;
|
||||
}
|
||||
else if (GetTagFromEnd(0) == "trkpt")
|
||||
{
|
||||
m_geometryType = GEOMETRY_TYPE_LINE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void GpxParser::AddAttr(std::string const & attr, std::string const & value)
|
||||
{
|
||||
std::string attrInLowerCase = attr;
|
||||
strings::AsciiToLower(attrInLowerCase);
|
||||
|
||||
if (GetTagFromEnd(0) == "wpt")
|
||||
{
|
||||
if (attr == "lat")
|
||||
{
|
||||
m_lat = stod(value);
|
||||
}
|
||||
else if (attr == "lon")
|
||||
{
|
||||
m_lon = stod(value);
|
||||
}
|
||||
}
|
||||
else if (GetTagFromEnd(0) == "trkpt" && GetTagFromEnd(1) == "trkseg")
|
||||
{
|
||||
if (attr == "lat")
|
||||
{
|
||||
m_lat = stod(value);
|
||||
}
|
||||
else if (attr == "lon")
|
||||
{
|
||||
m_lon = stod(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
std::string const & GpxParser::GetTagFromEnd(size_t n) const
|
||||
{
|
||||
ASSERT_LESS(n, m_tags.size(), ());
|
||||
return m_tags[m_tags.size() - n - 1];
|
||||
}
|
||||
|
||||
void GpxParser::Pop(std::string const & tag)
|
||||
{
|
||||
ASSERT_EQUAL(m_tags.back(), tag, ());
|
||||
|
||||
if (tag == "trkpt")
|
||||
{
|
||||
m2::Point p = mercator::FromLatLon(m_lat, m_lon);
|
||||
|
||||
if (m_line.empty() || !AlmostEqualAbs(m_line.back().GetPoint(), p, kMwmPointAccuracy))
|
||||
m_line.emplace_back(p);
|
||||
|
||||
}
|
||||
else if (tag == "trkseg")
|
||||
{
|
||||
m_geometry.m_lines.push_back(std::move(m_line));
|
||||
}
|
||||
else if (tag == "wpt")
|
||||
{
|
||||
m_org = mercator::FromLatLon(m_lat, m_lon);
|
||||
}
|
||||
|
||||
if (tag == "trkseg" || tag == "wpt")
|
||||
{
|
||||
if (MakeValid())
|
||||
{
|
||||
if (GEOMETRY_TYPE_POINT == m_geometryType)
|
||||
{
|
||||
BookmarkData data;
|
||||
data.m_name = std::move(m_name);
|
||||
data.m_description = std::move(m_description);
|
||||
data.m_color.m_predefinedColor = m_predefinedColor;
|
||||
data.m_color.m_rgba = m_color;
|
||||
data.m_icon = m_icon;
|
||||
data.m_viewportScale = m_viewportScale;
|
||||
data.m_timestamp = m_timestamp;
|
||||
data.m_point = m_org;
|
||||
data.m_featureTypes = std::move(m_featureTypes);
|
||||
data.m_customName = std::move(m_customName);
|
||||
data.m_boundTracks = std::move(m_boundTracks);
|
||||
data.m_visible = m_visible;
|
||||
data.m_nearestToponym = std::move(m_nearestToponym);
|
||||
data.m_minZoom = m_minZoom;
|
||||
data.m_properties = std::move(m_properties);
|
||||
data.m_compilations = std::move(m_compilations);
|
||||
|
||||
// Here we set custom name from 'name' field for KML-files exported from 3rd-party services.
|
||||
if (data.m_name.size() == 1 && data.m_name.begin()->first == kDefaultLangCode &&
|
||||
data.m_customName.empty() && data.m_featureTypes.empty())
|
||||
{
|
||||
data.m_customName = data.m_name;
|
||||
}
|
||||
|
||||
m_data.m_bookmarksData.push_back(std::move(data));
|
||||
}
|
||||
else if (GEOMETRY_TYPE_LINE == m_geometryType)
|
||||
{
|
||||
TrackData data;
|
||||
data.m_localId = m_localId;
|
||||
data.m_name = std::move(m_name);
|
||||
data.m_description = std::move(m_description);
|
||||
data.m_layers = std::move(m_trackLayers);
|
||||
data.m_timestamp = m_timestamp;
|
||||
data.m_geometry = std::move(m_geometry);
|
||||
data.m_visible = m_visible;
|
||||
data.m_nearestToponyms = std::move(m_nearestToponyms);
|
||||
data.m_properties = std::move(m_properties);
|
||||
m_data.m_tracksData.push_back(std::move(data));
|
||||
}
|
||||
}
|
||||
ResetPoint();
|
||||
}
|
||||
m_tags.pop_back();
|
||||
}
|
||||
|
||||
void GpxParser::CharData(std::string value)
|
||||
{
|
||||
strings::Trim(value);
|
||||
|
||||
size_t const count = m_tags.size();
|
||||
if (count > 1 && !value.empty())
|
||||
{
|
||||
std::string const & currTag = m_tags[count - 1];
|
||||
std::string const & prevTag = m_tags[count - 2];
|
||||
std::string const ppTag = count > 2 ? m_tags[count - 3] : std::string();
|
||||
std::string const pppTag = count > 3 ? m_tags[count - 4] : std::string();
|
||||
std::string const ppppTag = count > 4 ? m_tags[count - 5] : std::string();
|
||||
|
||||
if (prevTag == "wpt")
|
||||
{
|
||||
if (currTag == "name")
|
||||
{
|
||||
m_name[gpx::kDefaultLang] = value;
|
||||
}
|
||||
else if (currTag == "desc")
|
||||
{
|
||||
m_description[gpx::kDefaultLang] = value;
|
||||
}
|
||||
}
|
||||
else if (prevTag == "trk")
|
||||
{
|
||||
if (currTag == "name")
|
||||
{
|
||||
m_categoryData->m_name[gpx::kDefaultLang] = value;
|
||||
}
|
||||
else if (currTag == "desc")
|
||||
{
|
||||
m_categoryData->m_description[gpx::kDefaultLang] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DeserializerGpx::DeserializerGpx(FileData & fileData)
|
||||
: m_fileData(fileData)
|
||||
{
|
||||
m_fileData = {};
|
||||
}
|
||||
|
||||
} // namespace kml
|
129
kml/serdes_gpx.hpp
Normal file
129
kml/serdes_gpx.hpp
Normal file
|
@ -0,0 +1,129 @@
|
|||
#pragma once
|
||||
|
||||
#include "kml/types.hpp"
|
||||
|
||||
#include "coding/parse_xml.hpp"
|
||||
#include "coding/reader.hpp"
|
||||
#include "coding/writer.hpp"
|
||||
|
||||
#include "geometry/point2d.hpp"
|
||||
#include "geometry/point_with_altitude.hpp"
|
||||
|
||||
#include "base/exception.hpp"
|
||||
#include "base/stl_helpers.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <string>
|
||||
|
||||
namespace kml
|
||||
{
|
||||
|
||||
class GpxParser
|
||||
{
|
||||
public:
|
||||
explicit GpxParser(FileData & data);
|
||||
bool Push(std::string const & name);
|
||||
void AddAttr(std::string const & attr, std::string const & value);
|
||||
bool IsValidAttribute(std::string const & type, std::string const & value,
|
||||
std::string const & attrInLowerCase) const;
|
||||
std::string const & GetTagFromEnd(size_t n) const;
|
||||
void Pop(std::string const & tag);
|
||||
void CharData(std::string value);
|
||||
|
||||
static kml::TrackLayer GetDefaultTrackLayer();
|
||||
|
||||
private:
|
||||
enum GeometryType
|
||||
{
|
||||
GEOMETRY_TYPE_UNKNOWN,
|
||||
GEOMETRY_TYPE_POINT,
|
||||
GEOMETRY_TYPE_LINE
|
||||
};
|
||||
|
||||
void ResetPoint();
|
||||
void SetOrigin(std::string const & s);
|
||||
void ParseLineCoordinates(std::string const & s, char const * blockSeparator,
|
||||
char const * coordSeparator);
|
||||
bool MakeValid();
|
||||
void ParseColor(std::string const &value);
|
||||
bool GetColorForStyle(std::string const & styleUrl, uint32_t & color) const;
|
||||
double GetTrackWidthForStyle(std::string const & styleUrl) const;
|
||||
|
||||
FileData & m_data;
|
||||
CategoryData m_compilationData;
|
||||
CategoryData * m_categoryData; // never null
|
||||
|
||||
std::vector<std::string> m_tags;
|
||||
GeometryType m_geometryType;
|
||||
MultiGeometry m_geometry;
|
||||
uint32_t m_color;
|
||||
|
||||
std::string m_styleId;
|
||||
std::string m_mapStyleId;
|
||||
std::string m_styleUrlKey;
|
||||
std::map<std::string, uint32_t> m_styleUrl2Color;
|
||||
std::map<std::string, double> m_styleUrl2Width;
|
||||
std::map<std::string, std::string> m_mapStyle2Style;
|
||||
|
||||
int8_t m_attrCode;
|
||||
std::string m_attrId;
|
||||
std::string m_attrKey;
|
||||
|
||||
LocalizableString m_name;
|
||||
LocalizableString m_description;
|
||||
PredefinedColor m_predefinedColor;
|
||||
Timestamp m_timestamp;
|
||||
m2::PointD m_org;
|
||||
|
||||
|
||||
|
||||
double m_lat;
|
||||
double m_lon;
|
||||
|
||||
MultiGeometry::LineT m_line;
|
||||
|
||||
|
||||
uint8_t m_viewportScale;
|
||||
std::vector<uint32_t> m_featureTypes;
|
||||
LocalizableString m_customName;
|
||||
std::vector<LocalId> m_boundTracks;
|
||||
LocalId m_localId;
|
||||
BookmarkIcon m_icon;
|
||||
std::vector<TrackLayer> m_trackLayers;
|
||||
bool m_visible;
|
||||
std::string m_nearestToponym;
|
||||
std::vector<std::string> m_nearestToponyms;
|
||||
int m_minZoom = 1;
|
||||
kml::Properties m_properties;
|
||||
std::vector<CompilationId> m_compilations;
|
||||
double m_trackWidth;
|
||||
};
|
||||
|
||||
class DeserializerGpx
|
||||
{
|
||||
public:
|
||||
DECLARE_EXCEPTION(DeserializeException, RootException);
|
||||
|
||||
explicit DeserializerGpx(FileData & fileData);
|
||||
|
||||
template <typename ReaderType>
|
||||
void Deserialize(ReaderType const & reader)
|
||||
{
|
||||
NonOwningReaderSource src(reader);
|
||||
|
||||
GpxParser parser(m_fileData);
|
||||
if (!ParseXML(src, parser, true))
|
||||
{
|
||||
// Print corrupted KML file for debug and restore purposes.
|
||||
std::string kmlText;
|
||||
reader.ReadAsString(kmlText);
|
||||
if (!kmlText.empty() && kmlText[0] == '<')
|
||||
LOG(LWARNING, (kmlText));
|
||||
MYTHROW(DeserializeException, ("Could not parse KML."));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
FileData & m_fileData;
|
||||
};
|
||||
} // namespace kml
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#include "kml/serdes.hpp"
|
||||
#include "kml/serdes_binary.hpp"
|
||||
#include "kml/serdes_gpx.hpp"
|
||||
|
||||
#include "indexer/classificator.hpp"
|
||||
#include "indexer/feature_data.hpp"
|
||||
|
@ -269,6 +270,7 @@ std::string GenerateValidAndUniqueFilePathForKML(std::string const & fileName)
|
|||
std::string const kKmzExtension = ".kmz";
|
||||
std::string const kKmlExtension = ".kml";
|
||||
std::string const kKmbExtension = ".kmb";
|
||||
std::string const kGpxExtension = ".gpx";
|
||||
std::string const kDefaultBookmarksFileName = "Bookmarks";
|
||||
|
||||
std::unique_ptr<kml::FileData> LoadKmlFile(std::string const & file, KmlFileType fileType)
|
||||
|
@ -292,7 +294,7 @@ std::string GetKMLPath(std::string const & filePath)
|
|||
{
|
||||
std::string const fileExt = GetFileExt(filePath);
|
||||
std::string fileSavePath;
|
||||
if (fileExt == kKmlExtension)
|
||||
if (fileExt == kKmlExtension || fileExt == kGpxExtension)
|
||||
{
|
||||
fileSavePath = GenerateValidAndUniqueFilePathForKML(base::FileNameFromFullPath(filePath));
|
||||
if (!base::CopyFileX(filePath, fileSavePath))
|
||||
|
@ -360,6 +362,11 @@ std::unique_ptr<kml::FileData> LoadKmlData(Reader const & reader, KmlFileType fi
|
|||
kml::DeserializerKml des(*data);
|
||||
des.Deserialize(reader);
|
||||
}
|
||||
else if (fileType == KmlFileType::Gpx)
|
||||
{
|
||||
kml::DeserializerGpx des(*data);
|
||||
des.Deserialize(reader);
|
||||
}
|
||||
else
|
||||
{
|
||||
CHECK(false, ("Not supported KmlFileType"));
|
||||
|
|
|
@ -68,11 +68,13 @@ enum class BookmarkBaseType : uint16_t
|
|||
extern std::string const kKmzExtension;
|
||||
extern std::string const kKmlExtension;
|
||||
extern std::string const kKmbExtension;
|
||||
extern std::string const kGpxExtension;
|
||||
extern std::string const kDefaultBookmarksFileName;
|
||||
|
||||
enum class KmlFileType
|
||||
{
|
||||
Text,
|
||||
Gpx,
|
||||
![]() Don't change the enum order, please. Add Gpx at the end. Don't change the enum order, please. Add Gpx at the end.
|
||||
Binary
|
||||
};
|
||||
|
||||
|
|
|
@ -1869,7 +1869,17 @@ void BookmarkManager::LoadBookmarkRoutine(std::string const & filePath, bool isT
|
|||
std::string fileSavePath = GetKMLPath(filePath);
|
||||
if (!fileSavePath.empty())
|
||||
{
|
||||
auto kmlData = LoadKmlFile(fileSavePath, KmlFileType::Text);
|
||||
auto const ext = base::GetFileExtension(filePath);
|
||||
std::unique_ptr<kml::FileData> kmlData;
|
||||
if (ext == ".gpx")
|
||||
{
|
||||
kmlData = LoadKmlFile(fileSavePath, KmlFileType::Gpx);
|
||||
![]() Please check docs/CPP_STYLE.md and use it everywhere, to save the reviewer's and your time later. Please check docs/CPP_STYLE.md and use it everywhere, to save the reviewer's and your time later.
|
||||
}
|
||||
else
|
||||
{
|
||||
kmlData = LoadKmlFile(fileSavePath, KmlFileType::Text);
|
||||
}
|
||||
|
||||
if (m_needTeardown)
|
||||
return;
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
45E4560120584DF200D9F45E /* serdes_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45E455FF20584DEF00D9F45E /* serdes_tests.cpp */; };
|
||||
45E4560320584E1C00D9F45E /* libkml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 45E4557D205849A600D9F45E /* libkml.a */; };
|
||||
45E456142058509200D9F45E /* testingmain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 45E456122058508C00D9F45E /* testingmain.cpp */; };
|
||||
464344F3294F952700984CB7 /* gpx_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 464344F2294F952700984CB7 /* gpx_tests.cpp */; };
|
||||
46AA9E60294549B000ECED73 /* serdes_gpx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 464BD0FB294546B20011955A /* serdes_gpx.cpp */; };
|
||||
E2AA225E25275C6B002589E2 /* minzoom_quadtree_tests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E2AA225C25275C6B002589E2 /* minzoom_quadtree_tests.cpp */; };
|
||||
E2DC9C9125264E3E0098174E /* types.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E2DC9C9025264E3E0098174E /* types.cpp */; };
|
||||
FA67C84B26BB365600B33DCA /* libplatform.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FA67C84A26BB365600B33DCA /* libplatform.a */; };
|
||||
|
@ -55,6 +57,9 @@
|
|||
45E455ED20584DCB00D9F45E /* kml_tests.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = kml_tests.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
45E455FF20584DEF00D9F45E /* serdes_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = serdes_tests.cpp; sourceTree = "<group>"; };
|
||||
45E456122058508C00D9F45E /* testingmain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = testingmain.cpp; path = ../../testing/testingmain.cpp; sourceTree = "<group>"; };
|
||||
464344F2294F952700984CB7 /* gpx_tests.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = gpx_tests.cpp; sourceTree = "<group>"; };
|
||||
464BD0FB294546B20011955A /* serdes_gpx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.cpp; path = serdes_gpx.cpp; sourceTree = "<group>"; };
|
||||
464BD0FC294546B20011955A /* serdes_gpx.hpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 2; lastKnownFileType = sourcecode.cpp.h; path = serdes_gpx.hpp; sourceTree = "<group>"; };
|
||||
E2AA225925275C1D002589E2 /* minzoom_quadtree.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = minzoom_quadtree.hpp; sourceTree = "<group>"; };
|
||||
E2AA225C25275C6B002589E2 /* minzoom_quadtree_tests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = minzoom_quadtree_tests.cpp; sourceTree = "<group>"; };
|
||||
E2AA225D25275C6B002589E2 /* tests_data.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = tests_data.hpp; sourceTree = "<group>"; };
|
||||
|
@ -145,6 +150,8 @@
|
|||
E2DC9C9025264E3E0098174E /* types.cpp */,
|
||||
45E4559420584ABA00D9F45E /* types.hpp */,
|
||||
45E4559120584ABA00D9F45E /* visitors.hpp */,
|
||||
464BD0FB294546B20011955A /* serdes_gpx.cpp */,
|
||||
464BD0FC294546B20011955A /* serdes_gpx.hpp */,
|
||||
);
|
||||
name = kml;
|
||||
path = ../../kml;
|
||||
|
@ -157,6 +164,7 @@
|
|||
45E455FF20584DEF00D9F45E /* serdes_tests.cpp */,
|
||||
45E456122058508C00D9F45E /* testingmain.cpp */,
|
||||
E2AA225D25275C6B002589E2 /* tests_data.hpp */,
|
||||
464344F2294F952700984CB7 /* gpx_tests.cpp */,
|
||||
);
|
||||
name = kml_tests;
|
||||
path = ../../kml/kml_tests;
|
||||
|
@ -268,7 +276,9 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
45E4559620584ABA00D9F45E /* serdes_binary.cpp in Sources */,
|
||||
464344F3294F952700984CB7 /* gpx_tests.cpp in Sources */,
|
||||
4568C86420BD455700E2192B /* type_utils.cpp in Sources */,
|
||||
46AA9E60294549B000ECED73 /* serdes_gpx.cpp in Sources */,
|
||||
45E4559520584ABA00D9F45E /* serdes.cpp in Sources */,
|
||||
E2DC9C9125264E3E0098174E /* types.cpp in Sources */,
|
||||
);
|
||||
|
|
Reference in a new issue
OSMand uses: