OSM Editor core.

This commit is contained in:
Alex Zolotarev 2015-11-18 00:03:47 -08:00 committed by Sergey Yershov
parent 3e9ced74c4
commit 319434c134
4 changed files with 223 additions and 1 deletions

View file

@ -21,7 +21,6 @@ namespace old_101 { namespace feature
class LoaderImpl;
}}
/// Base feature class for storing common data (without geometry).
class FeatureBase
{

View file

@ -41,6 +41,7 @@ SOURCES += \
map_style_reader.cpp \
mwm_set.cpp \
old/feature_loader_101.cpp \
osm_editor.cpp \
point_to_int64.cpp \
rank_table.cpp \
scales.cpp \
@ -88,6 +89,7 @@ HEADERS += \
mwm_set.hpp \
old/feature_loader_101.hpp \
old/interval_index_101.hpp \
osm_editor.hpp \
point_to_int64.hpp \
rank_table.hpp \
scale_index.hpp \

150
indexer/osm_editor.cpp Normal file
View file

@ -0,0 +1,150 @@
#include "indexer/classificator.hpp"
#include "indexer/feature_decl.hpp"
#include "indexer/index.hpp"
#include "indexer/osm_editor.hpp"
#include "platform/platform.hpp"
#include "base/logging.hpp"
#include "std/map.hpp"
#include "std/set.hpp"
#include "3party/pugixml/src/pugixml.hpp"
using namespace pugi;
using feature::EGeomType;
using feature::Metadata;
static char constexpr const * kEditorXMLFileName = "edits.xml";
namespace osm
{
// TODO(AlexZ): Normalize osm multivalue strings for correct merging
// (e.g. insert/remove spaces after ';' delimeter);
namespace
{
string GetEditorFilePath() { return GetPlatform().WritablePathForFile(kEditorXMLFileName); }
} // namespace
Editor::Editor()
{
// Load all previous edits from persistent storage.
Load(GetEditorFilePath());
}
Editor & Editor::Instance()
{
static Editor instance;
return instance;
}
void Editor::Load(string const & fullFilePath)
{
xml_document xml;
xml_parse_result res = xml.load_file(fullFilePath.c_str());
// Note: status_file_not_found is ok if user has never made any edits.
if (res != status_ok && res != status_file_not_found)
{
LOG(LERROR, ("Can't load XML Edits from disk:", fullFilePath));
}
// TODO(mgsergio): Implement XML deserialization into m_[deleted|edited|created]Features.
}
void Editor::Save(string const & /*fullFilePath*/) const
{
// Do not save empty xml file if no any edits were made.
if (m_deletedFeatures.empty() && m_editedFeatures.empty() && m_createdFeatures.empty())
return;
// TODO(mgsergio): Implement XML serialization from m_[deleted|edited|created]Features.
}
bool Editor::IsFeatureDeleted(FeatureID const & fid) const
{
// Most popular case optimization.
if (m_deletedFeatures.empty())
return false;
return m_deletedFeatures.find(fid) != m_deletedFeatures.end();
}
void Editor::DeleteFeature(FeatureType const & feature)
{
m_deletedFeatures.insert(feature.GetID());
// TODO(AlexZ): Synchronize Save call/make it on a separate thread.
Save(GetEditorFilePath());
if (m_invalidateFn)
m_invalidateFn();
}
//namespace
//{
//FeatureID GenerateNewFeatureId(FeatureID const & oldFeatureId)
//{
// // TODO(AlexZ): Stable & unique features ID generation.
// static uint32_t newOffset = 0x0effffff;
// return FeatureID(oldFeatureId.m_mwmId, newOffset++);
//}
//} // namespace
void Editor::EditFeature(FeatureType & editedFeature)
{
m_editedFeatures[editedFeature.GetID()] = editedFeature;
// TODO(AlexZ): Synchronize Save call/make it on a separate thread.
Save(GetEditorFilePath());
if (m_invalidateFn)
m_invalidateFn();
}
bool Editor::IsFeatureEdited(FeatureID const & fid) const
{
return m_editedFeatures.find(fid) != m_editedFeatures.end();
}
void Editor::ForEachFeatureInMwmRectAndScale(MwmSet::MwmId const & id,
function<void(FeatureID const &)> const & f,
m2::RectD const & /*rect*/,
uint32_t /*scale*/)
{
// TODO(AlexZ): Check that features are in the rect and are visible at this scale.
for (auto & feature : m_createdFeatures)
{
if (feature.first.m_mwmId == id)
f(feature.first);
}
}
void Editor::ForEachFeatureInMwmRectAndScale(MwmSet::MwmId const & id,
function<void(FeatureType &)> const & f,
m2::RectD const & /*rect*/,
uint32_t /*scale*/)
{
// TODO(AlexZ): Check that features are in the rect and are visible at this scale.
for (auto & feature : m_createdFeatures)
{
if (feature.first.m_mwmId == id)
f(feature.second);
}
}
bool Editor::GetEditedFeature(FeatureID const & fid, FeatureType & outFeature) const
{
auto found = m_editedFeatures.find(fid);
if (found == m_editedFeatures.end())
return false;
outFeature = found->second;
return true;
}
vector<Metadata::EType> Editor::EditableMetadataForType(uint32_t type) const
{
// TODO(mgsergio): Load editable fields into memory from XML and query them here.
// Enable opening hours for the first release.
return {Metadata::FMD_OPEN_HOURS};
}
} // namespace osm

71
indexer/osm_editor.hpp Normal file
View file

@ -0,0 +1,71 @@
#pragma once
#include "geometry/rect2d.hpp"
#include "indexer/feature_meta.hpp"
#include "indexer/mwm_set.hpp"
#include "std/function.hpp"
#include "std/map.hpp"
#include "std/set.hpp"
#include "std/string.hpp"
struct FeatureID;
class FeatureType;
class Index;
namespace osm
{
class Editor final
{
Editor();
public:
using TInvalidateFn = function<void()>;
static Editor & Instance();
void SetInvalidateFn(TInvalidateFn && fn) { m_invalidateFn = move(fn); }
void Load(string const & fullFilePath);
// TODO(AlexZ): Synchronize Save call/make it on a separate thread.
void Save(string const & fullFilePath) const;
void ForEachFeatureInMwmRectAndScale(MwmSet::MwmId const & id,
function<void(FeatureID const &)> const & f,
m2::RectD const & rect,
uint32_t scale);
void ForEachFeatureInMwmRectAndScale(MwmSet::MwmId const & id,
function<void(FeatureType &)> const & f,
m2::RectD const & rect,
uint32_t scale);
/// True if feature was deleted by user.
bool IsFeatureDeleted(FeatureID const & fid) const;
/// Marks feature as "deleted" from MwM file.
void DeleteFeature(FeatureType const & feature);
/// True if feature was edited by user.
bool IsFeatureEdited(FeatureID const & fid) const;
/// @returns false if feature wasn't edited.
/// @param outFeature is valid only if true was returned.
bool GetEditedFeature(FeatureID const & fid, FeatureType & outFeature) const;
/// Original feature with same FeatureID as newFeature is replaced by newFeature.
void EditFeature(FeatureType & editedFeature);
vector<feature::Metadata::EType> EditableMetadataForType(uint32_t type) const;
private:
// TODO(AlexZ): Synchronize multithread access to these structures.
set<FeatureID> m_deletedFeatures;
map<FeatureID, FeatureType> m_editedFeatures;
map<FeatureID, FeatureType> m_createdFeatures;
/// Invalidate map viewport after edits.
TInvalidateFn m_invalidateFn;
}; // class Editor
} // namespace osm