forked from organicmaps/organicmaps-tmp
Geometry serialization.
This commit is contained in:
parent
26b38cff75
commit
0e5fd3b1fb
4 changed files with 82 additions and 8 deletions
|
@ -236,3 +236,20 @@ UNIT_TEST(XMLFeature_FromXmlNode)
|
|||
TEST_EQUAL(copy.GetAttribute("id"), "4", ());
|
||||
TEST_EQUAL(copy.GetTagValue("amenity"), "fountain", ());
|
||||
}
|
||||
|
||||
UNIT_TEST(XMLFeature_Geometry)
|
||||
{
|
||||
XMLFeature::TMercatorGeometry const geometry = {
|
||||
{28.7206411, 3.7182409},
|
||||
{46.7569003, 47.0774689},
|
||||
{22.5909217, 41.6994874},
|
||||
{14.7537008, 17.7788229},
|
||||
{55.1261701, 10.3199476},
|
||||
{28.6519654, 50.0305930},
|
||||
{28.7206411, 3.7182409}
|
||||
};
|
||||
|
||||
XMLFeature feature(XMLFeature::Type::Way);
|
||||
feature.SetGeometry(geometry);
|
||||
TEST_EQUAL(feature.GetGeometry(), geometry, ());
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ pugi::xml_node FindTag(pugi::xml_document const & document, string const & key)
|
|||
return document.select_node(("//tag[@k='" + key + "']").data()).node();
|
||||
}
|
||||
|
||||
ms::LatLon PointFromLatLon(pugi::xml_node const & node)
|
||||
ms::LatLon GetLatLonFromNode(pugi::xml_node const & node)
|
||||
{
|
||||
ms::LatLon ll;
|
||||
if (!strings::to_double(node.attribute("lat").value(), ll.lat))
|
||||
|
@ -36,6 +36,16 @@ ms::LatLon PointFromLatLon(pugi::xml_node const & node)
|
|||
return ll;
|
||||
}
|
||||
|
||||
m2::PointD GetMercatorPointFromNode(pugi::xml_node const & node)
|
||||
{
|
||||
m2::PointD p;
|
||||
if (!strings::to_double(node.attribute("x").value(), p.x))
|
||||
MYTHROW(editor::NoXY, ("Can't parse x attribute: " + string(node.attribute("x").value())));
|
||||
if (!strings::to_double(node.attribute("y").value(), p.y))
|
||||
MYTHROW(editor::NoXY, ("Can't parse y attribute: " + string(node.attribute("y").value())));
|
||||
return p;
|
||||
}
|
||||
|
||||
void ValidateElement(pugi::xml_node const & nodeOrWay)
|
||||
{
|
||||
if (!nodeOrWay)
|
||||
|
@ -43,14 +53,13 @@ void ValidateElement(pugi::xml_node const & nodeOrWay)
|
|||
|
||||
string const type = nodeOrWay.name();
|
||||
if (type == kNodeType)
|
||||
UNUSED_VALUE(PointFromLatLon(nodeOrWay));
|
||||
UNUSED_VALUE(GetLatLonFromNode(nodeOrWay));
|
||||
else if (type != kWayType)
|
||||
MYTHROW(editor::InvalidXML, ("XMLFeature does not support root tag", type));
|
||||
|
||||
if (!nodeOrWay.attribute(kTimestamp))
|
||||
MYTHROW(editor::NoTimestamp, ("Node has no timestamp attribute"));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace editor
|
||||
|
@ -157,7 +166,7 @@ void XMLFeature::ApplyPatch(XMLFeature const & featureWithChanges)
|
|||
|
||||
ms::LatLon XMLFeature::GetCenter() const
|
||||
{
|
||||
return PointFromLatLon(GetRootNode());
|
||||
return GetLatLonFromNode(GetRootNode());
|
||||
}
|
||||
|
||||
void XMLFeature::SetCenter(ms::LatLon const & ll)
|
||||
|
@ -172,6 +181,32 @@ void XMLFeature::SetCenter(m2::PointD const & mercatorCenter)
|
|||
SetCenter(MercatorBounds::ToLatLon(mercatorCenter));
|
||||
}
|
||||
|
||||
XMLFeature::TMercatorGeometry XMLFeature::GetGeometry() const
|
||||
{
|
||||
ASSERT_EQUAL(GetType(), Type::Way, ("Only ways have geometry"));
|
||||
TMercatorGeometry geometry;
|
||||
for (auto const xCenter : GetRootNode().select_nodes("nd"))
|
||||
{
|
||||
ASSERT(xCenter.node(), ("no nd attribute."));
|
||||
geometry.emplace_back(GetMercatorPointFromNode(xCenter.node()));
|
||||
}
|
||||
return geometry;
|
||||
}
|
||||
|
||||
/// Geometry points are now stored in <nd x="..." y="..." /> nodes like in osm <way>.
|
||||
/// But they are not the same as osm's. I.e. osm's one stores reference to a <node>
|
||||
/// with it's own data and lat, lon. Here we store only cooridanes in mercator.
|
||||
void XMLFeature::SetGeometry(TMercatorGeometry const & geometry)
|
||||
{
|
||||
ASSERT_EQUAL(GetType(), Type::Way, ("Only ways have geometry"));
|
||||
for (auto const & point : geometry)
|
||||
{
|
||||
auto nd = GetRootNode().append_child("nd");
|
||||
nd.append_attribute("x") = strings::to_string_dac(point.x, kLatLonTolerance).data();
|
||||
nd.append_attribute("y") = strings::to_string_dac(point.y, kLatLonTolerance).data();
|
||||
}
|
||||
}
|
||||
|
||||
string XMLFeature::GetName(string const & lang) const
|
||||
{
|
||||
auto const suffix = (lang == kDefaultLang || lang.empty()) ? "" : ":" + lang;
|
||||
|
@ -332,4 +367,12 @@ string DebugPrint(XMLFeature const & feature)
|
|||
return ost.str();
|
||||
}
|
||||
|
||||
string DebugPrint(XMLFeature::Type const type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case XMLFeature::Type::Node: return "Node";
|
||||
case XMLFeature::Type::Way: return "Way";
|
||||
}
|
||||
}
|
||||
} // namespace editor
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace editor
|
|||
DECLARE_EXCEPTION(XMLFeatureError, RootException);
|
||||
DECLARE_EXCEPTION(InvalidXML, XMLFeatureError);
|
||||
DECLARE_EXCEPTION(NoLatLon, XMLFeatureError);
|
||||
DECLARE_EXCEPTION(NoXY, XMLFeatureError);
|
||||
DECLARE_EXCEPTION(NoTimestamp, XMLFeatureError);
|
||||
DECLARE_EXCEPTION(NoHeader, XMLFeatureError);
|
||||
|
||||
|
@ -34,6 +35,8 @@ public:
|
|||
Way
|
||||
};
|
||||
|
||||
using TMercatorGeometry = vector<m2::PointD>;
|
||||
|
||||
/// Creates empty node or way.
|
||||
XMLFeature(Type const type);
|
||||
XMLFeature(string const & xml);
|
||||
|
@ -60,6 +63,12 @@ public:
|
|||
void SetCenter(ms::LatLon const & ll);
|
||||
void SetCenter(m2::PointD const & mercatorCenter);
|
||||
|
||||
TMercatorGeometry GetGeometry() const;
|
||||
|
||||
/// Sets geometry in mercator to match against FeatureType's geometry in mwm
|
||||
/// when megrating to a new mwm build.
|
||||
void SetGeometry(TMercatorGeometry const & geometry);
|
||||
|
||||
string GetName(string const & lang) const;
|
||||
string GetName(uint8_t const langCode = StringUtf8Multilang::DEFAULT_CODE) const;
|
||||
|
||||
|
@ -133,5 +142,5 @@ private:
|
|||
};
|
||||
|
||||
string DebugPrint(XMLFeature const & feature);
|
||||
|
||||
string DebugPrint(XMLFeature::Type const type);
|
||||
} // namespace editor
|
||||
|
|
|
@ -96,10 +96,15 @@ editor::XMLFeature FeatureType::ToXML() const
|
|||
? editor::XMLFeature::Type::Node
|
||||
: editor::XMLFeature::Type::Way);
|
||||
|
||||
// Only Poins are completely serialized and deserialized.
|
||||
// Other types could only be patched.
|
||||
if (GetFeatureType() == feature::GEOM_POINT)
|
||||
{
|
||||
feature.SetCenter(GetCenter());
|
||||
}
|
||||
else
|
||||
{
|
||||
ParseTriangles(BEST_GEOMETRY);
|
||||
feature.SetGeometry({begin(m_triangles), end(m_triangles)});
|
||||
}
|
||||
|
||||
ForEachName([&feature](uint8_t const & lang, string const & name)
|
||||
{
|
||||
|
@ -124,7 +129,7 @@ editor::XMLFeature FeatureType::ToXML() const
|
|||
// feature.SetTagValue(tag.first, tag.second);
|
||||
// }
|
||||
|
||||
for (auto const type : m_metadata.GetPresentTypes())
|
||||
for (auto const type : GetMetadata().GetPresentTypes())
|
||||
{
|
||||
auto const attributeName = DebugPrint(static_cast<Metadata::EType>(type));
|
||||
feature.SetTagValue(attributeName, m_metadata.Get(type));
|
||||
|
|
Loading…
Add table
Reference in a new issue