Logo Search packages:      
Sourcecode: gamera version File versions  Download package

diff2d.hxx

/************************************************************************/
/*                                                                      */
/*                  Copyright 1998-2003 by Hans Meine                   */
/*       Cognitive Systems Group, University of Hamburg, Germany        */
/*                                                                      */
/*    This file is part of the VIGRA computer vision library.           */
/*    ( Version 1.6.0, Aug 13 2008 )                                    */
/*    The VIGRA Website is                                              */
/*        http://kogs-www.informatik.uni-hamburg.de/~koethe/vigra/      */
/*    Please direct questions, bug reports, and contributions to        */
/*        ullrich.koethe@iwr.uni-heidelberg.de    or                    */
/*        vigra@informatik.uni-hamburg.de                               */
/*                                                                      */
/*    Permission is hereby granted, free of charge, to any person       */
/*    obtaining a copy of this software and associated documentation    */
/*    files (the "Software"), to deal in the Software without           */
/*    restriction, including without limitation the rights to use,      */
/*    copy, modify, merge, publish, distribute, sublicense, and/or      */
/*    sell copies of the Software, and to permit persons to whom the    */
/*    Software is furnished to do so, subject to the following          */
/*    conditions:                                                       */
/*                                                                      */
/*    The above copyright notice and this permission notice shall be    */
/*    included in all copies or substantial portions of the             */
/*    Software.                                                         */
/*                                                                      */
/*    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND    */
/*    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES   */
/*    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND          */
/*    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT       */
/*    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,      */
/*    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING      */
/*    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR     */
/*    OTHER DEALINGS IN THE SOFTWARE.                                   */
/*                                                                      */
/************************************************************************/

#ifndef VIGRA_DIFF2D_HXX
#define VIGRA_DIFF2D_HXX

#include <cmath> // for sqrt()
#include <iosfwd>
#include "config.hxx"
#include "iteratortags.hxx"
#include "iteratortraits.hxx"
#include "iteratoradapter.hxx"
#include "tuple.hxx"

namespace vigra {

template <class Diff>
class Diff2DConstRowIteratorPolicy
{
  public:
    typedef Diff                            BaseType;
    typedef Diff                            value_type;
    typedef typename Diff::MoveX            difference_type;
    typedef Diff const &                    reference;
    typedef Diff                            index_reference;
    typedef Diff const *                    pointer;
    typedef std::random_access_iterator_tag iterator_category;

    static void initialize(BaseType &) {}

    static reference dereference(BaseType const & d)
        { return d; }

    static index_reference dereference(BaseType d, difference_type n)
    {
        d.x += n;
        return d;
    }

    static bool equal(BaseType const & d1, BaseType const & d2)
        { return d1.x == d2.x; }

    static bool less(BaseType const & d1, BaseType const & d2)
        { return d1.x < d2.x; }

    static difference_type difference(BaseType const & d1, BaseType const & d2)
        { return d1.x - d2.x; }

    static void increment(BaseType & d)
        { ++d.x; }

    static void decrement(BaseType & d)
        { --d.x; }

    static void advance(BaseType & d, difference_type n)
        { d.x += n; }
};

template <class Diff>
class Diff2DConstColumnIteratorPolicy
{
  public:
    typedef Diff                            BaseType;
    typedef Diff                            value_type;
    typedef typename Diff::MoveY            difference_type;
    typedef Diff const &                    reference;
    typedef Diff                            index_reference;
    typedef Diff const *                    pointer;
    typedef std::random_access_iterator_tag iterator_category;

    static void initialize(BaseType & /*d*/) {}

    static reference dereference(BaseType const & d)
        { return d; }

    static index_reference dereference(BaseType d, difference_type n)
    {
        d.y += n;
        return d;
    }

    static bool equal(BaseType const & d1, BaseType const & d2)
        { return d1.y == d2.y; }

    static bool less(BaseType const & d1, BaseType const & d2)
        { return d1.y < d2.y; }

    static difference_type difference(BaseType const & d1, BaseType const & d2)
        { return d1.y - d2.y; }

    static void increment(BaseType & d)
        { ++d.y; }

    static void decrement(BaseType & d)
        { --d.y; }

    static void advance(BaseType & d, difference_type n)
        { d.y += n; }
};

/** \addtogroup RangesAndPoints Two-dimensional Ranges and Points

    Specify a 2D position, extent, or rectangle.
*/
//@{

/********************************************************/
/*                                                      */
/*                      Diff2D                          */
/*                                                      */
/********************************************************/

/** \brief Two dimensional difference vector.

    This class acts primarily as a difference vector for specifying
    pixel coordinates and region sizes. In addition, Diff2D fulfills
    the requirements of an \ref ImageIterator, so that it can be used to
    simulate an image whose pixels' values equal their coordinates. This
    secondary usage is explained on page \ref CoordinateIterator.

    Standard usage as a difference vector is mainly needed in the context
    of images. For example, Diff2D may be used as an index for <TT>operator[]</TT>:

    \code
    vigra::Diff2D location(...);

    value = image[location];
    \endcode

    This is especially important in connection with accessors, where the
    offset variant of <TT>operator()</TT> takes only one offset object:

    \code
    // accessor(iterator, dx, dy); is not allowed
    value = accessor(iterator, vigra::Diff2D(dx, dy));
    \endcode


    Diff2D is also returned by <TT>image.size()</TT>, so that we can create
    new images by calculating their size using Diff2D's arithmetic
    functions:

    \code
    // create an image that is 10 pixels smaller in each direction
    Image new_image(old_image.size() - Diff2D(10,10));
    \endcode

    <b>\#include</b> <<a href="diff2d_8hxx-source.html">vigra/utilities.hxx</a>><br>
    Namespace: vigra
*/
00185 class Diff2D
{
  public:
        /** The iterator's value type: a coordinate.
        */
00190     typedef Diff2D PixelType;

        /** The iterator's value type: a coordinate.
        */
00194     typedef Diff2D value_type;

        /** the iterator's reference type (return type of <TT>*iter</TT>)
        */
00198     typedef Diff2D const &       reference;

        /** the iterator's index reference type (return type of <TT>iter[diff]</TT>)
        */
00202     typedef Diff2D               index_reference;

        /** the iterator's pointer type (return type of <TT>iter.operator->()</TT>)
        */
00206     typedef Diff2D const *       pointer;

        /** the iterator's difference type (argument type of <TT>iter[diff]</TT>)
        */
00210     typedef Diff2D               difference_type;

        /** the iterator tag (image traverser)
        */
00214     typedef image_traverser_tag  iterator_category;

        /** The associated row iterator.
        */
00218     typedef IteratorAdaptor<Diff2DConstRowIteratorPolicy<Diff2D> >    row_iterator;

        /** The associated column iterator.
        */
00222    typedef IteratorAdaptor<Diff2DConstColumnIteratorPolicy<Diff2D> > column_iterator;

        /** type of the iterator's x-navigator
        */
00226     typedef int MoveX;
        /** type of the iterator's y-navigator
        */
00229     typedef int MoveY;


        /** Default Constructor. Init iterator at position (0,0)
        */
00234     Diff2D()
    : x(0), y(0)
    {}

        /** Construct at given position.
        */
00240     Diff2D(int ax, int ay)
    : x(ax), y(ay)
    {}

        /** Copy Constructor.
        */
00246     Diff2D(Diff2D const & v)
    : x(v.x), y(v.y)
    {}

        /** Copy Assigment.
        */
00252     Diff2D & operator=(Diff2D const & v)
    {
        if(this != &v)
        {
            x = v.x;
            y = v.y;
        }
        return *this;
    }

        /** Unary negation.
        */
00264     Diff2D operator-() const
    {
        return Diff2D(-x, -y);
    }

        /** Increase coordinate by specified offset.
        */
00271     Diff2D & operator+=(Diff2D const & offset)
    {
        x += offset.x;
        y += offset.y;
        return *this;
    }

        /** Decrease coordinate by specified vector.
        */
00280     Diff2D & operator-=(Diff2D const & offset)
    {
        x -= offset.x;
        y -= offset.y;
        return *this;
    }

       /** Create vector by scaling by factor.
        */
00289     Diff2D & operator*=(int factor)
    {
        x *= factor;
        y *= factor;
        return *this;
    }

       /** Create vector by scaling by factor.
        */
00298     Diff2D & operator*=(double factor)
    {
        x = (int)(x * factor);
        y = (int)(y * factor);
        return *this;
    }

       /** Create vector by scaling by 1/factor.
        */
00307     Diff2D & operator/=(int factor)
    {
        x /= factor;
        y /= factor;
        return *this;
    }

       /** Create vector by scaling by 1/factor.
        */
00316     Diff2D & operator/=(double factor)
    {
        x = (int)(x / factor);
        y = (int)(y / factor);
        return *this;
    }

       /** Create vector by scaling by factor.
        */
00325     Diff2D operator*(int factor) const
    {
        return Diff2D(x * factor, y * factor);
    }

       /** Create vector by scaling by factor.
        */
00332     Diff2D operator*(double factor) const
    {
        return Diff2D((int)(x * factor), (int)(y * factor));
    }

       /** Create vector by scaling by 1/factor.
        */
00339     Diff2D operator/(int factor) const
    {
        return Diff2D(x / factor, y / factor);
    }

       /** Create vector by scaling by 1/factor.
        */
00346     Diff2D operator/(double factor) const
    {
        return Diff2D((int)(x / factor), (int)(y / factor));
    }

        /** Calculate length of difference vector.
        */
00353     int squaredMagnitude() const
    {
        return x*x + y*y;
    }

        /** Calculate length of difference vector.
        */
00360     double magnitude() const
    {
        return VIGRA_CSTD::sqrt((double)squaredMagnitude());
    }

        /** Equality.
        */
00367     bool operator==(Diff2D const & r) const
    {
        return (x == r.x) && (y == r.y);
    }

        /** Inequality.
        */
00374     bool operator!=(Diff2D const & r) const
    {
        return (x != r.x) || (y != r.y);
    }

        /** Used for both access to the current x-coordinate \em and
            to specify that an iterator navigation command is to be
            applied in x-direction. <br>
            usage:  <TT> x = diff2d.x </TT> (use \p Diff2D::x  as component of difference vector) <br>
            or <TT>&nbsp; ++diff.x &nbsp; </TT> (use Diff2D as iterator, move right)
         */
00385     int x;
        /** Used for both access to the current y-coordinate \em and
            to specify that an iterator navigation command is to be
            applied in y-direction. <br>
            usage:  <TT> y = diff2d.y </TT> (use \p Diff2D::y as component of difference vector) <br>
            or <TT>&nbsp; ++diff.y &nbsp; </TT> (use Diff2D as iterator, move right)
        */
00392     int y;

        /** Access current coordinate.
        */
00396     reference operator*() const
    {
        return *this;
    }

        /** Read coordinate at an offset.
        */
00403     index_reference operator()(int const & dx, int const & dy) const
    {
        return Diff2D(x + dx, y + dy);
    }

        /** Read coordinate at an offset.
        */
00410     index_reference operator[](Diff2D const & offset) const
    {
        return Diff2D(x + offset.x, y + offset.y);
    }

        /** Read vector components.
        */
00417     int operator[](int index) const
    {
        return (&x)[index];
    }

        /** Access current coordinate.
        */
00424     pointer operator->() const
    {
        return this;
    }

        /** Get a row iterator at the current position.
        */
00431     row_iterator rowIterator() const
        { return row_iterator(*this); }

        /** Get a column iterator at the current position.
        */
00436     column_iterator columnIterator() const
        { return column_iterator(*this); }
};


template <>
struct IteratorTraits<Diff2D >
{
    typedef Diff2D                               Iterator;
    typedef Iterator                             iterator;
    typedef Iterator                             const_iterator;
    // typedef                                   multable_iterator; undefined
    typedef iterator::iterator_category          iterator_category;
    typedef iterator::value_type                 value_type;
    typedef iterator::reference                  reference;
    typedef iterator::index_reference            index_reference;
    typedef iterator::pointer                    pointer;
    typedef iterator::difference_type            difference_type;
    typedef iterator::row_iterator               row_iterator;
    typedef iterator::column_iterator            column_iterator;
    typedef StandardConstValueAccessor<Diff2D>   DefaultAccessor;
    typedef StandardConstValueAccessor<Diff2D>   default_accessor;
    typedef VigraTrueType                        hasConstantStrides;

};


/********************************************************/
/*                                                      */
/*                      Size2D                          */
/*                                                      */
/********************************************************/

/** \brief Two dimensional size object.

    Specializes \ref Diff2D for the specification of a 2-dimensional
    extent, in contrast to a point or position (for the latter
    use \ref Point2D).

    \code
    // create an image that is 10 pixels squared
    Image new_image(Size2D(10,10));
    \endcode

    <b>\#include</b> <<a href="diff2d_8hxx-source.html">vigra/utilities.hxx</a>><br>
    Namespace: vigra
*/
00483 class Size2D : public Diff2D
{
public:
        /** Default Constructor. Init point at position (0,0)
        */
00488     Size2D()
    {}

        /** Construct point at given position.
        */
00493     Size2D(int width, int height)
    : Diff2D(width, height)
    {}

        /** Copy Constructor.
        */
00499     Size2D(Size2D const & v)
    : Diff2D(v)
    {}

        /** Explicit conversion Constructor.
        */
00505     explicit Size2D(Diff2D const & v)
    : Diff2D(v)
    {}

        /** Query the width.
         */
00511     int width() const
    {
        return x;
    }

        /** Query the height.
         */
00518     int height() const
    {
        return y;
    }

        /** Change the width.
         */
00525     void setWidth(int w)
    {
        x = w;
    }

        /** Change the height.
         */
00532     void setHeight(int h)
    {
        y = h;
    }

        /** Returns width()*height(), the area of a rectangle of this size.
         */
00539     int area() const
    {
        return width()*height();
    }

        /** Copy Assigment.
        */
00546     Size2D & operator=(Diff2D const & v)
    {
        return static_cast<Size2D &>(Diff2D::operator=(v));
    }

        /** Unary negation.
        */
00553     Size2D operator-() const
    {
        return Size2D(-x, -y);
    }

        /** Increase size by specified offset.
        */
00560     Size2D & operator+=(Diff2D const & offset)
    {
        return static_cast<Size2D &>(Diff2D::operator+=(offset));
    }

        /** Decrease size by specified offset.
        */
00567     Size2D & operator-=(Diff2D const & offset)
    {
        return static_cast<Size2D &>(Diff2D::operator-=(offset));
    }
};

/********************************************************/
/*                                                      */
/*                     Point2D                          */
/*                                                      */
/********************************************************/

/** \brief Two dimensional point or position.

    Specializes \ref Diff2D for the specification of a 2-dimensional
    point or position, in contrast to an extent (for the latter
    use \ref Size2D).

    \code
    // access an image at a point
    value = image[Point2D(10, 20)];
    \endcode

    <b>\#include</b> <<a href="diff2d_8hxx-source.html">vigra/utilities.hxx</a>><br>
    Namespace: vigra
*/
00593 class Point2D : public Diff2D
{
public:
        /** The iterator's value type: a coordinate.
        */
00598     typedef Point2D PixelType;

        /** The iterator's value type: a coordinate.
        */
00602     typedef Point2D value_type;

        /** the iterator's reference type (return type of <TT>*iter</TT>)
        */
00606     typedef Point2D const & reference;

        /** the iterator's index reference type (return type of <TT>iter[diff]</TT>)
        */
00610     typedef Point2D         index_reference;

        /** the iterator's pointer type (return type of <TT>iter.operator->()</TT>)
        */
00614     typedef Point2D const * pointer;

        /** Default Constructor. Init point at position (0,0)
        */
00618     Point2D()
    {}

        /** Construct point at given position.
        */
00623     Point2D(int x, int y)
    : Diff2D(x, y)
    {}

        /** Copy Constructor.
        */
00629     Point2D(Point2D const & v)
    : Diff2D(v)
    {}

        /** Explicit conversion Constructor.
        */
00635     explicit Point2D(Diff2D const & v)
    : Diff2D(v)
    {}

        /** Query the points' x coordinate
         */
00641     int px() const
    {
        return x;
    }

        /** Query the points' y coordinate
         */
00648     int py() const
    {
        return y;
    }

        /** Copy Assigment.
        */
00655     Point2D & operator=(Diff2D const & v)
    {
        return static_cast<Point2D &>(Diff2D::operator=(v));
    }

        /** Unary negation.
        */
00662     Point2D operator-() const
    {
        return Point2D(-x, -y);
    }

        /** Increase point coordinates by specified offset.
        */
00669     Point2D & operator+=(Diff2D const & offset)
    {
        return static_cast<Point2D &>(Diff2D::operator+=(offset));
    }

        /** Decrease point coordinates by specified offset.
        */
00676     Point2D & operator-=(Diff2D const & offset)
    {
        return static_cast<Point2D &>(Diff2D::operator-=(offset));
    }

        /** Access current point coordinate.
        */
00683     reference operator*() const
    {
        return *this;
    }

        /** Read point coordinate at an offset.
        */
00690     index_reference operator()(int const & dx, int const & dy) const
    {
        return Point2D(x + dx, y + dy);
    }

        /** Read point coordinate at an offset.
        */
00697     index_reference operator[](Diff2D const & offset) const
    {
        return Point2D(x + offset.x, y + offset.y);
    }

        /** Access current point coordinate.
        */
00704     pointer operator->() const
    {
        return this;
    }
};

/** Create vector by subtracting specified offset.
 */
00712 inline Diff2D operator-(Diff2D const &a, Diff2D const &b)
{
    return Diff2D(a.x - b.x, a.y - b.y);
}

/** Create size by subtracting specified offset.
 */
00719 inline Size2D operator-(Size2D const & s, Diff2D const &offset)
{
    return Size2D(s.x - offset.x, s.y - offset.y);
}

/** Calculate size of rect between two points.
 */
00726 inline Point2D operator-(Point2D const & s, Diff2D const & offset)
{
    return Point2D(s.x - offset.x, s.y - offset.y);
}

/** The difference of two points is a size
 */
00733 inline Size2D operator-(Point2D const & s, Point2D const & p)
{
    return Size2D(s.x - p.x, s.y - p.y);
}

/** Create vector by adding specified offset.
 */
00740 inline Diff2D operator+(Diff2D const &a, Diff2D const &b)
{
    return Diff2D(a.x + b.x, a.y + b.y);
}

/** Create size by adding specified offset.
 */
00747 inline Size2D operator+(Size2D const &a, Diff2D const &b)
{
    return Size2D(a.x + b.x, a.y + b.y);
}

/** Create point by adding specified offset.
 */
00754 inline Point2D operator+(Point2D const &a, Diff2D const &b)
{
    return Point2D(a.x + b.x, a.y + b.y);
}

/** Add size and point
 */
00761 inline Point2D operator+(Size2D const & s, Point2D const & p)
{
    return Point2D(s.x + p.x, s.y + p.y);
}

inline Point2D operator*(Point2D l, double r)
{
    l *= r;
    return l;
}

inline Point2D operator*(double l, Point2D r)
{
    r *= l;
    return r;
}

inline Size2D operator*(Size2D l, double r)
{
    l *= r;
    return l;
}

inline Size2D operator*(double l, Size2D r)
{
    r *= l;
    return r;
}

inline Point2D operator/(Point2D l, double r)
{
    l /= r;
    return l;
}

inline Size2D operator/(Size2D l, double r)
{
    l /= r;
    return l;
}

inline Point2D operator*(Point2D l, int r)
{
    l *= r;
    return l;
}

inline Point2D operator*(int l, Point2D r)
{
    r *= l;
    return r;
}

inline Size2D operator*(Size2D l, int r)
{
    l *= r;
    return l;
}

inline Size2D operator*(int l, Size2D r)
{
    r *= l;
    return r;
}

inline Point2D operator/(Point2D l, int r)
{
    l /= r;
    return l;
}

inline Size2D operator/(Size2D l, int r)
{
    l /= r;
    return l;
}


/********************************************************/
/*                                                      */
/*                      Rect2D                          */
/*                                                      */
/********************************************************/

/** \brief Two dimensional rectangle.

    This class stores a 2-dimensional rectangular range or region. Thus,
    it follows the VIGRA convention that the upper left corner is inside
    the rectangle, while the lower right is 1 pixel to the right and below the
    last pixel in the rectangle.

    A major advantage of this class is that it can be constructed from either
    a pair of \ref Point2D, or from a \ref Point2D and an extend
    (\ref Size2D). Rect2D overloads operators |=, &=, |, & to realize set
    union (in the sense of a minimal bounding rectangle) and set intersection.

    \code
    Rect2D r1(Point2D(0,0), Point2D(10, 20)),
           r2(Point2D(10, 15), Size2D(20, 20));
    Point2D p(0,100);

    Rect2D r3 =  r1 | r2; // upper left is (0,0), lower right is (30, 35)
    assert(r3.contains(r2));
    assert(!r3.contains(p));

    r3 |= p;       // lower right now (30,101) so that p is inside r3
    assert(r3.contains(p));
    \endcode

    <b>\#include</b> <<a href="diff2d_8hxx-source.html">vigra/utilities.hxx</a>><br>
    Namespace: vigra
*/
00873 class Rect2D
{
    Point2D upperLeft_, lowerRight_;

public:
        /** Construct a null rectangle (isEmpty() will return true)
         */
00880     Rect2D()
    {}

        /** Construct a rectangle representing the given range
         * (lowerRight is considered to be outside the rectangle as
         * usual in the VIGRA)
         */
00887     Rect2D(Point2D const &upperLeft, Point2D const &lowerRight)
    : upperLeft_(upperLeft), lowerRight_(lowerRight)
    {}

        /** Construct a rectangle representing the given range
         */
00893     Rect2D(int left, int top, int right, int bottom)
    : upperLeft_(left, top), lowerRight_(right, bottom)
    {}

        /** Construct a rectangle of given position and size
         */
00899     Rect2D(Point2D const &upperLeft, Size2D const &size)
    : upperLeft_(upperLeft), lowerRight_(upperLeft + size)
    {}

        /** Construct a rectangle of given size at position (0,0)
         */
00905     explicit Rect2D(Size2D const &size)
    : lowerRight_(Point2D(size))
    {}

        /** Return the first point (scan-order wise) which is
         * considered to be "in" the rectangle.
         */
00912     Point2D const & upperLeft() const
    {
        return upperLeft_;
    }

        /** Return the first point to the right and below the
         * rectangle.
         */
00920     Point2D const & lowerRight() const
    {
        return lowerRight_;
    }

        /** Change upperLeft() without changing lowerRight(), which
         * will change the size most probably.
         */
00928     void setUpperLeft(Point2D const &ul)
    {
        upperLeft_ = ul;
    }

        /** Change lowerRight() without changing upperLeft(), which
         * will change the size most probably.
         */
00936     void setLowerRight(Point2D const &lr)
    {
        lowerRight_ = lr;
    }

        /** Move the whole rectangle so that the given point will be
         * upperLeft() afterwards.
         */
00944     void moveTo(Point2D const &newUpperLeft)
    {
        lowerRight_ += newUpperLeft - upperLeft_;
        upperLeft_ = newUpperLeft;
    }

        /** Move the whole rectangle so that upperLeft() will become
         * Point2D(left, top) afterwards.
         */
00953     void moveTo(int left, int top)
    {
        moveTo(Point2D(left, top));
    }

        /** Move the whole rectangle by the given 2D offset.
         */
00960     void moveBy(Diff2D const &offset)
    {
        upperLeft_ += offset;
        lowerRight_ += offset;
    }

        /** Move the whole rectangle by the given x- and y-offsets.
         */
00968     void moveBy(int xOffset, int yOffset)
    {
        moveBy(Diff2D(xOffset, yOffset));
    }

        /** Return the left coordinate of this rectangle.
         */
00975     int left() const
    {
        return upperLeft_.x;
    }

        /** Return the top coordinate of this rectangle.
         */
00982     int top() const
    {
        return upperLeft_.y;
    }

        /** Return the right coordinate of this rectangle. That is the
         * first column to the right of the rectangle.
         */
00990     int right() const
    {
        return lowerRight_.x;
    }

        /** Return the bottom coordinate of this rectangle. That is the
         * first row below the rectangle.
         */
00998     int bottom() const
    {
        return lowerRight_.y;
    }

        /** Determine and return the width of this rectangle. It might be
         * zero or even negative, and if so, isEmpty() will return true.
         */
01006     int width() const
    {
        return lowerRight_.x - upperLeft_.x;
    }

        /** Determine and return the height of this rectangle. It might be
         * zero or even negative, and if so, isEmpty() will return true.
         */
01014     int height() const
    {
        return lowerRight_.y - upperLeft_.y;
    }

        /** Determine and return the area of this rectangle. That is, if
         * this rect isEmpty(), returns zero, otherwise returns
         * width()*height().
         */
01023     int area() const
    {
        return isEmpty() ? 0 : width()*height();
    }

        /** Determine and return the size of this rectangle. The width
         * and/or height might be zero or even negative, and if so,
         * isEmpty() will return true.
         */
01032     Size2D size() const
    {
        return lowerRight_ - upperLeft_;
    }

        /** Resize this rectangle to the given extents. This will move
         * the lower right corner only.
         */
01040     void setSize(Size2D const &size)
    {
        lowerRight_ = upperLeft_ + size;
    }

        /** Resize this rectangle to the given extents. This will move
         * the lower right corner only.
         */
01048     void setSize(int width, int height)
    {
        lowerRight_ = upperLeft_ + Size2D(width, height);
    }

        /** Increase the size of the rectangle by the given offset. This
         * will move the lower right corner only. (If any of offset's
         * components is negative, the rectangle will get smaller
         * accordingly.)
         */
01058     void addSize(Size2D const &offset)
    {
        lowerRight_ += offset;
    }

        /** Adds a border of the given width around the rectangle. That
         * means, upperLeft()'s components are moved by -borderWidth
         * and lowerRight()'s by borderWidth. (If borderWidth is
         * negative, the rectangle will get smaller accordingly.)
         */
01068     void addBorder(int borderWidth)
    {
        upperLeft_ += Diff2D(-borderWidth, -borderWidth);
        lowerRight_ += Diff2D(borderWidth, borderWidth);
    }

        /** Adds a border with possibly different widths in x- and
         * y-directions around the rectangle. That means, each x
         * component is moved borderWidth pixels and each y component
         * is moved borderHeight pixels to the outside. (If
         * borderWidth is negative, the rectangle will get smaller
         * accordingly.)
         */
01081     void addBorder(int borderWidth, int borderHeight)
    {
        upperLeft_ += Diff2D(-borderWidth, -borderHeight);
        lowerRight_ += Diff2D(borderWidth, borderHeight);
    }

        /// equality check
01088     bool operator==(Rect2D const &r) const
    {
        return (upperLeft_ == r.upperLeft_) && (lowerRight_ == r.lowerRight_);
    }

        /// inequality check
01094     bool operator!=(Rect2D const &r) const
    {
        return (upperLeft_ != r.upperLeft_) || (lowerRight_ != r.lowerRight_);
    }

        /** Return whether this rectangle is considered empty. It is
         * non-empty if both coordinates of the lower right corner are
         * greater than the corresponding coordinate of the upper left
         * corner. Uniting an empty rectangle with something will return
         * the bounding rectangle of the 'something', intersecting with an
         * empty rectangle will yield again an empty rectangle.
         */
01106     bool isEmpty() const
    {
        return ((lowerRight_.x <= upperLeft_.x) ||
                (lowerRight_.y <= upperLeft_.y));
    }

        /** Return whether this rectangle contains the given point. That
         * is, if the point lies within the valid range of an
         * ImageIterator walking from upperLeft() to lowerRight()
         * (excluding the latter).
         */
01117     bool contains(Point2D const &p) const
    {
        return ((upperLeft_.x <= p.x) &&
                (upperLeft_.y <= p.y) &&
                (p.x < lowerRight_.x) &&
                (p.y < lowerRight_.y));
    }

        /** Return whether this rectangle contains the given
         * one. <tt>r1.contains(r2)</tt> returns the same as
         * <tt>r1 == (r1|r2)</tt> (but is of course more
         * efficient). That also means, a rectangle (even an empty one!)
         * contains() any empty rectangle.
         */
01131     bool contains(Rect2D const &r) const
    {
        return r.isEmpty() ||
          (contains(r.upperLeft()) && contains(r.lowerRight()-Diff2D(1,1)));
    }

        /** Return whether this rectangle overlaps with the given
         * one. <tt>r1.intersects(r2)</tt> returns the same as
         * <tt>!(r1&r2).isEmpty()</tt> (but is of course much more
         * efficient).
         */
01142     bool intersects(Rect2D const &r) const
    {
        return ((r.upperLeft_.x < lowerRight_.x) &&
                (upperLeft_.x < r.lowerRight_.x) &&
                (r.upperLeft_.y < lowerRight_.y) &&
                (upperLeft_.y < r.lowerRight_.y))
            && !r.isEmpty();
    }

        /** Modifies this rectangle by including the given point. The
         * result is the bounding rectangle of the rectangle and the
         * point. If isEmpty returns true, the union will be a
         * rectangle containing only the given point.
         */
01156     Rect2D &operator|=(Point2D const &p)
    {
        if(isEmpty())
        {
            upperLeft_ = p;
            lowerRight_ = p + Diff2D(1, 1);
        }
        else
        {
            if(p.x < upperLeft_.x)
                upperLeft_.x = p.x;
            if(p.y < upperLeft_.y)
                upperLeft_.y = p.y;
            if(lowerRight_.x <= p.x)
                lowerRight_.x = p.x + 1;
            if(lowerRight_.y <= p.y)
                lowerRight_.y = p.y + 1;
        }
        return *this;
    }

        /** Returns the union of this rectangle and the given
         * point. The result is the bounding rectangle of the
         * rectangle and the point. If isEmpty returns true, the union
         * will be a rectangle containing only the given point.
         */
01182     Rect2D operator|(Point2D const &p) const
    {
        Rect2D result(*this);
        result |= p;
        return result;
    }

        /** Modifies this rectangle by uniting it with the given
         * one. The result is the bounding rectangle of both
         * rectangles. If one of the rectangles isEmpty(), the union
         * will be the other one.
         */
01194     Rect2D &operator|=(Rect2D const &r)
    {
        if(r.isEmpty())
            return *this;
        if(isEmpty())
            return operator=(r);

        if(r.upperLeft_.x < upperLeft_.x)
            upperLeft_.x = r.upperLeft_.x;
        if(r.upperLeft_.y < upperLeft_.y)
            upperLeft_.y = r.upperLeft_.y;
        if(lowerRight_.x < r.lowerRight_.x)
            lowerRight_.x = r.lowerRight_.x;
        if(lowerRight_.y < r.lowerRight_.y)
            lowerRight_.y = r.lowerRight_.y;
        return *this;
    }

        /** Returns the union of this rectangle and the given one. The
         * result is the bounding rectangle of both rectangles. If one
         * of the rectangles isEmpty(), the union will be the other
         * one.
         */
01217     Rect2D operator|(Rect2D const &r) const
    {
        Rect2D result(*this);
        result |= r;
        return result;
    }

        /** Modifies this rectangle by intersecting it with the given
         * point. The result is the bounding rect of the point (with
         * width and height equal to 1) if it was contained in the
         * original rect, or an empty rect otherwise.
         */
01229     Rect2D &operator&=(Point2D const &p)
    {
        if(contains(p))
        {
            upperLeft_ = p;
            lowerRight_ = p + Diff2D(1, 1);
        }
        else
            lowerRight_ = upperLeft_;
        return *this;
    }

        /** Intersects this rectangle with the given point. The result
         * is the bounding rect of the point (with width and height
         * equal to 1) if it was contained in the original rect, or an
         * empty rect otherwise.
         */
01246     Rect2D operator&(Point2D const &p) const
    {
        Rect2D result(*this);
        result &= p;
        return result;
    }

        /** Modifies this rectangle by intersecting it with the given
         * one. The result is the maximal rectangle contained in both
         * original ones. Intersecting with an empty rectangle will
         * yield again an empty rectangle.
         */
01258     Rect2D &operator&=(Rect2D const &r)
    {
        if(isEmpty())
            return *this;
        if(r.isEmpty())
            return operator=(r);

        if(upperLeft_.x < r.upperLeft_.x)
            upperLeft_.x = r.upperLeft_.x;
        if(upperLeft_.y < r.upperLeft_.y)
            upperLeft_.y = r.upperLeft_.y;
        if(r.lowerRight_.x < lowerRight_.x)
            lowerRight_.x = r.lowerRight_.x;
        if(r.lowerRight_.y < lowerRight_.y)
            lowerRight_.y = r.lowerRight_.y;
        return *this;
    }

        /** Intersects this rectangle with the given one. The result
         * is the maximal rectangle contained in both original ones.
         * Intersecting with an empty rectangle will yield again an
         * empty rectangle.
         */
01281     Rect2D operator&(Rect2D const &r) const
    {
        Rect2D result(*this);
        result &= r;
        return result;
    }
};

/********************************************************/
/*                                                      */
/*                      Dist2D                          */
/*                                                      */
/********************************************************/

/** @deprecated use \ref vigra::Diff2D instead
*/
01297 class Dist2D
{
  public:
    Dist2D(int the_width, int the_height)
    : width(the_width),
      height(the_height)
    {}

    Dist2D(Dist2D const & s)
    : width(s.width),
      height(s.height)
    {}

    Dist2D & operator=(Dist2D const & s)
    {
        if(this != &s)
        {
            width = s.width;
            height = s.height;
        }
        return *this;
    }

    Dist2D & operator+=(Dist2D const & s)
    {
        width += s.width;
        height += s.height;

        return *this;
    }

    Dist2D  operator+(Dist2D const & s) const
    {
        Dist2D ret(*this);
        ret += s;

        return ret;
    }

    operator Diff2D()
        { return Diff2D(width, height); }

    int width;
    int height;
 };

//@}

/**
 * Output a \ref vigra::Diff2D as a tuple.
 * Example Diff2D(-12, 13) -> "(-12, 13)"
 */
inline
std::ostream & operator<<(std::ostream & o, vigra::Diff2D const & d)
{
    o << '(' << d.x << ", " << d.y << ')';
    return o;
}

/**
 * Output a \ref vigra::Size2D.
 * Example Size2D(100, 200) -> "(100x200)"
 */
inline
std::ostream &operator <<(std::ostream &s, vigra::Size2D const &d)
{
    s << '(' << d.x << 'x' << d.y << ')';
    return s;
}

/**
 * Output a description of a \ref vigra::Rect2D.
 * Example Rect2D(10, 10, 30, 20) -> "[(10, 10) to (30, 20) = (20x10)]"
 */
inline
std::ostream &operator <<(std::ostream &s, vigra::Rect2D const &r)
{
    s << "[" << r.upperLeft() << " to " << r.lowerRight()
      << " = " << r.size() << "]";
    return s;
}

} // namespace vigra

#endif // VIGRA_DIFF2D_HXX

Generated by  Doxygen 1.6.0   Back to index