diff --git a/map/area_info.hpp b/map/area_info.hpp new file mode 100644 index 0000000000..52d9c92751 --- /dev/null +++ b/map/area_info.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include "../geometry/point2d.hpp" + +#include "../std/vector.hpp" +#include "../std/algorithm.hpp" + +namespace di +{ + class AreaInfo + { + m2::PointD m_center; + + public: + vector m_path; + + void reserve(size_t ptsCount) + { + m_path.reserve(ptsCount); + } + + void swap(AreaInfo & r) + { + m_path.swap(r.m_path); + std::swap(m_center, r.m_center); + } + + void push_back(m2::PointD const & pt) + { + m_path.push_back(pt); + } + + size_t size() const { return m_path.size(); } + + void SetCenter(m2::PointD const & p) { m_center = p; } + m2::PointD GetCenter() const { return m_center; } + }; +} + +inline void swap(di::AreaInfo & p1, di::AreaInfo & p2) +{ + p1.swap(p2); +} diff --git a/map/draw_processor.cpp b/map/draw_processor.cpp deleted file mode 100644 index ad7b0d2df6..0000000000 --- a/map/draw_processor.cpp +++ /dev/null @@ -1,358 +0,0 @@ -#include "draw_processor.hpp" -#include "drawer.hpp" - -#include "feature_styler.hpp" - -#include "../platform/preferred_languages.hpp" - -#include "../geometry/screenbase.hpp" -#include "../geometry/rect_intersect.hpp" - -#include "../indexer/feature_visibility.hpp" -#include "../indexer/drawing_rules.hpp" -#include "../indexer/feature_data.hpp" -#include "../indexer/feature_impl.hpp" - -#include "../std/bind.hpp" - - -namespace get_pts { - -using namespace di; - -m2::PointD base::g2p(m2::PointD const & pt) const -{ - return m_convertor->GtoP(pt); -} - -base_screen::base_screen(params const & p) -: base(p) -{ - m_convertor->GtoP(*p.m_rect, m_rect); -} - -void one_point::operator() (CoordPointT const & p) -{ - ASSERT ( !m_exist, ("point feature should have only one point") ); - - m2::PointD pt(make_point(p)); - - if (m_rect->IsPointInside(pt)) - { - m_exist = true; - m_point = convert_point(pt); - } - else m_exist = false; -} - -void path_points::StartPL(m2::PointD const & pt) -{ - EndPL(); - - m_points.push_back(PathInfo(m_length + m_prev.Length(pt))); - push_point(pt); - - m_newPL = false; -} - -void path_points::EndPL() -{ - if (!m_points.empty() && m_points.back().size() < 2) - m_points.pop_back(); -} - -void path_points::simple_filtration(m2::PointD const & pt) -{ - if (m_hasPrevPt) - { - if (!m2::RectD(m_prev, pt).IsIntersect(m_rect)) - m_newPL = true; - else - { - if (m_newPL) - StartPL(m_prev); - - push_point(pt); - } - - m_length += m_prev.Length(pt); - } - else - { - m_hasPrevPt = true; - m_length = 0.0; - } - - m_prev = pt; -} - -void path_points::best_filtration(m2::PointD const & pt) -{ - if (m_hasPrevPt) - { - m2::PointD prev = m_prev; - m2::PointD curr = pt; - - double const segLen = curr.Length(prev); - - if ((m_startLength != 0) && (m_endLength != 0)) - { - if ((m_startLength >= m_length) && (m_startLength < m_length + segLen)) - m_startLength = m_length; - - if ((m_endLength > m_length) && (m_endLength <= m_length + segLen)) - m_endLength = m_length + segLen; - } - - if ((m_length >= m_startLength) && (m_endLength >= m_length + segLen)) - { - /// we're in the dead zone. add without clipping - if (m_newPL) - StartPL(prev); - - push_point(curr); - } - else - { - if (!m2::Intersect(m_rect, prev, curr)) - m_newPL = true; - else - { - if (!equal_glb_pts(prev, m_prev)) - m_newPL = true; - - if (m_newPL) - StartPL(prev); - - push_point(curr); - - if (!equal_glb_pts(curr, pt)) - m_newPL = true; - } - } - - m_length += segLen; - } - else - { - m_hasPrevPt = true; - m_length = 0.0; - } - - m_prev = pt; -} - -void path_points::operator() (m2::PointD const & p) -{ - // Choose simple (fast) or best (slow) filtration - - //simple_filtration(p); - best_filtration(p); -} - -bool path_points::IsExist() -{ - // finally, assign whole length to every cutted path - for_each(m_points.begin(), m_points.end(), - bind(&di::PathInfo::SetFullLength, _1, m_length)); - - EndPL(); - return base_type::IsExist(); -} - -void area_tess_points::StartPrimitive(size_t ptsCount) -{ - m_points.push_back(AreaInfo()); - m_points.back().reserve(ptsCount); -} - -void area_tess_points::operator() (m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3) -{ - push_point(p1); - push_point(p2); - push_point(p3); -} - -void area_tess_points::EndPrimitive() -{ - if (m_points.back().size() < 3) - m_points.pop_back(); -} - -bool area_tess_points::IsExist() const -{ - return !m_points.empty(); -} - -} - -namespace fwork -{ - namespace - { - template void assign_point(di::DrawInfo * p, TSrc & src) - { - p->m_point = src.m_point; - } - template void assign_path(di::DrawInfo * p, TSrc & src) - { - p->m_pathes.swap(src.m_points); - } - template void assign_area(di::DrawInfo * p, TSrc & src) - { - p->m_areas.swap(src.m_points); - - ASSERT ( !p->m_areas.empty(), () ); - p->m_areas.back().SetCenter(src.GetCenter()); - } - } - - DrawProcessor::DrawProcessor( m2::RectD const & r, - ScreenBase const & convertor, - shared_ptr const & e, - int scaleLevel) - : m_rect(r), - m_convertor(convertor), - m_paintEvent(e), - m_zoom(scaleLevel), - m_hasNonCoast(false), - m_glyphCache(e->drawer()->screen()->glyphCache()) -#ifdef PROFILER_DRAWING - , m_drawCount(0) -#endif - { - GetDrawer()->SetScale(m_zoom); - } - -#define GET_POINTS(f, for_each_fun, fun, assign_fun) \ - { \ - f.for_each_fun(fun, m_zoom); \ - if (fun.IsExist()) \ - { \ - isExist = true; \ - assign_fun(ptr.get(), fun); \ - } \ - } - - bool DrawProcessor::operator() (FeatureType const & f) - { - if (m_paintEvent->isCancelled()) - throw redraw_operation_cancelled(); - - feature::StylesContainer styles; - styles.GetStyles(f, m_zoom); - - if (styles.IsEmpty()) - return true; - - // Draw coastlines features only once. - if (styles.m_isCoastline) - { - if (!m_coasts.insert(styles.m_primaryText).second) - return true; - } - else - m_hasNonCoast = true; - - size_t count = styles.GetCount(); - -#ifdef PROFILER_DRAWING - m_drawCount += count; -#endif - - scoped_ptr ptr(new di::DrawInfo( - styles.m_primaryText, - styles.m_secondaryText, - styles.m_refText, - styles.m_popRank)); // FIXME - - Drawer * pDrawer = GetDrawer(); - - using namespace get_pts; - - bool isExist = false; - switch (styles.m_geometryType) - { - case feature::GEOM_POINT: - { - typedef get_pts::one_point functor_t; - - functor_t::params p; - p.m_convertor = &m_convertor; - p.m_rect = &m_rect; - - functor_t fun(p); - GET_POINTS(f, ForEachPointRef, fun, assign_point) - break; - } - - case feature::GEOM_AREA: - { - typedef filter_screenpts_adapter functor_t; - - functor_t::params p; - p.m_convertor = &m_convertor; - p.m_rect = &m_rect; - - functor_t fun(p); - GET_POINTS(f, ForEachTriangleExRef, fun, assign_area) - { - // continue rendering as line if feature has linear styles too - if (!styles.m_hasLineStyles) - break; - } - } - case feature::GEOM_LINE: - { - typedef filter_screenpts_adapter functor_t; - functor_t::params p; - p.m_convertor = &m_convertor; - p.m_rect = &m_rect; - - if (styles.m_hasPathText) - { - uint8_t fontSize = 0; - for (size_t i = 0; i < count; ++i) - { - if (!pDrawer->filter_text_size(styles.m_rules[i].m_rule)) - fontSize = max(fontSize, pDrawer->get_text_font_size(styles.m_rules[i].m_rule)); - } - - if (fontSize != 0) - { - double textLength = m_glyphCache->getTextLength(fontSize, ptr->GetPathName()); - typedef calc_length functor_t; - functor_t::params p1; - p1.m_convertor = &m_convertor; - p1.m_rect = &m_rect; - functor_t fun(p1); - - f.ForEachPointRef(fun, m_zoom); - - if ((fun.IsExist()) && (fun.m_length > textLength)) - { - p.m_startLength = (fun.m_length - textLength) / 2; - p.m_endLength = p.m_startLength + textLength; - } - } - } - - functor_t fun(p); - - GET_POINTS(f, ForEachPointRef, fun, assign_path) - - break; - } - } - - if (isExist) - pDrawer->Draw(ptr.get(), styles.m_rules.data(), count, f.GetID()); - - return true; - } - - bool DrawProcessor::IsEmptyDrawing() const - { - return (m_zoom >= feature::g_arrCountryScales[0] && !m_hasNonCoast); - } -} diff --git a/map/feature_info.cpp b/map/feature_info.cpp new file mode 100644 index 0000000000..e8dc75b3ba --- /dev/null +++ b/map/feature_info.cpp @@ -0,0 +1,14 @@ +#include "feature_info.hpp" + +namespace di +{ + FeatureInfo::FeatureInfo(FeatureType const & f, + int const zoom, + double const visualScale, + graphics::GlyphCache * glyphCache, + ScreenBase const * convertor, + m2::RectD const * rect) + : m_styler(f, zoom, visualScale, glyphCache, convertor, rect), + m_id(f.GetID()) + {} +} diff --git a/map/feature_info.hpp b/map/feature_info.hpp new file mode 100644 index 0000000000..6b52a1a155 --- /dev/null +++ b/map/feature_info.hpp @@ -0,0 +1,40 @@ +#pragma once + +#include "feature_styler.hpp" +#include "path_info.hpp" +#include "area_info.hpp" + +#include "../indexer/feature.hpp" + +#include "../geometry/point2d.hpp" + +#include "../std/list.hpp" + +namespace graphics +{ + class GlyphCache; +} + +class ScreenBase; + +namespace di +{ + struct FeatureInfo + { + typedef pair FeatureID; + + FeatureStyler m_styler; + FeatureID m_id; + + list m_pathes; + list m_areas; + m2::PointD m_point; + + FeatureInfo(FeatureType const & f, + int const zoom, + double const visualScale, + graphics::GlyphCache * glyphCache, + ScreenBase const * convertor, + m2::RectD const * rect); + }; +} diff --git a/map/feature_processor.cpp b/map/feature_processor.cpp new file mode 100644 index 0000000000..e119501fcb --- /dev/null +++ b/map/feature_processor.cpp @@ -0,0 +1,154 @@ +#include "feature_processor.hpp" +#include "geometry_processors.hpp" +#include "feature_info.hpp" +#include "drawer.hpp" + +//#include "../platform/preferred_languages.hpp" + +//#include "../geometry/screenbase.hpp" +//#include "../geometry/rect_intersect.hpp" + +//#include "../indexer/feature_visibility.hpp" +//#include "../indexer/drawing_rules.hpp" +//#include "../indexer/feature_data.hpp" +#include "../indexer/feature_impl.hpp" + +//#include "../std/bind.hpp" + +namespace fwork +{ + namespace + { + template void assign_point(di::FeatureInfo & p, TSrc & src) + { + p.m_point = src.m_point; + } + + template void assign_path(di::FeatureInfo & p, TSrc & src) + { + p.m_pathes.swap(src.m_points); + } + + template void assign_area(di::FeatureInfo & p, TSrc & src) + { + p.m_areas.swap(src.m_points); + + ASSERT ( !p.m_areas.empty(), () ); + p.m_areas.back().SetCenter(src.GetCenter()); + } + } + + FeatureProcessor::FeatureProcessor(m2::RectD const & r, + ScreenBase const & convertor, + shared_ptr const & e, + int scaleLevel) + : m_rect(r), + m_convertor(convertor), + m_paintEvent(e), + m_zoom(scaleLevel), + m_hasNonCoast(false), + m_glyphCache(e->drawer()->screen()->glyphCache()) + { + GetDrawer()->SetScale(m_zoom); + } + + bool FeatureProcessor::operator() (FeatureType const & f) + { + if (m_paintEvent->isCancelled()) + throw redraw_operation_cancelled(); + + Drawer * pDrawer = GetDrawer(); + di::FeatureInfo fi(f, m_zoom, pDrawer->VisualScale(), m_glyphCache, &m_convertor, &m_rect); + + if (fi.m_styler.IsEmpty()) + return true; + + // Draw coastlines features only once. + if (fi.m_styler.m_isCoastline) + { + if (!m_coasts.insert(fi.m_styler.m_primaryText).second) + return true; + } + else + m_hasNonCoast = true; + + using namespace gp; + + bool isExist = false; + + switch (fi.m_styler.m_geometryType) + { + case feature::GEOM_POINT: + { + typedef gp::one_point functor_t; + + functor_t::params p; + p.m_convertor = &m_convertor; + p.m_rect = &m_rect; + + functor_t fun(p); + f.ForEachPointRef(fun, m_zoom); + if (fun.IsExist()) + { + isExist = true; + assign_point(fi, fun); + } + + break; + } + + case feature::GEOM_AREA: + { + typedef filter_screenpts_adapter functor_t; + + functor_t::params p; + p.m_convertor = &m_convertor; + p.m_rect = &m_rect; + + functor_t fun(p); + f.ForEachTriangleExRef(fun, m_zoom); + if (fun.IsExist()) + { + isExist = true; + assign_area(fi, fun); + } + + // continue rendering as line if feature has linear styles too + if (!fi.m_styler.m_hasLineStyles) + break; + } + + case feature::GEOM_LINE: + { +// typedef filter_screenpts_adapter functor_t; + typedef filter_screenpts_adapter functor_t; + + functor_t::params p; + + p.m_convertor = &m_convertor; + p.m_rect = &m_rect; + p.m_intervals = &fi.m_styler.m_intervals; + + functor_t fun(p); + + f.ForEachPointRef(fun, m_zoom); + if (fun.IsExist()) + { + isExist = true; + assign_path(fi, fun); + } + break; + } + } + + if (isExist) + pDrawer->Draw(fi); + + return true; + } + + bool FeatureProcessor::IsEmptyDrawing() const + { + return (m_zoom >= feature::g_arrCountryScales[0] && !m_hasNonCoast); + } +} diff --git a/map/feature_processor.hpp b/map/feature_processor.hpp new file mode 100644 index 0000000000..34ad7233e5 --- /dev/null +++ b/map/feature_processor.hpp @@ -0,0 +1,51 @@ +#pragma once + +#include "events.hpp" + +#include "../indexer/drawing_rule_def.hpp" +#include "../indexer/feature.hpp" +#include "../indexer/data_header.hpp" +#include "../indexer/feature_data.hpp" + +#include "../geometry/rect2d.hpp" + +#include "../graphics/glyph_cache.hpp" + +class ScreenBase; + +class redraw_operation_cancelled {}; + +namespace fwork +{ + class FeatureProcessor + { + m2::RectD m_rect; + + set m_coasts; + + ScreenBase const & m_convertor; + + shared_ptr m_paintEvent; + + int m_zoom; + bool m_hasNonCoast; + bool m_hasAnyFeature; + + graphics::GlyphCache * m_glyphCache; + + inline Drawer * GetDrawer() const { return m_paintEvent->drawer(); } + + void PreProcessKeys(vector & keys) const; + + public: + + FeatureProcessor(m2::RectD const & r, + ScreenBase const & convertor, + shared_ptr const & paintEvent, + int scaleLevel); + + bool operator() (FeatureType const & f); + + bool IsEmptyDrawing() const; + }; +} diff --git a/map/geometry_processors.cpp b/map/geometry_processors.cpp new file mode 100644 index 0000000000..acda4e9d6c --- /dev/null +++ b/map/geometry_processors.cpp @@ -0,0 +1,300 @@ +#include "geometry_processors.hpp" + +#include "../std/bind.hpp" + +namespace gp +{ + using namespace di; + + base_screen::base_screen(params const & p) + : base(p) + { + m_convertor->GtoP(*p.m_rect, m_rect); + } + + void one_point::operator() (CoordPointT const & p) + { + ASSERT ( !m_exist, ("point feature should have only one point") ); + + m2::PointD pt(make_point(p)); + + if (m_rect->IsPointInside(pt)) + { + m_exist = true; + m_point = convert_point(pt); + } + else + m_exist = false; + } + + get_path_intervals::params::params() + : m_intervals(0) + {} + + get_path_intervals::get_path_intervals(params const & p) + : base_t(p), + m_hasPrevPt(false), + m_intervals(p.m_intervals), + m_isFirst(true), + m_length(0) + {} + + void get_path_intervals::operator()(m2::PointD const & pt) + { + if (m_hasPrevPt) + { + m2::PointD prev = m_prev; + m2::PointD cur = pt; + + double segLen = cur.Length(prev); + + if (m2::Intersect(base_t::m_rect, prev, cur)) + { + double clipStart = prev.Length(m_prev) + m_length; + double clipEnd = cur.Length(m_prev) + m_length; + + if (m_isFirst) + { + m_intervals->push_back(clipStart); + m_intervals->push_back(clipEnd); + m_isFirst = false; + } + else + { + if (fabs(m_intervals->back() - clipStart) < 1.0E-12) + m_intervals->back() = clipEnd; + else + { + m_intervals->push_back(clipStart); + m_intervals->push_back(clipEnd); + } + } + } + + m_prev = pt; + m_length += segLen; + } + else + { + m_prev = pt; + m_hasPrevPt = true; + } + } + + bool get_path_intervals::IsExist() const + { + return !m_isFirst; + } + + cut_path_intervals::params::params() : m_intervals(0) + {} + + cut_path_intervals::cut_path_intervals(params const & p) + : base_t(p), + m_length(0), + m_isInside(false), + m_hasPrevPt(false), + m_intervals(p.m_intervals), + m_pos(0) + {} + + void cut_path_intervals::operator()(m2::PointD const & pt) + { + if (m_hasPrevPt) + { + double segLen = pt.Length(m_prev); + + while (true) + { + m2::PointD dir = (pt - m_prev) / segLen; + + if (m_pos == m_intervals->size()) + break; + + double start = (*m_intervals)[m_pos]; + double end = (*m_intervals)[m_pos + 1]; + + if (start > m_length + segLen) + break; + + if (start >= m_length) + { + m_points.push_back(PathInfo(start)); + push_point(m_prev + dir * (start - m_length)); + m_isInside = true; + } + + if (end >= m_length + segLen) + { + push_point(pt); + break; + } + + if (end < m_length + segLen) + { + push_point(m_prev + dir * (end - m_length)); + m_isInside = false; + } + + m_pos += 2; + } + + m_prev = pt; + m_length += segLen; + } + else + { + m_hasPrevPt = true; + m_prev = pt; + } + } + + bool cut_path_intervals::IsExist() + { + // finally, assign whole length to every cutted path + for_each(m_points.begin(), m_points.end(), + bind(&di::PathInfo::SetFullLength, _1, m_length)); + + return !m_points.empty(); + } + + void path_points::StartPL(m2::PointD const & pt) + { + EndPL(); + + m_points.push_back(PathInfo(m_length + m_prev.Length(pt))); + push_point(pt); + + m_newPL = false; + } + + void path_points::EndPL() + { + if (!m_points.empty() && m_points.back().size() < 2) + m_points.pop_back(); + } + + void path_points::simple_filtration(m2::PointD const & pt) + { + if (m_hasPrevPt) + { + if (!m2::RectD(m_prev, pt).IsIntersect(m_rect)) + m_newPL = true; + else + { + if (m_newPL) + StartPL(m_prev); + + push_point(pt); + } + + m_length += m_prev.Length(pt); + } + else + { + m_hasPrevPt = true; + m_length = 0.0; + } + + m_prev = pt; + } + + void path_points::best_filtration(m2::PointD const & pt) + { + if (m_hasPrevPt) + { + m2::PointD prev = m_prev; + m2::PointD curr = pt; + + double const segLen = curr.Length(prev); + + if ((m_startLength != 0) && (m_endLength != 0)) + { + if ((m_startLength >= m_length) && (m_startLength < m_length + segLen)) + m_startLength = m_length; + + if ((m_endLength > m_length) && (m_endLength <= m_length + segLen)) + m_endLength = m_length + segLen; + } + + if ((m_length >= m_startLength) && (m_endLength >= m_length + segLen)) + { + /// we're in the dead zone. add without clipping + if (m_newPL) + StartPL(prev); + + push_point(curr); + } + else + { + if (!m2::Intersect(m_rect, prev, curr)) + m_newPL = true; + else + { + if (!equal_glb_pts(prev, m_prev)) + m_newPL = true; + + if (m_newPL) + StartPL(prev); + + push_point(curr); + + if (!equal_glb_pts(curr, pt)) + m_newPL = true; + } + } + + m_length += segLen; + } + else + { + m_hasPrevPt = true; + m_length = 0.0; + } + + m_prev = pt; + } + + void path_points::operator() (m2::PointD const & p) + { + // Choose simple (fast) or best (slow) filtration + + //simple_filtration(p); + best_filtration(p); + } + + bool path_points::IsExist() + { + // finally, assign whole length to every cutted path + for_each(m_points.begin(), m_points.end(), + bind(&di::PathInfo::SetFullLength, _1, m_length)); + + EndPL(); + return base_type::IsExist(); + } + + void area_tess_points::StartPrimitive(size_t ptsCount) + { + m_points.push_back(AreaInfo()); + m_points.back().reserve(ptsCount); + } + + void area_tess_points::operator() (m2::PointD const & p1, m2::PointD const & p2, m2::PointD const & p3) + { + push_point(p1); + push_point(p2); + push_point(p3); + } + + void area_tess_points::EndPrimitive() + { + if (m_points.back().size() < 3) + m_points.pop_back(); + } + + bool area_tess_points::IsExist() const + { + return !m_points.empty(); + } + +} diff --git a/map/draw_processor.hpp b/map/geometry_processors.hpp similarity index 76% rename from map/draw_processor.hpp rename to map/geometry_processors.hpp index 5dab0a1148..8307d90fa1 100644 --- a/map/draw_processor.hpp +++ b/map/geometry_processors.hpp @@ -1,25 +1,23 @@ #pragma once -#include "draw_info.hpp" -#include "events.hpp" +#include "area_info.hpp" +#include "path_info.hpp" -#include "../indexer/drawing_rule_def.hpp" -#include "../indexer/feature.hpp" #include "../indexer/cell_id.hpp" // CoordPointT -#include "../indexer/data_header.hpp" -#include "../indexer/feature_data.hpp" #include "../geometry/point2d.hpp" #include "../geometry/rect2d.hpp" +#include "../geometry/rect_intersect.hpp" +#include "../geometry/screenbase.hpp" #include "../std/list.hpp" #include "../std/limits.hpp" -#include "../graphics/glyph_cache.hpp" +#include "../base/buffer_vector.hpp" class ScreenBase; -namespace get_pts +namespace gp { /// @name Base class policies (use by inheritance) for points processing. /// Containt next functions:\n @@ -28,17 +26,8 @@ namespace get_pts /// - m_rect - clip rect;\n //@{ - class base + struct base { - protected: - ScreenBase const * m_convertor; - - static m2::PointD make_point(CoordPointT const & p) - { - return m2::PointD(p.first, p.second); - } - m2::PointD g2p(m2::PointD const & pt) const; - struct params { ScreenBase const * m_convertor; @@ -46,15 +35,27 @@ namespace get_pts {} }; - base(params const & p) : m_convertor(p.m_convertor) + base(params const & p) + : m_convertor(p.m_convertor) { } + + ScreenBase const * m_convertor; + + static m2::PointD make_point(CoordPointT const & p) + { + return m2::PointD(p.first, p.second); + } + + m2::PointD g2p(m2::PointD const & pt) const + { + return m_convertor->GtoP(pt); + } }; /// in global coordinates - class base_global : public base + struct base_global : public base { - protected: m2::RectD const * m_rect; m2::PointD convert_point(m2::PointD const & pt) const @@ -75,17 +76,10 @@ namespace get_pts }; /// in screen coordinates - class base_screen : public base + struct base_screen : public base { - protected: - m2::RectD m_rect; - m2::PointD convert_point(m2::PointD const & pt) const - { - return pt; - } - struct params : base::params { m2::RectD const * m_rect; @@ -94,16 +88,20 @@ namespace get_pts }; base_screen(params const & p); + + m2::PointD convert_point(m2::PointD const & pt) const + { + return pt; + } }; //@} template - class calc_length : public TBase + struct calc_length : public TBase { bool m_exist; m2::PointD m_prevPt; - public: double m_length; typedef typename TBase::params params; @@ -115,6 +113,7 @@ namespace get_pts void operator() (CoordPointT const & p) { m2::PointD pt(this->convert_point(this->make_point(p))); + if (m_exist) m_length += pt.Length(m_prevPt); @@ -122,14 +121,15 @@ namespace get_pts m_prevPt = pt; } - bool IsExist() const {return m_exist;} + bool IsExist() const + { + return m_exist; + } }; - class one_point : public base_global + struct one_point : public base_global { bool m_exist; - - public: m2::PointD m_point; typedef base_global::params params; @@ -141,10 +141,14 @@ namespace get_pts void operator() (CoordPointT const & p); - bool IsExist() const { return m_exist; } + bool IsExist() const + { + return m_exist; + } }; - template class geometry_base : public TBase + template + struct geometry_base : public TBase { public: list m_points; @@ -167,6 +171,54 @@ namespace get_pts } }; + struct get_path_intervals : public geometry_base + { + typedef geometry_base base_t; + + buffer_vector * m_intervals; + + bool m_hasPrevPt; + m2::PointD m_prev; + bool m_isFirst; + double m_length; + + struct params : base_t::params + { + buffer_vector * m_intervals; + params(); + }; + + get_path_intervals(params const & p); + + void operator() (m2::PointD const & pt); + + bool IsExist() const; + }; + + struct cut_path_intervals : public geometry_base + { + typedef geometry_base base_t; + + struct params : base_t::params + { + buffer_vector * m_intervals; + params(); + }; + + double m_length; + bool m_isInside; + bool m_hasPrevPt; + m2::PointD m_prev; + buffer_vector * m_intervals; + unsigned m_pos; + + cut_path_intervals(params const & p); + + void operator() (m2::PointD const & p); + + bool IsExist(); + }; + class path_points : public geometry_base { typedef geometry_base base_type; @@ -304,47 +356,3 @@ namespace get_pts m2::PointD GetCenter() const { return m_center / (3*m_count); } }; } - -namespace drule { class BaseRule; } -namespace di { class DrawInfo; } - -class redraw_operation_cancelled {}; - -namespace fwork -{ - class DrawProcessor - { - m2::RectD m_rect; - - set m_coasts; - - ScreenBase const & m_convertor; - - shared_ptr m_paintEvent; - - int m_zoom; - bool m_hasNonCoast; - bool m_hasAnyFeature; - - graphics::GlyphCache * m_glyphCache; - -#ifdef PROFILER_DRAWING - size_t m_drawCount; -#endif - - inline Drawer * GetDrawer() const { return m_paintEvent->drawer(); } - - void PreProcessKeys(vector & keys) const; - - public: - - DrawProcessor(m2::RectD const & r, - ScreenBase const & convertor, - shared_ptr const & paintEvent, - int scaleLevel); - - bool operator() (FeatureType const & f); - - bool IsEmptyDrawing() const; - }; -} diff --git a/map/map.pro b/map/map.pro index b535a38867..08110987bf 100644 --- a/map/map.pro +++ b/map/map.pro @@ -16,8 +16,8 @@ HEADERS += \ events.hpp \ navigator.hpp \ drawer.hpp \ - draw_processor.hpp \ - draw_info.hpp \ + feature_processor.hpp \ + path_info.hpp \ window_handle.hpp \ tile_renderer.hpp \ information_display.hpp \ @@ -52,13 +52,16 @@ HEADERS += \ mwm_url.hpp \ feature_styler.hpp \ bookmark_balloon.hpp \ + feature_info.hpp \ + area_info.hpp \ + geometry_processors.hpp SOURCES += \ feature_vec_model.cpp \ framework.cpp \ navigator.cpp \ drawer.cpp \ - draw_processor.cpp \ + feature_processor.cpp \ tile_renderer.cpp \ information_display.cpp \ location_state.cpp \ @@ -95,6 +98,8 @@ SOURCES += \ mwm_url.cpp \ feature_styler.cpp \ bookmark_balloon.cpp \ + feature_info.cpp \ + geometry_processors.cpp !iphone*:!bada*:!android* { HEADERS += qgl_render_context.hpp diff --git a/map/map_tests/draw_processor_test.cpp b/map/map_tests/draw_processor_test.cpp deleted file mode 100644 index 7b928829a8..0000000000 --- a/map/map_tests/draw_processor_test.cpp +++ /dev/null @@ -1,48 +0,0 @@ -#include "../../base/SRC_FIRST.hpp" - -#include "../../testing/testing.hpp" -#include "../../geometry/screenbase.hpp" -#include "../../base/logging.hpp" - -#include "../draw_processor.hpp" - - -UNIT_TEST(PathPoints_DeadZoneClipping) -{ - m2::PointD pts[10] = - { - m2::PointD(0, 0), - m2::PointD(10, 0), - m2::PointD(10, 10), - m2::PointD(20, 10), - m2::PointD(20, 0), - m2::PointD(30, 0), - m2::PointD(30, 20), - m2::PointD(80, 20), - m2::PointD(80, 0), - m2::PointD(90, 0) - }; - - ScreenBase s; - s.OnSize(45 - 640, 0, 640, 480); - - m2::RectD r = s.ClipRect(); - - get_pts::path_points::params p; - p.m_startLength = 80; - p.m_endLength = 90; - p.m_convertor = &s; - p.m_rect = &r; - get_pts::path_points fun(p); - - for (unsigned i = 0; i < 10; ++i) - fun(pts[i]); - - fun.IsExist(); - -// int pathCount = fun.m_points.size(); - - di::PathInfo pi = fun.m_points.front(); - vector pts1 = fun.m_points.front().m_path; -// LOG(LINFO, (pts1)); -} diff --git a/map/map_tests/feature_processor_test.cpp b/map/map_tests/feature_processor_test.cpp new file mode 100644 index 0000000000..80e8b02152 --- /dev/null +++ b/map/map_tests/feature_processor_test.cpp @@ -0,0 +1,106 @@ +#include "../../base/SRC_FIRST.hpp" + +#include "../../testing/testing.hpp" +#include "../../geometry/screenbase.hpp" +#include "../../base/logging.hpp" + +#include "../feature_processor.hpp" +#include "../geometry_processors.hpp" + +UNIT_TEST(PathPoints_ClipAsIntervals) +{ + m2::PointD pts[10] = + { + m2::PointD(0, 0), + m2::PointD(10, 0), + m2::PointD(10, 10), + m2::PointD(20, 10), + m2::PointD(20, 0), + m2::PointD(30, 0), + m2::PointD(30, 20), + m2::PointD(80, 20), + m2::PointD(80, 0), + m2::PointD(90, 0) + }; + + m2::RectD r(5, -5, 25, 15); + + ScreenBase s; + s.OnSize(r.minX(), r.minY(), r.SizeX(), r.SizeY()); + s.SetFromRect(m2::AnyRectD(r)); + m2::RectD r1 = s.ClipRect(); + + buffer_vector intervals; + + typedef gp::get_path_intervals functor_t; + + functor_t::params p; + + p.m_convertor = &s; + p.m_rect = &r1; + p.m_intervals = &intervals; + + functor_t fun(p); + + for (unsigned i = 0; i < 10; ++i) + fun(pts[i]); + + fun.IsExist(); + + LOG(LINFO, (*fun.m_intervals)); + + typedef gp::filter_screenpts_adapter cut_functor_t; + + cut_functor_t::params cp; + + cp.m_convertor = &s; + cp.m_rect = &r1; + cp.m_intervals = fun.m_intervals; + + cut_functor_t cut_fun(cp); + + for (unsigned i = 0; i < ARRAY_SIZE(pts); ++i) + cut_fun(CoordPointT(pts[i].x, pts[i].y)); + + LOG(LINFO, (cut_fun.m_points.back().m_path)); +} + +UNIT_TEST(PathPoints_DeadZoneClipping) +{ + m2::PointD pts[10] = + { + m2::PointD(0, 0), + m2::PointD(10, 0), + m2::PointD(10, 10), + m2::PointD(20, 10), + m2::PointD(20, 0), + m2::PointD(30, 0), + m2::PointD(30, 20), + m2::PointD(80, 20), + m2::PointD(80, 0), + m2::PointD(90, 0) + }; + + ScreenBase s; + s.OnSize(45 - 640, 0, 640, 480); + + m2::RectD r = s.ClipRect(); + + gp::path_points::params p; + p.m_startLength = 80; + p.m_endLength = 90; + p.m_convertor = &s; + p.m_rect = &r; + gp::path_points fun(p); + + for (unsigned i = 0; i < 10; ++i) + fun(pts[i]); + + fun.IsExist(); + +// int pathCount = fun.m_points.size(); + + di::PathInfo pi = fun.m_points.front(); + vector pts1 = fun.m_points.front().m_path; +// LOG(LINFO, (pts1)); +} diff --git a/map/map_tests/map_tests.pro b/map/map_tests/map_tests.pro index e9c06a3f1e..4cb3026836 100644 --- a/map/map_tests/map_tests.pro +++ b/map/map_tests/map_tests.pro @@ -24,9 +24,9 @@ SOURCES += \ kmz_unarchive_test.cpp \ navigator_test.cpp \ map_foreach_test.cpp \ - draw_processor_test.cpp \ multithread_map_test.cpp \ bookmarks_test.cpp \ geourl_test.cpp \ measurement_tests.cpp \ mwm_url_tests.cpp \ + feature_processor_test.cpp diff --git a/map/draw_info.hpp b/map/path_info.hpp similarity index 74% rename from map/draw_info.hpp rename to map/path_info.hpp index 2d97149bd0..56f8bf0bd2 100644 --- a/map/draw_info.hpp +++ b/map/path_info.hpp @@ -6,7 +6,6 @@ #include "../std/vector.hpp" #include "../std/algorithm.hpp" - namespace di { class PathInfo @@ -78,43 +77,9 @@ namespace di return rect; } }; - - class AreaInfo - { - m2::PointD m_center; - - public: - vector m_path; - - void reserve(size_t ptsCount) - { - m_path.reserve(ptsCount); - } - - void swap(AreaInfo & r) - { - m_path.swap(r.m_path); - std::swap(m_center, r.m_center); - } - - void push_back(m2::PointD const & pt) - { - m_path.push_back(pt); - } - - size_t size() const { return m_path.size(); } - - void SetCenter(m2::PointD const & p) { m_center = p; } - m2::PointD GetCenter() const { return m_center; } - }; } inline void swap(di::PathInfo & p1, di::PathInfo & p2) { p1.swap(p2); } - -inline void swap(di::AreaInfo & p1, di::AreaInfo & p2) -{ - p1.swap(p2); -}