[Refactoring]. Divide Feature class to:

- FeatureBase (base feature class)
- FeatureGeom (store geometry itself)
- FeatureGeomRef (in future, store reference to geometry).
This commit is contained in:
vng 2010-12-11 16:47:40 +02:00 committed by Alex Zolotarev
parent 3e8b50b925
commit ed9abd7b50
24 changed files with 473 additions and 318 deletions

View file

@ -1,8 +1,9 @@
#pragma once
#include "../base/base.hpp"
#include "../std/vector.hpp"
#include "../std/memcpy.hpp"
#include "../base/start_mem_debug.hpp"
class ArrayByteSource
{
@ -56,5 +57,3 @@ private:
TStorage & m_Storage;
size_t m_InitialStorageSize;
};
#include "../base/stop_mem_debug.hpp"

View file

@ -60,7 +60,8 @@ public:
{
uint32_t offset;
uint64_t nextPos = ReadRecord(pos, buffer, offset);
f(pos, &buffer[offset], buffer.size() - offset);
// uint64_t -> uint32_t : assume that feature dat file not more than 4Gb
f(static_cast<uint32_t>(pos), &buffer[offset], static_cast<uint32_t>(buffer.size() - offset));
pos = nextPos;
}
ASSERT_EQUAL(pos, m_ReaderSize, ());

View file

@ -68,13 +68,15 @@ namespace
};
}
vector<int64_t> covering::CoverFeature(Feature const & feature)
vector<int64_t> covering::CoverFeature(FeatureGeom const & feature)
{
vector<CoordPointT> geometry;
feature.ForEachPoint(MakeBackInsertFunctor(geometry));
ASSERT(!geometry.empty(), ());
if (geometry.empty())
return vector<int64_t>();
vector<RectId> ids;
if (geometry.size() > 1)
// TODO: Tweak CoverPolyLine() depth level.

View file

@ -1,16 +1,18 @@
#pragma once
#include "../geometry/rect2d.hpp"
#include "../base/base.hpp"
#include "../std/utility.hpp"
#include "../std/vector.hpp"
class Feature;
class FeatureGeom;
namespace covering
{
// Cover feature with RectIds and return their integer representations.
vector<int64_t> CoverFeature(Feature const & feature);
vector<int64_t> CoverFeature(FeatureGeom const & feature);
// Cover viewport with RectIds and append their RectIds as well.
vector<pair<int64_t, int64_t> > CoverViewportAndAppendLowerLevels(m2::RectD const & rect);
// Given a vector of intervals [a, b), sort them and merge overlapping intervals.

View file

@ -1,12 +1,17 @@
#include "feature.hpp"
#include "cell_id.hpp"
#include "../geometry/rect2d.hpp"
#include "../coding/byte_stream.hpp"
#include "../coding/reader.hpp"
#include "../coding/varint.hpp"
#include "../coding/write_to_sink.hpp"
#include "../base/logging.hpp"
#include "../std/bind.hpp"
#include "../std/map.hpp"
#include "../base/start_mem_debug.hpp"
namespace pts
{
@ -21,6 +26,10 @@ namespace pts
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// FeatureBuilder implementation
///////////////////////////////////////////////////////////////////////////////////////////////////
FeatureBuilder::FeatureBuilder() : m_Layer(0)
{
}
@ -80,16 +89,16 @@ void FeatureBuilder::Serialize(vector<char> & data) const
// Serializing header.
uint8_t header = static_cast<uint8_t>(m_Types.size());
if (m_Layer != 0)
header |= Feature::HEADER_HAS_LAYER;
header |= FeatureBase::HEADER_HAS_LAYER;
if (m_Geometry.size() > 1)
{
if (m_Triangles.empty())
header |= Feature::HEADER_IS_LINE;
header |= FeatureBase::HEADER_IS_LINE;
else
header |= Feature::HEADER_IS_AREA;
header |= FeatureBase::HEADER_IS_AREA;
}
if (!m_Name.empty())
header |= Feature::HEADER_HAS_NAME;
header |= FeatureBase::HEADER_HAS_NAME;
WriteToSink(sink, header);
// Serializing types.
@ -102,6 +111,13 @@ void FeatureBuilder::Serialize(vector<char> & data) const
if (m_Layer != 0)
WriteVarInt(sink, m_Layer);
// Serializing name.
if (!m_Name.empty())
{
WriteVarUint(sink, m_Name.size() - 1);
sink.Write(&m_Name[0], m_Name.size());
}
// Serializing geometry.
if (m_Geometry.size() == 1)
{
@ -123,67 +139,64 @@ void FeatureBuilder::Serialize(vector<char> & data) const
WriteVarInt(sink, i == 0 ? m_Triangles[i] : (m_Triangles[i] - m_Triangles[i-1]));
}
// Serializing name.
if (!m_Name.empty())
{
WriteVarUint(sink, m_Name.size() - 1);
sink.Write(&m_Name[0], m_Name.size());
}
ASSERT ( CheckCorrect(data), () );
}
#ifdef DEBUG
bool FeatureBuilder::CheckCorrect(vector<char> const & data) const
{
vector<char> data1 = data;
Feature feature;
FeatureGeom feature;
feature.DeserializeAndParse(data1);
FeatureBuilder const fb = feature.GetFeatureBuilder();
ASSERT_EQUAL(m_Types, fb.m_Types, (feature.DebugString()));
ASSERT_EQUAL(m_Layer, fb.m_Layer, (feature.DebugString()));
ASSERT_EQUAL(m_Geometry, fb.m_Geometry, (feature.DebugString()));
ASSERT_EQUAL(m_Triangles, fb.m_Triangles, (feature.DebugString()));
ASSERT_EQUAL(m_Name, fb.m_Name, (feature.DebugString()));
ASSERT(*this == fb, (feature.DebugString()));
#endif
FeatureBuilder fb;
feature.InitFeatureBuilder(fb);
string const s = feature.DebugString();
ASSERT_EQUAL(m_Types, fb.m_Types, (s));
ASSERT_EQUAL(m_Layer, fb.m_Layer, (s));
ASSERT_EQUAL(m_Geometry, fb.m_Geometry, (s));
ASSERT_EQUAL(m_Triangles, fb.m_Triangles, (s));
ASSERT_EQUAL(m_Name, fb.m_Name, (s));
ASSERT(*this == fb, (s));
return true;
}
Feature FeatureBuilder::GetFeature() const
{
vector<char> data;
Serialize(data);
Feature feature;
feature.Deserialize(data);
return feature;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// FeatureBase implementation
///////////////////////////////////////////////////////////////////////////////////////////////////
Feature::Feature(vector<char> & data, uint32_t offset)
{
Deserialize(data, offset);
}
void Feature::Deserialize(vector<char> & data, uint32_t offset)
void FeatureBase::Deserialize(vector<char> & data, uint32_t offset)
{
m_Offset = offset;
m_Data.swap(data);
m_LayerOffset = m_GeometryOffset = m_TrianglesOffset = m_NameOffset = 0;
m_bTypesParsed = m_bLayerParsed = m_bGeometryParsed = m_bTrianglesParsed = m_bNameParsed = false;
m_Layer = m_TriangleCount = 0;
m_Geometry.clear();
m_Triangles.clear();
m_Layer = 0;
m_Name.clear();
m_LimitRect = m2::RectD();
}
void Feature::ParseTypes() const
uint32_t FeatureBase::CalcOffset(ArrayByteSource const & source) const
{
return static_cast<uint32_t>(static_cast<char const *>(source.Ptr()) - DataPtr());
}
void FeatureBase::ParseTypes() const
{
ASSERT(!m_bTypesParsed, ());
ArrayByteSource source(DataPtr() + 1);
for (size_t i = 0; i < GetTypesCount(); ++i)
m_Types[i] = ReadVarUint<uint32_t>(source);
m_LayerOffset = static_cast<uint32_t>(static_cast<char const *>(source.Ptr()) - DataPtr());
m_bTypesParsed = true;
m_LayerOffset = CalcOffset(source);
}
void Feature::ParseLayer() const
void FeatureBase::ParseLayer() const
{
ASSERT(!m_bLayerParsed, ());
if (!m_bTypesParsed)
@ -193,76 +206,31 @@ void Feature::ParseLayer() const
if (Header() & HEADER_HAS_LAYER)
m_Layer = ReadVarInt<int32_t>(source);
m_GeometryOffset = static_cast<uint32_t>(static_cast<char const *>(source.Ptr()) - DataPtr());
m_bLayerParsed = true;
m_NameOffset = CalcOffset(source);
}
void Feature::ParseGeometry() const
{
ASSERT(!m_bGeometryParsed, ());
if (!m_bLayerParsed)
ParseLayer();
ArrayByteSource source(DataPtr() + m_GeometryOffset);
uint32_t const geometrySize =
(GetFeatureType() == FEATURE_TYPE_POINT ? 1 : ReadVarUint<uint32_t>(source) + 1);
m_Geometry.resize(geometrySize);
int64_t id = 0;
for (size_t i = 0; i < geometrySize; ++i)
m_LimitRect.Add(m_Geometry[i] = pts::ToPoint(id += ReadVarInt<int64_t>(source)));
m_TrianglesOffset = static_cast<uint32_t>(static_cast<char const *>(source.Ptr()) - DataPtr());
m_bGeometryParsed = true;
}
void Feature::ParseTriangles() const
{
ASSERT(!m_bTrianglesParsed, ());
if (!m_bGeometryParsed)
ParseGeometry();
ArrayByteSource source(DataPtr() + m_TrianglesOffset);
if (GetFeatureType() == FEATURE_TYPE_AREA)
{
m_TriangleCount = ReadVarUint<uint32_t>(source) + 1;
uint32_t const trianglePoints = m_TriangleCount * 3;
m_Triangles.resize(trianglePoints);
int64_t id = 0;
for (size_t i = 0; i < trianglePoints; ++i)
m_Triangles[i] = pts::ToPoint(id += ReadVarInt<int64_t>(source));
}
m_NameOffset = static_cast<uint32_t>(static_cast<char const *>(source.Ptr()) - DataPtr());
m_bTrianglesParsed = true;
}
void Feature::ParseName() const
void FeatureBase::ParseName() const
{
ASSERT(!m_bNameParsed, ());
if (!m_bTrianglesParsed)
ParseTriangles();
if (!m_bLayerParsed)
ParseLayer();
ArrayByteSource source(DataPtr() + m_NameOffset);
if (Header() & HEADER_HAS_NAME)
{
m_Name.resize(ReadVarUint<uint32_t>(source) + 1);
source.Read(&m_Name[0], m_Name.size());
}
m_bNameParsed = true;
ASSERT_EQUAL(static_cast<uint32_t>(static_cast<char const *>(source.Ptr()) - DataPtr()),
m_Data.size() - m_Offset, ());
m_GeometryOffset = CalcOffset(source);
}
void Feature::ParseAll() const
string FeatureBase::DebugString() const
{
if (!m_bNameParsed)
ParseName();
}
ASSERT(m_bNameParsed, ());
void Feature::DeserializeAndParse(vector<char> & data, uint32_t offset)
{
Deserialize(data, offset);
ParseAll();
}
string Feature::DebugString() const
{
ParseAll();
string res("Feature(");
res += "'" + m_Name + "' ";
@ -270,23 +238,105 @@ string Feature::DebugString() const
res += "Type:" + debug_print(m_Types[i]) + " ";
res += "Layer:" + debug_print(m_Layer) + " ";
return res;
}
void FeatureBase::InitFeatureBuilder(FeatureBuilder & fb) const
{
ASSERT(m_bNameParsed, ());
fb.AddTypes(m_Types, m_Types + GetTypesCount());
fb.AddLayer(m_Layer);
fb.AddName(m_Name);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
// FeatureGeom implementation
///////////////////////////////////////////////////////////////////////////////////////////////////
FeatureGeom::FeatureGeom(vector<char> & data, uint32_t offset)
{
Deserialize(data, offset);
}
void FeatureGeom::Deserialize(vector<char> & data, uint32_t offset)
{
base_type::Deserialize(data, offset);
m_Geometry.clear();
m_Triangles.clear();
}
void FeatureGeom::ParseGeometry() const
{
ASSERT(!m_bGeometryParsed, ());
if (!m_bNameParsed)
ParseName();
ArrayByteSource source(DataPtr() + m_GeometryOffset);
uint32_t const geometrySize =
(GetFeatureType() == FEATURE_TYPE_POINT ? 1 : ReadVarUint<uint32_t>(source) + 1);
m_Geometry.resize(geometrySize);
int64_t id = 0;
for (size_t i = 0; i < geometrySize; ++i)
m_LimitRect.Add(m_Geometry[i] = pts::ToPoint(id += ReadVarInt<int64_t>(source)));
m_bGeometryParsed = true;
m_TrianglesOffset = CalcOffset(source);
}
void FeatureGeom::ParseTriangles() const
{
ASSERT(!m_bTrianglesParsed, ());
if (!m_bGeometryParsed)
ParseGeometry();
ArrayByteSource source(DataPtr() + m_TrianglesOffset);
if (GetFeatureType() == FEATURE_TYPE_AREA)
{
uint32_t const trgPoints = (ReadVarUint<uint32_t>(source) + 1) * 3;
m_Triangles.resize(trgPoints);
int64_t id = 0;
for (size_t i = 0; i < trgPoints; ++i)
m_Triangles[i] = pts::ToPoint(id += ReadVarInt<int64_t>(source));
}
m_bTrianglesParsed = true;
ASSERT_EQUAL ( CalcOffset(source), m_Data.size() - m_Offset, () );
}
void FeatureGeom::ParseAll() const
{
if (!m_bTrianglesParsed)
ParseTriangles();
}
void FeatureGeom::DeserializeAndParse(vector<char> & data, uint32_t offset)
{
Deserialize(data, offset);
ParseAll();
}
string FeatureGeom::DebugString() const
{
ParseAll();
string res = base_type::DebugString();
res += debug_print(m_Geometry) + " ";
res += debug_print(m_Triangles) + ")";
return res;
}
FeatureBuilder Feature::GetFeatureBuilder() const
void FeatureGeom::InitFeatureBuilder(FeatureBuilder & fb) const
{
ParseAll();
FeatureBuilder fb;
fb.AddTypes(m_Types, m_Types + GetTypesCount());
fb.AddLayer(m_Layer);
base_type::InitFeatureBuilder(fb);
for (size_t i = 0; i < m_Geometry.size(); ++i)
fb.AddPoint(m_Geometry[i]);
ASSERT_EQUAL(m_Triangles.size() % 3, 0, ());
uint32_t const triangleCount = m_Triangles.size() / 3;
for (size_t i = 0; i < triangleCount; ++i)
fb.AddTriangle(m_Triangles[3*i + 0], m_Triangles[3*i + 1], m_Triangles[3*i + 2]);
fb.AddName(m_Name);
return fb;
}

View file

@ -1,7 +1,5 @@
#pragma once
#include "cell_id.hpp"
#include "../geometry/point2d.hpp"
#include "../geometry/rect2d.hpp"
@ -9,10 +7,9 @@
#include "../std/string.hpp"
#include "../std/vector.hpp"
#include "../std/iterator.hpp"
#include "../std/algorithm.hpp"
class Feature;
class ArrayByteSource;
class FeatureBuilder
{
@ -39,15 +36,14 @@ public:
void Serialize(vector<char> & data) const;
// Returns corresponding feature. Does Serialize() and feature.Deserialize() internally.
Feature GetFeature() const;
bool IsGeometryClosed() const;
size_t GetPointsCount() const { return m_Geometry.size(); }
bool operator == (FeatureBuilder const &) const;
private:
bool CheckCorrect(vector<char> const & data) const;
int32_t m_Layer;
string m_Name;
vector<uint32_t> m_Types;
@ -55,7 +51,7 @@ private:
vector<int64_t> m_Triangles;
};
class Feature
class FeatureBase
{
public:
enum FeatureType
@ -66,15 +62,14 @@ public:
FEATURE_TYPE_UNKNOWN = 17
};
Feature() {}
Feature(vector<char> & data, uint32_t offset = 0);
FeatureBase() {}
/// @name Use like polymorfic functions. Need to overwrite in derived classes.
//@{
void Deserialize(vector<char> & data, uint32_t offset = 0);
void DeserializeAndParse(vector<char> & data, uint32_t offset = 0);
string DebugString() const;
FeatureBuilder GetFeatureBuilder() const;
void InitFeatureBuilder(FeatureBuilder & fb) const;
//@}
inline FeatureType GetFeatureType() const
{
@ -96,27 +91,6 @@ public:
return m_Layer;
}
inline m2::RectD GetLimitRect() const
{
if (!m_bGeometryParsed)
ParseGeometry();
return m_LimitRect;
}
inline uint32_t GetGeometrySize() const
{
if (!m_bGeometryParsed)
ParseGeometry();
return m_Geometry.size();
}
inline uint32_t GetTriangleCount() const
{
if (!m_bTrianglesParsed)
ParseTriangles();
return m_TriangleCount;
}
inline string GetName() const
{
if (!(Header() & HEADER_HAS_NAME))
@ -126,6 +100,12 @@ public:
return m_Name;
}
inline m2::RectD GetLimitRect() const
{
ASSERT(m_bGeometryParsed, ());
return m_LimitRect;
}
class GetTypesFn
{
public:
@ -148,6 +128,83 @@ 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
};
protected:
vector<char> m_Data;
uint32_t m_Offset;
inline char const * DataPtr() const { return &m_Data[m_Offset]; }
inline uint8_t Header() const { return static_cast<uint8_t>(*DataPtr()); }
uint32_t CalcOffset(ArrayByteSource const & source) const;
mutable uint32_t m_Types[16];
mutable int32_t m_Layer;
mutable string m_Name;
mutable m2::RectD m_LimitRect;
mutable uint32_t m_LayerOffset;
mutable uint32_t m_NameOffset;
mutable uint32_t m_GeometryOffset;
mutable uint32_t m_TrianglesOffset;
mutable bool m_bTypesParsed;
mutable bool m_bLayerParsed;
mutable bool m_bNameParsed;
mutable bool m_bGeometryParsed;
mutable bool m_bTrianglesParsed;
void ParseTypes() const;
void ParseLayer() const;
void ParseName() const;
};
class FeatureGeom : public FeatureBase
{
typedef FeatureBase base_type;
public:
FeatureGeom() {}
FeatureGeom(vector<char> & data, uint32_t offset = 0);
/// @name Overwrite from base_type.
//@{
void Deserialize(vector<char> & data, uint32_t offset = 0);
string DebugString() const;
void InitFeatureBuilder(FeatureBuilder & fb) const;
//@}
inline m2::RectD GetLimitRect() const
{
if (!m_bGeometryParsed)
ParseGeometry();
return base_type::GetLimitRect();
}
void ParseAll() const;
void DeserializeAndParse(vector<char> & data, uint32_t offset = 0);
inline uint32_t GetGeometrySize() const
{
if (!m_bGeometryParsed)
ParseGeometry();
return m_Geometry.size();
}
inline uint32_t GetTriangleCount() const
{
if (!m_bTrianglesParsed)
ParseTriangles();
return (m_Triangles.size() / 3);
}
template <typename FunctorT>
void ForEachPointRef(FunctorT & f) const
{
@ -183,49 +240,21 @@ public:
f.EndPrimitive();
}
enum
{
HEADER_HAS_LAYER = 1U << 7,
HEADER_HAS_NAME = 1U << 6,
HEADER_IS_AREA = 1U << 5,
HEADER_IS_LINE = 1U << 4
};
private:
vector<char> m_Data;
uint32_t m_Offset;
inline char const * DataPtr() const { return &m_Data[m_Offset]; }
inline uint8_t Header() const { return static_cast<uint8_t>(*DataPtr()); }
mutable uint32_t m_Types[16];
mutable int32_t m_Layer;
mutable vector<m2::PointD> m_Geometry;
mutable m2::RectD m_LimitRect;
mutable vector<m2::PointD> m_Triangles;
mutable uint32_t m_TriangleCount;
mutable string m_Name;
mutable uint32_t m_LayerOffset;
mutable uint32_t m_GeometryOffset;
mutable uint32_t m_TrianglesOffset;
mutable uint32_t m_NameOffset;
mutable bool m_bTypesParsed;
mutable bool m_bLayerParsed;
mutable bool m_bGeometryParsed;
mutable bool m_bTrianglesParsed;
mutable bool m_bNameParsed;
void ParseTypes() const;
void ParseLayer() const;
void ParseGeometry() const;
void ParseTriangles() const;
void ParseName() const;
void ParseAll() const;
};
inline string debug_print(Feature const & f)
class FeatureGeomRef : public FeatureBase
{
};
inline string debug_print(FeatureGeom const & f)
{
return f.DebugString();
}

View file

@ -9,8 +9,8 @@
namespace feature
{
template <typename TSource>
void ReadFromSource(TSource & src, Feature & ft)
template <class TSource, class TFeature>
void ReadFromSource(TSource & src, TFeature & ft)
{
uint32_t const sz = ReadVarUint<uint32_t>(src);
vector<char> buffer(sz);
@ -40,7 +40,7 @@ namespace feature
// read features one by one
while (currPos < fSize)
{
Feature ft;
FeatureGeom ft;
ReadFromSource(src, ft);
toDo(ft, currPos);
currPos = src.Pos();

View file

@ -112,16 +112,16 @@ namespace
};
}
int GetDrawRule(Feature const & f, int level, vector<drule::Key> & keys, string & names)
int GetDrawRule(FeatureBase const & f, int level, vector<drule::Key> & keys, string & names)
{
Feature::FeatureType const geoType = f.GetFeatureType();
if (geoType == Feature::FEATURE_TYPE_UNKNOWN)
FeatureBase::FeatureType const geoType = f.GetFeatureType();
if (geoType == FeatureBase::FEATURE_TYPE_UNKNOWN)
{
ASSERT ( false, ("Logic Error! Unknown feature type.") );
return Feature::FEATURE_TYPE_UNKNOWN;
return FeatureBase::FEATURE_TYPE_UNKNOWN;
}
Feature::GetTypesFn types;
FeatureBase::GetTypesFn types;
f.ForEachTypeRef(types);
ASSERT ( keys.empty(), () );
@ -196,13 +196,13 @@ bool IsDrawableLike(vector<uint32_t> const & types, feature_geo_t ft)
return false;
}
bool IsDrawableForIndex(Feature const & f, int level)
bool IsDrawableForIndex(FeatureBase const & f, int level)
{
if (f.GetFeatureType() == Feature::FEATURE_TYPE_AREA)
if (f.GetFeatureType() == FeatureBase::FEATURE_TYPE_AREA)
if (!scales::IsGoodForLevel(level, f.GetLimitRect()))
return false;
Feature::GetTypesFn types;
FeatureBase::GetTypesFn types;
f.ForEachTypeRef(types);
Classificator const & c = classif();
@ -215,15 +215,15 @@ bool IsDrawableForIndex(Feature const & f, int level)
return false;
}
uint32_t MinDrawableScaleForFeature(Feature const & f)
int MinDrawableScaleForFeature(FeatureBase const & f)
{
uint32_t const upBound = scales::GetUpperScale();
int const upBound = scales::GetUpperScale();
for (uint32_t level = 0; level <= upBound; ++level)
for (int level = 0; level <= upBound; ++level)
if (feature::IsDrawableForIndex(f, level))
return level;
return uint32_t(-1);
return -1;
}
}

View file

@ -7,7 +7,7 @@
#include "../std/vector.hpp"
#include "../std/string.hpp"
class Feature;
class FeatureBase;
namespace feature
{
@ -15,9 +15,9 @@ namespace feature
bool IsDrawableAny(uint32_t type);
bool IsDrawableLike(vector<uint32_t> const & type, feature_geo_t ft);
bool IsDrawableForIndex(Feature const & f, int level);
uint32_t MinDrawableScaleForFeature(Feature const & f);
bool IsDrawableForIndex(FeatureBase const & f, int level);
int MinDrawableScaleForFeature(FeatureBase const & f);
int GetDrawRule(Feature const & f, int level, vector<drule::Key> & keys, string & names);
int GetDrawRule(FeatureBase const & f, int level, vector<drule::Key> & keys, string & names);
}

View file

@ -1,12 +1,18 @@
#pragma once
#include "../indexer/feature.hpp"
#include "../coding/var_record_reader.hpp"
#include "../base/base.hpp"
#include "../std/bind.hpp"
template <typename ReaderT>
class FeaturesVector
{
typedef FeatureGeom feature_t;
public:
typedef ReaderT ReaderType;
@ -14,7 +20,7 @@ public:
{
}
void Get(uint64_t pos, Feature & feature) const
void Get(uint64_t pos, feature_t & feature) const
{
vector<char> record;
uint32_t offset;
@ -24,14 +30,14 @@ public:
template <class TDo> void ForEachOffset(TDo const & toDo) const
{
Feature f;
feature_t f;
m_RecordReader.ForEachRecord(
bind<void>(toDo, bind(&FeaturesVector<ReaderT>::DeserializeFeature, this, _2, _3, &f), _1));
}
template <class TDo> void ForEach(TDo const & toDo) const
{
Feature f;
feature_t f;
m_RecordReader.ForEachRecord(
bind<void>(toDo, bind(&FeaturesVector<ReaderT>::DeserializeFeature, this, _2, _3, &f)));
}
@ -42,7 +48,7 @@ public:
}
private:
Feature const & DeserializeFeature(char const * data, uint32_t size, Feature * pFeature) const
feature_t const & DeserializeFeature(char const * data, uint32_t size, feature_t * pFeature) const
{
vector<char> data1(data, data + size);
pFeature->Deserialize(data1);

View file

@ -150,17 +150,21 @@ private:
FeatureVectorT m_FeatureVector;
template <typename F>
struct OffsetToFeatureReplacer
class OffsetToFeatureReplacer
{
typedef FeatureGeom feature_t;
FeatureVectorT const & m_V;
F const & m_F;
public:
OffsetToFeatureReplacer(FeatureVectorT const & v, F const & f) : m_V(v), m_F(f) {}
void operator() (uint32_t offset) const
{
Feature feature;
feature_t feature;
m_V.Get(offset, feature);
m_F(feature);
}
FeatureVectorT const & m_V;
F const & m_F;
};
};

View file

@ -1,10 +1,18 @@
#include "../../testing/testing.hpp"
#include "../indexer_tool/feature_bucketer.hpp"
#include "../feature.hpp"
#include "../mercator.hpp"
#include "../cell_id.hpp"
#include "../../base/stl_add.hpp"
namespace
{
typedef FeatureGeom feature_t;
class PushBackFeatureDebugStringOutput
{
public:
@ -13,7 +21,7 @@ namespace
PushBackFeatureDebugStringOutput(string const & name, InitDataType const & initData)
: m_pContainer(&((*initData)[name])) {}
void operator() (Feature const & feature)
void operator() (feature_t const & feature)
{
m_pContainer->push_back(feature.DebugString());
}
@ -29,11 +37,11 @@ namespace
RectId
> FeatureBucketer;
Feature MakeFeature(FeatureBuilder const & fb)
feature_t MakeFeature(FeatureBuilder const & fb)
{
vector<char> data;
fb.Serialize(data);
return Feature(data, 0);
return feature_t(data, 0);
}
}

View file

@ -1,6 +1,10 @@
#include "../../testing/testing.hpp"
#include "../feature.hpp"
#include "../cell_id.hpp"
#include "../../geometry/point2d.hpp"
#include "../../base/stl_add.hpp"
namespace
@ -30,6 +34,8 @@ namespace
UNIT_TEST(Feature_Deserialize)
{
typedef FeatureGeom feature_t;
vector<int> a;
a.push_back(1);
a.push_back(2);
@ -65,11 +71,11 @@ UNIT_TEST(Feature_Deserialize)
vector<char> serial;
builder.Serialize(serial);
vector<char> serial1 = serial;
Feature f(serial1);
feature_t f(serial1);
TEST_EQUAL(f.GetFeatureType(), Feature::FEATURE_TYPE_AREA, ());
TEST_EQUAL(f.GetFeatureType(), FeatureBase::FEATURE_TYPE_AREA, ());
Feature::GetTypesFn types;
FeatureBase::GetTypesFn types;
f.ForEachTypeRef(types);
TEST_EQUAL(types.m_types, vector<uint32_t>(arrTypes, arrTypes + typesCount), ());
@ -92,7 +98,10 @@ UNIT_TEST(Feature_Deserialize)
TEST_LESS(fabs(f.GetLimitRect().maxY() - 1.00), 0.0001, ());
vector<char> serial2;
f.GetFeatureBuilder().Serialize(serial2);
FeatureBuilder builder2;
f.InitFeatureBuilder(builder2);
builder2.Serialize(serial2);
TEST_EQUAL(serial, serial2,
(f.DebugString(), Feature(serial2).DebugString()));
(f.DebugString(), feature_t(serial2).DebugString()));
}

View file

@ -9,7 +9,6 @@
#include "../../indexer/feature.hpp"
#include "../../indexer/feature_visibility.hpp"
#include "../../std/map.hpp"
#include "../../std/string.hpp"
#include <boost/scoped_ptr.hpp>
@ -23,6 +22,8 @@ namespace feature
template <class FeatureOutT, class FeatureClipperT, class BoundsT, typename CellIdT>
class CellFeatureBucketer
{
typedef FeatureGeom feature_t;
public:
CellFeatureBucketer(int level, typename FeatureOutT::InitDataType const & featureOutInitData,
int maxWorldZoom = -1)
@ -44,25 +45,22 @@ public:
}
}
void operator () (Feature const & feature)
void operator () (feature_t const & f)
{
// separately store features needed for world map
if (m_worldBucket
&& m_maxWorldZoom >= feature::MinDrawableScaleForFeature(feature))
{
(*m_worldBucket)(feature);
}
if (m_worldBucket && m_maxWorldZoom >= feature::MinDrawableScaleForFeature(f))
(*m_worldBucket)(f);
FeatureClipperT clipper(feature);
FeatureClipperT clipper(f);
// TODO: Is feature fully inside GetLimitRect()?
m2::RectD const limitRect = feature.GetLimitRect();
m2::RectD const limitRect = f.GetLimitRect();
for (uint32_t i = 0; i < m_Buckets.size(); ++i)
{
// First quick and dirty limit rect intersection.
// Clipper may (or may not) do a better intersection.
if (m_Buckets[i].m_Rect.IsIntersect(limitRect))
{
Feature clippedFeature;
feature_t clippedFeature;
if (clipper(m_Buckets[i].m_Rect, clippedFeature))
{
if (!m_Buckets[i].m_pOut)
@ -74,7 +72,14 @@ public:
}
}
void operator () (FeatureBuilder const & fb) { (*this)(fb.GetFeature()); }
void operator () (FeatureBuilder const & fb)
{
vector<char> data;
fb.Serialize(data);
feature_t f;
f.Deserialize(data);
this->operator()(f);
}
template <typename F> void GetBucketNames(F f) const
{
@ -108,19 +113,21 @@ private:
class SimpleFeatureClipper
{
typedef FeatureGeom feature_t;
public:
explicit SimpleFeatureClipper(Feature const & feature) : m_Feature(feature)
explicit SimpleFeatureClipper(feature_t const & f) : m_Feature(f)
{
}
bool operator () (m2::RectD const & /*rect*/, Feature & clippedFeature) const
bool operator () (m2::RectD const & /*rect*/, feature_t & clippedFeature) const
{
clippedFeature = m_Feature;
return true;
}
private:
Feature const & m_Feature;
feature_t const & m_Feature;
};
}

View file

@ -2,16 +2,23 @@
#include "feature_bucketer.hpp"
#include "data_cache_file.hpp"
#include "osm_element.hpp"
#include "../../indexer/data_header.hpp"
#include "../../indexer/osm_decl.hpp"
#include "../../indexer/data_header_reader.hpp"
#include "../../indexer/mercator.hpp"
#include "../../indexer/cell_id.hpp"
#include "../../coding/varint.hpp"
#include "../../base/assert.hpp"
#include "../../base/logging.hpp"
#include "../../base/stl_add.hpp"
#include "../../std/bind.hpp"
#include "../../std/unordered_map.hpp"
namespace feature
{
@ -146,7 +153,7 @@ void FeaturesCollector::operator() (FeatureBuilder const & f)
// .dat file should be less than 4Gb
uint64_t const pos = m_datFile.Pos();
ASSERT_EQUAL ( static_cast<uint64_t>(static_cast<uint32_t>(pos)), pos,
("Feature offset is out of 32bit boundary :(") );
("Feature offset is out of 32bit boundary!") );
#endif
vector<char> bytes;
@ -159,11 +166,18 @@ void FeaturesCollector::operator() (FeatureBuilder const & f)
WriteVarUint(m_datFile, sz);
m_datFile.Write(&bytes[0], sz);
Feature feature(bytes);
m_bounds.Add(feature.GetLimitRect());
feature_t f(bytes);
m_bounds.Add(f.GetLimitRect());
}
}
void FeaturesCollector::operator() (feature_t const & f)
{
FeatureBuilder fb;
f.InitFeatureBuilder(fb);
this->operator()(fb);
}
FeaturesCollector::~FeaturesCollector()
{
// rewrite map information with actual data

View file

@ -1,10 +1,17 @@
#pragma once
#include "../../indexer/feature.hpp"
#include "../../indexer/osm_decl.hpp"
#include "../../geometry/rect2d.hpp"
#include "../../coding/file_writer.hpp"
#include "../../std/vector.hpp"
#include "../../std/string.hpp"
class FeatureBuilder;
class FeatureGeom;
namespace feature
{
struct GenerateInfo
@ -30,6 +37,8 @@ namespace feature
void Init();
typedef FeatureGeom feature_t;
public:
~FeaturesCollector();
@ -40,6 +49,6 @@ namespace feature
FeaturesCollector(string const & bucketName, InitDataType const & datFilePrefixSuffix);
void operator() (FeatureBuilder const & f);
void operator() (Feature const & f) { (*this)(f.GetFeatureBuilder()); }
void operator() (feature_t const & f);
};
}

View file

@ -1,11 +1,10 @@
#include "feature_sorter.hpp"
#include "feature_generator.hpp"
#include "../../indexer/data_header.hpp"
#include "../../indexer/data_header_reader.hpp"
#include "../../indexer/feature_processor.hpp"
#include "../../indexer/feature_visibility.hpp"
#include "../../indexer/scales.hpp"
#include "../../indexer/cell_id.hpp"
#include "../../platform/platform.hpp"
@ -28,7 +27,7 @@ namespace
public:
std::vector<TCellAndOffset> m_vec;
void operator() (Feature const & ft, uint64_t pos)
void operator() (FeatureGeom const & ft, uint64_t pos)
{
// reset state
m_midX = 0.0;
@ -39,10 +38,10 @@ namespace
m_midY /= m_counter;
uint64_t const pointAsInt64 = PointToInt64(m_midX, m_midY);
uint64_t const featureScale = feature::MinDrawableScaleForFeature(ft);
CHECK(featureScale <= scales::GetUpperScale(), ("Dat file contain invisible feature"));
uint64_t const minScale = feature::MinDrawableScaleForFeature(ft);
CHECK(minScale <= scales::GetUpperScale(), ("Dat file contain invisible feature"));
uint64_t const order = (featureScale << 59) | (pointAsInt64 >> 5);
uint64_t const order = (minScale << 59) | (pointAsInt64 >> 5);
m_vec.push_back(make_pair(order, pos));
}
@ -60,7 +59,7 @@ namespace
}
template <typename TReader>
void ReadFeature(TReader const & reader, Feature & ft, uint64_t offset)
void ReadFeature(TReader const & reader, FeatureGeom & ft, uint64_t offset)
{
ReaderSource<TReader> src(reader);
src.Skip(offset);
@ -95,11 +94,12 @@ namespace feature
{
FeaturesCollector collector(datFilePath);
FileReader notSortedFileReader(tempDatFilePath);
Feature ft;
FeatureGeom ft;
for (size_t i = 0; i < midPoints.m_vec.size(); ++i)
{
ReadFeature(notSortedFileReader, ft, midPoints.m_vec[i].second);
collector(ft.GetFeatureBuilder());
collector(ft);
}
}

View file

@ -1,6 +1,9 @@
#include "../../3party/sgitess/interface.h"
#include "osm_element.hpp"
#include "../cell_id.hpp"
#include "../../3party/sgitess/interface.h"
namespace feature
{
struct AddTessPointF
@ -14,59 +17,59 @@ namespace feature
}
};
void TesselateInterior(FeatureBuilder & featureBuilder, feature::holes_cont_t const & holes)
void TesselateInterior(FeatureBuilder & fb, feature::holes_cont_t const & holes)
{
vector<char> serial;
featureBuilder.Serialize(serial);
Feature feature(serial);
ASSERT(fb.IsGeometryClosed(), ());
ASSERT(featureBuilder.IsGeometryClosed(), ());
tess::VectorDispatcher disp;
tess::Tesselator tess;
tess.setDispatcher(&disp);
tess.setWindingRule(tess::WindingOdd);
tess.beginPolygon();
tess.beginContour();
{
tess::VectorDispatcher disp;
tess::Tesselator tess;
tess.setDispatcher(&disp);
tess.setWindingRule(tess::WindingOdd);
tess.beginPolygon();
vector<char> data;
fb.Serialize(data);
FeatureGeom f(data);
f.ForEachPoint(AddTessPointF(tess));
}
tess.endContour();
for (feature::holes_cont_t::const_iterator it = holes.begin(); it != holes.end(); ++it)
{
tess.beginContour();
feature.ForEachPoint(AddTessPointF(tess));
for (size_t i = 0; i < (*it).size(); ++i)
tess.add(tess::Vertex((*it)[i].x, (*it)[i].y));
tess.endContour();
}
for (feature::holes_cont_t::const_iterator it = holes.begin(); it != holes.end(); ++it)
tess.endPolygon();
for (size_t i = 0; i < disp.indices().size(); ++i)
{
vector<m2::PointD> vertices;
switch (disp.indices()[i].first)
{
tess.beginContour();
for (size_t i = 0; i < (*it).size(); ++i)
tess.add(tess::Vertex((*it)[i].x, (*it)[i].y));
tess.endContour();
case tess::TrianglesFan:
case tess::TrianglesStrip:
case tess::LineLoop:
ASSERT(0, ("We've got invalid type during teselation:", disp.indices()[i].first));
case tess::TrianglesList: break;
}
tess.endPolygon();
for (size_t i = 0; i < disp.indices().size(); ++i)
for (size_t j = 0; j < disp.indices()[i].second.size(); ++j)
{
vector<m2::PointD> vertices;
switch (disp.indices()[i].first)
{
case tess::TrianglesFan:
case tess::TrianglesStrip:
case tess::LineLoop:
ASSERT(0, ("We've got invalid type during teselation:", disp.indices()[i].first));
case tess::TrianglesList: break;
}
for (size_t j = 0; j < disp.indices()[i].second.size(); ++j)
{
int const idx = disp.indices()[i].second[j];
tess::Vertex const & v = disp.vertices()[idx];
vertices.push_back(m2::PointD(v.x, v.y));
}
ASSERT_EQUAL(vertices.size() % 3, 0, ());
size_t const triangleCount = vertices.size() / 3;
for (size_t i = 0; i < triangleCount; ++i)
featureBuilder.AddTriangle(vertices[3*i + 0], vertices[3*i + 1], vertices[3*i + 2]);
int const idx = disp.indices()[i].second[j];
tess::Vertex const & v = disp.vertices()[idx];
vertices.push_back(m2::PointD(v.x, v.y));
}
ASSERT_EQUAL(vertices.size() % 3, 0, ());
size_t const triangleCount = vertices.size() / 3;
for (size_t i = 0; i < triangleCount; ++i)
fb.AddTriangle(vertices[3*i + 0], vertices[3*i + 1], vertices[3*i + 2]);
}
}
}

View file

@ -2,8 +2,8 @@
#include "scale_index.hpp"
#include "feature_visibility.hpp"
#include "covering.hpp"
#include "feature.hpp"
#include "interval_index_builder.hpp"
#include "cell_id.hpp"
#include "../geometry/covering_stream_optimizer.hpp"
@ -52,7 +52,8 @@ public:
{
}
void operator() (Feature const & f, uint32_t offset) const
template <class TFeature>
void operator() (TFeature const & f, uint32_t offset) const
{
if (FeatureShouldBeIndexed(f))
{
@ -64,10 +65,13 @@ public:
}
}
bool FeatureShouldBeIndexed(Feature const & f) const
template <class TFeature>
bool FeatureShouldBeIndexed(TFeature const & f) const
{
uint32_t const minDrawableScale = feature::MinDrawableScaleForFeature(f);
return m_ScaleRange.first <= minDrawableScale && minDrawableScale < m_ScaleRange.second;
(void)f.GetLimitRect(); // dummy call to force TFeature::ParseGeometry
uint32_t const minScale = feature::MinDrawableScaleForFeature(f);
return (m_ScaleRange.first <= minScale && minScale < m_ScaleRange.second);
}
private:
@ -84,7 +88,8 @@ public:
void operator() (int64_t cellId, uint64_t value) const
{
CellFeaturePair cellFeaturePair(cellId, value);
// uint64_t -> uint32_t : assume that feature dat file not more than 4Gb
CellFeaturePair cellFeaturePair(cellId, static_cast<uint32_t>(value));
m_Sink.Write(&cellFeaturePair, sizeof(cellFeaturePair));
}

View file

@ -98,7 +98,7 @@ namespace fwork
} \
}
bool DrawProcessor::operator()(Feature const & f)
bool DrawProcessor::operator()(feature_t const & f)
{
if (m_paintEvent->isCancelled())
throw redraw_operation_cancelled();
@ -123,11 +123,11 @@ namespace fwork
bool isExist = false;
switch (type)
{
case Feature::FEATURE_TYPE_POINT:
case FeatureBase::FEATURE_TYPE_POINT:
GET_POINTS(get_pts::one_point, ForEachPointRef, assign_point)
break;
case Feature::FEATURE_TYPE_AREA:
case FeatureBase::FEATURE_TYPE_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
@ -138,11 +138,11 @@ namespace fwork
}
draw_line:
case Feature::FEATURE_TYPE_LINE:
case FeatureBase::FEATURE_TYPE_LINE:
GET_POINTS(filter_screenpts_adapter<path_points>, ForEachPointRef, assign_path)
break;
case Feature::FEATURE_TYPE_UNKNOWN:
case FeatureBase::FEATURE_TYPE_UNKNOWN:
ASSERT(0, ("Feature type is unknown"));
}

View file

@ -5,7 +5,6 @@
#include "render_queue.hpp"
#include "../indexer/drawing_rule_def.hpp"
#include "../indexer/feature.hpp"
#include "../indexer/mercator.hpp"
#include "../indexer/data_header_reader.hpp"
#include "../indexer/data_header.hpp"
@ -35,7 +34,9 @@
#include "../base/start_mem_debug.hpp"
class Feature;
class FeatureGeom;
namespace di { class DrawInfo; }
namespace drule { class BaseRule; }
@ -43,6 +44,8 @@ class redraw_operation_cancelled {};
namespace fwork
{
typedef FeatureGeom feature_t;
class DrawProcessor
{
m2::RectD m_rect;
@ -68,7 +71,7 @@ namespace fwork
shared_ptr<PaintEvent> paintEvent,
int scaleLevel);
bool operator() (Feature const & f);
bool operator() (feature_t const & f);
};
}
@ -424,11 +427,11 @@ public:
UpdateNow();
}
void ShowFeature(Feature const & f)
{
m_navigator.SetFromRect(f.GetLimitRect());
Repaint();
}
//void ShowFeature(Feature const & f)
//{
// m_navigator.SetFromRect(f.GetLimitRect());
// Repaint();
//}
void Repaint()
{

View file

@ -22,7 +22,8 @@
#include "../../base/start_mem_debug.hpp"
typedef vector<pair<Feature, string> > feature_cont_t;
typedef FeatureGeom feature_t;
typedef vector<pair<feature_t, string> > feature_cont_t;
class AccumulatorBase
{
@ -31,12 +32,12 @@ class AccumulatorBase
feature_cont_t & m_cont;
protected:
bool is_drawable(Feature const & f) const
bool is_drawable(feature_t const & f) const
{
return feature::IsDrawableForIndex(f, m_scale);
}
void add(Feature const & f) const
void add(feature_t const & f) const
{
string const s = f.DebugString();
m_cont.push_back(make_pair(f, s));
@ -49,7 +50,7 @@ public:
m_scale = scales::GetScaleLevel(r);
}
void operator() (Feature const & f) const
void operator() (feature_t const & f) const
{
ASSERT ( f.DebugString() == f.DebugString(), () );
@ -97,7 +98,7 @@ class AccumulatorEtalon : public AccumulatorBase
m2::RectD m_rect;
bool is_intersect(Feature const & f) const
bool is_intersect(feature_t const & f) const
{
IntersectCheck check(m_rect);
f.ForEachPointRef(check);
@ -110,7 +111,7 @@ public:
{
}
void operator() (Feature const & f, uint64_t /*offset*/) const
void operator() (feature_t const & f, uint64_t /*offset*/) const
{
ASSERT ( f.DebugString() == f.DebugString(), () );
@ -215,11 +216,11 @@ namespace
{
class FindOffset
{
pair<Feature, string> const & m_test;
pair<feature_t, string> const & m_test;
public:
FindOffset(pair<Feature, string> const & test) : m_test(test) {}
FindOffset(pair<feature_t, string> const & test) : m_test(test) {}
void operator() (Feature const & f, uint64_t offset)
void operator() (feature_t const & f, uint64_t offset)
{
if (f.DebugString() == m_test.second)
{

View file

@ -25,7 +25,7 @@ FindTableWnd::FindTableWnd(QWidget * pParent, FindEditorWnd * pEditor, model_t *
connect(m_pEditor, SIGNAL(textChanged(QString const &)), this, SLOT(OnTextChanged(QString const &)));
}
bool FindTableWnd::AddFeature(Feature const & f)
bool FindTableWnd::AddFeature(feature_t const & f)
{
string name = f.GetName();
@ -61,7 +61,7 @@ void FindTableWnd::OnTextChanged(QString const & s)
}
}
Feature const & FindTableWnd::GetFeature(size_t row) const
FindTableWnd::feature_t const & FindTableWnd::GetFeature(size_t row) const
{
ASSERT ( row < m_features.size(), (row, m_features.size()) );
return m_features[row];

View file

@ -1,6 +1,7 @@
#pragma once
#include "../indexer/feature.hpp"
#include "../std/vector.hpp"
#include <QtGui/QLineEdit>
@ -30,18 +31,20 @@ namespace qt
FindEditorWnd * m_pEditor;
model_t * m_pModel;
typedef FeatureGeom feature_t;
public:
FindTableWnd(QWidget * pParent, FindEditorWnd * pEditor, model_t * pModel);
Feature const & GetFeature(size_t row) const;
feature_t const & GetFeature(size_t row) const;
protected:
bool AddFeature(Feature const & f);
bool AddFeature(feature_t const & f);
protected Q_SLOTS:
void OnTextChanged(QString const & s);
private:
vector<Feature> m_features;
vector<feature_t> m_features;
};
}