LSSTApplications  17.0+11,17.0+34,17.0+56,17.0+57,17.0+59,17.0+7,17.0-1-g377950a+33,17.0.1-1-g114240f+2,17.0.1-1-g4d4fbc4+28,17.0.1-1-g55520dc+49,17.0.1-1-g5f4ed7e+52,17.0.1-1-g6dd7d69+17,17.0.1-1-g8de6c91+11,17.0.1-1-gb9095d2+7,17.0.1-1-ge9fec5e+5,17.0.1-1-gf4e0155+55,17.0.1-1-gfc65f5f+50,17.0.1-1-gfc6fb1f+20,17.0.1-10-g87f9f3f+1,17.0.1-11-ge9de802+16,17.0.1-16-ga14f7d5c+4,17.0.1-17-gc79d625+1,17.0.1-17-gdae4c4a+8,17.0.1-2-g26618f5+29,17.0.1-2-g54f2ebc+9,17.0.1-2-gf403422+1,17.0.1-20-g2ca2f74+6,17.0.1-23-gf3eadeb7+1,17.0.1-3-g7e86b59+39,17.0.1-3-gb5ca14a,17.0.1-3-gd08d533+40,17.0.1-30-g596af8797,17.0.1-4-g59d126d+4,17.0.1-4-gc69c472+5,17.0.1-6-g5afd9b9+4,17.0.1-7-g35889ee+1,17.0.1-7-gc7c8782+18,17.0.1-9-gc4bbfb2+3,w.2019.22
LSSTDataManagementBasePackage
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 
8 #include "lsst/pex/exceptions.h"
9 #include "lsst/geom/Extent.h"
11 
16 #include "lsst/afw/table/io/Persistable.cc"
17 
21 typedef boost::geometry::model::polygon<LsstPoint> BoostPolygon;
22 typedef boost::geometry::model::box<LsstPoint> BoostBox;
23 typedef boost::geometry::model::linestring<LsstPoint> BoostLineString;
24 
25 namespace boost {
26 namespace geometry {
27 namespace traits {
28 
29 // Setting up LsstPoint
30 template <>
31 struct tag<LsstPoint> {
32  typedef point_tag type;
33 };
34 template <>
35 struct coordinate_type<LsstPoint> {
37 };
38 template <>
39 struct coordinate_system<LsstPoint> {
40  typedef cs::cartesian type;
41 };
42 template <>
43 struct dimension<LsstPoint> : boost::mpl::int_<2> {};
44 template <std::size_t dim>
45 struct access<LsstPoint, dim> {
46  static double get(LsstPoint const& p) { return p[dim]; }
47  static void set(LsstPoint& p, LsstPoint::Element const& value) { p[dim] = value; }
48 };
49 
50 // Setting up LsstBox
51 //
52 // No setters, because it's inefficient (can't set individual elements of lsst::geom::Box2D directly).
53 // For box outputs from boost::geometry we'll use BoostBox and then convert.
54 template <>
55 struct tag<LsstBox> {
56  typedef box_tag type;
57 };
58 template <>
59 struct point_type<LsstBox> {
60  typedef LsstPoint type;
61 };
62 template <>
63 struct indexed_access<LsstBox, 0, 0> {
64  static double get(LsstBox const& box) { return box.getMinX(); }
65 };
66 template <>
67 struct indexed_access<LsstBox, 1, 0> {
68  static double get(LsstBox const& box) { return box.getMaxX(); }
69 };
70 template <>
71 struct indexed_access<LsstBox, 0, 1> {
72  static double get(LsstBox const& box) { return box.getMinY(); }
73 };
74 template <>
75 struct indexed_access<LsstBox, 1, 1> {
76  static double get(LsstBox const& box) { return box.getMaxY(); }
77 };
78 
79 // Setting up LsstRing
80 template <>
81 struct tag<LsstRing> {
82  typedef ring_tag type;
83 };
84 // template<> struct range_value<LsstRing> { typedef LsstPoint type; };
85 } // namespace traits
86 } // namespace geometry
87 } // namespace boost
88 
89 namespace {
90 
92 LsstBox boostBoxToLsst(BoostBox const& box) { return LsstBox(box.min_corner(), box.max_corner()); }
93 
95 std::vector<LsstPoint> boxToCorners(LsstBox const& box) {
96  std::vector<LsstPoint> corners;
97  corners.reserve(4);
98  corners.push_back(box.getMin());
99  corners.push_back(LsstPoint(box.getMaxX(), box.getMinY()));
100  corners.push_back(box.getMax());
101  corners.push_back(LsstPoint(box.getMinX(), box.getMaxY()));
102  return corners;
103 }
104 
110 void addSubSampledEdge(std::vector<LsstPoint>& vertices, // Vector of points to which to add
111  LsstPoint const& first, // First vertex defining edge
112  LsstPoint const& second, // Second vertex defining edge
113  size_t const num // Number of parts to divide edge into
114 ) {
115  lsst::geom::Extent2D const delta = (second - first) / num;
116  vertices.push_back(first);
117  for (size_t i = 1; i < num; ++i) {
118  vertices.push_back(first + delta * i);
119  }
120 }
121 
123 double pixelOverlap(BoostPolygon const& poly, int const x, int const y) {
124  std::vector<BoostPolygon> overlap; // Overlap between pixel and polygon
125  LsstBox const pixel(lsst::geom::Point2D(x - 0.5, y - 0.5), lsst::geom::Point2D(x + 0.5, y + 0.5));
126  boost::geometry::intersection(poly, pixel, overlap);
127  double area = 0.0;
128  for (std::vector<BoostPolygon>::const_iterator i = overlap.begin(); i != overlap.end(); ++i) {
129  double const polyArea = boost::geometry::area(*i);
130  area += std::min(polyArea, 1.0); // remove any rounding error
131  }
132  return area;
133 }
134 
136 void pixelRowOverlap(std::shared_ptr<lsst::afw::image::Image<float>> const image, BoostPolygon const& poly,
137  int const xStart, int const xStop, int const y) {
138  int x = xStart;
139  for (lsst::afw::image::Image<float>::x_iterator i = image->x_at(x - image->getX0(), y - image->getY0());
140  x <= xStop; ++i, ++x) {
141  *i = pixelOverlap(poly, x, y);
142  }
143 }
144 
145 } // anonymous namespace
146 
147 namespace lsst {
148 namespace afw {
149 
150 template std::shared_ptr<geom::polygon::Polygon> table::io::PersistableFacade<
151  geom::polygon::Polygon>::dynamicCast(std::shared_ptr<table::io::Persistable> const&);
152 
153 namespace geom {
154 namespace polygon {
155 
157 std::ostream& operator<<(std::ostream& os, std::vector<LsstPoint> const& vertices) {
158  os << "[";
159  size_t num = vertices.size();
160  for (size_t i = 0; i < num - 1; ++i) {
161  os << vertices[i] << ",";
162  }
163  os << vertices[vertices.size() - 1] << "]";
164  return os;
165 }
166 
169  return os << "BoostPolygon(" << poly.outer() << ")";
170 }
171 
173  os << poly.toString();
174  return os;
175 }
176 
178  Impl() : poly() {}
179  explicit Impl(Polygon::Box const& box) : poly() {
180  boost::geometry::assign(poly, box);
181  // Assignment from a box is correctly handled by BoostPolygon, so doesn't need a "check()"
182  }
183  explicit Impl(std::vector<LsstPoint> const& vertices) : poly() {
184  boost::geometry::assign(poly, vertices);
185  check(); // because the vertices might not have the correct orientation (CW vs CCW) or be open
186  }
187  explicit Impl(BoostPolygon const& _poly) : poly(_poly) {}
188 
189  void check() { boost::geometry::correct(poly); }
190 
192  static std::vector<std::shared_ptr<Polygon>> convertBoostPolygons(
193  std::vector<BoostPolygon> const& boostPolygons);
194 
195  template <class PolyT>
196  bool overlaps(PolyT const& other) const {
197  return !boost::geometry::disjoint(poly, other);
198  }
199 
200  template <class PolyT>
201  std::shared_ptr<Polygon> intersectionSingle(PolyT const& other) const;
202 
203  template <class PolyT>
204  std::vector<std::shared_ptr<Polygon>> intersection(PolyT const& other) const;
205 
206  template <class PolyT>
207  std::shared_ptr<Polygon> unionSingle(PolyT const& other) const;
208 
209  template <class PolyT>
210  std::vector<std::shared_ptr<Polygon>> union_(PolyT const& other) const;
211 
212  template <class PolyT>
213  std::vector<std::shared_ptr<Polygon>> symDifference(PolyT const& other) const;
214 
216 };
217 
218 std::vector<std::shared_ptr<Polygon>> Polygon::Impl::convertBoostPolygons(
219  std::vector<BoostPolygon> const& boostPolygons) {
221  lsstPolygons.reserve(boostPolygons.size());
222  for (std::vector<BoostPolygon>::const_iterator i = boostPolygons.begin(); i != boostPolygons.end(); ++i) {
224  lsstPolygons.push_back(tmp);
225  }
226  return lsstPolygons;
227 }
228 
229 template <class PolyT>
230 std::shared_ptr<Polygon> Polygon::Impl::intersectionSingle(PolyT const& other) const {
232  boost::geometry::intersection(poly, other, result);
233  if (result.size() == 0) {
234  throw LSST_EXCEPT(SinglePolygonException, "Polygons have no intersection");
235  }
236  if (result.size() > 1) {
237  throw LSST_EXCEPT(
239  (boost::format("Multiple polygons (%d) created by intersection()") % result.size()).str());
240  }
241  return std::shared_ptr<Polygon>(new Polygon(std::shared_ptr<Impl>(new Impl(result[0]))));
242 }
243 
244 template <class PolyT>
245 std::vector<std::shared_ptr<Polygon>> Polygon::Impl::intersection(PolyT const& other) const {
246  std::vector<BoostPolygon> boostResult;
247  boost::geometry::intersection(poly, other, boostResult);
248  return convertBoostPolygons(boostResult);
249 }
250 
251 template <class PolyT>
252 std::shared_ptr<Polygon> Polygon::Impl::unionSingle(PolyT const& other) const {
254  boost::geometry::union_(poly, other, result);
255  if (result.size() != 1) {
256  throw LSST_EXCEPT(
258  (boost::format("Multiple polygons (%d) created by union_()") % result.size()).str());
259  }
260  return std::shared_ptr<Polygon>(new Polygon(std::shared_ptr<Impl>(new Impl(result[0]))));
261 }
262 
263 template <class PolyT>
264 std::vector<std::shared_ptr<Polygon>> Polygon::Impl::union_(PolyT const& other) const {
265  std::vector<BoostPolygon> boostResult;
266  boost::geometry::union_(poly, other, boostResult);
267  return convertBoostPolygons(boostResult);
268 }
269 
270 template <class PolyT>
271 std::vector<std::shared_ptr<Polygon>> Polygon::Impl::symDifference(PolyT const& other) const {
272  std::vector<BoostPolygon> boostResult;
273  boost::geometry::sym_difference(poly, other, boostResult);
274  return convertBoostPolygons(boostResult);
275 }
276 
277 Polygon::Polygon(Polygon const&) = default;
278 Polygon::Polygon(Polygon&&) = default;
279 Polygon& Polygon::operator=(Polygon const&) = default;
280 Polygon& Polygon::operator=(Polygon&&) = default;
281 
282 Polygon::~Polygon() = default;
283 
284 Polygon::Polygon(Polygon::Box const& box) : _impl(new Polygon::Impl(box)) {}
285 
286 Polygon::Polygon(std::vector<LsstPoint> const& vertices) : _impl(new Polygon::Impl(vertices)) {}
287 
289  : _impl(new Polygon::Impl()) {
290  auto corners = transform.applyForward(boxToCorners(box));
291  boost::geometry::assign(_impl->poly, corners);
292  _impl->check();
293 }
294 
296  : _impl(new Polygon::Impl()) {
297  std::vector<LsstPoint> corners = boxToCorners(box);
298  for (std::vector<LsstPoint>::iterator p = corners.begin(); p != corners.end(); ++p) {
299  *p = transform(*p);
300  }
301  boost::geometry::assign(_impl->poly, corners);
302  _impl->check();
303 }
304 
305 size_t Polygon::getNumEdges() const {
306  // boost::geometry::models::polygon uses a "closed" polygon: the start/end point is included twice
307  return boost::geometry::num_points(_impl->poly) - 1;
308 }
309 
311  return boostBoxToLsst(boost::geometry::return_envelope<BoostBox>(_impl->poly));
312 }
313 
315  return boost::geometry::return_centroid<LsstPoint>(_impl->poly);
316 }
317 
318 double Polygon::calculateArea() const { return boost::geometry::area(_impl->poly); }
319 
320 double Polygon::calculatePerimeter() const { return boost::geometry::perimeter(_impl->poly); }
321 
323  std::vector<LsstPoint> const vertices = getVertices();
325  edges.reserve(getNumEdges());
326  for (std::vector<LsstPoint>::const_iterator i = vertices.begin(), j = vertices.begin() + 1;
327  j != vertices.end(); ++i, ++j) {
328  edges.push_back(std::make_pair(*i, *j));
329  }
330  return edges;
331 }
332 
333 std::vector<LsstPoint> Polygon::getVertices() const { return _impl->poly.outer(); }
334 
335 std::vector<LsstPoint>::const_iterator Polygon::begin() const { return _impl->poly.outer().begin(); }
336 
338  return _impl->poly.outer().end() - 1; // Note removal of final "closed" point
339 }
340 
341 bool Polygon::operator==(Polygon const& other) const {
342  return boost::geometry::equals(_impl->poly, other._impl->poly);
343 }
344 
346  // boost::hash allows hash functions to throw, but the container hashes throw
347  // only if the element [geom::Point] has a throwing hash
348  static boost::hash<BoostPolygon::ring_type> polygonHash;
349  return polygonHash(_impl->poly.outer());
350 }
351 
352 bool Polygon::contains(LsstPoint const& point) const { return boost::geometry::within(point, _impl->poly); }
353 
354 bool Polygon::overlaps(Polygon const& other) const { return _impl->overlaps(other._impl->poly); }
355 
356 bool Polygon::overlaps(Box const& box) const { return _impl->overlaps(box); }
357 
359  return _impl->intersectionSingle(other._impl->poly);
360 }
361 
363  return _impl->intersectionSingle(box);
364 }
365 
367  return _impl->intersection(other._impl->poly);
368 }
369 
371  return _impl->intersection(box);
372 }
373 
375  return _impl->unionSingle(other._impl->poly);
376 }
377 
378 std::shared_ptr<Polygon> Polygon::unionSingle(Box const& box) const { return _impl->unionSingle(box); }
379 
381  return _impl->union_(other._impl->poly);
382 }
383 
384 std::vector<std::shared_ptr<Polygon>> Polygon::union_(Box const& box) const { return _impl->union_(box); }
385 
387  return _impl->symDifference(other._impl->poly);
388 }
389 
391  return _impl->symDifference(box);
392 }
393 
396  boost::geometry::simplify(_impl->poly, result, distance);
398 }
399 
401  BoostPolygon hull;
402  boost::geometry::convex_hull(_impl->poly, hull);
404 }
405 
407  auto newVertices = transform.applyForward(getVertices());
408  return std::shared_ptr<Polygon>(new Polygon(std::shared_ptr<Impl>(new Impl(newVertices))));
409 }
410 
412  std::vector<LsstPoint> vertices; // New vertices
413  vertices.reserve(getNumEdges());
414  for (std::vector<LsstPoint>::const_iterator i = _impl->poly.outer().begin();
415  i != _impl->poly.outer().end(); ++i) {
416  vertices.push_back(transform(*i));
417  }
418  return std::shared_ptr<Polygon>(new Polygon(std::shared_ptr<Impl>(new Impl(vertices))));
419 }
420 
422  std::vector<LsstPoint> vertices; // New vertices
423  vertices.reserve(getNumEdges() * num);
425  for (std::vector<std::pair<Point, Point>>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
426  addSubSampledEdge(vertices, i->first, i->second, num);
427  }
428  return std::shared_ptr<Polygon>(new Polygon(std::shared_ptr<Impl>(new Impl(vertices))));
429 }
430 
432  std::vector<LsstPoint> vertices; // New vertices
433  vertices.reserve(getNumEdges() + static_cast<size_t>(::ceil(calculatePerimeter() / maxLength)));
435  for (std::vector<std::pair<Point, Point>>::const_iterator i = edges.begin(); i != edges.end(); ++i) {
436  Point const &p1 = i->first, p2 = i->second;
437  double const dist = ::sqrt(p1.distanceSquared(p2));
438  addSubSampledEdge(vertices, p1, p2, static_cast<size_t>(::ceil(dist / maxLength)));
439  }
440  return std::shared_ptr<Polygon>(new Polygon(std::shared_ptr<Impl>(new Impl(vertices))));
441 }
442 
444  typedef afw::image::Image<float> Image;
445  std::shared_ptr<Image> image = std::make_shared<Image>(bbox);
446  image->setXY0(bbox.getMin());
447  *image = 0.0;
448  lsst::geom::Box2D bounds = getBBox(); // Polygon bounds
449  int xMin = std::max(static_cast<int>(bounds.getMinX()), bbox.getMinX());
450  int xMax = std::min(static_cast<int>(::ceil(bounds.getMaxX())), bbox.getMaxX());
451  int yMin = std::max(static_cast<int>(bounds.getMinY()), bbox.getMinY());
452  int yMax = std::min(static_cast<int>(::ceil(bounds.getMaxY())), bbox.getMaxY());
453  for (int y = yMin; y <= yMax; ++y) {
454  double const yPixelMin = (double)y - 0.5, yPixelMax = (double)y + 0.5;
455  BoostPolygon row; // A polygon of row y
456  boost::geometry::assign(
457  row, LsstBox(lsst::geom::Point2D(xMin, yPixelMin), lsst::geom::Point2D(xMax, yPixelMax)));
458  std::vector<BoostPolygon> intersections;
459  boost::geometry::intersection(_impl->poly, row, intersections);
460 
461  if (intersections.size() == 1 && boost::geometry::num_points(intersections[0]) == 5) {
462  // This row is fairly tame, and should have a long run of pixels within the polygon
463  BoostPolygon const& row = intersections[0];
464  std::vector<double> top, bottom;
465  top.reserve(2);
466  bottom.reserve(2);
467  bool failed = false;
468  for (std::vector<Point>::const_iterator i = row.outer().begin(); i != row.outer().end() - 1;
469  ++i) {
470  double const xCoord = i->getX(), yCoord = i->getY();
471  if (yCoord == yPixelMin) {
472  bottom.push_back(xCoord);
473  } else if (yCoord == yPixelMax) {
474  top.push_back(xCoord);
475  } else {
476  failed = true;
477  break;
478  }
479  }
480  if (!failed && top.size() == 2 && bottom.size() == 2) {
481  std::sort(top.begin(), top.end());
482  std::sort(bottom.begin(), bottom.end());
483  int const xMin = std::min(top[0], bottom[0]);
484  int const xStart = ::ceil(std::max(top[0], bottom[0])) + 1;
485  int const xStop = std::min(top[1], bottom[1]) - 1;
486  int const xMax = ::ceil(std::max(top[1], bottom[1]));
487  pixelRowOverlap(image, _impl->poly, std::max(xMin, bbox.getMinX()),
488  std::min(xStart, bbox.getMaxX()), y);
489  int x = xStart;
490  for (Image::x_iterator i = image->x_at(std::max(xStart, bbox.getMinX()) - image->getX0(),
491  y - image->getY0());
492  x <= std::min(xStop, bbox.getMaxX()); ++i, ++x) {
493  *i = 1.0;
494  }
495  pixelRowOverlap(image, _impl->poly, std::max(xStop, bbox.getMinX()),
496  std::min(xMax, bbox.getMaxX()), y);
497  continue;
498  }
499  }
500 
501  // Last resort: do each pixel independently...
502  for (std::vector<BoostPolygon>::const_iterator p = intersections.begin(); p != intersections.end();
503  ++p) {
504  double xMinRow = xMax, xMaxRow = xMin;
505  std::vector<LsstPoint> const vertices = p->outer();
506  for (std::vector<LsstPoint>::const_iterator q = vertices.begin(); q != vertices.end(); ++q) {
507  double const x = q->getX();
508  if (x < xMinRow) xMinRow = x;
509  if (x > xMaxRow) xMaxRow = x;
510  }
511 
512  pixelRowOverlap(image, _impl->poly, std::max(static_cast<int>(xMinRow), bbox.getMinX()),
513  std::min(static_cast<int>(::ceil(xMaxRow)), bbox.getMaxX()), y);
514  }
515  }
516  return image;
517 }
518 
519 // -------------- Table-based Persistence -------------------------------------------------------------------
520 
521 /*
522  *
523  */
524 namespace {
525 
526 struct PolygonSchema {
527  afw::table::Schema schema;
528  afw::table::PointKey<double> vertices;
529 
530  static PolygonSchema const& get() {
531  static PolygonSchema instance;
532  return instance;
533  }
534 
535  // No copying
536  PolygonSchema(const PolygonSchema&) = delete;
537  PolygonSchema& operator=(const PolygonSchema&) = delete;
538 
539  // No moving
540  PolygonSchema(PolygonSchema&&) = delete;
541  PolygonSchema& operator=(PolygonSchema&&) = delete;
542 
543 private:
544  PolygonSchema()
545  : schema(),
546  vertices(afw::table::PointKey<double>::addFields(schema, "vertices", "list of vertex points",
547  "")) {
548  schema.getCitizen().markPersistent();
549  }
550 };
551 
552 class PolygonFactory : public table::io::PersistableFactory {
553 public:
554  explicit PolygonFactory(std::string const& name) : table::io::PersistableFactory(name) {}
555 
556  std::shared_ptr<table::io::Persistable> read(InputArchive const& archive,
557  CatalogVector const& catalogs) const override {
558  static PolygonSchema const& keys = PolygonSchema::get();
559 
560  LSST_ARCHIVE_ASSERT(catalogs.size() == 1u);
561  afw::table::BaseCatalog const& cat = catalogs.front();
562 
564  for (afw::table::BaseCatalog::const_iterator iter = cat.begin(); iter != cat.end(); ++iter) {
565  vertices.push_back(iter->get(keys.vertices));
566  }
567  std::shared_ptr<Polygon> result(new Polygon(vertices));
568  return result;
569  }
570 };
571 
572 std::string getPolygonPersistenceName() { return "Polygon"; }
573 
574 PolygonFactory registration(getPolygonPersistenceName());
575 
576 } // anonymous namespace
577 
578 std::string Polygon::getPersistenceName() const { return getPolygonPersistenceName(); }
579 
580 void Polygon::write(OutputArchiveHandle& handle) const {
581  static PolygonSchema const& keys = PolygonSchema::get();
582  afw::table::BaseCatalog catalog = handle.makeCatalog(keys.schema);
583 
584  std::vector<LsstPoint> vertices = this->getVertices();
585  for (std::vector<LsstPoint>::const_iterator i = vertices.begin(); i != vertices.end(); ++i) {
587  record->set(keys.vertices, *i);
588  }
589 
590  handle.saveCatalog(catalog);
591 }
592 
594  return std::make_unique<Polygon>(*this);
595 }
596 
598  std::stringstream buffer;
599  buffer << "Polygon(" << this->getVertices() << ")";
600  return buffer.str();
601 }
602 
603 bool Polygon::equals(typehandling::Storable const& other) const noexcept {
604  return singleClassEquals(*this, other);
605 }
606 
607 } // namespace polygon
608 } // namespace geom
609 } // namespace afw
610 } // namespace lsst
std::shared_ptr< Polygon > convexHull() const
Produce a polygon from the convex hull.
Definition: Polygon.cc:400
double getMinY() const noexcept
Definition: Box.h:395
bool operator==(Polygon const &other) const
Definition: Polygon.cc:341
std::vector< Point >::const_iterator begin() const
Iterator for vertices.
Definition: Polygon.cc:335
std::vector< std::shared_ptr< Polygon > > intersection(Polygon const &other) const
Returns the intersection of two polygons.
Definition: Polygon.cc:366
Extent< int, N > ceil(Extent< double, N > const &input) noexcept
Return the component-wise ceil (round towards more positive).
Definition: Extent.cc:118
ToPoint applyForward(FromPoint const &point) const
Transform one point in the forward direction ("from" to "to")
Definition: Transform.cc:79
Polygon & operator=(Polygon const &)
boost::geometry::model::box< LsstPoint > BoostBox
Definition: Polygon.cc:22
Definition: Polygon.cc:25
Impl(BoostPolygon const &_poly)
Definition: Polygon.cc:187
bool overlaps(Polygon const &other) const
Returns whether the polygons overlap each other.
Definition: Polygon.cc:354
A floating-point coordinate rectangle geometry.
Definition: Box.h:305
CatalogT< BaseRecord > BaseCatalog
Definition: fwd.h:71
An object passed to Persistable::write to allow it to persist itself.
lsst::afw::geom::polygon::Polygon::Point LsstPoint
Definition: Polygon.cc:18
Low-level polynomials (including special polynomials) in C++.
Definition: Basis1d.h:26
An affine coordinate transformation consisting of a linear transformation and an offset.
double getMinX() const noexcept
Definition: Box.h:394
A coordinate class intended to represent absolute positions.
Interface supporting iteration over heterogenous containers.
Definition: Storable.h:56
Impl(std::vector< LsstPoint > const &vertices)
Definition: Polygon.cc:183
lsst::afw::geom::polygon::Polygon::Box LsstBox
Definition: Polygon.cc:19
Polygon(Box const &box)
Construct a rectangular Polygon whose vertices are the corners of a box.
Definition: Polygon.cc:284
py::object result
Definition: schema.cc:418
_view_t::x_iterator x_iterator
An iterator for traversing the pixels in a row.
Definition: ImageBase.h:134
int y
Definition: SpanSet.cc:49
bool overlaps(PolyT const &other) const
Definition: Polygon.cc:196
static PointKey addFields(Schema &schema, std::string const &name, std::string const &doc, std::string const &unit)
Add a pair of _x, _y fields to a Schema, and return a PointKey that points to them.
Definition: aggregates.cc:36
double getMaxX() const noexcept
Definition: Box.h:398
T end(T... args)
afw::table::PointKey< double > vertices
Definition: Polygon.cc:528
Point2D const getMin() const noexcept
Definition: Box.h:393
boost::geometry::model::linestring< LsstPoint > BoostLineString
Definition: Polygon.cc:23
std::vector< std::shared_ptr< Polygon > > symDifference(Polygon const &other) const
Return the symmetric difference of two polygons.
Definition: Polygon.cc:386
STL class.
T min(T... args)
std::shared_ptr< Polygon > unionSingle(Polygon const &other) const
Returns the union of two polygons.
Definition: Polygon.cc:374
Point2I const getMin() const noexcept
Definition: Box.h:143
Box getBBox() const
Return bounding box.
Definition: Polygon.cc:310
T push_back(T... args)
double getMaxY() const noexcept
Definition: Box.h:399
A base class for image defects.
std::vector< LsstPoint > LsstRing
Definition: Polygon.cc:20
reference front() const
Return the first record.
Definition: Catalog.h:453
std::vector< std::pair< Point, Point > > getEdges() const
Get vector of edges.
Definition: Polygon.cc:322
std::string toString() const override
Create a string representation of this object.
Definition: Polygon.cc:597
int getMaxY() const noexcept
Definition: Box.h:149
bool equals(typehandling::Storable const &other) const noexcept override
Compare this object to another Storable.
Definition: Polygon.cc:603
std::vector< std::shared_ptr< Polygon > > union_(Polygon const &other) const
Returns the union of two polygons.
Definition: Polygon.cc:380
def format(config, name=None, writeSourceLine=True, prefix="", verbose=False)
Definition: history.py:168
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Definition: Polygon.cc:580
Impl(Polygon::Box const &box)
Definition: Polygon.cc:179
T str(T... args)
T make_pair(T... args)
boost::geometry::model::polygon< LsstPoint > BoostPolygon
Definition: Polygon.cc:21
std::size_t hash_value() const noexcept override
Return a hash of this object.
Definition: Polygon.cc:345
table::Box2IKey bbox
Definition: Detector.cc:169
T max(T... args)
int getMaxX() const noexcept
Definition: Box.h:148
An exception that indicates the single-polygon assumption has been violated.
Definition: Polygon.h:53
CatalogIterator< typename Internal::const_iterator > const_iterator
Definition: Catalog.h:111
double x
std::shared_ptr< Polygon > subSample(size_t num) const
Sub-sample each edge.
Definition: Polygon.cc:421
BaseCatalog makeCatalog(Schema const &schema)
Return a new, empty catalog with the given schema.
Point2D const getMax() const noexcept
Definition: Box.h:397
int getMinX() const noexcept
Definition: Box.h:144
std::vector< Point > getVertices() const
Get vector of vertices.
Definition: Polygon.cc:333
T size(T... args)
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
Definition: Exception.h:48
STL class.
T begin(T... args)
size_t getNumEdges() const
Return number of edges.
Definition: Polygon.cc:305
std::shared_ptr< Polygon > simplify(double const distance) const
Return a simplified polygon.
Definition: Polygon.cc:394
std::shared_ptr< Polygon > intersectionSingle(Polygon const &other) const
Returns the intersection of two polygons.
Definition: Polygon.cc:358
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
Definition: Persistable.h:48
afw::table::Key< afw::table::Array< ImagePixelT > > image
std::ostream & operator<<(std::ostream &os, BoostPolygon const &poly)
Definition: Polygon.cc:168
std::vector< Point >::const_iterator end() const
Iterator for vertices.
Definition: Polygon.cc:337
table::PointKey< int > pixel
ItemVariant const * other
Definition: Schema.cc:56
Cartesian polygons.
Definition: Polygon.h:59
afw::table::Schema schema
Definition: Polygon.cc:527
T sort(T... args)
void saveCatalog(BaseCatalog const &catalog)
Save a catalog in the archive.
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
Definition: Polygon.cc:578
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
std::shared_ptr< typehandling::Storable > cloneStorable() const override
Create a new Polygon that is a copy of this one.
Definition: Polygon.cc:593
bool contains(Point const &point) const
Returns whether the polygon contains the point.
Definition: Polygon.cc:352
An integer coordinate rectangle.
Definition: Box.h:54
STL class.
std::shared_ptr< afw::image::Image< float > > createImage(lsst::geom::Box2I const &bbox) const
Create image of polygon.
Definition: Polygon.cc:443
A class to represent a 2-dimensional array of pixels.
Definition: Image.h:59
std::shared_ptr< Polygon > transform(TransformPoint2ToPoint2 const &transform) const
Transform the polygon.
Definition: Polygon.cc:406
double distanceSquared(PointBase< T, N > const &other) const noexcept(Super::IS_ELEMENT_NOTHROW_COPYABLE)
Definition: Point.h:138
int getMinY() const noexcept
Definition: Box.h:145
std::ostream * os
Definition: Schema.cc:746
Transform LSST spatial data, such as lsst::geom::Point2D and lsst::geom::SpherePoint, using an AST mapping.
Definition: Transform.h:67
T reserve(T... args)
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:485
int row
Definition: CR.cc:145
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:136
double calculatePerimeter() const
Definition: Polygon.cc:320