Limbo
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Limbo.Geometry

Table of Contents

Introduction

Geometry package provides API to adapt various geometry data structures such as Boost.Polygon and Boost.Geometry and various specialized geomtric algorithms such as computing area of polygons, conversion of rectilinear polygon to rectangles, etc. It is developed in a generic way to be flexible to different data types either in STL or Boost.

Examples

Custom Geometric Classes

Define custom classes for points and rectangles and use Polygon2Rectangle to convert polygon to rectangles.

See documented version: test/geometry/test_p2r.cpp

#include <iostream>
#include <vector>
#include <list>
#include <set>
using std::cout;
using std::endl;
using std::vector;
using std::list;
using std::set;
using namespace limbo::geometry;
struct Point
{
typedef int value_type;
value_type m_x;
value_type m_y;
value_type const& x() const {return m_x;}
value_type const& y() const {return m_y;}
void x(value_type v) {m_x = v;}
void y(value_type v) {m_y = v;}
//bool operator==(Point const& rhs) {return x() == rhs.x() && y() == rhs.y();}
};
namespace limbo { namespace geometry {
template <>
{
typedef Point point_type;
typedef int coordinate_type;
static coordinate_type get(const point_type& point, orientation_2d orient)
{
if (orient == HORIZONTAL) return point.x();
else if (orient == VERTICAL) return point.y();
else assert(0);
}
static void set(point_type& point, orientation_2d orient, coordinate_type value)
{
if (orient == HORIZONTAL) return point.x(value);
else if (orient == VERTICAL) return point.y(value);
else assert(0);
}
static point_type construct(coordinate_type x, coordinate_type y)
{
point_type p;
p.x(x); p.y(y);
return p;
}
};
}}
struct Rectangle
{
typedef int value_type;
value_type m_xl;
value_type m_yl;
value_type m_xh;
value_type m_yh;
value_type const& xl() const {return m_xl;}
value_type const& yl() const {return m_yl;}
value_type const& xh() const {return m_xh;}
value_type const& yh() const {return m_yh;}
void xl(value_type v) {m_xl = v;}
void yl(value_type v) {m_yl = v;}
void xh(value_type v) {m_xh = v;}
void yh(value_type v) {m_yh = v;}
};
namespace limbo { namespace geometry {
template <>
{
typedef Rectangle rectangle_type;
typedef int coordinate_type;
static coordinate_type get(const rectangle_type& rect, direction_2d dir)
{
switch (dir)
{
case LEFT: return rect.xl();
case BOTTOM: return rect.yl();
case RIGHT: return rect.xh();
case TOP: return rect.yh();
default: assert(0);
}
}
static void set(rectangle_type& rect, direction_2d dir, coordinate_type value)
{
switch (dir)
{
case LEFT: rect.xl(value); break;
case BOTTOM: rect.yl(value); break;
case RIGHT: rect.xh(value); break;
case TOP: rect.yh(value); break;
default: assert(0);
}
}
static rectangle_type construct(coordinate_type xl, coordinate_type yl, coordinate_type xh, coordinate_type yh)
{
rectangle_type rect;
rect.xl(xl); rect.yl(yl);
rect.xh(xh); rect.yh(yh);
return rect;
}
};
}}
void test1(string const& filename)
{
vector<Rectangle> vRect;
Polygon2Rectangle<vector<Point>, vector<Rectangle> > p2r (vRect, HOR_VER_SLICING);
assert(p2r.read(filename));
assert(p2r());
p2r.print("p2r1.gp");
}
void test2(string const& filename)
{
vector<Rectangle> vRect;
Polygon2Rectangle<list<Point>, vector<Rectangle> > p2r (vRect, HOR_VER_SLICING);
assert(p2r.read(filename));
assert(p2r());
p2r.print("p2r2.gp");
}
void test3(string const& filename)
{
vector<Rectangle> vRect;
assert(p2r.read(filename));
assert(p2r());
p2r.print("p2r3.gp");
}
int main(int argc, char** argv)
{
if (argc > 1)
{
test1(argv[1]);
test2(argv[1]);
test3(argv[1]);
}
else cout << "at least 1 argument is required" << endl;
return 0;
}

Compiling and running commands (assuming LIMBO_DIR is valid and limbo library has been properly installed)

1 g++ -o test_p2r test_p2r.cpp -I $LIMBO_DIR/include
2 ./test_p2r benchmarks/polygon1.gp

Output drawn with gnuplot

polygon1.png
original polygon
p2r1.png
test 1 solution
p2r2.png
test 2 solution
p2r3.png
test 3 solution

Boost.Polygon API

Use point and rectangle types in Boost.Polygon.

See documented version: test/geometry/test_boostpolygonapi.cpp

#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <set>
#include <boost/polygon/polygon.hpp>
using std::cout;
using std::endl;
using std::string;
using std::vector;
using std::list;
using std::set;
namespace gtl = boost::polygon;
namespace lg = limbo::geometry;
void test1(string const& filename)
{
std::vector<gtl::rectangle_data<int> > vRect;
lg::Polygon2Rectangle<vector<gtl::point_data<int> >, vector<gtl::rectangle_data<int> > > p2r (vRect, lg::HOR_VER_SLICING);
assert(p2r.read(filename));
assert(p2r());
p2r.print("p2r1.gp");
}
void test2(string const& filename)
{
std::vector<gtl::rectangle_data<int> > vRect;
lg::Polygon2Rectangle<list<gtl::point_data<int> >, vector<gtl::rectangle_data<int> > > p2r (vRect, lg::HOR_VER_SLICING);
assert(p2r.read(filename));
assert(p2r());
p2r.print("p2r2.gp");
}
void test3(string const& filename)
{
std::vector<gtl::rectangle_data<int> > vRect;
assert(p2r.read(filename));
assert(p2r());
p2r.print("p2r3.gp");
}
void test4()
{
vector<gtl::point_data<int> > vPoint (8);
vPoint[0] = gtl::construct<gtl::point_data<int> >(0, 0);
vPoint[1] = gtl::construct<gtl::point_data<int> >(0, 10);
vPoint[2] = gtl::construct<gtl::point_data<int> >(10, 10);
vPoint[3] = gtl::construct<gtl::point_data<int> >(10, 20);
vPoint[4] = gtl::construct<gtl::point_data<int> >(20, 20);
vPoint[5] = gtl::construct<gtl::point_data<int> >(20, 10);
vPoint[6] = gtl::construct<gtl::point_data<int> >(30, 10);
vPoint[7] = gtl::construct<gtl::point_data<int> >(30, 0);
//vPoint.push_back(gtl::construct<gtl::point_data<int> >(0, 0));
vector<gtl::rectangle_data<int> > vRectangle;
assert(lg::polygon2RectangleBoost(vPoint, vRectangle));
for (std::size_t i = 0; i != vRectangle.size(); ++i)
{
gtl::rectangle_data<int> const& rect = vRectangle[i];
cout << "(" << gtl::xl(rect) << ", " << gtl::yl(rect) << ", " << gtl::xh(rect) << ", " << gtl::yh(rect) << ")\n";
}
cout << "test 4 passed\n";
}
int main(int argc, char** argv)
{
test4();
if (argc > 1)
{
test1(argv[1]);
test2(argv[1]);
test3(argv[1]);
}
else cout << "at least 1 argument is required" << endl;
return 0;
}

Compiling and running commands (assuming LIMBO_DIR is valid and limbo library has been properly installed)

1 g++ -o test_boostpolygonapi test_boostpolygonapi.cpp -I $LIMBO_DIR/include -I $BOOST_DIR/include
2 ./test_boostpolygonapi benchmarks/polygon2.gp

Output drawn with gnuplot

polygon2.png
original polygon
p2rboost1.png
test 1 solution
p2rboost2.png
test 2 solution
p2rboost3.png
test 3 solution

All Examples

Possible dependencies: Boost.

References