Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortatiana-yan <tatiana.kondakova@gmail.com>2019-02-20 17:23:30 +0300
committerArsentiy Milchakov <milcars@mapswithme.com>2019-02-21 16:37:52 +0300
commitd3576782a0716364fdba40cf267e93acd64d3a64 (patch)
treecc9e31421419020df43eed61b8f2ab126a0e37de
parentbe773015f6f829b840d229bb85cc0d8809aa36f6 (diff)
[editor][indexer] Use EditableMapObject in editor instead of FeatureType.
-rw-r--r--editor/editor_tests/osm_editor_test.cpp27
-rw-r--r--editor/editor_tests/xml_feature_test.cpp10
-rw-r--r--editor/osm_editor.cpp153
-rw-r--r--editor/osm_editor.hpp11
-rw-r--r--editor/xml_feature.cpp76
-rw-r--r--editor/xml_feature.hpp11
-rw-r--r--indexer/editable_map_object.cpp26
-rw-r--r--indexer/editable_map_object.hpp11
-rw-r--r--indexer/feature.cpp176
-rw-r--r--indexer/feature.hpp25
-rw-r--r--indexer/indexer_tests/editable_map_object_test.cpp24
-rw-r--r--indexer/map_object.cpp5
-rw-r--r--indexer/map_object.hpp5
-rw-r--r--iphone/Maps/UI/Editor/MWMEditorViewController.mm2
-rw-r--r--map/framework.cpp4
-rw-r--r--search/editor_delegate.cpp14
-rw-r--r--search/editor_delegate.hpp7
-rw-r--r--search/reverse_geocoder.cpp8
-rw-r--r--search/reverse_geocoder.hpp2
19 files changed, 253 insertions, 344 deletions
diff --git a/editor/editor_tests/osm_editor_test.cpp b/editor/editor_tests/osm_editor_test.cpp
index 4660e672aa..13195724ac 100644
--- a/editor/editor_tests/osm_editor_test.cpp
+++ b/editor/editor_tests/osm_editor_test.cpp
@@ -151,8 +151,6 @@ void GenerateUploadedFeature(MwmSet::MwmId const & mwmId,
osm::EditableMapObject const & emo,
pugi::xml_document & out)
{
- auto & editor = osm::Editor::Instance();
-
pugi::xml_node root = out.append_child("mapsme");
root.append_attribute("format_version") = 1;
@@ -161,11 +159,8 @@ void GenerateUploadedFeature(MwmSet::MwmId const & mwmId,
mwmNode.append_attribute("version") = static_cast<long long>(mwmId.GetInfo()->GetVersion());
pugi::xml_node created = mwmNode.append_child("create");
- FeatureType ft;
- editor.GetEditedFeature(emo.GetID().m_mwmId, emo.GetID().m_index, ft);
-
- editor::XMLFeature xf = editor::ToXML(ft, true);
- xf.SetMWMFeatureIndex(ft.GetID().m_index);
+ editor::XMLFeature xf = editor::ToXML(emo, true);
+ xf.SetMWMFeatureIndex(emo.GetID().m_index);
xf.SetModificationTime(time(nullptr));
xf.SetUploadTime(time(nullptr));
xf.SetUploadStatus("Uploaded");
@@ -244,7 +239,7 @@ void EditorTest::GetFeatureTypeInfoTest()
auto const featuresAfter = editor.m_features.Get();
auto const fti = editor.GetFeatureTypeInfo(*featuresAfter, ft.GetID().m_mwmId, ft.GetID().m_index);
TEST_NOT_EQUAL(fti, 0, ());
- TEST_EQUAL(fti->m_feature.GetID(), ft.GetID(), ());
+ TEST_EQUAL(fti->m_object.GetID(), ft.GetID(), ());
});
}
@@ -307,26 +302,24 @@ void EditorTest::SetIndexTest()
osm::EditableMapObject emo;
CreateCafeAtPoint({2.0, 2.0}, gbMwmId, emo);
- ForEachCafeAtPoint(m_dataSource, m2::PointD(1.0, 1.0), [&editor](FeatureType & ft)
- {
- auto const firstPtr = editor.GetOriginalFeature(ft.GetID());
+ ForEachCafeAtPoint(m_dataSource, m2::PointD(1.0, 1.0), [&editor](FeatureType & ft) {
+ auto const firstPtr = editor.GetOriginalMapObject(ft.GetID());
TEST(firstPtr, ());
SetBuildingLevelsToOne(ft);
- auto const secondPtr = editor.GetOriginalFeature(ft.GetID());
+ auto const secondPtr = editor.GetOriginalMapObject(ft.GetID());
TEST(secondPtr, ());
TEST_EQUAL(firstPtr->GetID(), secondPtr->GetID(), ());
});
- ForEachCafeAtPoint(m_dataSource, m2::PointD(1.0, 1.0), [&editor](FeatureType & ft)
- {
- TEST_EQUAL(editor.GetOriginalFeatureStreet(ft), "Test street", ());
+ ForEachCafeAtPoint(m_dataSource, m2::PointD(1.0, 1.0), [&editor](FeatureType & ft) {
+ TEST_EQUAL(editor.GetOriginalFeatureStreet(ft.GetID()), "Test street", ());
EditFeature(ft, [](osm::EditableMapObject & emo)
{
osm::LocalizedStreet ls{"Some street", ""};
emo.SetStreet(ls);
});
- TEST_EQUAL(editor.GetOriginalFeatureStreet(ft), "Test street", ());
+ TEST_EQUAL(editor.GetOriginalFeatureStreet(ft.GetID()), "Test street", ());
});
uint32_t counter = 0;
@@ -991,7 +984,7 @@ void EditorTest::LoadMapEditsTest()
{
for (auto const & index : mwm.second)
{
- loadedFeatures.emplace_back(index.second.m_feature.GetID());
+ loadedFeatures.emplace_back(index.second.m_object.GetID());
}
}
};
diff --git a/editor/editor_tests/xml_feature_test.cpp b/editor/editor_tests/xml_feature_test.cpp
index fed6d4b45b..ff0a91bd74 100644
--- a/editor/editor_tests/xml_feature_test.cpp
+++ b/editor/editor_tests/xml_feature_test.cpp
@@ -3,7 +3,7 @@
#include "editor/xml_feature.hpp"
#include "indexer/classificator_loader.hpp"
-#include "indexer/feature.hpp"
+#include "indexer/editable_map_object.hpp"
#include "geometry/mercator.hpp"
@@ -368,13 +368,13 @@ UNIT_TEST(XMLFeature_FromXMLAndBackToXML)
editor::XMLFeature xmlWithType = xmlNoType;
xmlWithType.SetTagValue("amenity", "atm");
- FeatureType ft;
- editor::FromXML(xmlWithType, ft);
- auto fromFtWithType = editor::ToXML(ft, true);
+ osm::EditableMapObject emo;
+ editor::FromXML(xmlWithType, emo);
+ auto fromFtWithType = editor::ToXML(emo, true);
fromFtWithType.SetAttribute("timestamp", kTimestamp);
TEST_EQUAL(fromFtWithType, xmlWithType, ());
- auto fromFtWithoutType = editor::ToXML(ft, false);
+ auto fromFtWithoutType = editor::ToXML(emo, false);
fromFtWithoutType.SetAttribute("timestamp", kTimestamp);
TEST_EQUAL(fromFtWithoutType, xmlNoType, ());
}
diff --git a/editor/osm_editor.cpp b/editor/osm_editor.cpp
index 23db625a48..73898a97c6 100644
--- a/editor/osm_editor.cpp
+++ b/editor/osm_editor.cpp
@@ -119,37 +119,34 @@ bool NeedsUpload(string const & uploadStatus)
}
/// Compares editable fields connected with feature ignoring street.
-bool AreFeaturesEqualButStreet(FeatureType & a, FeatureType & b)
+bool AreObjectsEqualButStreet(osm::EditableMapObject const & lhs,
+ osm::EditableMapObject const & rhs)
{
- feature::TypesHolder const aTypes(a);
- feature::TypesHolder const bTypes(b);
+ feature::TypesHolder const & lhsTypes = lhs.GetTypes();
+ feature::TypesHolder const & rhsTypes = rhs.GetTypes();
- if (!aTypes.Equals(bTypes))
+ if (!lhsTypes.Equals(rhsTypes))
return false;
- if (a.GetHouseNumber() != b.GetHouseNumber())
+ if (lhs.GetHouseNumber() != rhs.GetHouseNumber())
return false;
- if (!a.GetMetadata().Equals(b.GetMetadata()))
+ if (!lhs.GetMetadata().Equals(rhs.GetMetadata()))
return false;
- if (a.GetNames() != b.GetNames())
+ if (lhs.GetNameMultilang() != rhs.GetNameMultilang())
return false;
return true;
}
-XMLFeature GetMatchingFeatureFromOSM(osm::ChangesetWrapper & cw, FeatureType & ft)
+XMLFeature GetMatchingFeatureFromOSM(osm::ChangesetWrapper & cw, osm::EditableMapObject & o)
{
- ASSERT_NOT_EQUAL(ft.GetFeatureType(), feature::GEOM_LINE,
- ("Line features are not supported yet."));
- if (ft.GetFeatureType() == feature::GEOM_POINT)
- return cw.GetMatchingNodeFeatureFromOSM(ft.GetCenter());
+ ASSERT_NOT_EQUAL(o.GetGeomType(), feature::GEOM_LINE, ("Line features are not supported yet."));
+ if (o.GetGeomType() == feature::GEOM_POINT)
+ return cw.GetMatchingNodeFeatureFromOSM(o.GetMercator());
- // Warning: geometry is cached in FeatureType. So if it wasn't BEST_GEOMETRY,
- // we can never have it. Features here came from editors loader and should
- // have BEST_GEOMETRY geometry.
- auto geometry = ft.GetTriangesAsPoints(FeatureType::BEST_GEOMETRY);
+ auto geometry = o.GetTriangesAsPoints();
ASSERT_GREATER_OR_EQUAL(geometry.size(), 3, ("Is it an area feature?"));
@@ -257,13 +254,10 @@ bool Editor::Save(FeaturesContainer const & features) const
for (auto & index : mwm.second)
{
FeatureTypeInfo const & fti = index.second;
- // Temporary solution because of FeatureType does not have constant getters.
- // TODO(a): Use constant reference instead of copy.
- auto feature = fti.m_feature;
// TODO: Do we really need to serialize deleted features in full details? Looks like mwm ID
// and meta fields are enough.
XMLFeature xf =
- editor::ToXML(feature, true /*type serializing helps during migration*/);
+ editor::ToXML(fti.m_object, true /* type serializing helps during migration */);
xf.SetMWMFeatureIndex(index.first);
if (!fti.m_street.empty())
xf.SetTagValue(kAddrStreetTag, fti.m_street);
@@ -415,15 +409,12 @@ Editor::SaveResult Editor::SaveEditedFeature(EditableMapObject const & emo)
if (wasCreatedByUser)
{
fti.m_status = FeatureStatus::Created;
- fti.m_feature.ReplaceBy(emo);
+ fti.m_object = emo;
if (featureStatus == FeatureStatus::Created)
{
auto const & editedFeatureInfo = features->at(fid.m_mwmId).at(fid.m_index);
- // Temporary solution because of FeatureType does not have constant getters.
- // TODO(a): Use constant reference instead of copy.
- auto feature = editedFeatureInfo.m_feature;
- if (AreFeaturesEqualButStreet(fti.m_feature, feature) &&
+ if (AreObjectsEqualButStreet(fti.m_object, editedFeatureInfo.m_object) &&
emo.GetStreet().m_defaultName == editedFeatureInfo.m_street)
{
return SaveResult::NothingWasChanged;
@@ -432,30 +423,23 @@ Editor::SaveResult Editor::SaveEditedFeature(EditableMapObject const & emo)
}
else
{
- auto const originalFeaturePtr = GetOriginalFeature(fid);
- if (!originalFeaturePtr)
+ auto const originalObjectPtr = GetOriginalMapObject(fid);
+ if (!originalObjectPtr)
{
LOG(LERROR, ("A feature with id", fid, "cannot be loaded."));
alohalytics::LogEvent("Editor_MissingFeature_Error");
return SaveResult::SavingError;
}
-
- fti.m_feature = featureStatus == FeatureStatus::Untouched
- ? *originalFeaturePtr
- : features->at(fid.m_mwmId).at(fid.m_index).m_feature;
- fti.m_feature.ReplaceBy(emo);
+ fti.m_object = emo;
bool const sameAsInMWM =
- AreFeaturesEqualButStreet(fti.m_feature, *originalFeaturePtr) &&
- emo.GetStreet().m_defaultName == GetOriginalFeatureStreet(fti.m_feature);
+ AreObjectsEqualButStreet(fti.m_object, *originalObjectPtr) &&
+ emo.GetStreet().m_defaultName == GetOriginalFeatureStreet(fti.m_object.GetID());
if (featureStatus != FeatureStatus::Untouched)
{
// A feature was modified and equals to the one in editor.
auto const & editedFeatureInfo = features->at(fid.m_mwmId).at(fid.m_index);
- // Temporary solution because of FeatureType does not have constant getters.
- // TODO(a): Use constant reference instead of copy.
- auto feature = editedFeatureInfo.m_feature;
- if (AreFeaturesEqualButStreet(fti.m_feature, feature) &&
+ if (AreObjectsEqualButStreet(fti.m_object, editedFeatureInfo.m_object) &&
emo.GetStreet().m_defaultName == editedFeatureInfo.m_street)
{
return SaveResult::NothingWasChanged;
@@ -527,10 +511,7 @@ void Editor::ForEachCreatedFeature(MwmSet::MwmId const & id, FeatureIndexFunctor
FeatureTypeInfo const & ftInfo = index.second;
if (ftInfo.m_status == FeatureStatus::Created)
{
- // Temporary solution because of FeatureType does not have constant getters.
- // TODO(a): Use constant reference instead of copy.
- auto feature = ftInfo.m_feature;
- if (rect.IsPointInside(feature.GetCenter()))
+ if (rect.IsPointInside(ftInfo.m_object.GetMercator()))
f(index.first);
}
}
@@ -544,7 +525,7 @@ bool Editor::GetEditedFeature(MwmSet::MwmId const & mwmId, uint32_t index,
if (featureInfo == nullptr)
return false;
- outFeature = featureInfo->m_feature;
+ outFeature = FeatureType::ConstructFromMapObject(featureInfo->m_object);
return true;
}
@@ -601,15 +582,15 @@ EditableProperties Editor::GetEditableProperties(FeatureType & feature) const
// Disable opening hours editing if opening hours cannot be parsed.
if (featureStatus != FeatureStatus::Created)
{
- auto const originalFeaturePtr = GetOriginalFeature(fid);
- if (!originalFeaturePtr)
+ auto const originalObjectPtr = GetOriginalMapObject(fid);
+ if (!originalObjectPtr)
{
LOG(LERROR, ("A feature with id", fid, "cannot be loaded."));
alohalytics::LogEvent("Editor_MissingFeature_Error");
return {};
}
- auto const & metadata = originalFeaturePtr->GetMetadata();
+ auto const & metadata = originalObjectPtr->GetMetadata();
auto const & featureOpeningHours = metadata.Get(feature::Metadata::FMD_OPEN_HOURS);
// Note: empty string is parsed as a valid opening hours rule.
if (!osmoh::OpeningHours(featureOpeningHours).IsValid())
@@ -693,9 +674,6 @@ void Editor::UploadChanges(string const & key, string const & secret, ChangesetT
// TODO(a): Use UploadInfo as part of FeatureTypeInfo.
UploadInfo uploadInfo = {fti.m_uploadAttemptTimestamp, fti.m_uploadStatus, fti.m_uploadError};
- // Temporary solution because of FeatureType does not have constant getters.
- // TODO(a): Use constant reference instead of copy.
- auto featureData = fti.m_feature;
string ourDebugFeatureString;
try
@@ -706,7 +684,7 @@ void Editor::UploadChanges(string const & key, string const & secret, ChangesetT
case FeatureStatus::Obsolete: continue; // Obsolete features will be deleted by OSMers.
case FeatureStatus::Created:
{
- XMLFeature feature = editor::ToXML(featureData, true);
+ XMLFeature feature = editor::ToXML(fti.m_object, true);
if (!fti.m_street.empty())
feature.SetTagValue(kAddrStreetTag, fti.m_street);
ourDebugFeatureString = DebugPrint(feature);
@@ -715,7 +693,7 @@ void Editor::UploadChanges(string const & key, string const & secret, ChangesetT
("Linear and area features creation is not supported yet."));
try
{
- auto const center = featureData.GetCenter();
+ auto const center = fti.m_object.GetMercator();
XMLFeature osmFeature = changeset.GetMatchingNodeFeatureFromOSM(center);
// If we are here, it means that object already exists at the given point.
@@ -757,24 +735,23 @@ void Editor::UploadChanges(string const & key, string const & secret, ChangesetT
{
// Do not serialize feature's type to avoid breaking OSM data.
// TODO: Implement correct types matching when we support modifying existing feature types.
- XMLFeature feature = editor::ToXML(featureData, false);
+ XMLFeature feature = editor::ToXML(fti.m_object, false);
if (!fti.m_street.empty())
feature.SetTagValue(kAddrStreetTag, fti.m_street);
ourDebugFeatureString = DebugPrint(feature);
- auto const originalFeaturePtr = GetOriginalFeature(fti.m_feature.GetID());
- if (!originalFeaturePtr)
+ auto const originalObjectPtr = GetOriginalMapObject(fti.m_object.GetID());
+ if (!originalObjectPtr)
{
- LOG(LERROR, ("A feature with id", fti.m_feature.GetID(), "cannot be loaded."));
+ LOG(LERROR, ("A feature with id", fti.m_object.GetID(), "cannot be loaded."));
alohalytics::LogEvent("Editor_MissingFeature_Error");
- GetPlatform().RunTask(Platform::Thread::Gui, [this, fid = fti.m_feature.GetID()]()
- {
+ GetPlatform().RunTask(Platform::Thread::Gui, [this, fid = fti.m_object.GetID()]() {
RemoveFeatureIfExists(fid);
});
continue;
}
- XMLFeature osmFeature = GetMatchingFeatureFromOSM(changeset, *originalFeaturePtr);
+ XMLFeature osmFeature = GetMatchingFeatureFromOSM(changeset, *originalObjectPtr);
XMLFeature const osmFeatureCopy = osmFeature;
osmFeature.ApplyPatch(feature);
// Check to avoid uploading duplicates into OSM.
@@ -793,18 +770,17 @@ void Editor::UploadChanges(string const & key, string const & secret, ChangesetT
break;
case FeatureStatus::Deleted:
- auto const originalFeaturePtr = GetOriginalFeature(fti.m_feature.GetID());
- if (!originalFeaturePtr)
+ auto const originalObjectPtr = GetOriginalMapObject(fti.m_object.GetID());
+ if (!originalObjectPtr)
{
- LOG(LERROR, ("A feature with id", fti.m_feature.GetID(), "cannot be loaded."));
+ LOG(LERROR, ("A feature with id", fti.m_object.GetID(), "cannot be loaded."));
alohalytics::LogEvent("Editor_MissingFeature_Error");
- GetPlatform().RunTask(Platform::Thread::Gui, [this, fid = fti.m_feature.GetID()]()
- {
+ GetPlatform().RunTask(Platform::Thread::Gui, [this, fid = fti.m_object.GetID()]() {
RemoveFeatureIfExists(fid);
});
continue;
}
- changeset.Delete(GetMatchingFeatureFromOSM(changeset, *originalFeaturePtr));
+ changeset.Delete(GetMatchingFeatureFromOSM(changeset, *originalObjectPtr));
break;
}
uploadInfo.m_uploadStatus = kUploaded;
@@ -837,22 +813,22 @@ void Editor::UploadChanges(string const & key, string const & secret, ChangesetT
if (uploadInfo.m_uploadStatus != kUploaded)
{
- ms::LatLon const ll = MercatorBounds::ToLatLon(feature::GetCenter(featureData));
+ ms::LatLon const ll = fti.m_object.GetLatLon();
alohalytics::LogEvent(
"Editor_DataSync_error",
{{"type", fti.m_uploadStatus},
{"details", fti.m_uploadError},
{"our", ourDebugFeatureString},
- {"mwm", fti.m_feature.GetID().GetMwmName()},
- {"mwm_version", strings::to_string(fti.m_feature.GetID().GetMwmVersion())}},
+ {"mwm", fti.m_object.GetID().GetMwmName()},
+ {"mwm_version", strings::to_string(fti.m_object.GetID().GetMwmVersion())}},
alohalytics::Location::FromLatLon(ll.lat, ll.lon));
}
- GetPlatform().RunTask(Platform::Thread::Gui, [this, id = fti.m_feature.GetID(), uploadInfo]()
- {
- // Call Save every time we modify each feature's information.
- SaveUploadedInformation(id, uploadInfo);
- });
+ GetPlatform().RunTask(Platform::Thread::Gui,
+ [this, id = fti.m_object.GetID(), uploadInfo]() {
+ // Call Save every time we modify each feature's information.
+ SaveUploadedInformation(id, uploadInfo);
+ });
}
}
@@ -915,23 +891,23 @@ bool Editor::FillFeatureInfo(FeatureStatus status, XMLFeature const & xml, Featu
{
if (status == FeatureStatus::Created)
{
- editor::FromXML(xml, fti.m_feature);
+ editor::FromXML(xml, fti.m_object);
}
else
{
- auto const originalFeaturePtr = GetOriginalFeature(fid);
- if (!originalFeaturePtr)
+ auto const originalObjectPtr = GetOriginalMapObject(fid);
+ if (!originalObjectPtr)
{
LOG(LERROR, ("A feature with id", fid, "cannot be loaded."));
alohalytics::LogEvent("Editor_MissingFeature_Error");
return false;
}
- fti.m_feature = *originalFeaturePtr;
- editor::ApplyPatch(xml, fti.m_feature);
+ fti.m_object = *originalObjectPtr;
+ editor::ApplyPatch(xml, fti.m_object);
}
- fti.m_feature.SetID(fid);
+ fti.m_object.SetID(fid);
fti.m_street = xml.GetTagValue(kAddrStreetTag);
fti.m_modificationTimestamp = xml.GetModificationTime();
@@ -1031,16 +1007,13 @@ Editor::Stats Editor::GetStats() const
for (auto & index : id.second)
{
auto const & fti = index.second;
- // Temporary solution because of FeatureType does not have constant getters.
- // TODO(a): Use constant reference instead of copy.
- auto feature = fti.m_feature;
stats.m_edits.push_back(make_pair(FeatureID(id.first, index.first),
fti.m_uploadStatus + " " + fti.m_uploadError));
LOG(LDEBUG, (fti.m_uploadAttemptTimestamp == base::INVALID_TIME_STAMP
? "NOT_UPLOADED_YET"
: base::TimestampToString(fti.m_uploadAttemptTimestamp),
- fti.m_uploadStatus, fti.m_uploadError, feature.GetFeatureType(),
- feature::GetCenter(feature)));
+ fti.m_uploadStatus, fti.m_uploadError, fti.m_object.GetGeomType(),
+ fti.m_object.GetMercator()));
if (fti.m_uploadStatus == kUploaded)
{
++stats.m_uploadedCount;
@@ -1161,16 +1134,16 @@ void Editor::MarkFeatureWithStatus(FeaturesContainer & editableFeatures, Feature
auto & fti = editableFeatures[fid.m_mwmId][fid.m_index];
- auto const originalFeaturePtr = GetOriginalFeature(fid);
+ auto const originalObjectPtr = GetOriginalMapObject(fid);
- if (!originalFeaturePtr)
+ if (!originalObjectPtr)
{
LOG(LERROR, ("A feature with id", fid, "cannot be loaded."));
alohalytics::LogEvent("Editor_MissingFeature_Error");
return;
}
- fti.m_feature = *originalFeaturePtr;
+ fti.m_object = *originalObjectPtr;
fti.m_status = status;
fti.m_modificationTimestamp = time(nullptr);
}
@@ -1185,24 +1158,24 @@ MwmSet::MwmId Editor::GetMwmIdByMapName(string const & name)
return m_delegate->GetMwmIdByMapName(name);
}
-unique_ptr<FeatureType> Editor::GetOriginalFeature(FeatureID const & fid) const
+unique_ptr<EditableMapObject> Editor::GetOriginalMapObject(FeatureID const & fid) const
{
if (!m_delegate)
{
LOG(LERROR, ("Can't get original feature by id:", fid, ", delegate is not set."));
return {};
}
- return m_delegate->GetOriginalFeature(fid);
+ return m_delegate->GetOriginalMapObject(fid);
}
-string Editor::GetOriginalFeatureStreet(FeatureType & ft) const
+string Editor::GetOriginalFeatureStreet(FeatureID const & fid) const
{
if (!m_delegate)
{
LOG(LERROR, ("Can't get feature street, delegate is not set."));
return {};
}
- return m_delegate->GetOriginalFeatureStreet(ft);
+ return m_delegate->GetOriginalFeatureStreet(fid);
}
void Editor::ForEachFeatureAtPoint(FeatureTypeFn && fn, m2::PointD const & point) const
diff --git a/editor/osm_editor.hpp b/editor/osm_editor.hpp
index 7666d15d6c..d5a229857a 100644
--- a/editor/osm_editor.hpp
+++ b/editor/osm_editor.hpp
@@ -58,8 +58,8 @@ public:
virtual ~Delegate() = default;
virtual MwmSet::MwmId GetMwmIdByMapName(string const & name) const = 0;
- virtual unique_ptr<FeatureType> GetOriginalFeature(FeatureID const & fid) const = 0;
- virtual string GetOriginalFeatureStreet(FeatureType & ft) const = 0;
+ virtual unique_ptr<EditableMapObject> GetOriginalMapObject(FeatureID const & fid) const = 0;
+ virtual string GetOriginalFeatureStreet(FeatureID const & fid) const = 0;
virtual void ForEachFeatureAtPoint(FeatureTypeFn && fn, m2::PointD const & point) const = 0;
};
@@ -196,8 +196,7 @@ private:
struct FeatureTypeInfo
{
FeatureStatus m_status;
- // TODO(AlexZ): Integrate EditableMapObject class into an editor instead of FeatureType.
- FeatureType m_feature;
+ EditableMapObject m_object;
/// If not empty contains Feature's addr:street, edited by user.
string m_street;
time_t m_modificationTimestamp = base::INVALID_TIME_STAMP;
@@ -236,8 +235,8 @@ private:
// These methods are just checked wrappers around Delegate.
MwmSet::MwmId GetMwmIdByMapName(string const & name);
- unique_ptr<FeatureType> GetOriginalFeature(FeatureID const & fid) const;
- string GetOriginalFeatureStreet(FeatureType & ft) const;
+ unique_ptr<EditableMapObject> GetOriginalMapObject(FeatureID const & fid) const;
+ string GetOriginalFeatureStreet(FeatureID const & fid) const;
void ForEachFeatureAtPoint(FeatureTypeFn && fn, m2::PointD const & point) const;
FeatureID GetFeatureIdByXmlFeature(FeaturesContainer const & features,
editor::XMLFeature const & xml, MwmSet::MwmId const & mwmId,
diff --git a/editor/xml_feature.cpp b/editor/xml_feature.cpp
index 58e7c5a36e..e6e7d57484 100644
--- a/editor/xml_feature.cpp
+++ b/editor/xml_feature.cpp
@@ -1,15 +1,17 @@
#include "editor/xml_feature.hpp"
#include "indexer/classificator.hpp"
-#include "indexer/feature.hpp"
+#include "indexer/editable_map_object.hpp"
+
+#include "coding/string_utf8_multilang.hpp"
+
+#include "geometry/latlon.hpp"
#include "base/exception.hpp"
#include "base/macros.hpp"
#include "base/string_utils.hpp"
#include "base/timer.hpp"
-#include "geometry/latlon.hpp"
-
#include <array>
#include <sstream>
#include <string>
@@ -381,52 +383,47 @@ XMLFeature::Type XMLFeature::StringToType(string const & type)
return Type::Unknown;
}
-void ApplyPatch(XMLFeature const & xml, FeatureType & feature)
+void ApplyPatch(XMLFeature const & xml, osm::EditableMapObject & object)
{
- xml.ForEachName([&feature](string const & lang, string const & name) {
- feature.GetParams().name.AddString(lang, name);
+ xml.ForEachName([&object](string const & lang, string const & name) {
+ object.SetName(name, StringUtf8Multilang::GetLangIndex(lang));
});
string const house = xml.GetHouse();
if (!house.empty())
- feature.GetParams().house.Set(house);
+ object.SetHouseNumber(house);
- xml.ForEachTag([&feature](string const & k, string const & v) {
- if (!feature.UpdateMetadataValue(k, v))
+ xml.ForEachTag([&object](string const & k, string const & v) {
+ if (!object.UpdateMetadataValue(k, v))
LOG(LWARNING, ("Patch feature has unknown tags", k, v));
});
-
- // If types count are changed here, in ApplyPatch, new number of types should be passed
- // instead of GetTypesCount().
- // So we call UpdateHeader for recalc header and update parsed parts.
- feature.UpdateHeader(true /* commonParsed */, true /* metadataParsed */);
}
-XMLFeature ToXML(FeatureType & fromFeature, bool serializeType)
+XMLFeature ToXML(osm::EditableMapObject const & object, bool serializeType)
{
- bool const isPoint = fromFeature.GetFeatureType() == feature::GEOM_POINT;
+ bool const isPoint = object.GetGeomType() == feature::GEOM_POINT;
XMLFeature toFeature(isPoint ? XMLFeature::Type::Node : XMLFeature::Type::Way);
if (isPoint)
{
- toFeature.SetCenter(fromFeature.GetCenter());
+ toFeature.SetCenter(object.GetMercator());
}
else
{
- auto const & triangles = fromFeature.GetTriangesAsPoints(FeatureType::BEST_GEOMETRY);
+ auto const & triangles = object.GetTriangesAsPoints();
toFeature.SetGeometry(begin(triangles), end(triangles));
}
- fromFeature.ForEachName(
+ object.GetNameMultilang().ForEach(
[&toFeature](uint8_t const & lang, string const & name) { toFeature.SetName(lang, name); });
- string const house = fromFeature.GetHouseNumber();
+ string const house = object.GetHouseNumber();
if (!house.empty())
toFeature.SetHouse(house);
if (serializeType)
{
- feature::TypesHolder th(fromFeature);
+ feature::TypesHolder th = object.GetTypes();
// TODO(mgsergio): Use correct sorting instead of SortBySpec based on the config.
th.SortBySpec();
// TODO(mgsergio): Either improve "OSM"-compatible serialization for more complex types,
@@ -455,31 +452,31 @@ XMLFeature ToXML(FeatureType & fromFeature, bool serializeType)
}
}
- fromFeature.ForEachMetadataItem(true /* skipSponsored */,
- [&toFeature](string const & tag, string const & value) {
- toFeature.SetTagValue(tag, value);
- });
+ object.ForEachMetadataItem(true /* skipSponsored */,
+ [&toFeature](string const & tag, string const & value) {
+ toFeature.SetTagValue(tag, value);
+ });
return toFeature;
}
-bool FromXML(XMLFeature const & xml, FeatureType & feature)
+bool FromXML(XMLFeature const & xml, osm::EditableMapObject & object)
{
ASSERT_EQUAL(XMLFeature::Type::Node, xml.GetType(),
- ("At the moment only new nodes (points) can can be created."));
- feature.SetCenter(xml.GetMercatorCenter());
- xml.ForEachName([&feature](string const & lang, string const & name) {
- feature.GetParams().name.AddString(lang, name);
+ ("At the moment only new nodes (points) can be created."));
+ object.SetPointType();
+ object.SetMercator(xml.GetMercatorCenter());
+ xml.ForEachName([&object](string const & lang, string const & name) {
+ object.SetName(name, StringUtf8Multilang::GetLangIndex(lang));
});
string const house = xml.GetHouse();
if (!house.empty())
- feature.GetParams().house.Set(house);
+ object.SetHouseNumber(house);
- uint32_t typesCount = 0;
- array<uint32_t, feature::kMaxTypesCount> types;
- xml.ForEachTag([&feature, &types, &typesCount](string const & k, string const & v) {
- if (feature.UpdateMetadataValue(k, v))
+ feature::TypesHolder types;
+ xml.ForEachTag([&object, &types](string const & k, string const & v) {
+ if (object.UpdateMetadataValue(k, v))
return;
// Simple heuristics. It works if all our supported types for
@@ -492,18 +489,17 @@ bool FromXML(XMLFeature const & xml, FeatureType & feature)
if (type == 0)
type = cl.GetTypeByPathSafe({"amenity", k}); // atm=yes, toilet=yes etc.
- if (type && typesCount >= feature::kMaxTypesCount)
+ if (type && types.Size() >= feature::kMaxTypesCount)
LOG(LERROR, ("Can't add type:", k, v, ". Types limit exceeded."));
else if (type)
- types[typesCount++] = type;
+ types.Add(type);
else
LOG(LWARNING, ("Can't load/parse type:", k, v));
});
- feature.SetTypes(types, typesCount);
- feature.UpdateHeader(true /* commonParsed */, true /* metadataParsed */);
+ object.SetTypes(types);
- return typesCount > 0;
+ return types.Size() > 0;
}
string DebugPrint(XMLFeature const & feature)
diff --git a/editor/xml_feature.hpp b/editor/xml_feature.hpp
index ecc10e90bd..abbab0388d 100644
--- a/editor/xml_feature.hpp
+++ b/editor/xml_feature.hpp
@@ -13,7 +13,10 @@
#include "3party/pugixml/src/pugixml.hpp"
-class FeatureType;
+namespace osm
+{
+class EditableMapObject;
+}
namespace editor
{
@@ -175,16 +178,16 @@ private:
/// Rewrites all but geometry and types.
/// Should be applied to existing features only (in mwm files).
-void ApplyPatch(XMLFeature const & xml, FeatureType & feature);
+void ApplyPatch(XMLFeature const & xml, osm::EditableMapObject & object);
/// @param serializeType if false, types are not serialized.
/// Useful for applying modifications to existing OSM features, to avoid issues when someone
/// has changed a type in OSM, but our users uploaded invalid outdated type after modifying feature.
-XMLFeature ToXML(FeatureType & feature, bool serializeType);
+XMLFeature ToXML(osm::EditableMapObject const & object, bool serializeType);
/// Creates new feature, including geometry and types.
/// @Note: only nodes (points) are supported at the moment.
-bool FromXML(XMLFeature const & xml, FeatureType & feature);
+bool FromXML(XMLFeature const & xml, osm::EditableMapObject & object);
string DebugPrint(XMLFeature const & feature);
string DebugPrint(XMLFeature::Type const type);
diff --git a/indexer/editable_map_object.cpp b/indexer/editable_map_object.cpp
index 2360cce6cc..5685e46cc4 100644
--- a/indexer/editable_map_object.cpp
+++ b/indexer/editable_map_object.cpp
@@ -213,8 +213,6 @@ vector<feature::Metadata::EType> const & EditableMapObject::GetEditableFields()
return m_editableProperties.m_metadata;
}
-StringUtf8Multilang const & EditableMapObject::GetName() const { return m_name; }
-
NamesDataSource EditableMapObject::GetNamesDataSource(bool needFakes /* = true */)
{
auto const mwmInfo = GetID().m_mwmId.GetInfo();
@@ -282,7 +280,6 @@ NamesDataSource EditableMapObject::GetNamesDataSource(StringUtf8Multilang const
}
vector<LocalizedStreet> const & EditableMapObject::GetNearbyStreets() const { return m_nearbyStreets; }
-string const & EditableMapObject::GetHouseNumber() const { return m_houseNumber; }
string EditableMapObject::GetPostcode() const
{
@@ -294,6 +291,18 @@ string EditableMapObject::GetWikipedia() const
return m_metadata.Get(feature::Metadata::FMD_WIKIPEDIA);
}
+void EditableMapObject::ForEachMetadataItem(
+ bool skipSponsored, function<void(string const & tag, string const & value)> const & fn) const
+{
+ for (auto const type : m_metadata.GetPresentTypes())
+ {
+ if (skipSponsored && m_metadata.IsSponsoredType(static_cast<feature::Metadata::EType>(type)))
+ continue;
+ auto const attributeName = ToString(static_cast<feature::Metadata::EType>(type));
+ fn(attributeName, m_metadata.Get(type));
+ }
+}
+
uint64_t EditableMapObject::GetTestId() const
{
istringstream iss(m_metadata.Get(feature::Metadata::FMD_TEST_ID));
@@ -420,6 +429,8 @@ void EditableMapObject::SetType(uint32_t featureType)
}
}
+void EditableMapObject::SetTypes(feature::TypesHolder const & types) { m_types = types; }
+
void EditableMapObject::SetID(FeatureID const & fid) { m_featureID = fid; }
void EditableMapObject::SetStreet(LocalizedStreet const & st) { m_street = st; }
@@ -433,6 +444,15 @@ void EditableMapObject::SetHouseNumber(string const & houseNumber)
m_houseNumber = houseNumber;
}
+bool EditableMapObject::UpdateMetadataValue(string const & key, string const & value)
+{
+ feature::Metadata::EType mdType;
+ if (!feature::Metadata::TypeFromString(key, mdType))
+ return false;
+ m_metadata.Set(mdType, value);
+ return true;
+}
+
void EditableMapObject::SetPostcode(string const & postcode)
{
m_metadata.Set(feature::Metadata::FMD_POSTCODE, postcode);
diff --git a/indexer/editable_map_object.hpp b/indexer/editable_map_object.hpp
index a11624949b..0945e7ab42 100644
--- a/indexer/editable_map_object.hpp
+++ b/indexer/editable_map_object.hpp
@@ -11,6 +11,7 @@
#include "coding/string_utf8_multilang.hpp"
#include <cstdint>
+#include <functional>
#include <string>
#include <vector>
@@ -103,15 +104,17 @@ public:
// TODO(AlexZ): Remove this method and use GetEditableProperties() in UI.
std::vector<feature::Metadata::EType> const & GetEditableFields() const;
- StringUtf8Multilang const & GetName() const;
/// See comment for NamesDataSource class.
NamesDataSource GetNamesDataSource(bool addFakes = true);
LocalizedStreet const & GetStreet() const;
std::vector<LocalizedStreet> const & GetNearbyStreets() const;
- std::string const & GetHouseNumber() const;
std::string GetPostcode() const;
std::string GetWikipedia() const;
+ void ForEachMetadataItem(
+ bool skipSponsored,
+ std::function<void(std::string const & tag, std::string const & value)> const & fn) const;
+
// These two methods should only be used in tests.
uint64_t GetTestId() const;
void SetTestId(uint64_t id);
@@ -122,12 +125,13 @@ public:
void SetName(std::string name, int8_t langCode = StringUtf8Multilang::kDefaultCode);
void SetMercator(m2::PointD const & center);
void SetType(uint32_t featureType);
+ void SetTypes(feature::TypesHolder const & types);
void SetID(FeatureID const & fid);
- // void SetTypes(feature::TypesHolder const & types);
void SetStreet(LocalizedStreet const & st);
void SetNearbyStreets(std::vector<LocalizedStreet> && streets);
void SetHouseNumber(std::string const & houseNumber);
+ bool UpdateMetadataValue(std::string const & key, std::string const & value);
void SetPostcode(std::string const & postcode);
void SetPhone(std::string const & phone);
void SetFax(std::string const & fax);
@@ -180,7 +184,6 @@ public:
static void RemoveFakeNames(FakeNames const & fakeNames, StringUtf8Multilang & name);
private:
- std::string m_houseNumber;
LocalizedStreet m_street;
std::vector<LocalizedStreet> m_nearbyStreets;
EditableProperties m_editableProperties;
diff --git a/indexer/feature.cpp b/indexer/feature.cpp
index 1c4bedc03b..89ea2333e8 100644
--- a/indexer/feature.cpp
+++ b/indexer/feature.cpp
@@ -1,11 +1,11 @@
#include "indexer/feature.hpp"
#include "indexer/classificator.hpp"
-#include "indexer/editable_map_object.hpp"
#include "indexer/feature_algo.hpp"
#include "indexer/feature_impl.hpp"
#include "indexer/feature_utils.hpp"
#include "indexer/feature_visibility.hpp"
+#include "indexer/map_object.hpp"
#include "indexer/scales.hpp"
#include "indexer/shared_load_info.hpp"
@@ -180,6 +180,55 @@ uint8_t ReadByte(TSource & src)
}
} // namespace
+// static
+FeatureType FeatureType::ConstructFromMapObject(osm::MapObject const & emo)
+{
+ FeatureType ft;
+ uint8_t const geomType = emo.GetGeomType();
+ ft.m_limitRect.MakeEmpty();
+
+ switch (geomType)
+ {
+ case feature::GEOM_POINT:
+ ft.m_center = emo.GetMercator();
+ ft.m_limitRect.Add(ft.m_center);
+ break;
+ case feature::GEOM_LINE:
+ ft.m_points = Points(emo.GetPoints().begin(), emo.GetPoints().end());
+ for (auto const & p : ft.m_points)
+ ft.m_limitRect.Add(p);
+ break;
+ case feature::GEOM_AREA:
+ ft.m_triangles = Points(emo.GetTriangesAsPoints().begin(), emo.GetTriangesAsPoints().end());
+ for (auto const & p : ft.m_triangles)
+ ft.m_limitRect.Add(p);
+ break;
+ }
+
+ ft.m_parsed.m_points = ft.m_parsed.m_triangles = true;
+
+ ft.m_params.name = emo.GetNameMultilang();
+ string const & house = emo.GetHouseNumber();
+ if (house.empty())
+ ft.m_params.house.Clear();
+ else
+ ft.m_params.house.Set(house);
+ ft.m_parsed.m_common = true;
+
+ ft.m_metadata = emo.GetMetadata();
+ ft.m_parsed.m_metadata = true;
+
+ CHECK_LESS_OR_EQUAL(emo.GetTypes().Size(), feature::kMaxTypesCount, ());
+ copy(emo.GetTypes().begin(), emo.GetTypes().end(), ft.m_types.begin());
+
+ ft.m_parsed.m_types = true;
+ ft.m_header = CalculateHeader(emo.GetTypes().Size(), geomType, ft.m_params);
+ ft.m_parsed.m_header2 = true;
+
+ ft.m_id = emo.GetID();
+ return ft;
+}
+
void FeatureType::Deserialize(SharedLoadInfo const * loadInfo, Buffer buffer)
{
CHECK(loadInfo, ());
@@ -204,17 +253,6 @@ feature::EGeomType FeatureType::GetFeatureType() const
}
}
-void FeatureType::SetTypes(array<uint32_t, feature::kMaxTypesCount> const & types, uint32_t count)
-{
- ASSERT_GREATER_OR_EQUAL(count, 1, ("Must be one type at least."));
- ASSERT_LESS(count, feature::kMaxTypesCount, ("Too many types for feature"));
- count = min(count, static_cast<uint32_t>(feature::kMaxTypesCount - 1));
- m_types.fill(0);
- copy_n(begin(types), count, begin(m_types));
- auto value = static_cast<uint8_t>((count - 1) & feature::HEADER_TYPE_MASK);
- m_header = (m_header & (~feature::HEADER_TYPE_MASK)) | value;
-}
-
void FeatureType::ParseTypes()
{
if (m_parsed.m_types)
@@ -284,44 +322,6 @@ int8_t FeatureType::GetLayer()
return m_params.layer;
}
-void FeatureType::ReplaceBy(osm::EditableMapObject const & emo)
-{
- uint8_t geoType;
- if (emo.IsPointType())
- {
- // We are here for existing point features and for newly created point features.
- m_center = emo.GetMercator();
- m_limitRect.MakeEmpty();
- m_limitRect.Add(m_center);
- m_parsed.m_points = m_parsed.m_triangles = true;
- geoType = feature::GEOM_POINT;
- }
- else
- {
- geoType = m_header & HEADER_GEOTYPE_MASK;
- }
-
- m_params.name = emo.GetName();
- string const & house = emo.GetHouseNumber();
- if (house.empty())
- m_params.house.Clear();
- else
- m_params.house.Set(house);
- m_parsed.m_common = true;
-
- m_metadata = emo.GetMetadata();
- m_parsed.m_metadata = true;
-
- uint32_t typesCount = 0;
- for (uint32_t const type : emo.GetTypes())
- m_types[typesCount++] = type;
- m_parsed.m_types = true;
- m_header = CalculateHeader(typesCount, geoType, m_params);
- m_parsed.m_header2 = true;
-
- m_id = emo.GetID();
-}
-
void FeatureType::ParseEverything()
{
// Also calls ParseCommon() and ParseTypes().
@@ -551,74 +551,6 @@ StringUtf8Multilang const & FeatureType::GetNames()
return m_params.name;
}
-void FeatureType::SetNames(StringUtf8Multilang const & newNames)
-{
- m_params.name.Clear();
- // Validate passed string to clean up empty names (if any).
- newNames.ForEach([this](int8_t langCode, string const & name) {
- if (!name.empty())
- m_params.name.AddString(langCode, name);
- });
-
- if (m_params.name.IsEmpty())
- m_header = m_header & ~feature::HEADER_HAS_NAME;
- else
- m_header = m_header | feature::HEADER_HAS_NAME;
-}
-
-void FeatureType::SetMetadata(feature::Metadata const & newMetadata)
-{
- m_parsed.m_metadata = true;
- m_metadata = newMetadata;
-}
-
-void FeatureType::UpdateHeader(bool commonParsed, bool metadataParsed)
-{
- feature::EHeaderTypeMask geomType =
- static_cast<feature::EHeaderTypeMask>(m_header & feature::HEADER_GEOTYPE_MASK);
- if (!geomType)
- {
- geomType = m_params.house.IsEmpty() && !m_params.ref.empty() ? feature::HEADER_GEOM_POINT
- : feature::HEADER_GEOM_POINT_EX;
- }
-
- m_header = feature::CalculateHeader(GetTypesCount(), geomType, m_params);
- m_parsed.m_header2 = true;
- m_parsed.m_types = true;
-
- m_parsed.m_common = commonParsed;
- m_parsed.m_metadata = metadataParsed;
-}
-
-bool FeatureType::UpdateMetadataValue(string const & key, string const & value)
-{
- feature::Metadata::EType mdType;
- if (!feature::Metadata::TypeFromString(key, mdType))
- return false;
- m_metadata.Set(mdType, value);
- return true;
-}
-
-void FeatureType::ForEachMetadataItem(
- bool skipSponsored, function<void(string const & tag, string const & value)> const & fn) const
-{
- for (auto const type : m_metadata.GetPresentTypes())
- {
- if (skipSponsored && m_metadata.IsSponsoredType(static_cast<feature::Metadata::EType>(type)))
- continue;
- auto const attributeName = ToString(static_cast<feature::Metadata::EType>(type));
- fn(attributeName, m_metadata.Get(type));
- }
-}
-
-void FeatureType::SetCenter(m2::PointD const & pt)
-{
- ASSERT_EQUAL(GetFeatureType(), GEOM_POINT, ("Only for point feature."));
- m_center = pt;
- m_limitRect.Add(m_center);
- m_parsed.m_points = m_parsed.m_triangles = true;
-}
-
namespace
{
template <class TCont>
@@ -807,14 +739,6 @@ string FeatureType::GetHouseNumber()
return m_params.house.Get();
}
-void FeatureType::SetHouseNumber(string const & number)
-{
- if (number.empty())
- m_params.house.Clear();
- else
- m_params.house.Set(number);
-}
-
bool FeatureType::GetName(int8_t lang, string & name)
{
if (!HasName())
diff --git a/indexer/feature.hpp b/indexer/feature.hpp
index 277ef4ca92..ed83bec055 100644
--- a/indexer/feature.hpp
+++ b/indexer/feature.hpp
@@ -23,7 +23,7 @@ class SharedLoadInfo;
namespace osm
{
-class EditableMapObject;
+class MapObject;
}
// Lazy feature loader. Loads needed data and caches it.
@@ -33,6 +33,8 @@ public:
using Buffer = char const *;
using GeometryOffsets = buffer_vector<uint32_t, feature::DataHeader::MAX_SCALES_COUNT>;
+ static FeatureType ConstructFromMapObject(osm::MapObject const & emo);
+
void Deserialize(feature::SharedLoadInfo const * loadInfo, Buffer buffer);
feature::EGeomType GetFeatureType() const;
@@ -68,27 +70,8 @@ public:
int8_t GetLayer();
- /// @name Editor methods.
- //@{
- /// Apply changes from UI for edited or newly created features.
- /// Replaces all FeatureType's components.
std::vector<m2::PointD> GetTriangesAsPoints(int scale);
- void ReplaceBy(osm::EditableMapObject const & ef);
-
- void SetNames(StringUtf8Multilang const & newNames);
- void SetTypes(std::array<uint32_t, feature::kMaxTypesCount> const & types, uint32_t count);
- void SetMetadata(feature::Metadata const & newMetadata);
-
- void UpdateHeader(bool commonParsed, bool metadataParsed);
- bool UpdateMetadataValue(std::string const & key, std::string const & value);
- void ForEachMetadataItem(
- bool skipSponsored,
- std::function<void(std::string const & tag, std::string const & value)> const & fn) const;
-
- void SetCenter(m2::PointD const &pt);
- //@}
-
void SetID(FeatureID const & id) { m_id = id; }
FeatureID const & GetID() const { return m_id; }
@@ -157,8 +140,6 @@ public:
std::string DebugString(int scale);
std::string GetHouseNumber();
- /// Needed for Editor, to change house numbers in runtime.
- void SetHouseNumber(std::string const & number);
/// @name Get names for feature.
/// @param[out] defaultName corresponds to osm tag "name"
diff --git a/indexer/indexer_tests/editable_map_object_test.cpp b/indexer/indexer_tests/editable_map_object_test.cpp
index ca7f9b2cd2..fe52ebd3e8 100644
--- a/indexer/indexer_tests/editable_map_object_test.cpp
+++ b/indexer/indexer_tests/editable_map_object_test.cpp
@@ -262,8 +262,8 @@ UNIT_TEST(EditableMapObject_GetNamesDataSource)
vector<int8_t> nativeMwmLanguages = {GetLangCode("de"), GetLangCode("fr")};
- auto const namesDataSource =
- EditableMapObject::GetNamesDataSource(emo.GetName(), nativeMwmLanguages, GetLangCode("ko"));
+ auto const namesDataSource = EditableMapObject::GetNamesDataSource(
+ emo.GetNameMultilang(), nativeMwmLanguages, GetLangCode("ko"));
TEST_EQUAL(namesDataSource.names.size(), 9, ("All names except the default should be pushed into "
"data source plus empty mandatory names"));
@@ -281,8 +281,8 @@ UNIT_TEST(EditableMapObject_GetNamesDataSource)
{
vector<int8_t> nativeMwmLanguages = {GetLangCode("de"), GetLangCode("fr")};
- auto const namesDataSource =
- EditableMapObject::GetNamesDataSource(emo.GetName(), nativeMwmLanguages, GetLangCode("fr"));
+ auto const namesDataSource = EditableMapObject::GetNamesDataSource(
+ emo.GetNameMultilang(), nativeMwmLanguages, GetLangCode("fr"));
TEST_EQUAL(namesDataSource.names.size(), 9,
("All names + empty mandatory names should be pushed into "
"the data source, except the default one."));
@@ -293,8 +293,8 @@ UNIT_TEST(EditableMapObject_GetNamesDataSource)
{
vector<int8_t> nativeMwmLanguages = {GetLangCode("fr"), GetLangCode("en")};
- auto const namesDataSource =
- EditableMapObject::GetNamesDataSource(emo.GetName(), nativeMwmLanguages, GetLangCode("fr"));
+ auto const namesDataSource = EditableMapObject::GetNamesDataSource(
+ emo.GetNameMultilang(), nativeMwmLanguages, GetLangCode("fr"));
TEST_EQUAL(namesDataSource.names.size(), 9,
("All names + empty mandatory names should be pushed into "
"the data source, except the default one."));
@@ -305,8 +305,8 @@ UNIT_TEST(EditableMapObject_GetNamesDataSource)
{
vector<int8_t> nativeMwmLanguages = {GetLangCode("en"), GetLangCode("en")};
- auto const namesDataSource =
- EditableMapObject::GetNamesDataSource(emo.GetName(), nativeMwmLanguages, GetLangCode("en"));
+ auto const namesDataSource = EditableMapObject::GetNamesDataSource(
+ emo.GetNameMultilang(), nativeMwmLanguages, GetLangCode("en"));
TEST_EQUAL(namesDataSource.names.size(), 8,
("All names + empty mandatory names should be pushed into "
"the data source, except the default one."));
@@ -594,7 +594,7 @@ UNIT_TEST(EditableMapObject_RemoveBlankNames)
emo.SetName(name);
emo.RemoveBlankAndDuplicationsForDefault();
- TEST_EQUAL(getCountOfNames(emo.GetName()), 4, ());
+ TEST_EQUAL(getCountOfNames(emo.GetNameMultilang()), 4, ());
name.Clear();
@@ -606,7 +606,7 @@ UNIT_TEST(EditableMapObject_RemoveBlankNames)
emo.SetName(name);
emo.RemoveBlankAndDuplicationsForDefault();
- TEST_EQUAL(getCountOfNames(emo.GetName()), 2, ());
+ TEST_EQUAL(getCountOfNames(emo.GetNameMultilang()), 2, ());
name.Clear();
@@ -618,7 +618,7 @@ UNIT_TEST(EditableMapObject_RemoveBlankNames)
emo.SetName(name);
emo.RemoveBlankAndDuplicationsForDefault();
- TEST_EQUAL(getCountOfNames(emo.GetName()), 1, ());
+ TEST_EQUAL(getCountOfNames(emo.GetNameMultilang()), 1, ());
name.Clear();
@@ -630,6 +630,6 @@ UNIT_TEST(EditableMapObject_RemoveBlankNames)
emo.SetName(name);
emo.RemoveBlankAndDuplicationsForDefault();
- TEST_EQUAL(getCountOfNames(emo.GetName()), 1, ());
+ TEST_EQUAL(getCountOfNames(emo.GetNameMultilang()), 1, ());
}
} // namespace
diff --git a/indexer/map_object.cpp b/indexer/map_object.cpp
index 7476087f57..c3e1d9203a 100644
--- a/indexer/map_object.cpp
+++ b/indexer/map_object.cpp
@@ -74,8 +74,8 @@ void MapObject::SetFromFeatureType(FeatureType & ft)
m_name = ft.GetNames();
m_types = feature::TypesHolder(ft);
m_metadata = ft.GetMetadata();
+ m_houseNumber = ft.GetHouseNumber();
m_featureID = ft.GetID();
- ASSERT(m_featureID.IsValid(), ());
m_geomType = ft.GetFeatureType();
if (m_geomType == feature::GEOM_AREA)
{
@@ -96,6 +96,7 @@ FeatureID const & MapObject::GetID() const { return m_featureID; }
ms::LatLon MapObject::GetLatLon() const { return MercatorBounds::ToLatLon(m_mercator); }
m2::PointD const & MapObject::GetMercator() const { return m_mercator; }
vector<m2::PointD> const & MapObject::GetTriangesAsPoints() const { return m_triangles; }
+vector<m2::PointD> const & MapObject::GetPoints() const { return m_points; }
feature::TypesHolder const & MapObject::GetTypes() const { return m_types; }
string MapObject::GetDefaultName() const
@@ -110,6 +111,8 @@ StringUtf8Multilang const & MapObject::GetNameMultilang() const
return m_name;
}
+string const & MapObject::GetHouseNumber() const { return m_houseNumber; }
+
string MapObject::GetLocalizedType() const
{
ASSERT(!m_types.Empty(), ());
diff --git a/indexer/map_object.hpp b/indexer/map_object.hpp
index 6f8de6ab36..60950ef58c 100644
--- a/indexer/map_object.hpp
+++ b/indexer/map_object.hpp
@@ -61,11 +61,14 @@ public:
ms::LatLon GetLatLon() const;
m2::PointD const & GetMercator() const;
std::vector<m2::PointD> const & GetTriangesAsPoints() const;
+ std::vector<m2::PointD> const & GetPoints() const;
feature::TypesHolder const & GetTypes() const;
std::string GetDefaultName() const;
StringUtf8Multilang const & GetNameMultilang() const;
+ std::string const & GetHouseNumber() const;
+
/// @name Metadata fields.
//@{
std::vector<Props> AvailableProperties() const;
@@ -99,6 +102,7 @@ public:
feature::Metadata const & GetMetadata() const;
bool IsPointType() const;
+ feature::EGeomType GetGeomType() const { return m_geomType; };
/// @returns true if object is of building type.
bool IsBuilding() const;
@@ -113,6 +117,7 @@ protected:
std::vector<m2::PointD> m_triangles;
StringUtf8Multilang m_name;
+ std::string m_houseNumber;
feature::TypesHolder m_types;
feature::Metadata m_metadata;
diff --git a/iphone/Maps/UI/Editor/MWMEditorViewController.mm b/iphone/Maps/UI/Editor/MWMEditorViewController.mm
index f25e0a66c0..f84a0a9a5f 100644
--- a/iphone/Maps/UI/Editor/MWMEditorViewController.mm
+++ b/iphone/Maps/UI/Editor/MWMEditorViewController.mm
@@ -1071,7 +1071,7 @@ void registerCellsForTableView(vector<MWMEditorCellType> const & cells, UITableV
{
MWMEditorAdditionalNamesTableViewController * dvc = segue.destinationViewController;
[dvc configWithDelegate:self
- name:m_mapObject.GetName()
+ name:m_mapObject.GetNameMultilang()
additionalSkipLanguageCodes:m_newAdditionalLanguages
selectedLanguageCode:((NSNumber *)sender).integerValue];
}
diff --git a/map/framework.cpp b/map/framework.cpp
index fd5a9e5385..2621c5c141 100644
--- a/map/framework.cpp
+++ b/map/framework.cpp
@@ -3128,7 +3128,7 @@ osm::Editor::SaveResult Framework::SaveEditedMapObject(osm::EditableMapObject em
}
else
{
- originalFeature.ReplaceBy(emo);
+ originalFeature = FeatureType::ConstructFromMapObject(emo);
}
// Handle only pois.
@@ -3155,7 +3155,7 @@ osm::Editor::SaveResult Framework::SaveEditedMapObject(osm::EditableMapObject em
string originalFeatureStreet;
if (!isCreatedFeature)
{
- originalFeatureStreet = coder.GetOriginalFeatureStreetName(originalFeature);
+ originalFeatureStreet = coder.GetOriginalFeatureStreetName(originalFeature.GetID());
}
else
{
diff --git a/search/editor_delegate.cpp b/search/editor_delegate.cpp
index d90a6111ab..0cb7383adc 100644
--- a/search/editor_delegate.cpp
+++ b/search/editor_delegate.cpp
@@ -18,20 +18,22 @@ MwmSet::MwmId EditorDelegate::GetMwmIdByMapName(string const & name) const
return m_dataSource.GetMwmIdByCountryFile(platform::CountryFile(name));
}
-unique_ptr<FeatureType> EditorDelegate::GetOriginalFeature(FeatureID const & fid) const
+unique_ptr<osm::EditableMapObject> EditorDelegate::GetOriginalMapObject(FeatureID const & fid) const
{
FeaturesLoaderGuard guard(m_dataSource, fid.m_mwmId);
auto feature = guard.GetOriginalFeatureByIndex(fid.m_index);
- if (feature)
- feature->ParseEverything();
+ if (!feature)
+ return {};
- return feature;
+ auto object = make_unique<osm::EditableMapObject>();
+ object->SetFromFeatureType(*feature);
+ return object;
}
-string EditorDelegate::GetOriginalFeatureStreet(FeatureType & ft) const
+string EditorDelegate::GetOriginalFeatureStreet(FeatureID const & fid) const
{
search::ReverseGeocoder const coder(m_dataSource);
- return coder.GetOriginalFeatureStreetName(ft);
+ return coder.GetOriginalFeatureStreetName(fid);
}
void EditorDelegate::ForEachFeatureAtPoint(osm::Editor::FeatureTypeFn && fn,
diff --git a/search/editor_delegate.hpp b/search/editor_delegate.hpp
index 8a653a7e12..db832ea223 100644
--- a/search/editor_delegate.hpp
+++ b/search/editor_delegate.hpp
@@ -2,6 +2,8 @@
#include "editor/osm_editor.hpp"
+#include "indexer/editable_map_object.hpp"
+
#include <memory>
#include <string>
@@ -16,8 +18,9 @@ public:
// osm::Editor::Delegate overrides:
MwmSet::MwmId GetMwmIdByMapName(std::string const & name) const override;
- std::unique_ptr<FeatureType> GetOriginalFeature(FeatureID const & fid) const override;
- std::string GetOriginalFeatureStreet(FeatureType & ft) const override;
+ std::unique_ptr<osm::EditableMapObject> GetOriginalMapObject(
+ FeatureID const & fid) const override;
+ std::string GetOriginalFeatureStreet(FeatureID const & fid) const override;
void ForEachFeatureAtPoint(osm::Editor::FeatureTypeFn && fn,
m2::PointD const & point) const override;
diff --git a/search/reverse_geocoder.cpp b/search/reverse_geocoder.cpp
index 793f195f70..2d9447f8be 100644
--- a/search/reverse_geocoder.cpp
+++ b/search/reverse_geocoder.cpp
@@ -171,11 +171,15 @@ string ReverseGeocoder::GetFeatureStreetName(FeatureType & ft) const
return addr.m_street.m_name;
}
-string ReverseGeocoder::GetOriginalFeatureStreetName(FeatureType & ft) const
+string ReverseGeocoder::GetOriginalFeatureStreetName(FeatureID const & fid) const
{
Address addr;
HouseTable table(m_dataSource);
- GetNearbyAddress(table, FromFeature(ft, 0.0 /* distMeters */), true /* ignoreEdits */, addr);
+ Building bld;
+
+ m_dataSource.ReadFeature([&](FeatureType & ft) { bld = FromFeature(ft, 0.0 /* distMeters */); },
+ fid);
+ GetNearbyAddress(table, bld, true /* ignoreEdits */, addr);
return addr.m_street.m_name;
}
diff --git a/search/reverse_geocoder.hpp b/search/reverse_geocoder.hpp
index 736458710f..22720c58a1 100644
--- a/search/reverse_geocoder.hpp
+++ b/search/reverse_geocoder.hpp
@@ -99,7 +99,7 @@ public:
/// Returns empty string when there is no street the feature belongs to.
std::string GetFeatureStreetName(FeatureType & ft) const;
/// Same with GetFeatureStreetName but gets street from mwm only (not editor).
- std::string GetOriginalFeatureStreetName(FeatureType & ft) const;
+ std::string GetOriginalFeatureStreetName(FeatureID const & fid) const;
/// For |houseId| with street information sets |streetId| to FeatureID of street corresponding to
/// |houseId| and returns true. Returs false otherwise.
bool GetStreetByHouse(FeatureType & house, FeatureID & streetId) const;