lsst.afw gf03f0b42f3+45adbcf3d0
Loading...
Searching...
No Matches
Polygon.cc
Go to the documentation of this file.
1#include <cmath>
2#include <algorithm>
3
4#include "boost/geometry/geometry.hpp"
5#include <boost/container_hash/hash.hpp>
6#include <memory>
7
9#include "lsst/geom/Extent.h"
11
16
20using BoostPolygon = boost::geometry::model::polygon<LsstPoint>;
21using BoostBox = boost::geometry::model::box<LsstPoint>;
22using BoostLineString = boost::geometry::model::linestring<LsstPoint>;
23
24namespace boost {
25namespace geometry {
26namespace traits {
27
28// Setting up LsstPoint
29template <>
30struct tag<LsstPoint> {
31 using type = point_tag;
32};
33template <>
34struct coordinate_type<LsstPoint> {
36};
37template <>
38struct coordinate_system<LsstPoint> {
39 using type = cs::cartesian;
40};
41template <>
42struct dimension<LsstPoint> : boost::mpl::int_<2> {};
43template <std::size_t dim>
44struct access<LsstPoint, dim> {
45 static double get(LsstPoint const& p) { return p[dim]; }
46 static void set(LsstPoint& p, LsstPoint::Element const& value) { p[dim] = value; }
47};
48
49// Setting up LsstBox
50//
51// No setters, because it's inefficient (can't set individual elements of lsst::geom::Box2D directly).
52// For box outputs from boost::geometry we'll use BoostBox and then convert.
53template <>
54struct tag<LsstBox> {
55 using type = box_tag;
56};
57template <>
58struct point_type<LsstBox> {
59 using type = LsstPoint;
60};
61template <>
62struct indexed_access<LsstBox, 0, 0> {
63 static double get(LsstBox const& box) { return box.getMinX(); }
64};
65template <>
66struct indexed_access<LsstBox, 1, 0> {
67 static double get(LsstBox const& box) { return box.getMaxX(); }
68};
69template <>
70struct indexed_access<LsstBox, 0, 1> {
71 static double get(LsstBox const& box) { return box.getMinY(); }
72};
73template <>
74struct indexed_access<LsstBox, 1, 1> {
75 static double get(LsstBox const& box) { return box.getMaxY(); }
76};
77
78// Setting up LsstRing
79template <>
80struct tag<LsstRing> {
81 using type = ring_tag;
82};
83// template<> struct range_value<LsstRing> { typedef LsstPoint type; };
84} // namespace traits
85} // namespace geometry
86} // namespace boost
87
88namespace {
89
91LsstBox boostBoxToLsst(BoostBox const& box) { return LsstBox(box.min_corner(), box.max_corner()); }
92
94std::vector<LsstPoint> boxToCorners(LsstBox const& box) {
96 corners.reserve(4);
97 corners.push_back(box.getMin());
98 corners.emplace_back(box.getMaxX(), box.getMinY());
99 corners.push_back(box.getMax());
100 corners.emplace_back(box.getMinX(), box.getMaxY());
101 return corners;
102}
103
109void addSubSampledEdge(std::vector<LsstPoint>& vertices, // Vector of points to which to add
110 LsstPoint const& first, // First vertex defining edge
111 LsstPoint const& second, // Second vertex defining edge
112 size_t const num // Number of parts to divide edge into
113) {
114 lsst::geom::Extent2D const delta = (second - first) / num;
115 vertices.push_back(first);
116 for (size_t i = 1; i < num; ++i) {
117 vertices.push_back(first + delta * i);
118 }
119}
120
122double pixelOverlap(BoostPolygon const& poly, int const x, int const y) {
123 std::vector<BoostPolygon> overlap; // Overlap between pixel and polygon
124 LsstBox const pixel(lsst::geom::Point2D(static_cast<double>(x) - 0.5, static_cast<double>(y) - 0.5),
125 lsst::geom::Point2D(static_cast<double>(x) + 0.5, static_cast<double>(y) + 0.5));
126 // Note that the output of boost::geometry::intersection depends
127 // on values down to the precision limit, so minor variations
128 // in poly input can lead to surprisingly large variations in the
129 // output overlap regions and area computation.
130 boost::geometry::intersection(poly, pixel, overlap);
131 double area = 0.0;
132 for (auto const &i : overlap) {
133 double const polyArea = boost::geometry::area(i);
134 area += std::min(polyArea, 1.0); // remove any rounding error
135 }
136 return area;
137}
138
140void pixelRowOverlap(std::shared_ptr<lsst::afw::image::Image<float>> const image, BoostPolygon const& poly,
141 int const xStart, int const xStop, int const y) {
142 int x = xStart;
143 for (lsst::afw::image::Image<float>::x_iterator i = image->x_at(x - image->getX0(), y - image->getY0());
144 x <= xStop; ++i, ++x) {
145 *i = pixelOverlap(poly, x, y);
146 }
147}
148
149} // anonymous namespace
150
151namespace lsst {
152namespace afw {
153
154template std::shared_ptr<geom::polygon::Polygon> table::io::PersistableFacade<
155 geom::polygon::Polygon>::dynamicCast(std::shared_ptr<table::io::Persistable> const&);
156
157namespace geom {
158namespace polygon {
159
162 os << "[";
163 size_t num = vertices.size();
164 for (size_t i = 0; i < num - 1; ++i) {
165 os << vertices[i] << ",";
166 }
167 os << vertices[vertices.size() - 1] << "]";
168 return os;
169}
170
173 return os << "BoostPolygon(" << poly.outer() << ")";
174}
175
177 os << poly.toString();
178 return os;
179}
180
182 Impl() : poly() {}
183 explicit Impl(Polygon::Box const& box) : poly() {
184 boost::geometry::assign(poly, box);
185 // Assignment from a box is correctly handled by BoostPolygon, so doesn't need a "check()"
186 }
187 explicit Impl(std::vector<LsstPoint> const& vertices) : poly() {
188 boost::geometry::assign(poly, vertices);
189 check(); // because the vertices might not have the correct orientation (CW vs CCW) or be open
190 }
191 explicit Impl(BoostPolygon const& _poly) : poly(_poly) {}
192
193 void check() { boost::geometry::correct(poly); }
194
197 std::vector<BoostPolygon> const& boostPolygons);
198
199 template <class PolyT>
200 bool overlaps(PolyT const& other) const {
201 return !boost::geometry::disjoint(poly, other);
202 }
203
204 template <class PolyT>
205 std::shared_ptr<Polygon> intersectionSingle(PolyT const& other) const;
206
207 template <class PolyT>
208 std::vector<std::shared_ptr<Polygon>> intersection(PolyT const& other) const;
209
210 template <class PolyT>
211 std::shared_ptr<Polygon> unionSingle(PolyT const& other) const;
212
213 template <class PolyT>
214 std::vector<std::shared_ptr<Polygon>> union_(PolyT const& other) const;
215
216 template <class PolyT>
217 std::vector<std::shared_ptr<Polygon>> symDifference(PolyT const& other) const;
218
220};
221
223 std::vector<BoostPolygon> const& boostPolygons) {
225 lsstPolygons.reserve(boostPolygons.size());
226 for (auto const &boostPolygon : boostPolygons) {
228 lsstPolygons.push_back(tmp);
229 }
230 return lsstPolygons;
231}
232
233template <class PolyT>
236 boost::geometry::intersection(poly, other, result);
237 if (result.size() == 0) {
238 throw LSST_EXCEPT(SinglePolygonException, "Polygons have no intersection");
239 }
240 if (result.size() > 1) {
241 throw LSST_EXCEPT(
243 (boost::format("Multiple polygons (%d) created by intersection()") % result.size()).str());
244 }
246}
247
248template <class PolyT>
250 std::vector<BoostPolygon> boostResult;
251 boost::geometry::intersection(poly, other, boostResult);
252 return convertBoostPolygons(boostResult);
253}
254
255template <class PolyT>
258 boost::geometry::union_(poly, other, result);
259 if (result.size() != 1) {
260 throw LSST_EXCEPT(
262 (boost::format("Multiple polygons (%d) created by union_()") % result.size()).str());
263 }
265}
266
267template <class PolyT>
269 std::vector<BoostPolygon> boostResult;
270 boost::geometry::union_(poly, other, boostResult);
271 return convertBoostPolygons(boostResult);
272}
273
274template <class PolyT>
276 std::vector<BoostPolygon> boostResult;
277 boost::geometry::sym_difference(poly, other, boostResult);
278 return convertBoostPolygons(boostResult);
279}
280
281Polygon::Polygon(Polygon const&) = default;
282Polygon::Polygon(Polygon&&) = default;
283Polygon& Polygon::operator=(Polygon const&) = default;
285
286Polygon::~Polygon() = default;
287
288Polygon::Polygon(Polygon::Box const& box) : _impl(new Polygon::Impl(box)) {}
289
290Polygon::Polygon(std::vector<LsstPoint> const& vertices) : _impl(new Polygon::Impl(vertices)) {}
291
293 : _impl(new Polygon::Impl()) {
294 auto corners = transform.applyForward(boxToCorners(box));
295 boost::geometry::assign(_impl->poly, corners);
296 _impl->check();
297}
298
300 : _impl(new Polygon::Impl()) {
301 std::vector<LsstPoint> corners = boxToCorners(box);
302 for (auto & corner : corners) {
303 corner = transform(corner);
304 }
305 boost::geometry::assign(_impl->poly, corners);
306 _impl->check();
307}
308
309size_t Polygon::getNumEdges() const {
310 // boost::geometry::models::polygon uses a "closed" polygon: the start/end point is included twice
311 return boost::geometry::num_points(_impl->poly) - 1;
312}
313
315 return boostBoxToLsst(boost::geometry::return_envelope<BoostBox>(_impl->poly));
316}
317
319 return boost::geometry::return_centroid<LsstPoint>(_impl->poly);
320}
321
322double Polygon::calculateArea() const { return boost::geometry::area(_impl->poly); }
323
324double Polygon::calculatePerimeter() const { return boost::geometry::perimeter(_impl->poly); }
325
327 std::vector<LsstPoint> const vertices = getVertices();
329 edges.reserve(getNumEdges());
330 for (std::vector<LsstPoint>::const_iterator i = vertices.begin(), j = vertices.begin() + 1;
331 j != vertices.end(); ++i, ++j) {
332 edges.emplace_back(*i, *j);
333 }
334 return edges;
335}
336
337std::vector<LsstPoint> Polygon::getVertices() const { return _impl->poly.outer(); }
338
339std::vector<LsstPoint>::const_iterator Polygon::begin() const { return _impl->poly.outer().begin(); }
340
341std::vector<LsstPoint>::const_iterator Polygon::end() const {
342 return _impl->poly.outer().end() - 1; // Note removal of final "closed" point
343}
344
345bool Polygon::operator==(Polygon const& other) const {
346 return boost::geometry::equals(_impl->poly, other._impl->poly);
347}
348
350 // boost::hash allows hash functions to throw, but the container hashes throw
351 // only if the element [geom::Point] has a throwing hash
352 static boost::hash<BoostPolygon::ring_type> polygonHash;
353 return polygonHash(_impl->poly.outer());
354}
355
356bool Polygon::contains(LsstPoint const& point) const { return boost::geometry::within(point, _impl->poly); }
357
359 std::vector<bool> results;
360 for (Point const & p : points) {
361 results.push_back(contains(p));
362 }
363 return results;
364}
365
367 std::vector<bool> results;
368 for (lsst::geom::PointI const & p : points) {
369 results.push_back(contains(Point(p)));
370 }
371 return results;
372}
373
374bool Polygon::overlaps(Polygon const& other) const { return _impl->overlaps(other._impl->poly); }
375
376bool Polygon::overlaps(Box const& box) const { return _impl->overlaps(box); }
377
379 return _impl->intersectionSingle(other._impl->poly);
380}
381
383 return _impl->intersectionSingle(box);
384}
385
387 return _impl->intersection(other._impl->poly);
388}
389
391 return _impl->intersection(box);
392}
393
395 return _impl->unionSingle(other._impl->poly);
396}
397
398std::shared_ptr<Polygon> Polygon::unionSingle(Box const& box) const { return _impl->unionSingle(box); }
399
401 return _impl->union_(other._impl->poly);
402}
403
404std::vector<std::shared_ptr<Polygon>> Polygon::union_(Box const& box) const { return _impl->union_(box); }
405
407 return _impl->symDifference(other._impl->poly);
408}
409
411 return _impl->symDifference(box);
412}
413
414std::shared_ptr<Polygon> Polygon::simplify(double const distance) const {
415 BoostPolygon result;
416 boost::geometry::simplify(_impl->poly, result, distance);
418}
419
421 BoostPolygon hull;
422 boost::geometry::convex_hull(_impl->poly, hull);
424}
425
427 auto newVertices = transform.applyForward(getVertices());
429}
430
432 std::vector<LsstPoint> vertices; // New vertices
433 vertices.reserve(getNumEdges());
434 for (auto const &i : _impl->poly.outer()) {
435 vertices.push_back(transform(i));
436 }
438}
439
441 std::vector<LsstPoint> vertices; // New vertices
442 vertices.reserve(getNumEdges() * num);
444 for (auto const &edge : edges) {
445 addSubSampledEdge(vertices, edge.first, edge.second, num);
446 }
448}
449
451 std::vector<LsstPoint> vertices; // New vertices
452 vertices.reserve(getNumEdges() + static_cast<size_t>(::ceil(calculatePerimeter() / maxLength)));
454 for (auto const &edge : edges) {
455 Point const &p1 = edge.first, p2 = edge.second;
456 double const dist = ::sqrt(p1.distanceSquared(p2));
457 addSubSampledEdge(vertices, p1, p2, static_cast<size_t>(::ceil(dist / maxLength)));
458 }
460}
461
463 using Image = afw::image::Image<float>;
465 image->setXY0(bbox.getMin());
466 *image = 0.0;
467 lsst::geom::Box2D bounds = getBBox(); // Polygon bounds
468 int xMin = std::max(static_cast<int>(bounds.getMinX()), bbox.getMinX());
469 int xMax = std::min(static_cast<int>(::ceil(bounds.getMaxX())), bbox.getMaxX());
470 int yMin = std::max(static_cast<int>(bounds.getMinY()), bbox.getMinY());
471 int yMax = std::min(static_cast<int>(::ceil(bounds.getMaxY())), bbox.getMaxY());
472 for (int y = yMin; y <= yMax; ++y) {
473 double const yPixelMin = (double)y - 0.5, yPixelMax = (double)y + 0.5;
474 BoostPolygon row; // A polygon of row y
475 boost::geometry::assign(
476 row, LsstBox(lsst::geom::Point2D(xMin, yPixelMin), lsst::geom::Point2D(xMax, yPixelMax)));
477 std::vector<BoostPolygon> intersections;
478 boost::geometry::intersection(_impl->poly, row, intersections);
479
480 if (intersections.size() == 1 && boost::geometry::num_points(intersections[0]) == 5) {
481 // This row is fairly tame, and should have a long run of pixels within the polygon
482 BoostPolygon const& row = intersections[0];
483 std::vector<double> top, bottom;
484 top.reserve(2);
485 bottom.reserve(2);
486 bool failed = false;
487 for (std::vector<Point>::const_iterator i = row.outer().begin(); i != row.outer().end() - 1;
488 ++i) {
489 double const xCoord = i->getX(), yCoord = i->getY();
490 if (yCoord == yPixelMin) {
491 bottom.push_back(xCoord);
492 } else if (yCoord == yPixelMax) {
493 top.push_back(xCoord);
494 } else {
495 failed = true;
496 break;
497 }
498 }
499 if (!failed && top.size() == 2 && bottom.size() == 2) {
500 std::sort(top.begin(), top.end());
501 std::sort(bottom.begin(), bottom.end());
502 int const xMin = std::min(top[0], bottom[0]);
503 int const xStart = ::ceil(std::max(top[0], bottom[0])) + 1;
504 int const xStop = std::min(top[1], bottom[1]) - 1;
505 int const xMax = ::ceil(std::max(top[1], bottom[1]));
506 pixelRowOverlap(image, _impl->poly, std::max(xMin, bbox.getMinX()),
507 std::min(xStart, bbox.getMaxX()), y);
508 int x = xStart;
509 for (Image::x_iterator i = image->x_at(std::max(xStart, bbox.getMinX()) - image->getX0(),
510 y - image->getY0());
511 x <= std::min(xStop, bbox.getMaxX()); ++i, ++x) {
512 *i = 1.0;
513 }
514 pixelRowOverlap(image, _impl->poly, std::max(xStop, bbox.getMinX()),
515 std::min(xMax, bbox.getMaxX()), y);
516 continue;
517 }
518 }
519
520 // Last resort: do each pixel independently...
521 for (auto const &intersection : intersections) {
522 double xMinRow = xMax, xMaxRow = xMin;
523 std::vector<LsstPoint> const vertices = intersection.outer();
524 for (auto const &vertice : vertices) {
525 double const x = vertice.getX();
526 if (x < xMinRow) xMinRow = x;
527 if (x > xMaxRow) xMaxRow = x;
528 }
529
530 pixelRowOverlap(image, _impl->poly, std::max(static_cast<int>(xMinRow), bbox.getMinX()),
531 std::min(static_cast<int>(::ceil(xMaxRow)), bbox.getMaxX()), y);
532 }
533 }
534 return image;
535}
536
537// -------------- Table-based Persistence -------------------------------------------------------------------
538
539/*
540 *
541 */
542namespace {
543
544struct PolygonSchema {
545 afw::table::Schema schema;
547
548 static PolygonSchema const& get() {
549 static PolygonSchema instance;
550 return instance;
551 }
552
553 // No copying
554 PolygonSchema(const PolygonSchema&) = delete;
555 PolygonSchema& operator=(const PolygonSchema&) = delete;
556
557 // No moving
558 PolygonSchema(PolygonSchema&&) = delete;
559 PolygonSchema& operator=(PolygonSchema&&) = delete;
560
561private:
562 PolygonSchema()
563 : schema(),
564 vertices(afw::table::PointKey<double>::addFields(schema, "vertices", "list of vertex points",
565 "")) {}
566};
567
568class PolygonFactory : public table::io::PersistableFactory {
569public:
570 explicit PolygonFactory(std::string const& name) : table::io::PersistableFactory(name) {}
571
572 std::shared_ptr<table::io::Persistable> read(InputArchive const& archive,
573 CatalogVector const& catalogs) const override {
574 static PolygonSchema const& keys = PolygonSchema::get();
575
576 LSST_ARCHIVE_ASSERT(catalogs.size() == 1u);
577 afw::table::BaseCatalog const& cat = catalogs.front();
578
579 std::vector<LsstPoint> vertices;
580 for (afw::table::BaseCatalog::const_iterator iter = cat.begin(); iter != cat.end(); ++iter) {
581 vertices.push_back(iter->get(keys.vertices));
582 }
583 std::shared_ptr<Polygon> result(new Polygon(vertices));
584 return result;
585 }
586};
587
588std::string getPolygonPersistenceName() { return "Polygon"; }
589
590PolygonFactory registration(getPolygonPersistenceName());
591
592} // anonymous namespace
593
594std::string Polygon::getPersistenceName() const { return getPolygonPersistenceName(); }
595
597 static PolygonSchema const& keys = PolygonSchema::get();
598 afw::table::BaseCatalog catalog = handle.makeCatalog(keys.schema);
599
600 std::vector<LsstPoint> vertices = this->getVertices();
601 for (auto const &vertice : vertices) {
603 record->set(keys.vertices, vertice);
604 }
605
606 handle.saveCatalog(catalog);
607}
608
610 return std::make_unique<Polygon>(*this);
611}
612
614 std::stringstream buffer;
615 buffer << "Polygon(" << this->getVertices() << ")";
616 return buffer.str();
617}
618
619bool Polygon::equals(typehandling::Storable const& other) const noexcept {
620 return singleClassEquals(*this, other);
621}
622
623} // namespace polygon
624} // namespace geom
625} // namespace afw
626} // namespace lsst
#define LSST_EXCEPT(type,...)
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Definition Persistable.h:48
lsst::afw::geom::polygon::Polygon::Box LsstBox
Definition Polygon.cc:18
boost::geometry::model::linestring< LsstPoint > BoostLineString
Definition Polygon.cc:22
std::vector< LsstPoint > LsstRing
Definition Polygon.cc:19
lsst::afw::geom::polygon::Polygon::Point LsstPoint
Definition Polygon.cc:17
boost::geometry::model::box< LsstPoint > BoostBox
Definition Polygon.cc:21
boost::geometry::model::polygon< LsstPoint > BoostPolygon
Definition Polygon.cc:20
T begin(T... args)
Cartesian polygons.
Definition Polygon.h:59
lsst::geom::Point2D Point
Definition Polygon.h:62
std::shared_ptr< Polygon > unionSingle(Polygon const &other) const
Returns the union of two polygons.
Definition Polygon.cc:394
std::vector< Point >::const_iterator begin() const
Iterator for vertices.
Definition Polygon.cc:339
bool overlaps(Polygon const &other) const
Returns whether the polygons overlap each other.
Definition Polygon.cc:374
Box getBBox() const
Return bounding box.
Definition Polygon.cc:314
std::shared_ptr< Polygon > convexHull() const
Produce a polygon from the convex hull.
Definition Polygon.cc:420
std::vector< std::pair< Point, Point > > getEdges() const
Get vector of edges.
Definition Polygon.cc:326
std::shared_ptr< Polygon > intersectionSingle(Polygon const &other) const
Returns the intersection of two polygons.
Definition Polygon.cc:378
std::shared_ptr< afw::image::Image< float > > createImage(lsst::geom::Box2I const &bbox) const
Create image of polygon.
Definition Polygon.cc:462
Polygon(Box const &box)
Construct a rectangular Polygon whose vertices are the corners of a box.
Definition Polygon.cc:288
std::shared_ptr< Polygon > subSample(size_t num) const
Sub-sample each edge.
Definition Polygon.cc:440
std::vector< std::shared_ptr< Polygon > > intersection(Polygon const &other) const
Returns the intersection of two polygons.
Definition Polygon.cc:386
size_t getNumEdges() const
Return number of edges.
Definition Polygon.cc:309
std::shared_ptr< Polygon > transform(TransformPoint2ToPoint2 const &transform) const
Transform the polygon.
Definition Polygon.cc:426
std::shared_ptr< typehandling::Storable > cloneStorable() const override
Create a new Polygon that is a copy of this one.
Definition Polygon.cc:609
std::vector< Point > getVertices() const
Get vector of vertices.
Definition Polygon.cc:337
std::shared_ptr< Polygon > simplify(double const distance) const
Return a simplified polygon.
Definition Polygon.cc:414
bool operator==(Polygon const &other) const
Definition Polygon.cc:345
std::string toString() const override
Create a string representation of this object.
Definition Polygon.cc:613
std::vector< std::shared_ptr< Polygon > > union_(Polygon const &other) const
Returns the union of two polygons.
Definition Polygon.cc:400
std::size_t hash_value() const noexcept override
Return a hash of this object.
Definition Polygon.cc:349
std::vector< std::shared_ptr< Polygon > > symDifference(Polygon const &other) const
Return the symmetric difference of two polygons.
Definition Polygon.cc:406
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
Definition Polygon.cc:594
bool contains(Point const &point) const
Returns whether the polygon contains the point.
Definition Polygon.cc:356
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Definition Polygon.cc:596
Polygon & operator=(Polygon const &)
std::vector< Point >::const_iterator end() const
Definition Polygon.cc:341
bool equals(typehandling::Storable const &other) const noexcept override
Compare this object to another Storable.
Definition Polygon.cc:619
An exception that indicates the single-polygon assumption has been violated.
Definition Polygon.h:53
typename _view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
Definition ImageBase.h:133
A class to represent a 2-dimensional array of pixels.
Definition Image.h:51
std::shared_ptr< RecordT > addNew()
Create a new record, add it to the end of the catalog, and return a pointer to it.
Definition Catalog.h:490
CatalogIterator< typename Internal::const_iterator > const_iterator
Definition Catalog.h:111
reference front() const
Return the first record.
Definition Catalog.h:458
A FunctorKey used to get or set a lsst::geom::Point from an (x,y) pair of int or double Keys.
Definition aggregates.h:51
Defines the fields and offsets for a table.
Definition Schema.h:51
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
A CRTP facade class for subclasses of Persistable.
io::OutputArchiveHandle OutputArchiveHandle
Interface supporting iteration over heterogenous containers.
Definition Storable.h:58
static bool singleClassEquals(T const &lhs, Storable const &rhs)
Test if a Storable is of a particular class and equal to another object.
Definition Storable.h:151
double getMaxY() const noexcept
Point2D const getMax() const noexcept
double getMaxX() const noexcept
double getMinY() const noexcept
Point2D const getMin() const noexcept
double getMinX() const noexcept
int getMinY() const noexcept
Point2I const getMin() const noexcept
int getMinX() const noexcept
int getMaxX() const noexcept
int getMaxY() const noexcept
double distanceSquared(PointBase< T, N > const &other) const noexcept(Super::IS_ELEMENT_NOTHROW_COPYABLE)
T emplace_back(T... args)
T end(T... args)
T make_shared(T... args)
T max(T... args)
T min(T... args)
DOXYGEN_IGNORE std::ostream & operator<<(std::ostream &os, Polygon const &poly)
Stream polygon.
Definition Polygon.cc:176
Transform< Point2Endpoint, Point2Endpoint > TransformPoint2ToPoint2
Definition Transform.h:300
CatalogT< BaseRecord > BaseCatalog
Definition fwd.h:72
Extent< double, 2 > Extent2D
Point< int, 2 > PointI
Point< double, 2 > Point2D
T push_back(T... args)
T reserve(T... args)
T size(T... args)
T sort(T... args)
T str(T... args)
static void set(LsstPoint &p, LsstPoint::Element const &value)
Definition Polygon.cc:46
static double get(LsstPoint const &p)
Definition Polygon.cc:45
static std::vector< std::shared_ptr< Polygon > > convertBoostPolygons(std::vector< BoostPolygon > const &boostPolygons)
Definition Polygon.cc:222
Impl(BoostPolygon const &_poly)
Definition Polygon.cc:191
std::vector< std::shared_ptr< Polygon > > symDifference(PolyT const &other) const
Definition Polygon.cc:275
Impl(Polygon::Box const &box)
Definition Polygon.cc:183
bool overlaps(PolyT const &other) const
Definition Polygon.cc:200
std::shared_ptr< Polygon > intersectionSingle(PolyT const &other) const
Definition Polygon.cc:234
std::vector< std::shared_ptr< Polygon > > union_(PolyT const &other) const
Definition Polygon.cc:268
std::shared_ptr< Polygon > unionSingle(PolyT const &other) const
Definition Polygon.cc:256
std::vector< std::shared_ptr< Polygon > > intersection(PolyT const &other) const
Definition Polygon.cc:249
Impl(std::vector< LsstPoint > const &vertices)
Definition Polygon.cc:187
std::shared_ptr< table::io::Persistable > read(table::io::InputArchive const &archive, table::io::CatalogVector const &catalogs) const override