41 namespace except = lsst::pex::exceptions;
42 namespace table = lsst::afw::table;
48 namespace lsst {
namespace ap {
namespace utils {
52 double orient2d(
Point2D const &a,
56 double detLeft = (a.getX() - c.getX()) * (b.getY() - c.getY());
57 double detRight = (a.getY() - c.getY()) * (b.getX() - c.getX());
58 double det = detLeft - detRight;
62 if (detRight <= 0.0) {
65 detSum = detLeft + detRight;
67 }
else if (detLeft < 0.0) {
68 if (detRight >= 0.0) {
71 detSum = -detLeft - detRight;
76 double epsilon = std::numeric_limits<double>::epsilon();
77 double errBound = detSum * ((3.0 + 16.0 * epsilon) * epsilon);
78 if (det >= errBound || -det >= errBound) {
95 v1(p1.getY() < p2.getY() ? &p1 : &p2),
96 v2(p1.getY() < p2.getY() ? &p2 : &p1),
99 dy =
v2->getY() -
v1->getY();
100 dx =
v2->getX() -
v1->getX();
105 return v1->getY() == e.v1->getY();
108 return v1->getY() < e.v1->getY();
113 bool rightOf(Edge
const &e)
const {
116 det = orient2d(*e.v1, *e.v2, *
v2);
117 }
else if (
v2 == e.v2) {
118 det = orient2d(*e.v1, *e.v2, *
v1);
120 det = orient2d(*e.v1, *e.v2, *
v1);
122 det = orient2d(*e.v1, *e.v2, *
v2);
131 std::pair<int, int>
const getXBounds(
double yMin,
double yMax,
int width)
const {
132 double xd1 =
v1->getX() + ((yMin -
v1->getY()) *
dx) /
dy;
133 double xd2 =
v1->getX() + ((yMax -
v1->getY()) *
dx) /
dy;
134 int x1 = width, x2 = width;
136 xd1 = xd1 <
v1->getX() ?
v1->getX() : (xd1 >
v2->getX() ?
v2->getX() : xd1);
137 xd2 = xd2 < xd1 ? xd1 : (xd2 >
v2->getX() ?
v2->getX() : xd2);
145 xd2 = xd2 <
v2->getX() ?
v2->getX() : (xd2 >
v1->getX() ?
v1->getX() : xd2);
146 xd1 = xd1 < xd2 ? xd2 : (xd1 >
v1->getX() ?
v1->getX() : xd1);
160 double getCoverage(
double const yMin,
double const yMax,
int x)
const;
164 double Edge::getCoverage(
double const yMin,
double const yMax,
int x)
const {
166 double const xMin = xp - 0.5;
167 double const xMax = xp + 0.5;
170 return (yMax - yMin) * (xMax -
v1->getX());
171 }
else if (
dx > 0.0) {
174 double y1 =
v1->getY() + ((xMin -
v1->getX()) *
dy) /
dx;
181 double x =
v1->getX() + ((yMin -
v1->getY()) *
dx) /
dy;
182 x1 = (x < xMin) ? xMin : (x > xMax) ? xMax : x;
187 double y2 =
v1->getY() + ((xMax -
v1->getX()) *
dy) /
dx;
193 double x =
v1->getX() + ((yMax -
v1->getY()) *
dx) /
dy;
194 x2 = (x < xMin) ? xMin : (x > xMax) ? xMax : x;
203 cov += (xMax - x2 + 0.5 * (x2 - x1)) * (y2 - y1);
207 double y1 =
v1->getY() + ((xMax -
v1->getX()) *
dy) /
dx;
213 double x =
v1->getX() + ((yMin -
v1->getY()) *
dx) /
dy;
214 x1 = (x < xMin) ? xMin : (x > xMax) ? xMax : x;
219 double y2 =
v1->getY() + ((xMin -
v1->getX()) *
dy) /
dx;
226 double x =
v1->getX() + ((yMax -
v1->getY()) *
dx) /
dy;
227 x2 = (x < xMin) ? xMin : (x > xMax) ? xMax : x;
236 cov += (xMax - x1 + 0.5 * (x2 - x1)) * (y2 - y1);
246 _cov(new double[img->getWidth()]),
267 Edge *before =
_head;
268 while (before != 0 && e.rightOf(*before)) {
270 before = before->next;
280 void advance(
double y);
287 void removeBelow(
double y) {
291 if (e->v2->getY() <=
y) {
296 prev->next = e->next;
308 void updateCoverage(
int y) {
313 double *cov =
_cov.get();
315 i != e; ++i, ++cov) {
319 *i +=
std::min(1.0f, static_cast<float>(c));
324 void rasterizeCoverage(
double yMin,
double yMax);
326 boost::scoped_array<double>
_cov;
334 void SweepLine::rasterizeCoverage(
double yMin,
double yMax) {
342 Edge *right = left->next;
346 std::pair<int, int> xl = left->getXBounds(yMin, yMax, width);
347 std::pair<int, int> xr = right->getXBounds(yMin, yMax, width);
348 for (
int x = xl.first; x < xl.second; ++x) {
349 _cov[
x] += left->getCoverage(yMin, yMax, x);
351 for (
int x = xl.second; x < xr.second; ++x) {
352 _cov[
x] += yMax - yMin;
354 for (
int x = xr.first; x < xr.second; ++x) {
355 _cov[
x] -= right->getCoverage(yMin, yMax, x);
361 void SweepLine::advance(
double y) {
369 rasterizeCoverage(
_y, yMax);
373 if (yIndex < height) {
374 rasterizeCoverage(
_y, y);
382 void SweepLine::finish() {
419 for (SourceIter i = sources.
begin(), e = sources.
end(); i != e; ++i) {
420 Point2D xy = wcs->skyToPixel(i->getCoord());
423 if (x < 0 || x >= histogram->
getWidth() ||
425 if (!ignoreOffImage) {
427 "SourceCatalog contains sources lying "
428 "outside the histogram image");
432 histogram->operator()(
x,
y) += 1;
444 std::vector<Point2D>
const &verts,
447 typedef std::vector<Point2D>::const_iterator VertexIter;
448 typedef std::vector<Edge>::iterator EdgeIter;
452 "image width/height must be at least 1");
454 if (verts.size() < 3) {
456 "polygon must have at least 3 vertices");
458 std::vector<Edge> edges;
459 edges.reserve(verts.size());
462 for (VertexIter
v2 = verts.begin(), e = verts.end(),
v1 = e - 1;
466 if (v->getY() ==
v2->getY()) {
468 }
else if (v->getY() <
v2->getY()) {
469 if (v->getY() >= maxY ||
v2->getY() < minY) {
473 if (
v2->getY() >= maxY || v->getY() < minY) {
477 edges.push_back(Edge(*v, *
v2));
479 if (edges.size() > 0) {
480 std::sort(edges.begin(), edges.end());
481 SweepLine sweeper(img, edges.front().v1->getY());
482 EdgeIter i = edges.begin(), e = edges.end();
484 for (; i != e && i->v1->getY() <= minY; ++i) {
488 double y = i->v1->getY();
491 for (++i; i != e && i->v1->getY() ==
y; ++i) {
523 typedef std::vector<Point2D>::iterator VertexIter;
524 if (width <= 0 || height <= 0) {
526 "Width/height of input image must be positive");
528 std::vector<Point2D> v;
531 v.push_back(
Point2D(-0.5, -0.5));
532 v.push_back(
Point2D(width - 0.5, -0.5));
533 v.push_back(
Point2D(width - 0.5, height - 0.5));
534 v.push_back(
Point2D(-0.5, height - 0.5));
536 v.reserve(2 * width + 2 * height + 2);
537 for (
int i = 0; i < width; i += step) {
538 v.push_back(
Point2D(i - 0.5, -0.5));
540 for (
int i = 0; i < height; i += step) {
541 v.push_back(
Point2D(width - 0.5, i - 0.5));
543 for (
int i = width; i > 0; i -= step) {
544 v.push_back(
Point2D(i - 0.5, height - 0.5));
546 for (
int i = height; i > 0; i -= step) {
547 v.push_back(
Point2D(-0.5, i - 0.5));
551 for (VertexIter i = v.begin(), e = v.end(); i != e; ++i) {
552 *i = covMapWcs->skyToPixel(*wcs->pixelToSky(*i));
image::Image< float >::Ptr _img
void rasterizePolygon(std::vector< Point2D > const &verts, lsst::afw::image::Image< float >::Ptr img)
double indexToPosition(double ind)
Convert image index to image position.
x_iterator row_begin(int y) const
x_iterator row_end(int y) const
Return an x_iterator to the end of the y'th row.
int positionToIndex(double pos)
Convert image position to nearest integer index.
void makeSourceHistogram(lsst::afw::image::Image< unsigned short >::Ptr histogram, lsst::afw::table::SourceCatalog const &sources, lsst::afw::image::Wcs::Ptr wcs, bool ignoreOffImage)
void updateCoverageMap(lsst::afw::image::Image< float >::Ptr covMap, lsst::afw::image::Wcs::Ptr covMapWcs, lsst::afw::image::Wcs::Ptr wcs, int width, int height, int step)
boost::shared_ptr< Wcs > Ptr
boost::shared_ptr< Image< PixelT > > Ptr
table::Key< table::Array< Kernel::Pixel > > image
int getWidth() const
Return the number of columns in the image.
boost::scoped_array< double > _cov
Custom catalog class for record/table subclasses that are guaranteed to have an ID, and should generally be sorted by that ID.
bool operator==(Ellipse< DataT > const &a, Ellipse< DataT > const &b)
std::pair< int, double > positionToIndex(double const pos, lsst::afw::image::xOrY const xy) const
Convert image position to index (nearest integer and fractional parts)
A coordinate class intended to represent absolute positions.
#define LSST_EXCEPT(type,...)
const double PixelZeroPos
FITS uses 1.0, SDSS uses 0.5, LSST uses 0.0 (http://dev.lsstcorp.org/trac/wiki/BottomLeftPixelProposa...
afw::table::Key< double > b
Point< double, 2 > Point2D
int getHeight() const
Return the number of rows in the image.
Base::const_iterator const_iterator
bool operator<(Ellipse< DataT > const &a, Ellipse< DataT > const &b)
A class to represent a 2-dimensional array of pixels.
Include files required for standard LSST Exception handling.