From f8b146675f5f525a42040bc9e17381ef235ec245 Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Fri, 15 Mar 2019 08:40:51 +0300 Subject: [PATCH] [drape] Fixed some buildings rendering --- drape_frontend/apply_feature_functors.cpp | 82 +++++++++++++---------- drape_frontend/apply_feature_functors.hpp | 39 +++++++++-- drape_frontend/area_shape.cpp | 16 ++--- qt/place_page_dialog.cpp | 3 + 4 files changed, 89 insertions(+), 51 deletions(-) diff --git a/drape_frontend/apply_feature_functors.cpp b/drape_frontend/apply_feature_functors.cpp index 662366154f..d76ce49c48 100644 --- a/drape_frontend/apply_feature_functors.cpp +++ b/drape_frontend/apply_feature_functors.cpp @@ -673,7 +673,7 @@ void ApplyAreaFeature::operator()(m2::PointD const & p1, m2::PointD const & p2, return; double const crossProduct = m2::CrossProduct(v1.Normalize(), v2.Normalize()); - double const kEps = 1e-7; + double constexpr kEps = 1e-7; if (fabs(crossProduct) < kEps) return; @@ -684,7 +684,7 @@ void ApplyAreaFeature::operator()(m2::PointD const & p1, m2::PointD const & p2, m_triangles.push_back(p3); }; - if (m2::CrossProduct(p2 - p1, p3 - p1) < 0) + if (crossProduct < 0) m2::ClipTriangleByRect(m_tileRect, p1, p2, p3, clipFunctor); else m2::ClipTriangleByRect(m_tileRect, p1, p3, p2, clipFunctor); @@ -701,50 +701,53 @@ void ApplyAreaFeature::ProcessBuildingPolygon(m2::PointD const & p1, m2::PointD return; double const crossProduct = m2::CrossProduct(v1.Normalize(), v2.Normalize()); - double const kEps = 0.01; + double constexpr kEps = 0.01; if (fabs(crossProduct) < kEps) return; + // Triangles near to degenerate are drawn two-side, because we can't strictly determine + // vertex traversal direction. + double constexpr kTwoSideEps = 0.05; + bool const isTwoSide = fabs(crossProduct) < kTwoSideEps; + + auto const i1 = GetIndex(p1); + auto const i2 = GetIndex(p2); + auto const i3 = GetIndex(p3); if (crossProduct < 0) { m_triangles.push_back(p1); m_triangles.push_back(p2); m_triangles.push_back(p3); - BuildEdges(GetIndex(p1), GetIndex(p2), GetIndex(p3)); + BuildEdges(i1, i2, i3, isTwoSide); } else { m_triangles.push_back(p1); m_triangles.push_back(p3); m_triangles.push_back(p2); - BuildEdges(GetIndex(p1), GetIndex(p3), GetIndex(p2)); + BuildEdges(i1, i3, i2, isTwoSide); } } int ApplyAreaFeature::GetIndex(m2::PointD const & pt) { + double constexpr kEps = 1e-7; for (size_t i = 0; i < m_points.size(); i++) { - if (pt.EqualDxDy(m_points[i], 1e-7)) + if (pt.EqualDxDy(m_points[i], kEps)) return static_cast(i); } m_points.push_back(pt); return static_cast(m_points.size()) - 1; } -bool ApplyAreaFeature::EqualEdges(TEdge const & edge1, TEdge const & edge2) const +bool ApplyAreaFeature::IsDuplicatedEdge(Edge const & edge) { - return (edge1.first == edge2.first && edge1.second == edge2.second) || - (edge1.first == edge2.second && edge1.second == edge2.first); -} - -bool ApplyAreaFeature::FindEdge(TEdge const & edge) -{ - for (size_t i = 0; i < m_edges.size(); i++) + for (auto & e : m_edges) { - if (EqualEdges(m_edges[i].first, edge)) + if (e.m_edge == edge) { - m_edges[i].second = -1; + e.m_internalVertexIndex = -1; return true; } } @@ -763,45 +766,52 @@ m2::PointD ApplyAreaFeature::CalculateNormal(m2::PointD const & p1, m2::PointD c return normal; } -void ApplyAreaFeature::BuildEdges(int vertexIndex1, int vertexIndex2, int vertexIndex3) +void ApplyAreaFeature::BuildEdges(int vertexIndex1, int vertexIndex2, int vertexIndex3, bool twoSide) { // Check if triangle is degenerate. if (vertexIndex1 == vertexIndex2 || vertexIndex2 == vertexIndex3 || vertexIndex1 == vertexIndex3) return; - TEdge edge1 = make_pair(vertexIndex1, vertexIndex2); - if (!FindEdge(edge1)) - m_edges.push_back(make_pair(move(edge1), vertexIndex3)); + auto edge1 = Edge(vertexIndex1, vertexIndex2); + if (!IsDuplicatedEdge(edge1)) + m_edges.emplace_back(std::move(edge1), vertexIndex3, twoSide); - TEdge edge2 = make_pair(vertexIndex2, vertexIndex3); - if (!FindEdge(edge2)) - m_edges.push_back(make_pair(move(edge2), vertexIndex1)); + auto edge2 = Edge(vertexIndex2, vertexIndex3); + if (!IsDuplicatedEdge(edge2)) + m_edges.emplace_back(std::move(edge2), vertexIndex1, twoSide); - TEdge edge3 = make_pair(vertexIndex3, vertexIndex1); - if (!FindEdge(edge3)) - m_edges.push_back(make_pair(move(edge3), vertexIndex2)); + auto edge3 = Edge(vertexIndex3, vertexIndex1); + if (!IsDuplicatedEdge(edge3)) + m_edges.emplace_back(std::move(edge3), vertexIndex2, twoSide); } void ApplyAreaFeature::CalculateBuildingOutline(bool calculateNormals, BuildingOutline & outline) { - outline.m_vertices = move(m_points); + outline.m_vertices = std::move(m_points); outline.m_indices.reserve(m_edges.size() * 2); if (calculateNormals) outline.m_normals.reserve(m_edges.size()); - for (auto & e : m_edges) + for (auto const & e : m_edges) { - if (e.second < 0) + if (e.m_internalVertexIndex < 0) continue; - outline.m_indices.push_back(e.first.first); - outline.m_indices.push_back(e.first.second); + outline.m_indices.push_back(e.m_edge.m_startIndex); + outline.m_indices.push_back(e.m_edge.m_endIndex); + if (e.m_twoSide) + { + outline.m_indices.push_back(e.m_edge.m_endIndex); + outline.m_indices.push_back(e.m_edge.m_startIndex); + } if (calculateNormals) { - outline.m_normals.emplace_back(CalculateNormal(outline.m_vertices[e.first.first], - outline.m_vertices[e.first.second], - outline.m_vertices[e.second])); + outline.m_normals.emplace_back(CalculateNormal(outline.m_vertices[e.m_edge.m_startIndex], + outline.m_vertices[e.m_edge.m_endIndex], + outline.m_vertices[e.m_internalVertexIndex])); + if (e.m_twoSide) + outline.m_normals.push_back(outline.m_normals.back()); } } } @@ -809,7 +819,7 @@ void ApplyAreaFeature::CalculateBuildingOutline(bool calculateNormals, BuildingO void ApplyAreaFeature::ProcessAreaRule(Stylist::TRuleWrapper const & rule) { drule::BaseRule const * pRule = rule.first; - float const depth = static_cast(rule.second); + auto const depth = static_cast(rule.second); AreaRuleProto const * areaRule = pRule->GetArea(); if (areaRule && !m_triangles.empty()) @@ -838,7 +848,7 @@ void ApplyAreaFeature::ProcessAreaRule(Stylist::TRuleWrapper const & rule) params.m_is3D = !outline.m_indices.empty() && calculateNormals; } - m_insertShape(make_unique_dp(move(m_triangles), move(outline), params)); + m_insertShape(make_unique_dp(std::vector(m_triangles), move(outline), params)); } else { diff --git a/drape_frontend/apply_feature_functors.hpp b/drape_frontend/apply_feature_functors.hpp index fa77094500..5f0db29a2f 100644 --- a/drape_frontend/apply_feature_functors.hpp +++ b/drape_frontend/apply_feature_functors.hpp @@ -118,21 +118,46 @@ public: void operator()(m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3); void ProcessAreaRule(Stylist::TRuleWrapper const & rule); -private: - using TEdge = std::pair; + struct Edge + { + Edge() = default; + Edge(int startIndex, int endIndex) : m_startIndex(startIndex), m_endIndex(endIndex) {} + bool operator==(Edge const & edge) const + { + return (m_startIndex == edge.m_startIndex && m_endIndex == edge.m_endIndex) || + (m_startIndex == edge.m_endIndex && m_endIndex == edge.m_startIndex); + } + + int m_startIndex = -1; + int m_endIndex = -1; + }; + + struct ExtendedEdge + { + ExtendedEdge() = default; + ExtendedEdge(Edge && edge, int internalVertexIndex, bool twoSide) + : m_edge(std::move(edge)) + , m_internalVertexIndex(internalVertexIndex) + , m_twoSide(twoSide) + {} + + Edge m_edge; + int m_internalVertexIndex = -1; + bool m_twoSide = false; + }; + +private: void ProcessBuildingPolygon(m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3); void CalculateBuildingOutline(bool calculateNormals, BuildingOutline & outline); int GetIndex(m2::PointD const & pt); - void BuildEdges(int vertexIndex1, int vertexIndex2, int vertexIndex3); - bool EqualEdges(TEdge const & edge1, TEdge const & edge2) const; - bool FindEdge(TEdge const & edge); + void BuildEdges(int vertexIndex1, int vertexIndex2, int vertexIndex3, bool twoSide); + bool IsDuplicatedEdge(Edge const & edge); m2::PointD CalculateNormal(m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3) const; std::vector m_triangles; - buffer_vector m_points; - buffer_vector, kBuildingOutlineSize> m_edges; + buffer_vector m_edges; float const m_minPosZ; bool const m_isBuilding; diff --git a/drape_frontend/area_shape.cpp b/drape_frontend/area_shape.cpp index d3b41ed21d..04a27b8528 100644 --- a/drape_frontend/area_shape.cpp +++ b/drape_frontend/area_shape.cpp @@ -81,7 +81,7 @@ void AreaShape::DrawArea(ref_ptr context, ref_ptr context, ref_ptraddWidget(new QLabel("Feature ID"), row, 0); + grid->addWidget(new QLabel(QString::fromStdString(DebugPrint(info.GetID()))), row++, 1); + grid->addWidget(new QLabel("Raw Types"), row, 0); QLabel * label = new QLabel(QString::fromStdString(DebugPrint(info.GetTypes()))); label->setTextInteractionFlags(Qt::TextSelectableByMouse);