diff --git a/generator/feature_builder.cpp b/generator/feature_builder.cpp index a383f1ba39..36e4221733 100644 --- a/generator/feature_builder.cpp +++ b/generator/feature_builder.cpp @@ -16,9 +16,15 @@ using namespace feature; // FeatureBuilder1 implementation /////////////////////////////////////////////////////////////////////////////////////////////////// +FeatureBuilder1::FeatureBuilder1() +{ + m_Polygons.push_back(points_t()); +} + bool FeatureBuilder1::IsGeometryClosed() const { - return (m_Geometry.size() > 2 && m_Geometry.front() == m_Geometry.back()); + points_t const & poly = GetGeometry(); + return (poly.size() > 2 && poly.front() == poly.back()); } void FeatureBuilder1::SetCenter(m2::PointD const & p) @@ -30,25 +36,26 @@ void FeatureBuilder1::SetCenter(m2::PointD const & p) void FeatureBuilder1::AddPoint(m2::PointD const & p) { - m_Geometry.push_back(p); + m_Polygons.front().push_back(p); m_LimitRect.Add(p); } void FeatureBuilder1::SetAreaAddHoles(list const & holes) { m_Params.SetGeomType(GEOM_AREA); - m_Holes.clear(); + m_Polygons.resize(1); if (holes.empty()) return; - m2::Region rgn(m_Geometry.begin(), m_Geometry.end()); + points_t const & poly = GetGeometry(); + m2::Region rgn(poly.begin(), poly.end()); for (list::const_iterator i = holes.begin(); i != holes.end(); ++i) { ASSERT ( !i->empty(), () ); if (rgn.Contains(i->front())) - m_Holes.push_back(*i); + m_Polygons.push_back(*i); } } @@ -155,15 +162,12 @@ bool FeatureBuilder1::operator == (FeatureBuilder1 const & fb) const if (!is_equal(m_LimitRect, fb.m_LimitRect)) return false; - if (!is_equal(m_Geometry, fb.m_Geometry)) + if (m_Polygons.size() != fb.m_Polygons.size()) return false; - if (m_Holes.size() != fb.m_Holes.size()) - return false; - - list::const_iterator i = m_Holes.begin(); - list::const_iterator j = fb.m_Holes.begin(); - for (; i != m_Holes.end(); ++i, ++j) + list::const_iterator i = m_Polygons.begin(); + list::const_iterator j = fb.m_Polygons.begin(); + for (; i != m_Polygons.end(); ++i, ++j) if (!is_equal(*i, *j)) return false; @@ -175,15 +179,19 @@ bool FeatureBuilder1::CheckValid() const CHECK(m_Params.CheckValid(), ()); EGeomType const type = m_Params.GetGeomType(); + CHECK ( type != GEOM_UNDEFINED, () ); - CHECK(type != GEOM_LINE || m_Geometry.size() >= 2, ()); + points_t const & poly = GetGeometry(); - CHECK(type != GEOM_AREA || m_Geometry.size() >= 3, ()); + if (type == GEOM_LINE) + CHECK(poly.size() >= 2, (*this)); - CHECK(m_Holes.empty() || type == GEOM_AREA, ()); - - for (list::const_iterator i = m_Holes.begin(); i != m_Holes.end(); ++i) - CHECK(i->size() >= 3, ()); + if (type == GEOM_AREA) + { + // Use '4' because the first point should be equal with the last one + for (list::const_iterator i = m_Polygons.begin(); i != m_Polygons.end(); ++i) + CHECK(i->size() >= 4, ()); + } return true; } @@ -211,16 +219,11 @@ void FeatureBuilder1::Serialize(buffer_t & data) const PushBackByteSink sink(data); - EGeomType const type = m_Params.GetGeomType(); - - if (type != GEOM_POINT) - serial::SaveOuterPath(m_Geometry, cp, sink); - - if (type == GEOM_AREA) + if (m_Params.GetGeomType() != GEOM_POINT) { - WriteVarUint(sink, uint32_t(m_Holes.size())); + WriteVarUint(sink, uint32_t(m_Polygons.size())); - for (list::const_iterator i = m_Holes.begin(); i != m_Holes.end(); ++i) + for (list::const_iterator i = m_Polygons.begin(); i != m_Polygons.end(); ++i) serial::SaveOuterPath(*i, cp, sink); } @@ -252,17 +255,15 @@ void FeatureBuilder1::Deserialize(buffer_t & data) return; } - serial::LoadOuterPath(source, cp, m_Geometry); - CalcRect(m_Geometry, m_LimitRect); + m_Polygons.clear(); + uint32_t const count = ReadVarUint(source); + ASSERT_GREATER ( count, 0, () ); - if (type == GEOM_AREA) + for (uint32_t i = 0; i < count; ++i) { - uint32_t const count = ReadVarUint(source); - for (uint32_t i = 0; i < count; ++i) - { - m_Holes.push_back(points_t()); - serial::LoadOuterPath(source, cp, m_Holes.back()); - } + m_Polygons.push_back(points_t()); + serial::LoadOuterPath(source, cp, m_Polygons.back()); + CalcRect(m_Polygons.back(), m_LimitRect); } CHECK ( CheckValid(), () ); @@ -286,6 +287,7 @@ string debug_print(FeatureBuilder1 const & f) ostringstream out; for (size_t i = 0; i < f.m_osmIds.size(); ++i) out << f.m_osmIds[i].Type() << " id=" << f.m_osmIds[i].Id() << " "; + switch (f.GetGeomType()) { case feature::GEOM_POINT: out << "(" << f.m_Center << ")"; break; @@ -303,7 +305,7 @@ string debug_print(FeatureBuilder1 const & f) bool FeatureBuilder2::IsDrawableInRange(int lowS, int highS) const { - if (!m_Geometry.empty()) + if (!GetGeometry().empty()) { FeatureBase const fb = GetFeatureBase(); diff --git a/generator/feature_builder.hpp b/generator/feature_builder.hpp index 5df9b6b82d..c80d8528d0 100644 --- a/generator/feature_builder.hpp +++ b/generator/feature_builder.hpp @@ -18,6 +18,8 @@ class FeatureBuilder1 friend string debug_print(FeatureBuilder1 const & f); public: + FeatureBuilder1(); + /// @name Geometry manipulating functions. //@{ /// Set center (origin) point of feature and set that feature is point. @@ -57,23 +59,18 @@ public: bool IsGeometryClosed() const; - inline size_t GetPointsCount() const { return m_Geometry.size(); } - - template - void ForEachPointRef(ToDo & toDo) const - { - for_each(m_Geometry.begin(), m_Geometry.end(), bind(ref(toDo), _1)); - } + inline size_t GetPointsCount() const { return GetGeometry().size(); } // stops processing when functor returns false template - void ForEachTruePointRef(ToDo & toDo) const + void ForEachGeometryPoint(ToDo & toDo) const { if (m_Params.GetGeomType() == feature::GEOM_POINT) toDo(m_Center); else { - for (points_t::const_iterator it = m_Geometry.begin(); it != m_Geometry.end(); ++it) + points_t const & poly = GetGeometry(); + for (points_t::const_iterator it = poly.begin(); it != poly.end(); ++it) if (!toDo(*it)) return; } @@ -112,13 +109,10 @@ protected: typedef vector points_t; - /// Can be one of the following: - /// - geometry in line-feature - /// - boundary in area-feature - points_t m_Geometry; // Check HEADER_IS_LINE + inline points_t const & GetGeometry() const { return m_Polygons.front(); } - /// List of holes in area-feature. - list m_Holes; // Check HEADER_IS_AREA + /// List of geometry polygons. + list m_Polygons; // Check HEADER_IS_AREA }; /// Used for serialization of features during final pass. @@ -154,8 +148,8 @@ public: bool IsArea() const { return (m_Params.GetTypeMask() & feature::HEADER_GEOM_AREA) != 0; } bool IsDrawableInRange(int lowS, int highS) const; - points_t const & GetGeometry() const { return m_Geometry; } - list const & GetHoles() const { return m_Holes; } + points_t const & GetOuterPoly() const { return GetGeometry(); } + list const & GetPolygons() const { return m_Polygons; } /// @name Overwrite from base_type. //@{ diff --git a/generator/feature_merger.cpp b/generator/feature_merger.cpp index fc21ee399b..cbc8a5df43 100644 --- a/generator/feature_merger.cpp +++ b/generator/feature_merger.cpp @@ -13,7 +13,8 @@ MergedFeatureBuilder1::MergedFeatureBuilder1(FeatureBuilder1 const & fb) void MergedFeatureBuilder1::SetRound() { m_isRound = true; - m_roundBounds[0] = m_roundBounds[1] = m_Geometry; + + m_roundBounds[0] = m_roundBounds[1] = GetGeometry(); } void MergedFeatureBuilder1::AppendFeature(MergedFeatureBuilder1 const & fb, bool fromBegin, bool toBack) @@ -21,12 +22,15 @@ void MergedFeatureBuilder1::AppendFeature(MergedFeatureBuilder1 const & fb, bool // Also merge Osm IDs for debugging m_osmIds.insert(m_osmIds.end(), fb.m_osmIds.begin(), fb.m_osmIds.end()); + points_t & thisG = m_Polygons.front(); + points_t const & fbG = fb.GetGeometry(); + if (fb.m_isRound) { if (toBack) - m_roundBounds[1] = fb.m_Geometry; + m_roundBounds[1] = fbG; else - m_roundBounds[0] = fb.m_Geometry; + m_roundBounds[0] = fbG; return; } @@ -37,28 +41,28 @@ void MergedFeatureBuilder1::AppendFeature(MergedFeatureBuilder1 const & fb, bool m_isRound = false; - for (size_t i = 0; i < fb.m_Geometry.size(); ++i) - m_LimitRect.Add(fb.m_Geometry[i]); + for (size_t i = 0; i < fbG.size(); ++i) + m_LimitRect.Add(fbG[i]); if (fromBegin) { if (toBack) - m_Geometry.insert(m_Geometry.end(), fb.m_Geometry.begin() + 1, fb.m_Geometry.end()); + thisG.insert(thisG.end(), fbG.begin() + 1, fbG.end()); else - m_Geometry.insert(m_Geometry.begin(), fb.m_Geometry.begin(), fb.m_Geometry.end() - 1); + thisG.insert(thisG.begin(), fbG.begin(), fbG.end() - 1); } else { if (toBack) - m_Geometry.insert(m_Geometry.end(), fb.m_Geometry.rbegin() + 1, fb.m_Geometry.rend()); + thisG.insert(thisG.end(), fbG.rbegin() + 1, fbG.rend()); else - m_Geometry.insert(m_Geometry.begin(), fb.m_Geometry.rbegin(), fb.m_Geometry.rend() - 1); + thisG.insert(thisG.begin(), fbG.rbegin(), fbG.rend() - 1); } } bool MergedFeatureBuilder1::EqualGeometry(MergedFeatureBuilder1 const & fb) const { - return (m_Geometry == fb.m_Geometry); + return (GetGeometry() == fb.GetGeometry()); } pair MergedFeatureBuilder1::GetKeyPoint(size_t i) const @@ -89,9 +93,11 @@ size_t MergedFeatureBuilder1::GetKeyPointsCount() const double MergedFeatureBuilder1::GetPriority() const { + points_t const & poly = GetGeometry(); + double pr = 0.0; - for (size_t i = 1; i < m_Geometry.size(); ++i) - pr += m_Geometry[i-1].SquareLength(m_Geometry[i]); + for (size_t i = 1; i < poly.size(); ++i) + pr += poly[i-1].SquareLength(poly[i]); return pr; } diff --git a/generator/feature_merger.hpp b/generator/feature_merger.hpp index ec91d7c71c..29d7f0f598 100644 --- a/generator/feature_merger.hpp +++ b/generator/feature_merger.hpp @@ -26,10 +26,10 @@ public: bool EqualGeometry(MergedFeatureBuilder1 const & fb) const; - inline bool NotEmpty() const { return !m_Geometry.empty(); } + inline bool NotEmpty() const { return !GetGeometry().empty(); } - inline m2::PointD FirstPoint() const { return m_Geometry.front(); } - inline m2::PointD LastPoint() const { return m_Geometry.back(); } + inline m2::PointD FirstPoint() const { return GetGeometry().front(); } + inline m2::PointD LastPoint() const { return GetGeometry().back(); } inline void SetType(uint32_t type) { m_Params.SetType(type); } inline bool PopAnyType(uint32_t & type) { return m_Params.PopAnyType(type); } @@ -43,8 +43,9 @@ public: template void ForEachMiddlePoints(ToDo toDo) const { - for (size_t i = 1; i < m_Geometry.size()-1; ++i) - toDo(m_Geometry[i]); + points_t const & poly = GetGeometry(); + for (size_t i = 1; i < poly.size()-1; ++i) + toDo(poly[i]); } pair GetKeyPoint(size_t i) const; diff --git a/generator/feature_sorter.cpp b/generator/feature_sorter.cpp index 8ddc1c8c1a..d9f9b4f4ee 100644 --- a/generator/feature_sorter.cpp +++ b/generator/feature_sorter.cpp @@ -48,7 +48,7 @@ namespace m_midLoc = m2::PointD(0, 0); m_locCount = 0; - ft.ForEachPointRef(*this); + ft.ForEachGeometryPoint(*this); m_midLoc = m_midLoc / m_locCount; uint64_t const pointAsInt64 = PointToInt64(m_midLoc.x, m_midLoc.y, m_coordBits); @@ -59,12 +59,13 @@ namespace m_vec.push_back(make_pair(order, pos)); } - void operator() (m2::PointD const & p) + bool operator() (m2::PointD const & p) { m_midLoc += p; m_midAll += p; ++m_locCount; ++m_allCount; + return true; } m2::PointD GetCenter() const { return m_midAll / m_allCount; } @@ -147,7 +148,7 @@ namespace feature private: typedef vector points_t; - typedef list holes_t; + typedef list polygons_t; class GeometryHolder { @@ -169,14 +170,14 @@ namespace feature serial::SaveOuterPath(points, m_codingParams, *m_rMain.m_geoFile[i]); } - void WriteOuterTriangles(points_t const & bound, holes_t const & holes, int i) + void WriteOuterTriangles(polygons_t const & polys, int i) { m_buffer.m_trgMask |= (1 << i); m_buffer.m_trgOffset.push_back(m_rMain.GetFileSize(*m_rMain.m_trgFile[i])); // tesselation tesselator::TrianglesInfo info; - tesselator::TesselateInterior(bound, holes, info); + tesselator::TesselateInterior(polys, info); serial::TrianglesChainSaver saver(m_codingParams); @@ -255,7 +256,7 @@ namespace feature points_t const & GetSourcePoints() { - return (!m_current.empty() ? m_current : m_rFB.GetGeometry()); + return (!m_current.empty() ? m_current : m_rFB.GetOuterPoly()); } void AddPoints(points_t const & points, int scaleIndex) @@ -327,12 +328,12 @@ namespace feature return true; } - void AddTriangles(points_t const & bound, holes_t const & holes, int scaleIndex) + void AddTriangles(polygons_t const & polys, int scaleIndex) { CHECK ( m_buffer.m_innerTrg.empty(), () ); m_trgInner = false; - WriteOuterTriangles(bound, holes, scaleIndex); + WriteOuterTriangles(polys, scaleIndex); } }; @@ -361,23 +362,25 @@ namespace feature { // simplify and serialize triangles - holes_t const & holes = fb.GetHoles(); - - if (holes.empty() && holder.TryToMakeStrip(points)) + polygons_t const & polys = fb.GetPolygons(); + if (polys.size() == 1 && holder.TryToMakeStrip(points)) continue; - holes_t simpleHoles; - for (holes_t::const_iterator iH = holes.begin(); iH != holes.end(); ++iH) + polygons_t simplified; + simplified.push_back(points); + + polygons_t::const_iterator iH = polys.begin(); + for (++iH; iH != polys.end(); ++iH) { - simpleHoles.push_back(points_t()); + simplified.push_back(points_t()); - SimplifyPoints(*iH, simpleHoles.back(), m_header.GetScale(i)); + SimplifyPoints(*iH, simplified.back(), m_header.GetScale(i)); - if (simpleHoles.back().size() < 3) - simpleHoles.pop_back(); + if (simplified.back().size() < 3) + simplified.pop_back(); } - holder.AddTriangles(points, simpleHoles, i); + holder.AddTriangles(simplified, i); } } } diff --git a/generator/polygonizer.hpp b/generator/polygonizer.hpp index ff150433be..9edb8b07c5 100644 --- a/generator/polygonizer.hpp +++ b/generator/polygonizer.hpp @@ -195,7 +195,7 @@ namespace feature for (size_t i = 0; i < m_Countries.size(); ++i) { PointChecker doCheck(m_Countries[i]->m_regions); - m_FB.ForEachTruePointRef(doCheck); + m_FB.ForEachGeometryPoint(doCheck); if (doCheck.m_belongs) m_pPolygonizer->EmitFeature(m_Countries[i], m_FB); diff --git a/indexer/tesselator.cpp b/indexer/tesselator.cpp index 2afa035a80..a8ac5fc094 100644 --- a/indexer/tesselator.cpp +++ b/indexer/tesselator.cpp @@ -26,7 +26,7 @@ namespace tesselator } }; - void TesselateInterior(PointsT const & bound, HolesT const & holes, TrianglesInfo & info) + void TesselateInterior(PolygonsT const & polys, TrianglesInfo & info) { tess::VectorDispatcher disp; tess::Tesselator tess; @@ -35,11 +35,7 @@ namespace tesselator tess.beginPolygon(); - tess.beginContour(); - for_each(bound.begin(), bound.end(), AddTessPointF(tess)); - tess.endContour(); - - for (HolesT::const_iterator it = holes.begin(); it != holes.end(); ++it) + for (PolygonsT::const_iterator it = polys.begin(); it != polys.end(); ++it) { tess.beginContour(); for_each(it->begin(), it->end(), AddTessPointF(tess)); diff --git a/indexer/tesselator.hpp b/indexer/tesselator.hpp index 061cf76369..d5ca0148c4 100644 --- a/indexer/tesselator.hpp +++ b/indexer/tesselator.hpp @@ -13,7 +13,7 @@ namespace tesselator { typedef vector PointsT; - typedef list HolesT; + typedef list PolygonsT; struct Triangle { @@ -162,5 +162,5 @@ namespace tesselator }; /// Main tesselate function. - void TesselateInterior(PointsT const & bound, HolesT const & holes, TrianglesInfo & info); + void TesselateInterior(PolygonsT const & polys, TrianglesInfo & info); }