// -*- C++ -*- // $RCSfile: shape.C,v $ // $Revision: 1.6 $ // $Author: langer $ // $Date: 2000/09/06 20:11:48 $ /* This software was produced by NIST, an agency of the U.S. government, * and by statute is not subject to copyright in the United States. * Recipients of this software assume all responsibilities associated * with its operation, modification and maintenance. However, to * facilitate maintenance we ask that before distributing modifed * versions of this software, you first contact the authors at * oof_manager@ctcms.nist.gov. */ // Shapes with integer coordinates (shapes defined on an image) #include "cell_coordinate.h" #include "ishape.h" #include "meshcoord.h" #include "shape.h" #include Rectangle::Rectangle(const MeshCoord &c1, const MeshCoord &c2) { if(c1.x < c2.x) { ll.x = c1.x; ur.x = c2.x; } else { ll.x = c2.x; ur.x = c1.x; } if(c1.y < c2.y) { ll.y = c1.y; ur.y = c2.y; } else { ll.y = c2.y; ur.y = c1.y; } } Shape *Rectangle::clone() const { return new Rectangle(*this); } ImageRect Rectangle::containing_rectangle() const { return ImageRect(mesh2cell_dn(ll), mesh2cell_up(ur)); } int Rectangle::contains(const MeshCoord &c) const { return (c.x >= ll.x && c.x < ur.x && c.y >= ll.y && c.y < ur.y); } double Rectangle::width() const { return ur.x - ll.x; } double Rectangle::height() const { return ur.y - ll.y; } //=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=// Circle::Circle(const MeshCoord &c1, const MeshCoord &c2) : xcenter(c1.x), ycenter(c1.y) { double dx = c1.x - c2.x; double dy = c1.y - c2.y; rsquare = dx*dx + dy*dy; r = sqrt(rsquare); MeshCoord diag(M_SQRT2*r, M_SQRT2*r); // diagonal of containing box container = ImageRect(mesh2cell_dn(c1-diag), mesh2cell_up(c1+diag)); } int Circle::contains(const MeshCoord &c) const { double dx = c.x - xcenter; double dy = c.y - ycenter; return dx*dx + dy*dy < rsquare; } Shape *Circle::clone() const { return new Circle(*this); } //=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=// Ellipse::Ellipse(const MeshCoord &c1, const MeshCoord &c2) : container(mesh2cell_dn(c1), mesh2cell_up(c2)), null(0) { double dx = c2.x - c1.x; double dy = c2.y - c1.y; if(dx == 0.0 || dy == 0.0) { null = 1; return; } invxaxis = 4./(dx*dx); // 1/semi-axis^2 invyaxis = 4./(dy*dy); xcenter = 0.5*(c1.x + c2.x); ycenter = 0.5*(c1.y + c2.y); } int Ellipse::contains(const MeshCoord &c) const { if(null) return 0; double dx = c.x - xcenter; double dy = c.y - ycenter; return dx*dx*invxaxis + dy*dy*invyaxis < 1.0; } Shape *Ellipse::clone() const { return new Ellipse(*this); } //=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=// Intersection::Intersection(const Shape &s1, const Shape &s2) : shape1(s1.clone()), shape2(s2.clone()) { ImageRect r1 = shape1->containing_rectangle(); ImageRect r2 = shape2->containing_rectangle(); container = r1 && r2; } Intersection::~Intersection() { delete shape1; delete shape2; } Shape *Intersection::clone() const { return new Intersection(*shape1, *shape2); } int Intersection::contains(const MeshCoord &c) const { return shape1->contains(c) && shape2->contains(c); } ImageRect Intersection::containing_rectangle() const { return container; } Intersection operator&&(const Shape &s1, const Shape &s2) { return Intersection(s1, s2); } //=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=//=\\=// int ShapeIterator::operator()(Cell_coordinate &pixel) { while(iter(pixel)) if(shape->contains(cell2mesh(pixel))) return 1; return 0; } ShapeIterator::~ShapeIterator() { delete shape; } int ShapeIterator::upperbound() const { ImageRect boundingbox = shape->containing_rectangle(); return boundingbox.height()*boundingbox.width(); }