|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/levelselection.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzTools includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/tool.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tools/toolhandle.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// TnzCore includes
|
|
Toshihiro Shimizu |
890ddd |
#include "tfilepath.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tvectorimage.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tstroke.h"
|
|
Toshihiro Shimizu |
890ddd |
#include "tregion.h"
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Boost includes
|
|
Toshihiro Shimizu |
890ddd |
#include <boost algorithm="" copy_if.hpp="" cxx11=""></boost>
|
|
Toshihiro Shimizu |
890ddd |
#include <boost counting_iterator.hpp="" iterator=""></boost>
|
|
Toshihiro Shimizu |
890ddd |
#include <boost bind.hpp=""></boost>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace boost_a = boost::algorithm;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*******************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Local namespace stuff
|
|
Toshihiro Shimizu |
890ddd |
//*******************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
namespace
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
TTool *tool()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return TTool::getApplication()->getCurrentTool()->getTool();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//========================================================================
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct StrokeData {
|
|
Toshihiro Shimizu |
890ddd |
UCHAR m_hasColor,
|
|
Toshihiro Shimizu |
890ddd |
m_hasRegion;
|
|
Toshihiro Shimizu |
890ddd |
};
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void getBoundaries(TVectorImage &vi, std::vector<int> &strokes)</int>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
enum { FORWARD = 0x1,
|
|
Toshihiro Shimizu |
890ddd |
BACKWARD = 0x2,
|
|
Toshihiro Shimizu |
890ddd |
INTERNAL = FORWARD | BACKWARD };
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
struct locals {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static inline bool isBoundary(const std::vector<strokedata> &sData, UINT s)</strokedata>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (sData[s].m_hasColor != INTERNAL);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static void markEdges(const TRegion ®ion, std::vector<strokedata> &sData,</strokedata>
|
|
Toshihiro Shimizu |
890ddd |
bool parentRegionHasColor)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
bool regionHasColor = (region.getStyle() != 0);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Traverse region edges, marking associated strokes accordingly
|
|
Toshihiro Shimizu |
890ddd |
UINT e, eCount = region.getEdgeCount();
|
|
Toshihiro Shimizu |
890ddd |
for (e = 0; e != eCount; ++e) {
|
|
Toshihiro Shimizu |
890ddd |
const TEdge &ed = *region.getEdge(e);
|
|
Toshihiro Shimizu |
890ddd |
assert(ed.m_s);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int strokeIdx = ed.m_index;
|
|
Toshihiro Shimizu |
890ddd |
if (strokeIdx >= 0) // Could be <0 in case the corresponding
|
|
Toshihiro Shimizu |
890ddd |
{ // stroke is a region 'closure' (autoclose)
|
|
Toshihiro Shimizu |
890ddd |
assert(0 <= strokeIdx && strokeIdx < sData.size());
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
StrokeData &sd = sData[strokeIdx];
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
UCHAR side = (ed.m_w1 > ed.m_w0) ? FORWARD : BACKWARD;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
sd.m_hasRegion |= side;
|
|
Toshihiro Shimizu |
890ddd |
if (regionHasColor)
|
|
Toshihiro Shimizu |
890ddd |
sd.m_hasColor |= side;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (parentRegionHasColor) {
|
|
Toshihiro Shimizu |
890ddd |
// Mark non-region edge sides with color
|
|
Toshihiro Shimizu |
890ddd |
for (e = 0; e != eCount; ++e) {
|
|
Toshihiro Shimizu |
890ddd |
const TEdge &ed = *region.getEdge(e);
|
|
Toshihiro Shimizu |
890ddd |
assert(ed.m_s);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
int strokeIdx = ed.m_index;
|
|
Toshihiro Shimizu |
890ddd |
if (strokeIdx >= 0) {
|
|
Toshihiro Shimizu |
890ddd |
StrokeData &sd = sData[strokeIdx];
|
|
Toshihiro Shimizu |
890ddd |
sd.m_hasColor |= (INTERNAL & ~sd.m_hasRegion);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Mark recursively on sub-regions
|
|
Toshihiro Shimizu |
890ddd |
UINT sr, srCount = region.getSubregionCount();
|
|
Toshihiro Shimizu |
890ddd |
for (sr = 0; sr != srCount; ++sr)
|
|
Toshihiro Shimizu |
890ddd |
markEdges(*region.getSubregion(sr), sData, regionHasColor);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}; // locals
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<strokedata> sData(vi.getStrokeCount());</strokedata>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Traverse regions, mark each stroke edge with the side a COLORED region is on
|
|
Toshihiro Shimizu |
890ddd |
UINT r, rCount = vi.getRegionCount();
|
|
Toshihiro Shimizu |
890ddd |
for (r = 0; r != rCount; ++r)
|
|
Toshihiro Shimizu |
890ddd |
locals::markEdges(*vi.getRegion(r), sData, false);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Strokes not appearing as region edges must be checked for region inclusion separately
|
|
Toshihiro Shimizu |
890ddd |
UINT s, sCount = vi.getStrokeCount();
|
|
Toshihiro Shimizu |
890ddd |
for (s = 0; s != sCount; ++s) {
|
|
Toshihiro Shimizu |
890ddd |
if (!sData[s].m_hasRegion) {
|
|
Toshihiro Shimizu |
890ddd |
TRegion *parentRegion = vi.getRegion(vi.getStroke(s)->getPoint(0.5));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
if (parentRegion && parentRegion->getStyle())
|
|
Toshihiro Shimizu |
890ddd |
sData[s].m_hasColor = INTERNAL;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
// Output all not internal regions
|
|
Toshihiro Shimizu |
890ddd |
boost_a::copy_if(boost::make_counting_iterator(0u), boost::make_counting_iterator(vi.getStrokeCount()),
|
|
Toshihiro Shimizu |
890ddd |
std::back_inserter(strokes), boost::bind(locals::isBoundary, sData, _1));
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
} // namespace
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*******************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// VectorLevelSelection implementation
|
|
Toshihiro Shimizu |
890ddd |
//*******************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
LevelSelection::LevelSelection()
|
|
Toshihiro Shimizu |
890ddd |
: m_framesMode(FRAMES_NONE), m_filter(EMPTY)
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
bool LevelSelection::isEmpty() const
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
return (m_framesMode == FRAMES_NONE || m_filter == EMPTY);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//---------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
void LevelSelection::selectNone()
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
m_framesMode = FRAMES_NONE;
|
|
Toshihiro Shimizu |
890ddd |
m_filter = EMPTY;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
m_styles.clear();
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//*******************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
// Related standalone functions
|
|
Toshihiro Shimizu |
890ddd |
//*******************************************************************************
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<int> getBoundaryStrokes(TVectorImage &vi)</int>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
std::vector<int> result;</int>
|
|
Toshihiro Shimizu |
890ddd |
getBoundaries(vi, result);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return result;
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
//------------------------------------------------------------------------
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<int> getSelectedStrokes(TVectorImage &vi, const LevelSelection &levelSelection)</int>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
struct locals {
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
static void selectStyles(const TVectorImage &vi, const std::set<int> &styles,</int>
|
|
Toshihiro Shimizu |
890ddd |
std::vector<int> &strokes)</int>
|
|
Toshihiro Shimizu |
890ddd |
{
|
|
Toshihiro Shimizu |
890ddd |
UINT s, sCount = vi.getStrokeCount();
|
|
Toshihiro Shimizu |
890ddd |
for (s = 0; s != sCount; ++s) {
|
|
Toshihiro Shimizu |
890ddd |
if (styles.count(vi.getStroke(s)->getStyle()))
|
|
Toshihiro Shimizu |
890ddd |
strokes.push_back(s);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
}; // locals
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
std::vector<int> strokes;</int>
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
switch (levelSelection.filter()) {
|
|
Toshihiro Shimizu |
890ddd |
case LevelSelection::EMPTY:;
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CASE LevelSelection::WHOLE : strokes.assign(boost::make_counting_iterator(0u),
|
|
Toshihiro Shimizu |
890ddd |
boost::make_counting_iterator(vi.getStrokeCount()));
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CASE LevelSelection::SELECTED_STYLES : locals::selectStyles(vi, levelSelection.styles(), strokes);
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
CASE LevelSelection::BOUNDARY_STROKES : getBoundaries(vi, strokes);
|
|
Toshihiro Shimizu |
890ddd |
}
|
|
Toshihiro Shimizu |
890ddd |
|
|
Toshihiro Shimizu |
890ddd |
return strokes;
|
|
Toshihiro Shimizu |
890ddd |
}
|