4#include "boost/geometry/geometry.hpp"
5#include <boost/container_hash/hash.hpp>
21using BoostBox = boost::geometry::model::box<LsstPoint>;
39 using type = cs::cartesian;
42struct dimension<
LsstPoint> : boost::mpl::int_<2> {};
43template <std::
size_t dim>
116 for (
size_t i = 1; i < num; ++i) {
117 vertices.push_back(first + delta * i);
130 boost::geometry::intersection(
poly, pixel, overlap);
132 for (
auto const &i : overlap) {
133 double const polyArea = boost::geometry::area(i);
141 int const xStart,
int const xStop,
int const y) {
144 x <= xStop; ++i, ++
x) {
145 *i = pixelOverlap(
poly,
x,
y);
164 for (
size_t i = 0; i < num - 1; ++i) {
173 return os <<
"BoostPolygon(" <<
poly.outer() <<
")";
177 os <<
poly.toString();
184 boost::geometry::assign(
poly, box);
199 template <
class PolyT>
201 return !boost::geometry::disjoint(
poly, other);
204 template <
class PolyT>
207 template <
class PolyT>
210 template <
class PolyT>
213 template <
class PolyT>
216 template <
class PolyT>
226 for (
auto const &boostPolygon : boostPolygons) {
233template <
class PolyT>
236 boost::geometry::intersection(
poly, other,
result);
243 (boost::format(
"Multiple polygons (%d) created by intersection()") %
result.size()).str());
248template <
class PolyT>
251 boost::geometry::intersection(
poly, other, boostResult);
252 return convertBoostPolygons(boostResult);
255template <
class PolyT>
262 (boost::format(
"Multiple polygons (%d) created by union_()") %
result.size()).str());
267template <
class PolyT>
270 boost::geometry::union_(
poly, other, boostResult);
271 return convertBoostPolygons(boostResult);
274template <
class PolyT>
277 boost::geometry::sym_difference(
poly, other, boostResult);
278 return convertBoostPolygons(boostResult);
294 auto corners = transform.applyForward(boxToCorners(box));
295 boost::geometry::assign(_impl->
poly, corners);
302 for (
auto & corner : corners) {
303 corner = transform(corner);
305 boost::geometry::assign(_impl->
poly, corners);
311 return boost::geometry::num_points(_impl->
poly) - 1;
315 return boostBoxToLsst(boost::geometry::return_envelope<BoostBox>(_impl->
poly));
319 return boost::geometry::return_centroid<LsstPoint>(_impl->
poly);
330 for (std::vector<LsstPoint>::const_iterator i =
vertices.begin(), j =
vertices.begin() + 1;
342 return _impl->
poly.outer().end() - 1;
346 return boost::geometry::equals(_impl->
poly, other._impl->
poly);
352 static boost::hash<BoostPolygon::ring_type> polygonHash;
353 return polygonHash(_impl->
poly.outer());
360 for (
Point const & p : points) {
416 boost::geometry::simplify(_impl->
poly,
result, distance);
422 boost::geometry::convex_hull(_impl->
poly, hull);
427 auto newVertices = transform.applyForward(
getVertices());
434 for (
auto const &i : _impl->
poly.outer()) {
444 for (
auto const &edge : edges) {
445 addSubSampledEdge(
vertices, edge.first, edge.second, num);
454 for (
auto const &edge : edges) {
455 Point const &p1 = edge.first, p2 = edge.second;
457 addSubSampledEdge(
vertices, p1, p2,
static_cast<size_t>(::ceil(dist / maxLength)));
472 for (
int y = yMin;
y <= yMax; ++
y) {
473 double const yPixelMin = (double)
y - 0.5, yPixelMax = (
double)
y + 0.5;
475 boost::geometry::assign(
478 boost::geometry::intersection(_impl->
poly,
row, intersections);
480 if (intersections.
size() == 1 && boost::geometry::num_points(intersections[0]) == 5) {
487 for (std::vector<Point>::const_iterator i =
row.outer().begin(); i !=
row.outer().end() - 1;
489 double const xCoord = i->getX(), yCoord = i->getY();
490 if (yCoord == yPixelMin) {
492 }
else if (yCoord == yPixelMax) {
499 if (!failed && top.
size() == 2 && bottom.
size() == 2) {
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]));
522 double xMinRow = xMax, xMaxRow = xMin;
524 for (
auto const &vertice :
vertices) {
525 double const x = vertice.getX();
526 if (
x < xMinRow) xMinRow =
x;
527 if (
x > xMaxRow) xMaxRow =
x;
531 std::min(
static_cast<int>(::ceil(xMaxRow)),
bbox.getMaxX()),
y);
544struct PolygonSchema {
545 afw::table::Schema schema;
548 static PolygonSchema
const& get() {
549 static PolygonSchema instance;
554 PolygonSchema(
const PolygonSchema&) =
delete;
555 PolygonSchema& operator=(
const PolygonSchema&) =
delete;
558 PolygonSchema(PolygonSchema&&) =
delete;
559 PolygonSchema& operator=(PolygonSchema&&) =
delete;
564 vertices(
afw::table::PointKey<double>::addFields(schema,
"vertices",
"list of vertex points",
568class PolygonFactory :
public table::io::PersistableFactory {
570 explicit PolygonFactory(
std::string const& name) : table::io::PersistableFactory(name) {}
573 CatalogVector
const& catalogs)
const override {
574 static PolygonSchema
const&
keys = PolygonSchema::get();
588std::string getPolygonPersistenceName() {
return "Polygon"; }
590PolygonFactory registration(getPolygonPersistenceName());
597 static PolygonSchema
const& keys = PolygonSchema::get();
601 for (
auto const &vertice :
vertices) {
603 record->set(keys.vertices, vertice);
610 return std::make_unique<Polygon>(*
this);
615 buffer <<
"Polygon(" << this->
getVertices() <<
")";
620 return singleClassEquals(*
this, other);
table::PointKey< int > pixel
#define LSST_EXCEPT(type,...)
Create an exception with a given type.
lsst::afw::geom::polygon::Polygon::Box LsstBox
boost::geometry::model::linestring< LsstPoint > BoostLineString
afw::table::PointKey< double > vertices
lsst::afw::geom::polygon::Polygon::Point LsstPoint
boost::geometry::model::box< LsstPoint > BoostBox
boost::geometry::model::polygon< LsstPoint > BoostPolygon
#define LSST_ARCHIVE_ASSERT(EXPR)
An assertion macro used to validate the structure of an InputArchive.
std::shared_ptr< Polygon > transform(TransformPoint2ToPoint2 const &transform) const
Transform the polygon.
std::shared_ptr< Polygon > unionSingle(Polygon const &other) const
Returns the union of two polygons.
std::vector< std::shared_ptr< Polygon > > intersection(Polygon const &other) const
Returns the intersection of two polygons.
std::shared_ptr< Polygon > subSample(size_t num) const
Sub-sample each edge.
Box getBBox() const
Return bounding box.
bool operator==(Polygon const &other) const
std::vector< Point > getVertices() const
Get vector of vertices.
std::vector< std::shared_ptr< Polygon > > union_(Polygon const &other) const
Returns the union of two polygons.
size_t getNumEdges() const
Return number of edges.
std::shared_ptr< Polygon > simplify(double const distance) const
Return a simplified polygon.
double calculateArea() const
std::vector< std::shared_ptr< Polygon > > symDifference(Polygon const &other) const
Return the symmetric difference of two polygons.
Polygon(Box const &box)
Construct a rectangular Polygon whose vertices are the corners of a box.
void write(OutputArchiveHandle &handle) const override
Write the object to one or more catalogs.
Polygon & operator=(Polygon const &)
std::vector< std::pair< Point, Point > > getEdges() const
Get vector of edges.
std::shared_ptr< Polygon > convexHull() const
Produce a polygon from the convex hull.
std::shared_ptr< typehandling::Storable > cloneStorable() const override
Create a new Polygon that is a copy of this one.
Point calculateCenter() const
std::vector< Point >::const_iterator end() const
bool overlaps(Polygon const &other) const
Returns whether the polygons overlap each other.
bool contains(Point const &point) const
Returns whether the polygon contains the point.
std::vector< Point >::const_iterator begin() const
Iterator for vertices.
double calculatePerimeter() const
lsst::geom::Point2D Point
std::shared_ptr< Polygon > intersectionSingle(Polygon const &other) const
Returns the intersection of two polygons.
std::shared_ptr< afw::image::Image< float > > createImage(lsst::geom::Box2I const &bbox) const
Create image of polygon.
std::string getPersistenceName() const override
Return the unique name used to persist this object and look up its factory.
bool equals(typehandling::Storable const &other) const noexcept override
Compare this object to another Storable.
std::size_t hash_value() const noexcept override
Return a hash of this object.
std::string toString() const override
Create a string representation of this object.
An exception that indicates the single-polygon assumption has been violated.
A class to represent a 2-dimensional array of pixels.
CatalogIterator< typename Internal::const_iterator > const_iterator
reference front() const
Return the first record.
An object passed to Persistable::write to allow it to persist itself.
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.
Interface supporting iteration over heterogenous containers.
A floating-point coordinate rectangle geometry.
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
An integer coordinate rectangle.
double distanceSquared(PointBase< T, N > const &other) const noexcept(Super::IS_ELEMENT_NOTHROW_COPYABLE)
Cast this object to an Extent of the same numeric type and dimensionality.
T emplace_back(T... args)
DOXYGEN_IGNORE std::ostream & operator<<(std::ostream &os, Polygon const &poly)
Stream polygon.
CatalogT< BaseRecord > BaseCatalog
Low-level polynomials (including special polynomials) in C++.
static void set(LsstPoint &p, LsstPoint::Element const &value)
static double get(LsstPoint const &p)
static double get(LsstBox const &box)
static double get(LsstBox const &box)
static double get(LsstBox const &box)
static double get(LsstBox const &box)
std::vector< std::shared_ptr< Polygon > > union_(PolyT const &other) const
std::vector< std::shared_ptr< Polygon > > symDifference(PolyT const &other) const
Impl(Polygon::Box const &box)
Impl(std::vector< LsstPoint > const &vertices)
std::shared_ptr< Polygon > unionSingle(PolyT const &other) const
Impl(BoostPolygon const &_poly)
bool overlaps(PolyT const &other) const
std::vector< std::shared_ptr< Polygon > > intersection(PolyT const &other) const
static std::vector< std::shared_ptr< Polygon > > convertBoostPolygons(std::vector< BoostPolygon > const &boostPolygons)
std::shared_ptr< Polygon > intersectionSingle(PolyT const &other) const
g2d::python::Image< double > Image
std::shared_ptr< table::io::Persistable > read(table::io::InputArchive const &archive, table::io::CatalogVector const &catalogs) const override