Skip to content

Commit

Permalink
Add an iterator class to the ConvexPolygon
Browse files Browse the repository at this point in the history
This is just a simple forward iterator that doesn't implement the full
iterator interface.
Refs #12584
  • Loading branch information
martyngigg committed Jun 23, 2015
1 parent bce83dd commit e7eec18
Show file tree
Hide file tree
Showing 5 changed files with 188 additions and 11 deletions.
2 changes: 2 additions & 0 deletions Code/Mantid/Framework/Geometry/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ set ( SRC_FILES
src/Math/Algebra.cpp
src/Math/BnId.cpp
src/Math/ConvexPolygon.cpp
src/Math/ConvexPolygonIterator.cpp
src/Math/LaszloIntersection.cpp
src/Math/PolyBase.cpp
src/Math/PolygonEdge.cpp
Expand Down Expand Up @@ -256,6 +257,7 @@ set ( TEST_FILES
ConeTest.h
ConventionalCellTest.h
ConvexPolygonTest.h
ConvexPolygonIteratorTest.h
CrystalStructureTest.h
CyclicGroupTest.h
CylinderTest.h
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ class V2D;
}

namespace Geometry {
//---------------------------------------------------------------------------
// Forward declarations
//---------------------------------------------------------------------------
class PolygonEdge;

//---------------------------------------------------------------------------
// Typedefs
Expand Down Expand Up @@ -62,6 +66,33 @@ class MANTID_GEOMETRY_DLL ConvexPolygon {
/// Type of the point list
typedef std::vector<Kernel::V2D> Vertices;

//-----------------------------------------------------------------
// Forward directional iterator inner class
//-----------------------------------------------------------------
class Iterator {
public:
/// Constructor
Iterator(const ConvexPolygon &polygon);

/// Dereference operator
const Kernel::V2D &operator*() const;
/// Prefix increment operator
void operator++();
/// Create a directed edge between this and the next point
PolygonEdge edge() const;

private:
/// Compute the next index
size_t nextIndex() const;

const ConvexPolygon &m_polygon;
size_t m_index;
};

//-----------------------------------------------------------------
// ConvexPolygon class
//-----------------------------------------------------------------

/// Default constructor
ConvexPolygon();
/// Construct a polygon from a collection of points
Expand Down
55 changes: 55 additions & 0 deletions Code/Mantid/Framework/Geometry/src/Math/ConvexPolygonIterator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
//-----------------------------------------------------------------------------
// Includes
//-----------------------------------------------------------------------------
#include "MantidGeometry/Math/ConvexPolygon.h"
#include "MantidGeometry/Math/PolygonEdge.h"
#include "MantidKernel/Exception.h"

namespace Mantid {
namespace Geometry {

//-----------------------------------------------------------------------------
// Public member functions
//-----------------------------------------------------------------------------
/**
* @param polygon A reference to the initializing polygon
*/
ConvexPolygon::Iterator::Iterator(const ConvexPolygon &polygon)
: m_polygon(polygon), m_index(0) {
if (!polygon.isValid()) {
throw std::invalid_argument("Cannot create iterator for invalid polygon.");
}
}

/**
* @return Dereference the iterator and return the current value
*/
const Kernel::V2D &ConvexPolygon::Iterator::operator*() const {
return m_polygon[m_index];
}

/**
* Advance the iterator to the next point. When the iterator points to the
* last point the next increment will take it back to the "first" point.
*/
void ConvexPolygon::Iterator::operator++() {
m_index = nextIndex();
}

/**
* @return A PolygonEdge defining the edge with the current point and the next
*/
PolygonEdge ConvexPolygon::Iterator::edge() const {
return PolygonEdge(**this, m_polygon[nextIndex()]);
}

//-----------------------------------------------------------------------------
// Private member functions
//-----------------------------------------------------------------------------
/// @return The next index, taking into account cycling back after npoints()
size_t ConvexPolygon::Iterator::nextIndex() const {
return (m_index + 1) % m_polygon.npoints();
}

} // namespace Geometry
} // namespace Mantid
89 changes: 89 additions & 0 deletions Code/Mantid/Framework/Geometry/test/ConvexPolygonIteratorTest.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#ifndef MANTID_GEOMETRY_POLYGONPOINTITERATORTEST_H_
#define MANTID_GEOMETRY_POLYGONPOINTITERATORTEST_H_

#include <cxxtest/TestSuite.h>

#include "MantidGeometry/Math/ConvexPolygon.h"
#include "MantidGeometry/Math/PolygonEdge.h"
#include "MantidKernel/V2D.h"

using Mantid::Geometry::ConvexPolygon;
using Mantid::Kernel::V2D;

class ConvexPolygonIteratorTest : public CxxTest::TestSuite {
public:
// This pair of boilerplate methods prevent the suite being created statically
// This means the constructor isn't called when running other tests
static ConvexPolygonIteratorTest *createSuite() {
return new ConvexPolygonIteratorTest();
}
static void destroySuite(ConvexPolygonIteratorTest *suite) { delete suite; }

// --------------------- Success cases --------------------------------------

void test_Iterator_Initially_Points_At_Index_Zero() {
auto poly = makeRectangle();
ConvexPolygon::Iterator iter(poly);
TS_ASSERT_EQUALS(V2D(), *iter);
}

void test_Increment_Moves_On_One_Point() {
auto poly = makeRectangle();
ConvexPolygon::Iterator iter(poly);
++iter;
TS_ASSERT_EQUALS(V2D(0.0, 1.0), *iter);
}

void test_Incrementing_By_Number_Of_Points_Produces_First_Point() {
auto poly = makeRectangle();
ConvexPolygon::Iterator iter(poly);
for (size_t i = 0; i < poly.npoints(); ++i) {
++iter;
}
TS_ASSERT_EQUALS(V2D(), *iter);
}

void test_edge_points_from_current_to_next() {
auto poly = makeRectangle();
ConvexPolygon::Iterator iter(poly);
auto p01 = iter.edge();
TS_ASSERT_EQUALS(V2D(), p01.start());
TS_ASSERT_EQUALS(V2D(0.0,1.0), p01.end());

++iter;
auto p12 = iter.edge();
TS_ASSERT_EQUALS(V2D(0.0,1.0), p12.start());
TS_ASSERT_EQUALS(V2D(2.0,1.0), p12.end());

// Check final has first as end point
++iter;
++iter;
auto p40 = iter.edge();
TS_ASSERT_EQUALS(V2D(2.0,0.0), p40.start());
TS_ASSERT_EQUALS(V2D(), p40.end());
}

// --------------------- Failure cases --------------------------------------

void test_Invalid_Polygon_Theows_Error_On_Construction() {
ConvexPolygon invalid;
// TS_ASSERT_THROWS cannot be used if there is no default constructor
// so use a pointer instead
ConvexPolygon::Iterator *iter(NULL);
TS_ASSERT_THROWS(iter = new ConvexPolygon::Iterator(invalid),
std::invalid_argument);
delete iter;
}

private:
ConvexPolygon makeRectangle() {
ConvexPolygon rectangle;
rectangle.insert(0.0, 0.0);
rectangle.insert(0.0, 1.0);
rectangle.insert(2.0, 1.0);
rectangle.insert(2.0, 0.0);
return rectangle;
}
};

#endif /* MANTID_GEOMETRY_POLYGONPOINTITERATORTEST_H_ */
22 changes: 11 additions & 11 deletions Code/Mantid/Framework/Geometry/test/ConvexPolygonTest.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@
#define CONVEXPOLYGONTEST_H_

#include "MantidGeometry/Math/ConvexPolygon.h"
#include "MantidGeometry/Math/Vertex2D.h"
#include "MantidKernel/Exception.h"
#include "MantidKernel/V2D.h"
#include <cxxtest/TestSuite.h>
#include <cmath>
#include <cfloat>

using Mantid::Kernel::V2D;
using Mantid::Geometry::ConvexPolygon;
using Mantid::Geometry::Vertex2D;
using Mantid::Geometry::PolygonEdge;

class ConvexPolygonTest : public CxxTest::TestSuite
{
Expand Down Expand Up @@ -51,14 +49,6 @@ class ConvexPolygonTest : public CxxTest::TestSuite
TS_ASSERT_EQUALS(rect[3], V2D(2.0, 0.0));
}

void test_Invalid_Index_Access_Throws()
{
using Mantid::Kernel::Exception::IndexError;
ConvexPolygon triangle = makeEquilateralTriangle();
TS_ASSERT_THROWS(triangle[3], IndexError);
TS_ASSERT_THROWS(triangle[-1], IndexError);
}

void test_Point_Inside_Polygon_Returns_True()
{
ConvexPolygon poly = makeRectangle();
Expand Down Expand Up @@ -117,6 +107,16 @@ class ConvexPolygonTest : public CxxTest::TestSuite
TS_ASSERT_EQUALS(largeTriangle.contains(smallTriangle), true);
TS_ASSERT_EQUALS(smallTriangle.contains(largeTriangle), false);
}

// ------------------------ Failure cases --------------------------------

void test_Invalid_Index_Access_Throws()
{
using Mantid::Kernel::Exception::IndexError;
ConvexPolygon triangle = makeEquilateralTriangle();
TS_ASSERT_THROWS(triangle[3], IndexError);
TS_ASSERT_THROWS(triangle[-1], IndexError);
}

private:
/// Side length 2
Expand Down

0 comments on commit e7eec18

Please sign in to comment.