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:
authorvng <viktor.govako@gmail.com>2011-05-09 02:53:49 +0400
committerAlex Zolotarev <alex@maps.me>2015-09-23 01:17:06 +0300
commit2400357a3db3f7eaf00e8c75d7603168f441fd80 (patch)
tree4597cb81b97faf0e1d92185128d5b0bfd58c5046
parent4ec7dff6c7b847264eb0091b89fe86df1eea95d2 (diff)
Refactoring of feature structure:
- multilanguage names - separate house numbers - point feature rank - refs for linear features
-rw-r--r--docs/feature structure.txt10
-rw-r--r--generator/feature_merger.cpp5
-rw-r--r--generator/feature_merger.hpp5
-rw-r--r--generator/generator_tests/feature_bucketer_test.cpp1
-rw-r--r--generator/osm2type.cpp83
-rw-r--r--generator/osm2type.hpp9
-rw-r--r--generator/osm_element.hpp69
-rw-r--r--generator/statistics.cpp8
-rw-r--r--generator/statistics.hpp2
-rw-r--r--generator/world_map_generator.hpp2
-rw-r--r--indexer/feature.cpp223
-rw-r--r--indexer/feature.hpp124
-rw-r--r--indexer/feature_data.cpp129
-rw-r--r--indexer/feature_data.hpp163
-rw-r--r--indexer/feature_visibility.cpp4
-rw-r--r--indexer/indexer.pro2
-rw-r--r--map/framework.cpp12
-rw-r--r--qt/searchwindow.cpp7
18 files changed, 534 insertions, 324 deletions
diff --git a/docs/feature structure.txt b/docs/feature structure.txt
index ff01b23e9f..e882d27e89 100644
--- a/docs/feature structure.txt
+++ b/docs/feature structure.txt
@@ -2,11 +2,13 @@
0. кол-во типов (1-8, пишем 0-7, 3 бита)
3. имя
4. слой
-5. точка
-6. линия
-7. площадной
+5, 6. - тип геометрии (точка = 00, линия = 01, площадной = 10)
+7. бит присутствия дополнительной информации:
+ - точка - ранг (1 байт как логарифм населения по основанию 1.1);
+ - линейный - № дороги (строка);
+ - площадной - № дома (строка, оптимизированная для хранения двузначного числа);
-* пишем типы, слой, имя, точку
+* пишем типы, имя, слой, дополнительную информацию, точку (для точечного типа)
1 или 2 байта следующего заголовка (только для линейного и\или площадного объекта):
* 4 бита кол-ва внутренних точек для линейного объекта:
diff --git a/generator/feature_merger.cpp b/generator/feature_merger.cpp
index 547ef882c0..5cdb681e73 100644
--- a/generator/feature_merger.cpp
+++ b/generator/feature_merger.cpp
@@ -17,10 +17,11 @@ bool FeatureBuilder1Merger::ReachedMaxPointsCount() const
void FeatureBuilder1Merger::AppendFeature(FeatureBuilder1Merger const & fb)
{
// check that both features are of linear type
- CHECK(fb.m_bLinear && m_bLinear, ("Not linear feature"));
+ CHECK(fb.m_Params.GetGeomType() == feature::GEOM_LINE &&
+ m_Params.GetGeomType() == feature::GEOM_LINE, ("Not linear feature"));
// check that classificator types are the same
- CHECK_EQUAL(fb.m_Types, m_Types, ("Not equal types"));
+ //CHECK_EQUAL(fb.m_Types, m_Types, ("Not equal types"));
// check last-first points equality
//CHECK_EQUAL(m_Geometry.back(), fb.m_Geometry.front(), ("End and Start point are no equal"));
diff --git a/generator/feature_merger.hpp b/generator/feature_merger.hpp
index 0bede7358c..0662309097 100644
--- a/generator/feature_merger.hpp
+++ b/generator/feature_merger.hpp
@@ -16,14 +16,13 @@ public:
if (m_Geometry.size() < 3)
return false;
- m_bArea = true;
+ m_Params.SetGeomType(feature::GEOM_AREA);
return true;
}
uint32_t KeyType() const
{
- ASSERT_EQUAL ( m_Types.size(), 1, () );
- return m_Types.front();
+ return m_Params.KeyType();
}
bool ReachedMaxPointsCount() const;
diff --git a/generator/generator_tests/feature_bucketer_test.cpp b/generator/generator_tests/feature_bucketer_test.cpp
index 648a83e26e..4cdbf527aa 100644
--- a/generator/generator_tests/feature_bucketer_test.cpp
+++ b/generator/generator_tests/feature_bucketer_test.cpp
@@ -60,6 +60,7 @@ UNIT_TEST(FeatureBucketerSmokeTest)
fb.AddPoint(m2::PointD(10, 10));
fb.AddPoint(m2::PointD(20, 20));
fb.SetType(0);
+ fb.SetLinear();
bucketer(fb);
FeatureType f;
diff --git a/generator/osm2type.cpp b/generator/osm2type.cpp
index 864b2fe876..dc630f81c5 100644
--- a/generator/osm2type.cpp
+++ b/generator/osm2type.cpp
@@ -450,7 +450,8 @@ namespace ftype {
string const & k = p->childs[i].attrs["k"];
string const & v = p->childs[i].attrs["v"];
- if (is_skip_tag(k, v)) continue;
+ if (k.empty() || is_skip_tag(k, v))
+ continue;
// this means "no"
//if (get_mark_value(k, v) == -1)
@@ -485,33 +486,70 @@ namespace ftype {
class do_find_name
{
size_t & m_count;
- string & m_name;
- string & m_addr;
- int32_t & m_layer;
+ FeatureParams & m_params;
+
+ class get_lang
+ {
+ bool m_ok;
+ string & m_lang;
+
+ public:
+ get_lang(string & lang) : m_ok(false), m_lang(lang) {}
+
+ void operator() (string const & s)
+ {
+ if (m_ok)
+ m_lang = s;
+ else if (s == "name")
+ {
+ m_ok = true;
+ m_lang = "def";
+ }
+ }
+ };
public:
typedef bool result_type;
- do_find_name(size_t & count, string & name, string & addr, int32_t & layer)
- : m_count(count), m_name(name), m_addr(addr), m_layer(layer)
+ do_find_name(size_t & count, FeatureParams & params)
+ : m_count(count), m_params(params)
{
m_count = 0;
- m_layer = 0;
}
bool operator() (string const & k, string const & v)
{
++m_count;
- // do not call is_name_tag(k), but exactly "name" tag
- if (m_name.empty() && k == "name")
- m_name = v;
+ if (v.empty()) return false;
- // add house number
- if (m_addr.empty() && k == "addr:housenumber")
- m_addr = v;
+ // get names
+ string lang;
+ utils::TokenizeString(k, "\t :", get_lang(lang));
+ if (!lang.empty())
+ m_params.name.AddString(lang, v);
- if (k == "layer" && m_layer == 0)
- m_layer = atoi(v.c_str());
+ // get layer
+ if (k == "layer" && m_params.layer == 0)
+ m_params.layer = atoi(v.c_str());
+
+ // get reference (we process road numbers only)
+ if (k == "ref")
+ m_params.ref = v;
+
+ // get house number
+ if ((m_params.house.IsEmpty() && k == "addr:housenumber") ||
+ (k == "addr:housename"))
+ {
+ m_params.house.Set(v);
+ }
+
+ // get population rank
+ if (k == "population")
+ {
+ int n;
+ if (utils::to_int(v, n))
+ m_params.rank = static_cast<uint8_t>(log(double(n)) / log(1.1));
+ }
return false;
}
@@ -565,13 +603,10 @@ namespace ftype {
return for_each_tag(p, do_find_obj(parent, isKey));
}
- size_t find_name_and_count(XMLElement * p, string & name, int32_t & layer)
+ size_t process_common_params(XMLElement * p, FeatureParams & params)
{
size_t count;
- string addr;
- for_each_tag(p, do_find_name(count, name, addr, layer));
-
- if (name.empty()) name = addr;
+ for_each_tag(p, do_find_name(count, params));
return count;
}
@@ -589,7 +624,7 @@ namespace ftype {
// };
//#endif
- bool GetNameAndType(XMLElement * p, vector<uint32_t> & types, string & name, int32_t & layer)
+ bool GetNameAndType(XMLElement * p, FeatureParams & params)
{
//#ifdef DEBUG
// // code to set a breakpoint
@@ -600,7 +635,7 @@ namespace ftype {
//#endif
// maybe an empty feature
- if (find_name_and_count(p, name, layer) == 0)
+ if (process_common_params(p, params) == 0)
return false;
set<string> skipRootKeys;
@@ -639,7 +674,7 @@ namespace ftype {
// use features only with drawing rules
if (feature::IsDrawableAny(t))
- types.push_back(t);
+ params.AddType(t);
}
if (pRoot)
@@ -652,6 +687,6 @@ namespace ftype {
} while (true);
- return !types.empty();
+ return params.IsValid();
}
}
diff --git a/generator/osm2type.hpp b/generator/osm2type.hpp
index 6a2449c29d..fa399ba6ef 100644
--- a/generator/osm2type.hpp
+++ b/generator/osm2type.hpp
@@ -1,9 +1,6 @@
#pragma once
-#include "../base/base.hpp"
-
-#include "../std/string.hpp"
-#include "../std/vector.hpp"
+#include "../indexer/feature_data.hpp"
#include "../base/start_mem_debug.hpp"
@@ -13,8 +10,8 @@ namespace ftype
{
void ParseOSMTypes(char const * fPath, int scale);
- /// Get the types, name and layer fot feature with the tree of tags.
- bool GetNameAndType(XMLElement * p, vector<uint32_t> & types, string & name, int32_t & layer);
+ /// Get the types, name and layer for feature with the tree of tags.
+ bool GetNameAndType(XMLElement * p, FeatureParams & params);
}
#include "../base/stop_mem_debug.hpp"
diff --git a/generator/osm_element.hpp b/generator/osm_element.hpp
index 70e34e7e69..06b8b1c25c 100644
--- a/generator/osm_element.hpp
+++ b/generator/osm_element.hpp
@@ -28,9 +28,6 @@ protected:
TEmitter & m_emitter;
THolder & m_holder;
- /// max possible number of types per feature
- static const size_t max_number_of_types = 16;
-
SecondPassParserBase(TEmitter & emitter, THolder & holder)
: m_emitter(emitter), m_holder(holder)
{
@@ -189,25 +186,6 @@ protected:
list<vector<m2::PointD> > & GetHoles() { return m_holes.m_holes; }
};
- /// Feature description struct.
- struct value_t
- {
- typedef vector<uint32_t> types_t;
- types_t types; ///< 1-n types, not empty
- string name; ///< 1-1 name, @todo 1-n names
- int32_t layer; ///< layer
-
- value_t()
- {
- types.reserve(max_number_of_types);
- }
- bool IsValid() const { return !types.empty(); }
- void Add(value_t const & v)
- {
- types.insert(types.end(), v.types.begin(), v.types.end());
- }
- };
-
/// Feature types processor.
class type_processor
{
@@ -229,14 +207,14 @@ protected:
uint64_t m_featureID;
/// @param[out] Feature value as result.
- value_t * m_val;
+ FeatureParams * m_val;
/// Cache: relation id -> feature value (for fast feature parsing)
- unordered_map<uint64_t, value_t> m_typeCache;
+ unordered_map<uint64_t, FeatureParams> m_typeCache;
public:
/// Start process new feature.
- void Reset(uint64_t fID, value_t * val)
+ void Reset(uint64_t fID, FeatureParams * val)
{
m_featureID = fID;
m_val = val;
@@ -245,10 +223,10 @@ protected:
/// 1. "initial relation" process
int operator() (uint64_t id)
{
- typename unordered_map<uint64_t, value_t>::const_iterator i = m_typeCache.find(id);
+ typename unordered_map<uint64_t, FeatureParams>::const_iterator i = m_typeCache.find(id);
if (i != m_typeCache.end())
{
- m_val->Add(i->second);
+ m_val->AddTypes(i->second);
return -1; // continue process relations
}
return 0; // read relation from file (see next operator)
@@ -268,14 +246,14 @@ protected:
else
{
// process types of relation and add them to m_val
- value_t val;
- if (ftype::GetNameAndType(&e, val.types, val.name, val.layer))
+ FeatureParams val;
+ if (ftype::GetNameAndType(&e, val))
{
m_typeCache[id] = val;
- m_val->Add(val);
+ m_val->AddTypes(val);
}
else
- m_typeCache[id] = value_t();
+ m_typeCache[id] = FeatureParams();
}
// continue process relations
@@ -294,13 +272,13 @@ protected:
ft.SetAreaAddHoles(processor.GetHoles());
}
- bool ParseType(XMLElement * p, uint64_t & id, value_t & fValue)
+ bool ParseType(XMLElement * p, uint64_t & id, FeatureParams & fValue)
{
VERIFY ( utils::to_uint64(p->attrs["id"], id),
("Unknown element with invalid id : ", p->attrs["id"]) );
// try to get type from element tags
- ftype::GetNameAndType(p, fValue.types, fValue.name, fValue.layer);
+ ftype::GetNameAndType(p, fValue);
// try to get type from relations tags
m_typeProcessor.Reset(id, &fValue);
@@ -316,9 +294,7 @@ protected:
m_holder.ForEachRelationByWayCached(id, m_typeProcessor);
}
- // remove duplicating types
- sort(fValue.types.begin(), fValue.types.end());
- fValue.types.erase(unique(fValue.types.begin(), fValue.types.end()), fValue.types.end());
+ fValue.FinishAddingTypes();
// unrecognized feature by classificator
return fValue.IsValid();
@@ -421,12 +397,12 @@ protected:
virtual void EmitElement(XMLElement * p)
{
uint64_t id;
- typename base_type::value_t fValue;
+ FeatureParams fValue;
if (!ParseType(p, id, fValue))
return;
// check, if we can make united feature
- for (typename base_type::value_t::types_t::iterator i = fValue.types.begin(); i != fValue.types.end(); ++i)
+ for (typename FeatureParams::types_t::iterator i = fValue.types.begin(); i != fValue.types.end(); ++i)
if (feature::NeedUnite(*i))
{
typename base_type::feature_builder_t ft;
@@ -452,21 +428,18 @@ class SecondPassParserUsual : public SecondPassParserBase<TEmitter, THolder>
{
typedef SecondPassParserBase<TEmitter, THolder> base_type;
- typedef typename base_type::value_t type_t;
typedef typename base_type::feature_builder_t feature_t;
- void InitFeature(type_t const & fValue, feature_t & ft)
+ void InitFeature(FeatureParams const & fValue, feature_t & ft)
{
- ft.AddName(fValue.name);
- ft.AddTypes(fValue.types.begin(), fValue.types.end());
- ft.AddLayer(fValue.layer);
+ ft.SetParams(fValue);
}
protected:
virtual void EmitElement(XMLElement * p)
{
uint64_t id;
- type_t fValue;
+ FeatureParams fValue;
if (!ParseType(p, id, fValue))
return;
@@ -475,7 +448,7 @@ protected:
if (p->name == "node")
{
- if (!feature::IsDrawableLike(fValue.types, feature::fpoint))
+ if (!feature::IsDrawableLike(fValue.m_Types, feature::fpoint))
return;
m2::PointD pt;
@@ -491,8 +464,8 @@ protected:
// __debugbreak();
//#endif
- bool const isLine = feature::IsDrawableLike(fValue.types, feature::fline);
- bool const isArea = feature::IsDrawableLike(fValue.types, feature::farea);
+ bool const isLine = feature::IsDrawableLike(fValue.m_Types, feature::fline);
+ bool const isArea = feature::IsDrawableLike(fValue.m_Types, feature::farea);
if (!isLine && !isArea)
return;
@@ -533,7 +506,7 @@ protected:
// __debugbreak();
//#endif
- if (!feature::IsDrawableLike(fValue.types, feature::farea))
+ if (!feature::IsDrawableLike(fValue.m_Types, feature::farea))
return;
// check, if this is our processable relation
diff --git a/generator/statistics.cpp b/generator/statistics.cpp
index 84c99ea74a..0d9da58ad7 100644
--- a/generator/statistics.cpp
+++ b/generator/statistics.cpp
@@ -13,6 +13,8 @@
#include "../base/start_mem_debug.hpp"
+using namespace feature;
+
namespace stats
{
void FileContainerStatistic(string const & fName)
@@ -88,12 +90,12 @@ namespace stats
cout << prefix << ": size = " << info.m_size << "; count = " << info.m_count << endl;
}
- string GetKey(FeatureBase::FeatureType type)
+ string GetKey(EGeomType type)
{
switch (type)
{
- case FeatureBase::FEATURE_TYPE_LINE: return "Line";
- case FeatureBase::FEATURE_TYPE_AREA: return "Area";
+ case GEOM_LINE: return "Line";
+ case GEOM_AREA: return "Area";
default: return "Point";
}
}
diff --git a/generator/statistics.hpp b/generator/statistics.hpp
index a4a73c03c1..2f4956fd20 100644
--- a/generator/statistics.hpp
+++ b/generator/statistics.hpp
@@ -51,7 +51,7 @@ namespace stats
struct MapInfo
{
- set<GeneralInfoKey<FeatureBase::FeatureType> > m_byGeomType;
+ set<GeneralInfoKey<feature::EGeomType> > m_byGeomType;
set<GeneralInfoKey<TypeTag> > m_byClassifType;
set<GeneralInfoKey<uint32_t> > m_byPointsCount, m_byTrgCount;
diff --git a/generator/world_map_generator.hpp b/generator/world_map_generator.hpp
index 75928828b1..9838de9ec3 100644
--- a/generator/world_map_generator.hpp
+++ b/generator/world_map_generator.hpp
@@ -194,7 +194,7 @@ public:
if (m_maxWorldScale >= minScale)
{
- if (m_mergeCoastlines && fBase.GetFeatureType() == FeatureBase::FEATURE_TYPE_LINE)
+ if (m_mergeCoastlines && fBase.GetFeatureType() == feature::GEOM_LINE)
{
for (size_t i = 0; i < m_MergeTypes.size(); ++i)
{
diff --git a/indexer/feature.cpp b/indexer/feature.cpp
index 8accf58a70..e4fda8ab1a 100644
--- a/indexer/feature.cpp
+++ b/indexer/feature.cpp
@@ -23,15 +23,12 @@
#include "../base/start_mem_debug.hpp"
+using namespace feature;
+
///////////////////////////////////////////////////////////////////////////////////////////////////
// FeatureBuilder1 implementation
///////////////////////////////////////////////////////////////////////////////////////////////////
-FeatureBuilder1::FeatureBuilder1()
-: m_Layer(0), m_bPoint(false), m_bLinear(false), m_bArea(false)
-{
-}
-
bool FeatureBuilder1::IsGeometryClosed() const
{
return (m_Geometry.size() > 2 && m_Geometry.front() == m_Geometry.back());
@@ -40,7 +37,7 @@ bool FeatureBuilder1::IsGeometryClosed() const
void FeatureBuilder1::SetCenter(m2::PointD const & p)
{
m_Center = p;
- m_bPoint = true;
+ m_Params.SetGeomType(GEOM_POINT);
m_LimitRect.Add(p);
}
@@ -52,7 +49,7 @@ void FeatureBuilder1::AddPoint(m2::PointD const & p)
void FeatureBuilder1::SetAreaAddHoles(list<points_t> const & holes)
{
- m_bArea = true;
+ m_Params.SetGeomType(GEOM_AREA);
m_Holes.clear();
if (holes.empty()) return;
@@ -68,47 +65,16 @@ void FeatureBuilder1::SetAreaAddHoles(list<points_t> const & holes)
}
}
-void FeatureBuilder1::AddName(string const & name)
-{
- m_Name = name;
-}
-
-bool FeatureBuilder1::IsTypeExist(uint32_t t) const
-{
- return (find(m_Types.begin(), m_Types.end(), t) != m_Types.end());
-}
-
-bool FeatureBuilder1::AssignType_SetDifference(vector<uint32_t> const & diffTypes)
-{
- vector<uint32_t> src;
- src.swap(m_Types);
-
- sort(src.begin(), src.end());
- set_difference(src.begin(), src.end(), diffTypes.begin(), diffTypes.end(), back_inserter(m_Types));
-
- return !m_Types.empty();
-}
-
-void FeatureBuilder1::AddLayer(int32_t layer)
-{
- int const bound = 10;
- if (layer < -bound) layer = -bound;
- else if (layer > bound) layer = bound;
- m_Layer = layer;
-}
-
FeatureBase FeatureBuilder1::GetFeatureBase() const
{
CHECK ( CheckValid(), () );
FeatureBase f;
- f.SetHeader(GetHeader());
+ f.SetHeader(m_Params.GetHeader());
- f.m_Layer = m_Layer;
- for (size_t i = 0; i < m_Types.size(); ++i)
- f.m_Types[i] = m_Types[i];
+ f.m_Params = m_Params;
+ memcpy(f.m_Types, &m_Params.m_Types[0], sizeof(uint32_t) * m_Params.m_Types.size());
f.m_LimitRect = m_LimitRect;
- f.m_Name = m_Name;
f.m_bTypesParsed = f.m_bCommonParsed = true;
@@ -149,20 +115,40 @@ namespace
}
}
-bool FeatureBuilder1::operator == (FeatureBuilder1 const & fb) const
+bool FeatureBuilder1::PreSerialize()
{
- if (m_Types != fb.m_Types ||
- m_Layer != fb.m_Layer ||
- m_Name != fb.m_Name ||
- m_bPoint != fb.m_bPoint ||
- m_bLinear != fb.m_bLinear ||
- m_bArea != fb.m_bArea)
+ if (!m_Params.IsValid()) return false;
+
+ switch (m_Params.GetGeomType())
{
+ case GEOM_POINT:
+ m_Params.ref = string();
+ m_Params.house.Clear();
+ break;
+ case GEOM_LINE:
+ m_Params.rank = 0;
+ m_Params.house.Clear();
+ break;
+ case GEOM_AREA:
+ m_Params.rank = 0;
+ m_Params.ref = string();
+ break;
+ default:
return false;
}
- if (m_bPoint && !is_equal(m_Center, fb.m_Center))
+ return true;
+}
+
+bool FeatureBuilder1::operator == (FeatureBuilder1 const & fb) const
+{
+ if (!(m_Params == fb.m_Params)) return false;
+
+ if (m_Params.GetGeomType() == GEOM_POINT &&
+ !is_equal(m_Center, fb.m_Center))
+ {
return false;
+ }
if (!is_equal(m_LimitRect, fb.m_LimitRect))
return false;
@@ -184,17 +170,15 @@ bool FeatureBuilder1::operator == (FeatureBuilder1 const & fb) const
bool FeatureBuilder1::CheckValid() const
{
- CHECK(!m_Types.empty() && m_Types.size() <= m_maxTypesCount, ());
+ CHECK(m_Params.CheckValid(), ());
- CHECK(m_Layer >= -10 && m_Layer <= 10, ());
+ EGeomType const type = m_Params.GetGeomType();
- CHECK(m_bPoint || m_bLinear || m_bArea, ());
+ CHECK(type != GEOM_LINE || m_Geometry.size() >= 2, ());
- CHECK(!m_bLinear || m_Geometry.size() >= 2, ());
+ CHECK(type != GEOM_AREA || m_Geometry.size() >= 3, ());
- CHECK(!m_bArea || m_Geometry.size() >= 3, ());
-
- CHECK(m_Holes.empty() || m_bArea, ());
+ CHECK(m_Holes.empty() || type == GEOM_AREA, ());
for (list<points_t>::const_iterator i = m_Holes.begin(); i != m_Holes.end(); ++i)
CHECK(i->size() >= 3, ());
@@ -202,47 +186,13 @@ bool FeatureBuilder1::CheckValid() const
return true;
}
-uint8_t FeatureBuilder1::GetHeader() const
-{
- uint8_t header = static_cast<uint8_t>(m_Types.size());
-
- if (!m_Name.empty())
- header |= FeatureBase::HEADER_HAS_NAME;
-
- if (m_Layer != 0)
- header |= FeatureBase::HEADER_HAS_LAYER;
-
- if (m_bPoint)
- header |= FeatureBase::HEADER_HAS_POINT;
-
- if (m_bLinear)
- header |= FeatureBase::HEADER_IS_LINE;
-
- if (m_bArea)
- header |= FeatureBase::HEADER_IS_AREA;
-
- return header;
-}
-
void FeatureBuilder1::SerializeBase(buffer_t & data, serial::CodingParams const & params) const
{
PushBackByteSink<buffer_t> sink(data);
- WriteToSink(sink, GetHeader());
-
- for (size_t i = 0; i < m_Types.size(); ++i)
- WriteVarUint(sink, m_Types[i]);
-
- if (m_Layer != 0)
- WriteVarInt(sink, m_Layer);
-
- if (!m_Name.empty())
- {
- WriteVarUint(sink, m_Name.size() - 1);
- sink.Write(&m_Name[0], m_Name.size());
- }
+ m_Params.Write(sink);
- if (m_bPoint)
+ if (m_Params.GetGeomType() == GEOM_POINT)
WriteVarUint(sink, EncodeDelta(PointD2PointU(m_Center.x, m_Center.y, params.GetCoordBits()),
params.GetBasePoint()));
}
@@ -257,10 +207,12 @@ void FeatureBuilder1::Serialize(buffer_t & data) const
PushBackByteSink<buffer_t> sink(data);
- if (m_bLinear || m_bArea)
+ EGeomType const type = m_Params.GetGeomType();
+
+ if (type != GEOM_POINT)
serial::SaveOuterPath(m_Geometry, serial::CodingParams(), sink);
- if (m_bArea)
+ if (type == GEOM_AREA)
{
WriteVarUint(sink, uint32_t(m_Holes.size()));
@@ -295,13 +247,15 @@ void FeatureBuilder1::Deserialize(buffer_t & data)
ArrayByteSource src(f.DataPtr() + f.m_Header2Offset);
- if (m_bLinear || m_bArea)
+ EGeomType const type = m_Params.GetGeomType();
+
+ if (type != GEOM_POINT)
{
serial::LoadOuterPath(src, serial::CodingParams(), m_Geometry);
CalcRect(m_Geometry, m_LimitRect);
}
- if (m_bArea)
+ if (type == GEOM_AREA)
{
uint32_t const count = ReadVarUint<uint32_t>(src);
for (uint32_t i = 0; i < count; ++i)
@@ -336,10 +290,10 @@ bool FeatureBuilder2::PreSerialize(buffers_holder_t const & data)
{
// make flags actual before header serialization
if (data.m_ptsMask == 0 && data.m_innerPts.empty())
- m_bLinear = false;
+ m_Params.RemoveGeomType(GEOM_LINE);
if (data.m_trgMask == 0 && data.m_innerTrg.empty())
- m_bArea = false;
+ m_Params.RemoveGeomType(GEOM_AREA);
// we don't need empty features without geometry
return base_type::PreSerialize();
@@ -399,14 +353,16 @@ void FeatureBuilder2::Serialize(buffers_holder_t & data, serial::CodingParams co
BitSink< PushBackByteSink<buffer_t> > bitSink(sink);
- if (m_bLinear)
+ EGeomType const type = m_Params.GetGeomType();
+
+ if (type == GEOM_LINE)
{
bitSink.Write(ptsCount, 4);
if (ptsCount == 0)
bitSink.Write(data.m_ptsMask, 4);
}
- if (m_bArea)
+ if (type == GEOM_AREA)
{
bitSink.Write(trgCount, 4);
if (trgCount == 0)
@@ -415,7 +371,7 @@ void FeatureBuilder2::Serialize(buffers_holder_t & data, serial::CodingParams co
bitSink.Finish();
- if (m_bLinear)
+ if (type == GEOM_LINE)
{
if (ptsCount > 0)
{
@@ -440,7 +396,7 @@ void FeatureBuilder2::Serialize(buffers_holder_t & data, serial::CodingParams co
}
}
- if (m_bArea)
+ if (type == GEOM_AREA)
{
if (trgCount > 0)
serial::SaveInnerTriangles(data.m_innerTrg, params, sink);
@@ -467,8 +423,7 @@ void FeatureBase::Deserialize(buffer_t & data, uint32_t offset, serial::CodingPa
m_CommonOffset = m_Header2Offset = 0;
m_bTypesParsed = m_bCommonParsed = false;
- m_Layer = 0;
- m_Name.clear();
+ m_Params = FeatureParamsBase();
m_LimitRect = m2::RectD::GetEmptyRect();
}
@@ -506,16 +461,11 @@ void FeatureBase::ParseCommon() const
uint8_t const h = Header();
- if (h & HEADER_HAS_LAYER)
- m_Layer = ReadVarInt<int32_t>(source);
+ EGeomType const type = GetFeatureType();
- if (h & HEADER_HAS_NAME)
- {
- m_Name.resize(ReadVarUint<uint32_t>(source) + 1);
- source.Read(&m_Name[0], m_Name.size());
- }
+ m_Params.Read(source, h, type);
- if (h & HEADER_HAS_POINT)
+ if (type == GEOM_POINT)
{
CoordPointT center = PointU2PointD(DecodeDelta(ReadVarUint<uint64_t>(source),
m_CodingParams.GetBasePoint()),
@@ -539,14 +489,13 @@ string FeatureBase::DebugString() const
ASSERT(m_bCommonParsed, ());
string res("FEATURE: ");
- res += "'" + m_Name + "' ";
for (size_t i = 0; i < GetTypesCount(); ++i)
res += "Type:" + debug_print(m_Types[i]) + " ";
- res += "Layer:" + debug_print(m_Layer) + " ";
+ res += m_Params.DebugString();
- if (Header() & HEADER_HAS_POINT)
+ if (GetFeatureType() == GEOM_POINT)
res += "Center:" + debug_print(m_Center) + " ";
return res;
@@ -556,23 +505,14 @@ void FeatureBase::InitFeatureBuilder(FeatureBuilder1 & fb) const
{
ParseAll();
- fb.AddTypes(m_Types, m_Types + GetTypesCount());
- fb.AddLayer(m_Layer);
- fb.AddName(m_Name);
+ FeatureParams params(m_Params);
+ params.AssignTypes(m_Types, m_Types + GetTypesCount());
+ params.SetGeomType(GetFeatureType());
- uint8_t const h = Header();
+ fb.SetParams(params);
- if (h & HEADER_HAS_POINT)
+ if (GetFeatureType() == GEOM_POINT)
fb.SetCenter(m_Center);
-
- if (h & HEADER_IS_LINE)
- fb.SetLinear();
-
- if (h & HEADER_IS_AREA)
- {
- list<vector<m2::PointD> > l;
- fb.SetAreaAddHoles(l);
- }
}
///////////////////////////////////////////////////////////////////////////////////////////////////
@@ -674,11 +614,9 @@ bool FeatureType::IsEmptyGeometry(int scale) const
switch (GetFeatureType())
{
- case FEATURE_TYPE_AREA: return m_Triangles.empty();
- case FEATURE_TYPE_LINE: return m_Points.empty();
- default:
- ASSERT ( Header() & HEADER_HAS_POINT, () );
- return false;
+ case GEOM_AREA: return m_Triangles.empty();
+ case GEOM_LINE: return m_Points.empty();
+ default: return false;
}
}
@@ -686,7 +624,7 @@ m2::RectD FeatureType::GetLimitRect(int scale) const
{
ParseAll(scale);
- if (m_Triangles.empty() && m_Points.empty() && (Header() & HEADER_HAS_POINT) == 0)
+ if (m_Triangles.empty() && m_Points.empty() && (GetFeatureType() != GEOM_POINT))
{
// This function is called during indexing, when we need
// to check visibility according to feature sizes.
@@ -751,10 +689,11 @@ void FeatureType::ParseHeader2() const
uint8_t ptsCount, ptsMask, trgCount, trgMask;
- uint8_t const commonH = Header();
BitSource bitSource(DataPtr() + m_Header2Offset);
- if (commonH & HEADER_IS_LINE)
+ EGeomType const type = GetFeatureType();
+
+ if (type == GEOM_LINE)
{
ptsCount = bitSource.Read(4);
if (ptsCount == 0)
@@ -765,7 +704,7 @@ void FeatureType::ParseHeader2() const
}
}
- if (commonH & HEADER_IS_AREA)
+ if (type == GEOM_AREA)
{
trgCount = bitSource.Read(4);
if (trgCount == 0)
@@ -774,7 +713,7 @@ void FeatureType::ParseHeader2() const
ArrayByteSource src(bitSource.RoundPtr());
- if (commonH & HEADER_IS_LINE)
+ if (type == GEOM_LINE)
{
if (ptsCount > 0)
{
@@ -797,7 +736,7 @@ void FeatureType::ParseHeader2() const
ReadOffsets(src, ptsMask, m_ptsOffsets);
}
- if (commonH & HEADER_IS_AREA)
+ if (type == GEOM_AREA)
{
if (trgCount > 0)
{
@@ -832,7 +771,7 @@ uint32_t FeatureType::ParseGeometry(int scale) const
ParseHeader2();
uint32_t sz = 0;
- if (Header() & HEADER_IS_LINE)
+ if (GetFeatureType() == GEOM_LINE)
{
if (m_Points.empty())
{
@@ -885,7 +824,7 @@ uint32_t FeatureType::ParseTriangles(int scale) const
ParseHeader2();
uint32_t sz = 0;
- if (Header() & HEADER_IS_AREA)
+ if (GetFeatureType() == GEOM_AREA)
{
if (m_Triangles.empty())
{
diff --git a/indexer/feature.hpp b/indexer/feature.hpp
index e5c99e8ece..f2c7dc4d98 100644
--- a/indexer/feature.hpp
+++ b/indexer/feature.hpp
@@ -2,6 +2,7 @@
#include "cell_id.hpp"
#include "data_header.hpp"
+#include "feature_data.hpp"
#include "../geometry/point2d.hpp"
#include "../geometry/rect2d.hpp"
@@ -18,12 +19,11 @@
class ArrayByteSource;
class FeatureBase;
+
/// Used for serialization\deserialization of features during --generate_features.
class FeatureBuilder1
{
public:
- FeatureBuilder1();
-
/// @name Geometry manipulating functions.
//@{
/// Set center (origin) point of feature and set that feature is point.
@@ -33,34 +33,26 @@ public:
void AddPoint(m2::PointD const & p);
/// Set that feature is linear type.
- void SetLinear() { m_bLinear = true; }
+ void SetLinear() { m_Params.SetGeomType(feature::GEOM_LINE); }
- /// Set that featue is area and get ownership of holes.
+ /// Set that feature is area and get ownership of holes.
void SetAreaAddHoles(list<vector<m2::PointD> > const & holes);
//@}
- void AddName(string const & name);
-
- static const int m_maxTypesCount = 7;
+ inline void SetType(uint32_t type)
+ {
+ m_Params.SetType(type);
+ }
- template <class TIter>
- inline void AddTypes(TIter beg, TIter end)
+ inline bool IsTypeExist(uint32_t t) const
{
- // !WTF! with GCC
- int const count = min(static_cast<int>(m_maxTypesCount), static_cast<int>(distance(beg, end)));
- m_Types.assign(beg, beg + count);
+ return m_Params.IsTypeExist(t);
}
- inline void SetType(uint32_t type)
+ inline bool AssignType_SetDifference(vector<uint32_t> const & diffTypes)
{
- m_Types.clear();
- m_Types.push_back(type);
+ return m_Params.AssignType_SetDifference(diffTypes);
}
- bool IsTypeExist(uint32_t t) const;
- bool AssignType_SetDifference(vector<uint32_t> const & diffTypes);
-
- void AddLayer(int32_t layer);
-
typedef vector<char> buffer_t;
/// @name Serialization.
@@ -92,7 +84,7 @@ public:
template <class ToDo>
void ForEachTruePointRef(ToDo & toDo) const
{
- if (m_bPoint)
+ if (m_Params.GetGeomType() == feature::GEOM_POINT)
toDo(m_Center);
else
{
@@ -102,10 +94,12 @@ public:
}
}
- m2::PointD CenterPoint() const { return m_Center; }
+ inline m2::PointD CenterPoint() const { return m_Center; }
//@}
- bool PreSerialize() { return m_bPoint || m_bLinear || m_bArea; }
+ bool PreSerialize();
+
+ inline void SetParams(FeatureParams const & params) { m_Params = params; }
protected:
@@ -116,18 +110,7 @@ protected:
bool CheckValid() const;
//@}
- typedef vector<m2::PointD> points_t;
-
- uint8_t GetHeader() const;
-
- /// Name. Can be empty. Check HEADER_HAS_NAME.
- string m_Name;
-
- /// Feature classificator-types. Can not be empty.
- vector<uint32_t> m_Types;
-
- /// Drawable layer of feature. Can be empty, Check HEADER_HAS_LAYER.
- int32_t m_Layer;
+ FeatureParams m_Params;
m2::RectD m_LimitRect;
@@ -137,6 +120,8 @@ protected:
/// - origin point of text or symbol in area-feature
m2::PointD m_Center; // Check HEADER_HAS_POINT
+ typedef vector<m2::PointD> points_t;
+
/// Can be one of the following:
/// - geometry in line-feature
/// - boundary in area-feature
@@ -144,13 +129,6 @@ protected:
/// List of holes in area-feature.
list<points_t> m_Holes; // Check HEADER_IS_AREA
-
- /// @name This flags can be combined.
- //@{
- bool m_bPoint; ///< this is point feature (also m_Center exists)
- bool m_bLinear; ///< this is linear-feature
- bool m_bArea; ///< this is area-feature
- //@}
};
/// Used for serialization of features during final pass.
@@ -182,8 +160,8 @@ public:
buffers_holder_t() : m_ptsMask(0), m_trgMask(0), m_ptsSimpMask(0) {}
};
- bool IsLine() const { return m_bLinear; }
- bool IsArea() const { return m_bArea; }
+ bool IsLine() const { return (m_Params.GetGeomType() == feature::GEOM_LINE); }
+ bool IsArea() const { return (m_Params.GetGeomType() == feature::GEOM_AREA); }
bool IsDrawableInRange(int lowS, int highS) const;
points_t const & GetGeometry() const { return m_Geometry; }
@@ -201,52 +179,46 @@ class FeatureBase
{
static const int m_maxTypesCount = 7;
public:
- enum FeatureType
- {
- FEATURE_TYPE_POINT = 0,
- FEATURE_TYPE_LINE = 1,
- FEATURE_TYPE_AREA = 2
- };
-
FeatureBase() : m_Offset(0) {}
typedef vector<char> buffer_t;
- inline FeatureType GetFeatureType() const
+ inline feature::EGeomType GetFeatureType() const
{
- uint8_t const h = Header();
- if (h & HEADER_IS_AREA)
- return FEATURE_TYPE_AREA;
- else if (h & HEADER_IS_LINE)
- return FEATURE_TYPE_LINE;
+ uint8_t const h = Header() & feature::HEADER_GEOTYPE_MASK;
+
+ if (h == feature::HEADER_GEOM_POINT)
+ return feature::GEOM_POINT;
+ else if (h == feature::HEADER_GEOM_LINE)
+ return feature::GEOM_LINE;
else
{
- ASSERT ( h & HEADER_HAS_POINT, () );
- return FEATURE_TYPE_POINT;
+ ASSERT ( h == feature::HEADER_GEOM_AREA, (h) );
+ return feature::GEOM_AREA;
}
}
- inline uint32_t GetTypesCount() const
+ inline uint8_t GetTypesCount() const
{
- return Header() & m_maxTypesCount;
+ return ((Header() & feature::HEADER_TYPE_MASK) + 1);
}
- inline int32_t GetLayer() const
+ inline int8_t GetLayer() const
{
- if (!(Header() & HEADER_HAS_LAYER))
+ if (!(Header() & feature::HEADER_HAS_LAYER))
return 0;
if (!m_bCommonParsed)
ParseCommon();
- return m_Layer;
+ return m_Params.layer;
}
- inline string GetName() const
+ inline bool GetName(char lang, string & utf8s) const
{
- if (!(Header() & HEADER_HAS_NAME))
- return string();
+ if (!(Header() & feature::HEADER_HAS_NAME))
+ return false;
if (!m_bCommonParsed)
ParseCommon();
- return m_Name;
+ return m_Params.name.GetString(lang, utf8s);
}
inline m2::RectD GetLimitRect() const
@@ -279,15 +251,6 @@ public:
f(m_Types[i]);
}
- enum
- {
- HEADER_HAS_LAYER = 1U << 7,
- HEADER_HAS_NAME = 1U << 6,
- HEADER_IS_AREA = 1U << 5,
- HEADER_IS_LINE = 1U << 4,
- HEADER_HAS_POINT = 1U << 3
- };
-
void InitFeatureBuilder(FeatureBuilder1 & fb) const;
/// @name Statistic functions.
@@ -312,8 +275,9 @@ protected:
uint32_t CalcOffset(ArrayByteSource const & source) const;
mutable uint32_t m_Types[m_maxTypesCount];
- mutable int32_t m_Layer;
- mutable string m_Name;
+
+ mutable FeatureParamsBase m_Params;
+
mutable m2::PointD m_Center;
mutable m2::RectD m_LimitRect;
@@ -377,7 +341,7 @@ public:
if (m_Points.empty())
{
// it's a point feature
- if (Header() & HEADER_HAS_POINT)
+ if (GetFeatureType() == feature::GEOM_POINT)
f(CoordPointT(m_Center.x, m_Center.y));
}
else
diff --git a/indexer/feature_data.cpp b/indexer/feature_data.cpp
new file mode 100644
index 0000000000..0a8ca2f511
--- /dev/null
+++ b/indexer/feature_data.cpp
@@ -0,0 +1,129 @@
+#include "feature_data.hpp"
+
+#include "../std/algorithm.hpp"
+
+
+using namespace feature;
+
+bool FeatureParamsBase::operator == (FeatureParamsBase const & rhs) const
+{
+ return (name == rhs.name && house == rhs.house && ref == rhs.ref &&
+ layer == rhs.layer && rank == rhs.rank);
+}
+
+bool FeatureParamsBase::CheckValid() const
+{
+ CHECK(layer >= -10 && layer <= 10, ());
+ return true;
+}
+
+string FeatureParamsBase::DebugString() const
+{
+ string utf8name;
+ name.GetString(0, utf8name);
+
+ return ("'" + utf8name + "' Layer:" + debug_print(layer) +
+ (rank != 0 ? " Rank:" + debug_print(rank) : "") +
+ (!house.IsEmpty() ? " House:" + house.Get() : "") +
+ (!ref.empty() ? " Ref:" + ref : "") + " ");
+}
+
+bool FeatureParams::IsValid() const
+{
+ return !m_Types.empty();
+}
+
+uint32_t FeatureParams::KeyType() const
+{
+ ASSERT_EQUAL ( m_Types.size(), 1, () );
+ return m_Types.front();
+}
+
+void FeatureParams::AddType(uint32_t t)
+{
+ m_Types.push_back(t);
+}
+
+void FeatureParams::AddTypes(FeatureParams const & v)
+{
+ m_Types.insert(m_Types.end(), v.m_Types.begin(), v.m_Types.end());
+}
+
+namespace
+{
+ size_t GetMaximunTypesCount() { return HEADER_TYPE_MASK + 1; }
+}
+
+void FeatureParams::FinishAddingTypes()
+{
+ sort(m_Types.begin(), m_Types.end());
+ m_Types.erase(unique(m_Types.begin(), m_Types.end()), m_Types.end());
+ if (m_Types.size() > GetMaximunTypesCount())
+ m_Types.resize(GetMaximunTypesCount());
+}
+
+void FeatureParams::SetType(uint32_t t)
+{
+ m_Types.clear();
+ m_Types.push_back(t);
+}
+
+bool FeatureParams::IsTypeExist(uint32_t t) const
+{
+ return (find(m_Types.begin(), m_Types.end(), t) != m_Types.end());
+}
+
+bool FeatureParams::AssignType_SetDifference(vector<uint32_t> const & diffTypes)
+{
+ vector<uint32_t> src;
+ src.swap(m_Types);
+
+ sort(src.begin(), src.end());
+ set_difference(src.begin(), src.end(), diffTypes.begin(), diffTypes.end(), back_inserter(m_Types));
+
+ return !m_Types.empty();
+}
+
+bool FeatureParams::operator == (FeatureParams const & rhs) const
+{
+ return (FeatureParamsBase::operator ==(rhs) &&
+ m_Types == rhs.m_Types &&
+ m_Geom == rhs.m_Geom);
+}
+
+bool FeatureParams::CheckValid() const
+{
+ CHECK(!m_Types.empty() && m_Types.size() <= GetMaximunTypesCount(), ());
+ CHECK(m_Geom != GEOM_UNDEFINED, ());
+
+ return FeatureParamsBase::CheckValid();
+}
+
+uint8_t FeatureParams::GetHeader() const
+{
+ uint8_t header = static_cast<uint8_t>(m_Types.size() - 1);
+
+ if (!name.IsEmpty())
+ header |= HEADER_HAS_NAME;
+
+ if (layer != 0)
+ header |= HEADER_HAS_LAYER;
+
+ switch (m_Geom)
+ {
+ case GEOM_POINT:
+ header |= HEADER_GEOM_POINT;
+ if (rank != 0) header |= HEADER_HAS_ADDINFO;
+ break;
+ case GEOM_LINE:
+ header |= HEADER_GEOM_LINE;
+ if (!ref.empty()) header |= HEADER_HAS_ADDINFO;
+ break;
+ case GEOM_AREA:
+ header |= HEADER_GEOM_AREA;
+ if (!house.IsEmpty()) header |= HEADER_HAS_ADDINFO;
+ break;
+ }
+
+ return header;
+}
diff --git a/indexer/feature_data.hpp b/indexer/feature_data.hpp
new file mode 100644
index 0000000000..8686666940
--- /dev/null
+++ b/indexer/feature_data.hpp
@@ -0,0 +1,163 @@
+#pragma once
+
+#include "../coding/multilang_utf8_string.hpp"
+#include "../coding/value_opt_string.hpp"
+
+#include "../std/string.hpp"
+#include "../std/vector.hpp"
+
+
+namespace feature
+{
+ enum EGeomType
+ {
+ GEOM_UNDEFINED = -1,
+ GEOM_POINT = 0,
+ GEOM_LINE = 1,
+ GEOM_AREA = 2
+ };
+
+ enum EHeaderMask
+ {
+ HEADER_TYPE_MASK = 7U,
+ HEADER_HAS_NAME = 1U << 3,
+ HEADER_HAS_LAYER = 1U << 4,
+ HEADER_GEOTYPE_MASK = 3U << 5,
+ HEADER_HAS_ADDINFO = 1U << 7
+ };
+
+ enum EHeaderTypeMask
+ {
+ HEADER_GEOM_POINT = 0,
+ HEADER_GEOM_LINE = 1U << 5,
+ HEADER_GEOM_AREA = 1U << 6
+ };
+}
+
+/// Feature description struct.
+struct FeatureParamsBase
+{
+ StringUtf8Multilang name;
+ StringNumericOptimal house;
+ string ref;
+ int8_t layer;
+ uint8_t rank;
+
+ FeatureParamsBase() : layer(0), rank(0) {}
+
+ bool operator == (FeatureParamsBase const & rhs) const;
+
+ bool CheckValid() const;
+
+ string DebugString() const;
+
+ template <class TSink>
+ void Write(TSink & sink, uint8_t header, feature::EGeomType type) const
+ {
+ if (header & HEADER_HAS_NAME)
+ name.Write(sink);
+
+ if (header & HEADER_HAS_LAYER)
+ WriteToSink(sink, layer);
+
+ if (header & HEADER_HAS_ADDINFO)
+ {
+ switch (type)
+ {
+ case GEOM_POINT:
+ WriteToSink(sink, rank);
+ break;
+ case GEOM_LINE:
+ utils::WriteString(sink, ref);
+ break;
+ case GEOM_AREA:
+ house.Write(sink);
+ break;
+ }
+ }
+ }
+
+ template <class TSrc>
+ void Read(TSrc & src, uint8_t header, feature::EGeomType type)
+ {
+ if (header & HEADER_HAS_NAME)
+ name.Read(src);
+
+ if (header & HEADER_HAS_LAYER)
+ layer = ReadPrimitiveFromSource<int8_t>(src);
+
+ if (header & HEADER_HAS_ADDINFO)
+ {
+ switch (type)
+ {
+ case GEOM_POINT:
+ rank = ReadPrimitiveFromSource<uint8_t>(src);
+ break;
+ case GEOM_LINE:
+ utils::ReadString(src, ref);
+ break;
+ case GEOM_AREA:
+ house.Read(src);
+ break;
+ }
+ }
+ }
+};
+
+class FeatureParams : public FeatureParamsBase
+{
+ feature::EGeomType m_Geom;
+
+public:
+ typedef vector<uint32_t> types_t;
+ types_t m_Types;
+
+ FeatureParams(FeatureParamsBase const & rhs)
+ : FeatureParamsBase(rhs), m_Geom(feature::GEOM_UNDEFINED)
+ {
+ }
+ FeatureParams() : m_Geom(feature::GEOM_UNDEFINED) {}
+
+ bool IsValid() const;
+ uint32_t KeyType() const;
+
+ inline void SetGeomType(feature::EGeomType t) { m_Geom = t; }
+ inline void RemoveGeomType(feature::EGeomType t)
+ {
+ if (m_Geom == t) m_Geom = feature::GEOM_UNDEFINED;
+ }
+ inline feature::EGeomType GetGeomType() const { return m_Geom; }
+
+ void AddType(uint32_t t);
+ void AddTypes(FeatureParams const & v);
+ void SetType(uint32_t t);
+
+ void FinishAddingTypes();
+
+ template <class TIter>
+ void AssignTypes(TIter b, TIter e)
+ {
+ m_Types.assign(b, e);
+ }
+
+ bool IsTypeExist(uint32_t t) const;
+ bool AssignType_SetDifference(vector<uint32_t> const & diffTypes);
+
+ bool operator == (FeatureParams const & rhs) const;
+
+ bool CheckValid() const;
+
+ uint8_t GetHeader() const;
+
+ template <class TSink> void Write(TSink & sink) const
+ {
+ uint8_t const header = GetHeader();
+
+ WriteToSink(sink, header);
+
+ for (size_t i = 0; i < m_Types.size(); ++i)
+ WriteVarUint(sink, m_Types[i]);
+
+ FeatureParamsBase::Write(sink, header, m_Geom);
+ }
+};
diff --git a/indexer/feature_visibility.cpp b/indexer/feature_visibility.cpp
index eb82ddd846..623d6e739b 100644
--- a/indexer/feature_visibility.cpp
+++ b/indexer/feature_visibility.cpp
@@ -132,7 +132,7 @@ namespace
int GetDrawRule(FeatureBase const & f, int level, vector<drule::Key> & keys, string & names)
{
- FeatureBase::FeatureType const geoType = f.GetFeatureType();
+ feature::EGeomType const geoType = f.GetFeatureType();
FeatureBase::GetTypesFn types;
f.ForEachTypeRef(types);
@@ -211,7 +211,7 @@ bool IsDrawableLike(vector<uint32_t> const & types, feature_geo_t ft)
bool IsDrawableForIndex(FeatureBase const & f, int level)
{
- if (f.GetFeatureType() == FeatureBase::FEATURE_TYPE_AREA)
+ if (f.GetFeatureType() == feature::GEOM_AREA)
if (!scales::IsGoodForLevel(level, f.GetLimitRect()))
return false;
diff --git a/indexer/indexer.pro b/indexer/indexer.pro
index 6680c2fb95..379fd3aff6 100644
--- a/indexer/indexer.pro
+++ b/indexer/indexer.pro
@@ -28,6 +28,7 @@ SOURCES += \
geometry_coding.cpp \
geometry_serialization.cpp \
tesselator.cpp \
+ feature_data.cpp \
HEADERS += \
feature.hpp \
@@ -60,3 +61,4 @@ HEADERS += \
point_to_int64.hpp \
tesselator.hpp \
tesselator_decl.hpp \
+ feature_data.hpp \
diff --git a/map/framework.cpp b/map/framework.cpp
index 3c80975d63..532e567d53 100644
--- a/map/framework.cpp
+++ b/map/framework.cpp
@@ -21,6 +21,8 @@
#include "../base/start_mem_debug.hpp"
+using namespace feature;
+
namespace fwork
{
namespace
@@ -135,18 +137,20 @@ namespace fwork
m_renderState->m_isEmptyModelCurrent = false;
- shared_ptr<di::DrawInfo> ptr(new di::DrawInfo(f.GetName()));
+ string utf8name;
+ f.GetName(0, utf8name);
+ shared_ptr<di::DrawInfo> ptr(new di::DrawInfo(utf8name));
using namespace get_pts;
bool isExist = false;
switch (type)
{
- case FeatureBase::FEATURE_TYPE_POINT:
+ case GEOM_POINT:
GET_POINTS(get_pts::one_point, ForEachPointRef, assign_point)
break;
- case FeatureBase::FEATURE_TYPE_AREA:
+ case GEOM_AREA:
GET_POINTS(filter_screenpts_adapter<area_tess_points>, ForEachTriangleExRef, assign_area)
{
// if area feature has any line-drawing-rules, than draw it like line
@@ -157,7 +161,7 @@ namespace fwork
}
draw_line:
- case FeatureBase::FEATURE_TYPE_LINE:
+ case GEOM_LINE:
GET_POINTS(filter_screenpts_adapter<path_points>, ForEachPointRef, assign_path)
break;
}
diff --git a/qt/searchwindow.cpp b/qt/searchwindow.cpp
index 7ad497295e..f208678005 100644
--- a/qt/searchwindow.cpp
+++ b/qt/searchwindow.cpp
@@ -27,9 +27,8 @@ FindTableWnd::FindTableWnd(QWidget * pParent, FindEditorWnd * pEditor, model_t *
bool FindTableWnd::AddFeature(FeatureType const & f)
{
- string name = f.GetName();
-
- if (!name.empty())
+ string utf8name;
+ if (f.GetName(0, utf8name) && !utf8name.empty())
{
// 200 rows is enough
int const r = rowCount();
@@ -38,7 +37,7 @@ bool FindTableWnd::AddFeature(FeatureType const & f)
insertRow(r);
- QTableWidgetItem * item = new QTableWidgetItem(QString::fromUtf8(name.c_str()));
+ QTableWidgetItem * item = new QTableWidgetItem(QString::fromUtf8(utf8name.c_str()));
item->setFlags(item->flags() ^ Qt::ItemIsEditable);
setItem(r, 0, item);