187 lines
4.9 KiB
C++
187 lines
4.9 KiB
C++
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
|
|
// License: Boost Software License See LICENSE.txt for the full license.
|
|
#ifndef DLIB_BORDER_EnUMERATOR_H_
|
|
#define DLIB_BORDER_EnUMERATOR_H_
|
|
|
|
#include "border_enumerator_abstract.h"
|
|
#include "rectangle.h"
|
|
|
|
namespace dlib
|
|
{
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
class border_enumerator
|
|
{
|
|
public:
|
|
border_enumerator(
|
|
)
|
|
{
|
|
reset();
|
|
}
|
|
|
|
border_enumerator(
|
|
const rectangle& rect_,
|
|
unsigned long border_size
|
|
) :
|
|
rect(rect_),
|
|
inner_rect(shrink_rect(rect_, border_size))
|
|
{
|
|
reset();
|
|
}
|
|
|
|
border_enumerator(
|
|
const rectangle& rect_,
|
|
const rectangle& non_border_region
|
|
) :
|
|
rect(rect_),
|
|
inner_rect(non_border_region.intersect(rect))
|
|
{
|
|
reset();
|
|
}
|
|
|
|
void reset (
|
|
)
|
|
{
|
|
// make the four rectangles that surround inner_rect and intersect them
|
|
// with rect.
|
|
bleft = rect.intersect(rectangle(std::numeric_limits<long>::min(),
|
|
std::numeric_limits<long>::min(),
|
|
inner_rect.left()-1,
|
|
std::numeric_limits<long>::max()));
|
|
|
|
bright = rect.intersect(rectangle(inner_rect.right()+1,
|
|
std::numeric_limits<long>::min(),
|
|
std::numeric_limits<long>::max(),
|
|
std::numeric_limits<long>::max()));
|
|
|
|
btop = rect.intersect(rectangle(inner_rect.left(),
|
|
std::numeric_limits<long>::min(),
|
|
inner_rect.right(),
|
|
inner_rect.top()-1));
|
|
|
|
bbottom = rect.intersect(rectangle(inner_rect.left(),
|
|
inner_rect.bottom()+1,
|
|
inner_rect.right(),
|
|
std::numeric_limits<long>::max()));
|
|
|
|
p = bleft.tl_corner();
|
|
p.x() -= 1;
|
|
|
|
mode = atleft;
|
|
}
|
|
|
|
bool at_start (
|
|
) const
|
|
{
|
|
point temp = bleft.tl_corner();
|
|
temp.x() -=1;
|
|
return temp == p;
|
|
}
|
|
|
|
bool current_element_valid(
|
|
) const
|
|
{
|
|
return rect.contains(p);
|
|
}
|
|
|
|
bool move_next()
|
|
{
|
|
if (mode == atleft)
|
|
{
|
|
if (advance_point(bleft, p))
|
|
return true;
|
|
|
|
mode = attop;
|
|
p = btop.tl_corner();
|
|
p.x() -= 1;
|
|
}
|
|
if (mode == attop)
|
|
{
|
|
if (advance_point(btop, p))
|
|
return true;
|
|
|
|
mode = atright;
|
|
p = bright.tl_corner();
|
|
p.x() -= 1;
|
|
}
|
|
if (mode == atright)
|
|
{
|
|
if (advance_point(bright, p))
|
|
return true;
|
|
|
|
mode = atbottom;
|
|
p = bbottom.tl_corner();
|
|
p.x() -= 1;
|
|
}
|
|
|
|
if (advance_point(bbottom, p))
|
|
return true;
|
|
|
|
// put p outside rect since there are no more points to enumerate
|
|
p = rect.br_corner();
|
|
p.x() += 1;
|
|
|
|
return false;
|
|
}
|
|
|
|
size_t size (
|
|
) const
|
|
{
|
|
return rect.area() - inner_rect.area();
|
|
}
|
|
|
|
const point& element (
|
|
) const
|
|
{
|
|
// make sure requires clause is not broken
|
|
DLIB_ASSERT(current_element_valid(),
|
|
"\t point border_enumerator::element()"
|
|
<< "\n\t This function can't be called unless the element is valid."
|
|
<< "\n\t this: " << this
|
|
);
|
|
|
|
return p;
|
|
}
|
|
|
|
private:
|
|
|
|
bool advance_point (
|
|
const rectangle& r,
|
|
point& p
|
|
) const
|
|
{
|
|
p.x() += 1;
|
|
if (p.x() > r.right())
|
|
{
|
|
p.x() = r.left();
|
|
p.y() += 1;
|
|
}
|
|
|
|
return r.contains(p);
|
|
}
|
|
|
|
point p;
|
|
rectangle rect;
|
|
rectangle inner_rect; // the non-border regions of rect
|
|
|
|
enum emode
|
|
{
|
|
atleft,
|
|
atright,
|
|
atbottom,
|
|
attop
|
|
};
|
|
|
|
emode mode;
|
|
|
|
rectangle btop, bleft, bright, bbottom;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------------------
|
|
|
|
}
|
|
|
|
#endif // DLIB_BORDER_EnUMERATOR_H_
|
|
|