Mantid
Loading...
Searching...
No Matches
ConvexPolygon.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
7//-----------------------------------------------------------------------------
8// Includes
9//-----------------------------------------------------------------------------
13#include "MantidKernel/V2D.h"
14#include <algorithm>
15#include <cfloat>
16#include <sstream>
17#include <utility>
18
19namespace Mantid::Geometry {
20
21using Kernel::V2D;
22
23//-----------------------------------------------------------------------------
24// Public member functions
25//-----------------------------------------------------------------------------
29ConvexPolygon::ConvexPolygon() : m_minX(DBL_MAX), m_maxX(-DBL_MAX), m_minY(DBL_MAX), m_maxY(-DBL_MAX), m_vertices() {}
30
34ConvexPolygon::ConvexPolygon(Vertices vertices) : m_vertices(std::move(vertices)) { setup(); }
35
37bool ConvexPolygon::isValid() const { return (npoints() > 2); }
38
41 m_vertices.clear();
42 m_minX = DBL_MAX;
43 m_maxX = -DBL_MAX;
44 m_minY = DBL_MAX;
45 m_maxY = -DBL_MAX;
46}
47
52void ConvexPolygon::insert(const V2D &pt) {
53 m_vertices.emplace_back(pt);
54 // Update extrema
55 m_minX = std::min(m_minX, pt.X());
56 m_maxX = std::max(m_maxX, pt.X());
57 m_minY = std::min(m_minY, pt.Y());
58 m_maxY = std::max(m_maxY, pt.Y());
59}
60
65void ConvexPolygon::insert(double x, double y) { this->insert(V2D(x, y)); }
66
75const V2D &ConvexPolygon::operator[](const size_t index) const { return m_vertices[index]; }
76
83const Kernel::V2D &ConvexPolygon::at(const size_t index) const {
84 if (index < npoints()) {
85 return m_vertices[index];
86 } else {
87 throw Kernel::Exception::IndexError(index, npoints(), "ConvexPolygon::at()");
88 }
89}
90
92size_t ConvexPolygon::npoints() const { return m_vertices.size(); }
93
99bool ConvexPolygon::contains(const Kernel::V2D &point) const {
100 for (size_t i = 0; i < npoints(); ++i) {
101 PolygonEdge edge(m_vertices[i], m_vertices[(i + 1) % npoints()]);
102 if (classify(point, edge) == OnLeft) {
103 return false;
104 }
105 }
106 return true;
107}
108
110
115bool ConvexPolygon::contains(const ConvexPolygon &poly) const {
116 // Basically just have to test if each point is inside us, this could be
117 // slow
118 for (size_t i = 0; i < poly.npoints(); ++i) {
119 if (!this->contains(poly[i]))
120 return false;
121 }
122 return true;
123}
124
132double ConvexPolygon::area() const { return 0.5 * this->determinant(); }
133
141 // Arrange the points in a Nx2 matrix where N = npoints+1
142 // and each row is a vertex point with the last row equal to the first.
143 // Calculate the "determinant". The matrix class needs and NxN matrix
144 // as the correct definition of a determinant only exists for
145 // square matrices. We could fool it by putting extra zeroes but this
146 // would increase the workload for no gain
147
148 // Loop over all and compute the individual elements. We assume
149 // that calling next() on the vertex takes us clockwise within
150 // the polygon.
151 double lhs(0.0), rhs(0.0);
152 for (size_t i = 0; i < npoints(); ++i) {
153 const V2D &v_i = m_vertices[i];
154 const V2D &v_ip1 = m_vertices[(i + 1) % npoints()];
155
156 lhs += v_ip1.X() * v_i.Y();
157 rhs += v_i.X() * v_ip1.Y();
158 }
159 return lhs - rhs;
160}
161
166double ConvexPolygon::minX() const { return m_minX; }
167
172double ConvexPolygon::maxX() const { return m_maxX; }
173
178double ConvexPolygon::minY() const { return m_minY; }
179
184double ConvexPolygon::maxY() const { return m_maxY; }
185
189ConvexPolygon ConvexPolygon::toPoly() const { return *this; }
190
195 m_minX = DBL_MAX;
196 m_maxX = -DBL_MAX;
197 m_minY = DBL_MAX;
198 m_maxY = -DBL_MAX;
199
200 for (const auto &vertex : m_vertices) {
201 double x{vertex.X()}, y{vertex.Y()};
202 m_minX = std::min(m_minX, x);
203 m_maxX = std::max(m_maxX, x);
204 m_minY = std::min(m_minY, y);
205 m_maxY = std::max(m_maxY, y);
206 }
207}
208
216double ConvexPolygon::triangleArea(const V2D &a, const V2D &b, const V2D &c) const {
217 return 0.5 * (b.X() - a.X()) * (c.Y() - a.Y()) - (c.X() - a.X()) * (b.Y() - a.Y());
218}
219
220//-----------------------------------------------------------------------------
221// Non-member non-friend functions
222//-----------------------------------------------------------------------------
230std::ostream &operator<<(std::ostream &os, const ConvexPolygon &polygon) {
231 os << "ConvexPolygon(";
232 const size_t npoints(polygon.npoints());
233 for (size_t i = 0; i < npoints; ++i) {
234 os << polygon[i];
235 if (i < npoints - 1)
236 os << ",";
237 }
238 os << ")";
239 return os;
240}
241
242} // namespace Mantid::Geometry
const std::vector< double > & rhs
std::map< DeltaEMode::Type, std::string > index
Definition: DeltaEMode.cpp:19
An implementation of a convex polygon.
Definition: ConvexPolygon.h:36
double m_minX
Lowest X value.
virtual size_t npoints() const
Return the number of vertices.
virtual const Kernel::V2D & operator[](const size_t index) const
Index access.
double m_maxY
Highest Y value.
ConvexPolygon()
Default constructor.
void insert(const Kernel::V2D &pt)
Insert a new vertex.
double m_minY
Lowest Y value.
virtual double area() const
Compute the area of the polygon using triangulation.
void clear()
Clears all points.
void setup()
Setup the meta-data.
bool isValid() const
Check if polygon is valid.
double m_maxX
Highest X value.
virtual bool contains(const Kernel::V2D &point) const
Is a point inside this polygon.
virtual double minY() const
Return the lowest Y value in the polygon.
virtual double determinant() const
Compute the 'determinant' of the points.
virtual double maxY() const
Return the largest Y value in the polygon.
std::vector< Kernel::V2D > Vertices
Type of the point list.
Definition: ConvexPolygon.h:40
virtual double maxX() const
Return the largest X value in the polygon.
virtual double minX() const
Return the lowest X value in the polygon.
double triangleArea(const Kernel::V2D &a, const Kernel::V2D &b, const Kernel::V2D &c) const
Compute the area of a triangle given by 3 points.
virtual ConvexPolygon toPoly() const
Return a new Polygon based on the current type.
virtual const Kernel::V2D & at(const size_t index) const
Bounds-checked index access.
PolygonEdge Defines a directed edge between two points on a polygon.
Definition: PolygonEdge.h:23
Exception for index errors.
Definition: Exception.h:284
Implements a 2-dimensional vector embedded in a 3D space, i.e.
Definition: V2D.h:29
double Y() const
Y position.
Definition: V2D.h:49
double X() const
X position.
Definition: V2D.h:44
MANTID_GEOMETRY_DLL PointClassification classify(const Kernel::V2D &pt, const PolygonEdge &edge)
Helper function for classification.
Definition: PolygonEdge.cpp:47
MANTID_GEOMETRY_DLL std::ostream & operator<<(std::ostream &stream, const PointGroup &self)
Returns a streamed representation of the PointGroup object.
Definition: PointGroup.cpp:312
@ OnLeft
Point is to left of edge.
Definition: PolygonEdge.h:59
STL namespace.