/***********************************************************************
* frect.cpp - Rectangle with position and size *
* *
* This file is part of the FINAL CUT widget toolkit *
* *
* Copyright 2014-2020 Markus Gans *
* *
* FINAL CUT is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as *
* published by the Free Software Foundation; either version 3 of *
* the License, or (at your option) any later version. *
* *
* FINAL CUT is distributed in the hope that it will be useful, but *
* WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public *
* License along with this program. If not, see *
* . *
***********************************************************************/
#include
#include
#include "final/fpoint.h"
#include "final/frect.h"
#include "final/fsize.h"
namespace finalcut
{
//----------------------------------------------------------------------
// class FRect
//----------------------------------------------------------------------
// constructor and destructor
//----------------------------------------------------------------------
FRect::FRect (const FPoint& p, const FSize& s)
: X1{p.getX()}
, Y1{p.getY()}
, X2{p.getX() + int(s.getWidth()) - 1}
, Y2{p.getY() + int(s.getHeight()) - 1}
{ }
//----------------------------------------------------------------------
FRect::FRect (const FPoint& p1, const FPoint& p2)
: X1{p1.getX()}
, Y1{p1.getY()}
, X2{p2.getX()}
, Y2{p2.getY()}
{ }
//----------------------------------------------------------------------
FRect::~FRect() // destructor
{ }
// public methods of FRect
//----------------------------------------------------------------------
FRect& FRect::operator = (const FRect& r)
{
X1 = r.X1;
Y1 = r.Y1;
X2 = r.X2;
Y2 = r.Y2;
return *this;
}
//----------------------------------------------------------------------
FRect& FRect::operator = (FRect&& r) noexcept
{
X1 = std::move(r.X1);
Y1 = std::move(r.Y1);
X2 = std::move(r.X2);
Y2 = std::move(r.Y2);
return *this;
}
//----------------------------------------------------------------------
bool FRect::isEmpty() const
{
return X2 == X1 - 1 && Y2 == Y1 - 1;
}
//----------------------------------------------------------------------
FPoint FRect::getPos() const
{
return { X1, Y1 };
}
//----------------------------------------------------------------------
FPoint FRect::getUpperLeftPos() const
{
return { X1, Y1 };
}
//----------------------------------------------------------------------
FPoint FRect::getUpperRightPos() const
{
return { X2, Y1 };
}
//----------------------------------------------------------------------
FPoint FRect::getLowerLeftPos() const
{
return { X1, Y2 };
}
//----------------------------------------------------------------------
FPoint FRect::getLowerRightPos() const
{
return { X2, Y2 };
}
//----------------------------------------------------------------------
FSize FRect::getSize() const
{
return { getWidth(), getHeight() };
}
//----------------------------------------------------------------------
void FRect::setX1 (int n)
{
X1 = n;
}
//----------------------------------------------------------------------
void FRect::setY1 (int n)
{
Y1 = n;
}
//----------------------------------------------------------------------
void FRect::setX2 (int n)
{
X2 = n;
}
//----------------------------------------------------------------------
void FRect::setY2 (int n)
{
Y2 = n;
}
//----------------------------------------------------------------------
void FRect::setX (int n)
{
const int dX = X2 - X1;
X1 = n;
X2 = X1 + dX;
}
//----------------------------------------------------------------------
void FRect::setY (int n)
{
const int dY = Y2 - Y1;
Y1 = n;
Y2 = Y1 + dY;
}
//----------------------------------------------------------------------
void FRect::setPos (int x, int y)
{
const int dX = X2 - X1;
const int dY = Y2 - Y1;
X1 = x;
Y1 = y;
X2 = X1 + dX;
Y2 = Y1 + dY;
}
//----------------------------------------------------------------------
void FRect::setPos (const FPoint& p)
{
const int dX = X2 - X1;
const int dY = Y2 - Y1;
X1 = p.getX();
Y1 = p.getY();
X2 = X1 + dX;
Y2 = Y1 + dY;
}
//----------------------------------------------------------------------
void FRect::setWidth (std::size_t w)
{
X2 = X1 + int(w) - 1;
}
//----------------------------------------------------------------------
void FRect::setHeight (std::size_t h)
{
Y2 = Y1 + int(h) - 1;
}
//----------------------------------------------------------------------
void FRect::setSize (std::size_t width, std::size_t height)
{
X2 = X1 + int(width) - 1;
Y2 = Y1 + int(height) - 1;
}
//----------------------------------------------------------------------
void FRect::setSize (const FSize& s)
{
X2 = X1 + int(s.getWidth()) - 1;
Y2 = Y1 + int(s.getHeight()) - 1;
}
//----------------------------------------------------------------------
void FRect::setRect (const FRect& r)
{
X1 = r.X1;
Y1 = r.Y1;
X2 = r.X2;
Y2 = r.Y2;
}
//----------------------------------------------------------------------
void FRect::setRect (const FPoint& p, const FSize& s)
{
X1 = p.getX();
Y1 = p.getY();
X2 = p.getX() + int(s.getWidth()) - 1;
Y2 = p.getY() + int(s.getHeight()) - 1;
}
//----------------------------------------------------------------------
void FRect::setRect (int x, int y, std::size_t width, std::size_t height)
{
X1 = x;
Y1 = y;
X2 = x + int(width) - 1;
Y2 = y + int(height) - 1;
}
//----------------------------------------------------------------------
void FRect::setCoordinates (const FPoint& p1, const FPoint& p2)
{
setCoordinates (p1.getX(), p1.getY(), p2.getX(), p2.getY());
}
//----------------------------------------------------------------------
void FRect::setCoordinates (int x1, int y1, int x2, int y2)
{
X1 = x1;
Y1 = y1;
X2 = x2;
Y2 = y2;
}
//----------------------------------------------------------------------
void FRect::move (int dx, int dy)
{
X1 += dx;
Y1 += dy;
X2 += dx;
Y2 += dy;
}
//----------------------------------------------------------------------
void FRect::move (const FPoint& d)
{
X1 += d.getX();
Y1 += d.getY();
X2 += d.getX();
Y2 += d.getY();
}
//----------------------------------------------------------------------
void FRect::scaleBy (int dx, int dy)
{
X2 += dx;
Y2 += dy;
}
//----------------------------------------------------------------------
void FRect::scaleBy (const FPoint& d)
{
X2 += d.getX();
Y2 += d.getY();
}
//----------------------------------------------------------------------
bool FRect::contains (int x, int y) const
{
return x >= X1 && x <= X2
&& y >= Y1 && y <= Y2;
}
//----------------------------------------------------------------------
bool FRect::contains (const FPoint& p) const
{
return p.getX() >= X1 && p.getX() <= X2
&& p.getY() >= Y1 && p.getY() <= Y2;
}
//----------------------------------------------------------------------
bool FRect::contains (const FRect& r) const
{
return r.X1 >= X1 && r.X2 <= X2
&& r.Y1 >= Y1 && r.Y2 <= Y2;
}
//----------------------------------------------------------------------
bool FRect::overlap (const FRect &r) const
{
return ( std::max(X1, r.X1) <= std::min(X2, r.X2)
&& std::max(Y1, r.Y1) <= std::min(Y2, r.Y2) );
}
//----------------------------------------------------------------------
FRect FRect::intersect (const FRect& r) const
{
// intersection: this ∩ r
int _X1 = std::max(X1, r.X1);
int _Y1 = std::max(Y1, r.Y1);
int _X2 = std::min(X2, r.X2);
int _Y2 = std::min(Y2, r.Y2);
const FPoint p1{ _X1, _Y1 };
const FPoint p2{ _X2, _Y2 };
return { p1, p2 };
}
//----------------------------------------------------------------------
FRect FRect::combined (const FRect& r) const
{
// Union: this ∪ r
int _X1 = std::min(X1, r.X1);
int _Y1 = std::min(Y1, r.Y1);
int _X2 = std::max(X2, r.X2);
int _Y2 = std::max(Y2, r.Y2);
const FPoint p1{ _X1, _Y1 };
const FPoint p2{ _X2, _Y2 };
return { p1, p2 };
}
// FRect non-member operators
//----------------------------------------------------------------------
FRect operator + (const FRect& r, const FSize& s)
{
return { r.X1
, r.Y1
, std::size_t(r.X2 - r.X1) + 1 + s.getWidth()
, std::size_t(r.Y2 - r.Y1) + 1 + s.getHeight() };
}
//----------------------------------------------------------------------
FRect operator - (const FRect& r, const FSize& s)
{
return { r.X1
, r.Y1
, std::size_t(r.X2 - r.X1) + 1 - s.getWidth()
, std::size_t(r.Y2 - r.Y1) + 1 - s.getHeight() };
}
//----------------------------------------------------------------------
bool operator == (const FRect& r1, const FRect& r2)
{
return r1.X1 == r2.X1
&& r1.Y1 == r2.Y1
&& r1.X2 == r2.X2
&& r1.Y2 == r2.Y2;
}
//----------------------------------------------------------------------
bool operator != (const FRect& r1, const FRect& r2)
{
return r1.X1 != r2.X1
|| r1.Y1 != r2.Y1
|| r1.X2 != r2.X2
|| r1.Y2 != r2.Y2;
}
//----------------------------------------------------------------------
std::ostream& operator << (std::ostream& outstr, const FRect& r)
{
outstr << r.X1 << " "
<< r.Y1 << " "
<< r.X2 << " "
<< r.Y2;
return outstr;
}
//----------------------------------------------------------------------
std::istream& operator >> (std::istream& instr, FRect& r)
{
int x1{};
int y1{};
int x2{};
int y2{};
instr >> x1;
instr >> y1;
instr >> x2;
instr >> y2;
r.setCoordinates (x1, y1, x2, y2);
return instr;
}
} // namespace finalcut