| |
| |
| #include "tools/levelselection.h" |
| |
| |
| #include "tools/tool.h" |
| #include "tools/toolhandle.h" |
| |
| |
| #include "tfilepath.h" |
| #include "tvectorimage.h" |
| #include "tstroke.h" |
| #include "tregion.h" |
| |
| |
| #include <boost/algorithm/cxx11/copy_if.hpp> |
| #include <boost/iterator/counting_iterator.hpp> |
| #include <boost/bind.hpp> |
| |
| namespace boost_a = boost::algorithm; |
| |
| |
| |
| |
| |
| namespace { |
| |
| TTool *tool() { return TTool::getApplication()->getCurrentTool()->getTool(); } |
| |
| |
| |
| struct StrokeData { |
| UCHAR m_hasColor, m_hasRegion; |
| }; |
| |
| void getBoundaries(TVectorImage &vi, std::vector<int> &strokes) { |
| enum { FORWARD = 0x1, BACKWARD = 0x2, INTERNAL = FORWARD | BACKWARD }; |
| |
| struct locals { |
| static inline bool isBoundary(const std::vector<StrokeData> &sData, |
| UINT s) { |
| return (sData[s].m_hasColor != INTERNAL); |
| } |
| |
| static void markEdges(const TRegion ®ion, std::vector<StrokeData> &sData, |
| bool parentRegionHasColor) { |
| bool regionHasColor = (region.getStyle() != 0); |
| |
| |
| UINT e, eCount = region.getEdgeCount(); |
| for (e = 0; e != eCount; ++e) { |
| const TEdge &ed = *region.getEdge(e); |
| assert(ed.m_s); |
| |
| int strokeIdx = ed.m_index; |
| if (strokeIdx >= 0) |
| { |
| assert(0 <= strokeIdx && strokeIdx < sData.size()); |
| |
| StrokeData &sd = sData[strokeIdx]; |
| |
| UCHAR side = (ed.m_w1 > ed.m_w0) ? FORWARD : BACKWARD; |
| |
| sd.m_hasRegion |= side; |
| if (regionHasColor) sd.m_hasColor |= side; |
| } |
| } |
| |
| if (parentRegionHasColor) { |
| |
| for (e = 0; e != eCount; ++e) { |
| const TEdge &ed = *region.getEdge(e); |
| assert(ed.m_s); |
| |
| int strokeIdx = ed.m_index; |
| if (strokeIdx >= 0) { |
| StrokeData &sd = sData[strokeIdx]; |
| sd.m_hasColor |= (INTERNAL & ~sd.m_hasRegion); |
| } |
| } |
| } |
| |
| |
| UINT sr, srCount = region.getSubregionCount(); |
| for (sr = 0; sr != srCount; ++sr) |
| markEdges(*region.getSubregion(sr), sData, regionHasColor); |
| } |
| }; |
| |
| std::vector<StrokeData> sData(vi.getStrokeCount()); |
| |
| |
| |
| UINT r, rCount = vi.getRegionCount(); |
| for (r = 0; r != rCount; ++r) |
| locals::markEdges(*vi.getRegion(r), sData, false); |
| |
| |
| |
| UINT s, sCount = vi.getStrokeCount(); |
| for (s = 0; s != sCount; ++s) { |
| if (!sData[s].m_hasRegion) { |
| TRegion *parentRegion = vi.getRegion(vi.getStroke(s)->getPoint(0.5)); |
| |
| if (parentRegion && parentRegion->getStyle()) |
| sData[s].m_hasColor = INTERNAL; |
| } |
| } |
| |
| |
| boost_a::copy_if(boost::make_counting_iterator(0u), |
| boost::make_counting_iterator(vi.getStrokeCount()), |
| std::back_inserter(strokes), |
| boost::bind(locals::isBoundary, sData, _1)); |
| } |
| |
| } |
| |
| |
| |
| |
| |
| LevelSelection::LevelSelection() : m_framesMode(FRAMES_NONE), m_filter(EMPTY) {} |
| |
| |
| |
| bool LevelSelection::isEmpty() const { |
| return (m_framesMode == FRAMES_NONE || m_filter == EMPTY); |
| } |
| |
| |
| |
| void LevelSelection::selectNone() { |
| m_framesMode = FRAMES_NONE; |
| m_filter = EMPTY; |
| |
| m_styles.clear(); |
| } |
| |
| |
| |
| |
| |
| std::vector<int> getBoundaryStrokes(TVectorImage &vi) { |
| std::vector<int> result; |
| getBoundaries(vi, result); |
| |
| return result; |
| } |
| |
| |
| |
| std::vector<int> getSelectedStrokes(TVectorImage &vi, |
| const LevelSelection &levelSelection) { |
| struct locals { |
| static void selectStyles(const TVectorImage &vi, |
| const std::set<int> &styles, |
| std::vector<int> &strokes) { |
| UINT s, sCount = vi.getStrokeCount(); |
| for (s = 0; s != sCount; ++s) { |
| if (styles.count(vi.getStroke(s)->getStyle())) strokes.push_back(s); |
| } |
| } |
| }; |
| |
| std::vector<int> strokes; |
| |
| switch (levelSelection.filter()) { |
| case LevelSelection::EMPTY: |
| break; |
| case LevelSelection::WHOLE: |
| strokes.assign(boost::make_counting_iterator(0u), |
| boost::make_counting_iterator(vi.getStrokeCount())); |
| break; |
| case LevelSelection::SELECTED_STYLES: |
| locals::selectStyles(vi, levelSelection.styles(), strokes); |
| break; |
| case LevelSelection::BOUNDARY_STROKES: |
| getBoundaries(vi, strokes); |
| break; |
| } |
| |
| return strokes; |
| } |
| |