From 7b61f1e351b328886ada81f7f5b95751123f455f Mon Sep 17 00:00:00 2001 From: vng Date: Mon, 14 Feb 2011 03:52:30 +0200 Subject: [PATCH] Fix bug in tesselator processing. Sgitess passes triangles in ONE list, even if they are divided on many clusters. --- indexer/geometry_serialization.hpp | 8 +++++--- indexer/tesselator.cpp | 15 +++++++------- indexer/tesselator.hpp | 32 +++++++++++++++++++++++------- 3 files changed, 37 insertions(+), 18 deletions(-) diff --git a/indexer/geometry_serialization.hpp b/indexer/geometry_serialization.hpp index 134388f0e3..ff52f55622 100644 --- a/indexer/geometry_serialization.hpp +++ b/indexer/geometry_serialization.hpp @@ -161,9 +161,11 @@ namespace serial template void Save(TSink & sink) { + // assume that 2 byte is enough for triangles count size_t const count = m_buffers.size(); - CHECK_LESS(count, 256, ()); - WriteToSink(sink, static_cast(count)); + CHECK_LESS_OR_EQUAL(count, 0x3FFF, ()); + + WriteVarUint(sink, static_cast(count)); for_each(m_buffers.begin(), m_buffers.end(), bind(&WriteBufferToSink, _1, ref(sink))); } @@ -177,7 +179,7 @@ namespace serial template void LoadOuterTriangles(TSource & src, int64_t base, OutPointsT & triangles) { - int const count = ReadPrimitiveFromSource(src); + int const count = ReadVarUint(src); for (int i = 0; i < count; ++i) LoadOuter(&DecodeTriangles, src, base, triangles, 3); diff --git a/indexer/tesselator.cpp b/indexer/tesselator.cpp index 8c25e241c4..ff54c289de 100644 --- a/indexer/tesselator.cpp +++ b/indexer/tesselator.cpp @@ -116,7 +116,8 @@ namespace tesselator for (iter_t i = m_neighbors.begin(); i != m_neighbors.end(); ++i) { - if (m_neighbors.find(make_pair(i->first.second, i->first.first)) == m_neighbors.end()) + if (!m_visited[i->second] && + m_neighbors.find(make_pair(i->first.second, i->first.first)) == m_neighbors.end()) { uint64_t deltas[3]; deltas[0] = EncodeDelta(points.m_points[i->first.first], points.m_base); @@ -193,15 +194,13 @@ namespace tesselator void TrianglesInfo::ListInfo::MakeTrianglesChainImpl( PointsInfo const & points, iter_t start, vector & chain) const { + chain.clear(); + Triangle const fictive(start->first.second, start->first.first, -1); priority_queue, TPopOrder> q; q.push(Edge(-1, start->second, 0, -1)); - // marks of visited nodes - vector visited; - visited.resize(m_triangles.size()); - while (!q.empty()) { // pop current element @@ -209,9 +208,9 @@ namespace tesselator q.pop(); // check if already processed - if (visited[e.m_p[1]]) + if (m_visited[e.m_p[1]]) continue; - visited[e.m_p[1]] = true; + m_visited[e.m_p[1]] = true; // push to chain chain.push_back(e); @@ -224,7 +223,7 @@ namespace tesselator // push neighbors to queue for (int i = 0; i < 2; ++i) - if (nb[i] != empty_key && !visited[nb[i]]) + if (nb[i] != empty_key && !m_visited[nb[i]]) q.push(Edge(e.m_p[1], nb[i], CalcDelta(points, trg, m_triangles[nb[i]]), i)); } } diff --git a/indexer/tesselator.hpp b/indexer/tesselator.hpp index 9f23ff6bc9..c47c6828d9 100644 --- a/indexer/tesselator.hpp +++ b/indexer/tesselator.hpp @@ -60,6 +60,8 @@ namespace tesselator vector m_triangles; + mutable vector m_visited; + // directed edge -> triangle typedef unordered_map, int> neighbors_t; neighbors_t m_neighbors; @@ -82,6 +84,18 @@ namespace tesselator void Add(uintptr_t const * arr); + void Start() const + { + m_visited.resize(m_triangles.size()); + } + + bool HasUnvisited() const + { + vector test; + test.assign(m_triangles.size(), true); + return (m_visited != test); + } + iter_t FindStartTriangle(PointsInfo const & points) const; private: @@ -129,15 +143,19 @@ namespace tesselator vector chain; for (list::const_iterator i = m_triangles.begin(); i != m_triangles.end(); ++i) { - chain.clear(); - typename ListInfo::iter_t start = i->FindStartTriangle(points); - i->MakeTrianglesChain(points, start, chain, goodOrder); + i->Start(); - m2::PointU arr[] = { points.m_points[start->first.first], - points.m_points[start->first.second], - points.m_points[i->GetTriangle(start->second).GetPoint3(start->first)] }; + do + { + typename ListInfo::iter_t start = i->FindStartTriangle(points); + i->MakeTrianglesChain(points, start, chain, goodOrder); - emitter(arr, chain); + m2::PointU arr[] = { points.m_points[start->first.first], + points.m_points[start->first.second], + points.m_points[i->GetTriangle(start->second).GetPoint3(start->first)] }; + + emitter(arr, chain); + } while (i->HasUnvisited()); } } };