Commit b5ce5e49 authored by Davis King's avatar Davis King

Added an object to help iterate over the border elements of a rectangle.

parent 7e7612eb
......@@ -5,6 +5,7 @@
#include "geometry/rectangle.h"
#include "geometry/vector.h"
#include "geometry/border_enumerator.h"
#endif // DLIB_GEOMETRy_HEADER
......
// 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(
)
{
}
border_enumerator(
const rectangle& rect_,
unsigned long border_size
) :
rect(rect_),
inner_rect(shrink_rect(rect_, border_size))
{
reset();
}
void reset (
)
{
p = rect.tl_corner();
p.x() -= 1;
}
bool at_start (
) const
{
point temp = rect.tl_corner();
temp.x() -=1;
return temp == p;
}
bool current_element_valid(
) const
{
return rect.contains(p) && !inner_rect.contains(p);
}
bool move_next()
{
p.x() += 1;
if (p.x() > rect.right())
{
p.y() += 1;
p.x() = rect.left();
}
else if (inner_rect.contains(p))
{
p.x() = inner_rect.right()+1;
}
return current_element_valid();
}
unsigned long 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:
point p;
rectangle rect;
rectangle inner_rect; // the non-border regions of rect
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BORDER_EnUMERATOR_H_
// Copyright (C) 2011 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#undef DLIB_BORDER_EnUMERATOR_ABSTRACT_H_
#ifdef DLIB_BORDER_EnUMERATOR_ABSTRACT_H_
#include "rectangle.h"
namespace dlib
{
// ----------------------------------------------------------------------------------------
class border_enumerator
{
/*!
POINTERS AND REFERENCES TO INTERNAL DATA
All operations on this object other than calling element() invalidate
pointers and references to internal data.
WHAT THIS OBJECT REPRESENTS
This object is an enumerator over the border points of a rectangle.
!*/
public:
border_enumerator(
);
/*!
ensures
- #move_next() == false
(i.e. this object is "empty" and won't enumerate anything)
- current_element_valid() == false
- at_start() == true
- size() == 0
!*/
border_enumerator(
const rectangle& rect,
unsigned long border_size
);
/*!
ensures
- This object will enumerate over the border points which are inside rect
but within border_size of the edge. For example, if border_size == 1
then it enumerates over the single point wide strip of points all around
the interior edge of rect.
- current_element_valid() == false
- at_start() == true
- size() == rect.area() - shrink_rect(rect,border_size).area()
(i.e. the number of points in the border area of rect)
!*/
bool at_start (
) const;
/*!
ensures
- returns true if *this represents one position before the first point
(this would also make the current element invalid) else returns false
!*/
void reset (
);
/*!
ensures
- #current_element_valid() == false
- #at_start() == true
!*/
bool current_element_valid(
) const;
/*!
ensures
- returns true if we are currently at a valid element else
returns false
!*/
bool move_next(
);
/*!
ensures
- moves to the next element. i.e. #element() will now
return the next border point.
- the return value will be equal to #current_element_valid()
- #at_start() == false
- returns true if there is another element
- returns false if there are no more elements in the container
!*/
unsigned long size (
) const;
/*!
ensures
- returns the number of border points
!*/
const point& element (
) const;
/*!
requires
- current_element_valid() == true
ensures
- returns the current border point
!*/
};
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_BORDER_EnUMERATOR_ABSTRACT_H_
......@@ -10,6 +10,8 @@
#include <dlib/string.h>
#include <dlib/matrix.h>
#include <dlib/rand.h>
#include <dlib/array2d.h>
#include <dlib/image_transforms.h>
#include "tester.h"
......@@ -366,10 +368,168 @@ namespace
}
// ----------------------------------------------------------------------------------------
void test_border_enumerator()
{
border_enumerator be;
DLIB_TEST(be.at_start() == true);
DLIB_TEST(be.size() == 0);
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(be.move_next() == false);
DLIB_TEST(be.at_start() == false);
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(be.move_next() == false);
DLIB_TEST(be.at_start() == false);
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(be.size() == 0);
be = border_enumerator(rectangle(4,4,4,4),1);
DLIB_TEST(be.at_start() == true);
DLIB_TEST(be.size() == 1);
be = border_enumerator(rectangle(4,4,4,4),3);
DLIB_TEST(be.at_start() == true);
DLIB_TEST(be.size() == 1);
be = border_enumerator(rectangle(4,4,4,4),0);
DLIB_TEST(be.at_start() == true);
DLIB_TEST(be.size() == 0);
be = border_enumerator(rectangle(4,4,5,5),0);
DLIB_TEST(be.at_start() == true);
DLIB_TEST(be.size() == 0);
be = border_enumerator(rectangle(4,4,5,5),1);
DLIB_TEST(be.at_start() == true);
DLIB_TEST(be.size() == 4);
be = border_enumerator(rectangle(4,4,5,5),2);
DLIB_TEST(be.size() == 4);
be = border_enumerator(rectangle(4,4,6,6),1);
DLIB_TEST(be.size() == 8);
be = border_enumerator(rectangle(4,4,6,6),2);
DLIB_TEST(be.size() == 9);
be = border_enumerator(rectangle(4,4,6,6),3);
DLIB_TEST(be.size() == 9);
DLIB_TEST(be.at_start() == true);
array2d<unsigned char> img, img2;
for (int size = 1; size < 10; ++size)
{
for (int bs = 0; bs < 4; ++bs)
{
img.set_size(size,size);
img2.set_size(size,size);
assign_all_pixels(img, 1);
assign_all_pixels(img2, 1);
zero_border_pixels(img2, bs,bs);
be = border_enumerator(get_rect(img),bs);
DLIB_TEST(be.at_start() == true);
DLIB_TEST(be.current_element_valid() == false);
while (be.move_next())
{
DLIB_TEST(be.at_start() == false);
DLIB_TEST(be.current_element_valid() == true);
DLIB_TEST_MSG(get_rect(img).contains(be.element()) == true,
get_rect(img) << " " << be.element()
);
const point p = be.element();
img[p.y()][p.x()] = 0;
}
DLIB_TEST(be.at_start() == false);
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(be.move_next() == false);
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(be.move_next() == false);
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(be.at_start() == false);
DLIB_TEST(array_to_matrix(img) == array_to_matrix(img2));
}
}
for (int size = 1; size < 10; ++size)
{
for (int bs = 0; bs < 4; ++bs)
{
img.set_size(size,size+5);
img2.set_size(size,size+5);
assign_all_pixels(img, 1);
assign_all_pixels(img2, 1);
zero_border_pixels(img2, bs,bs);
const point shift(4,5);
be = border_enumerator(translate_rect(get_rect(img),shift),bs);
DLIB_TEST(be.at_start() == false);
DLIB_TEST(be.current_element_valid() == false);
while (be.move_next())
{
DLIB_TEST(be.current_element_valid() == true);
DLIB_TEST(be.at_start() == false);
DLIB_TEST_MSG(get_rect(img).contains(be.element()-shift) == true,
get_rect(img) << " " << be.element()
);
const point p = be.element()-shift;
img[p.y()][p.x()] = 0;
}
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(be.move_next() == false);
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(be.move_next() == false);
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(be.at_start() == false);
DLIB_TEST(array_to_matrix(img) == array_to_matrix(img2));
}
}
for (int size = 1; size < 10; ++size)
{
for (int bs = 0; bs < 4; ++bs)
{
img.set_size(size+2,size);
img2.set_size(size+2,size);
assign_all_pixels(img, 1);
assign_all_pixels(img2, 1);
zero_border_pixels(img2, bs,bs);
const point shift(-4,5);
be = border_enumerator(translate_rect(get_rect(img),shift),bs);
DLIB_TEST(be.current_element_valid() == false);
while (be.move_next())
{
DLIB_TEST(be.current_element_valid() == true);
DLIB_TEST_MSG(get_rect(img).contains(be.element()-shift) == true,
get_rect(img) << " " << be.element()
);
const point p = be.element()-shift;
img[p.y()][p.x()] = 0;
}
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(be.move_next() == false);
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(be.move_next() == false);
DLIB_TEST(be.current_element_valid() == false);
DLIB_TEST(array_to_matrix(img) == array_to_matrix(img2));
}
}
}
// ----------------------------------------------------------------------------------------
class geometry_tester : public tester
{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment