forked from organicmaps/organicmaps
OSM Editor core.
This commit is contained in:
parent
3e9ced74c4
commit
319434c134
4 changed files with 223 additions and 1 deletions
|
@ -21,7 +21,6 @@ namespace old_101 { namespace feature
|
|||
class LoaderImpl;
|
||||
}}
|
||||
|
||||
|
||||
/// Base feature class for storing common data (without geometry).
|
||||
class FeatureBase
|
||||
{
|
||||
|
|
|
@ -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
150
indexer/osm_editor.cpp
Normal 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
71
indexer/osm_editor.hpp
Normal 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
|
Loading…
Add table
Reference in a new issue