You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
637 lines
16 KiB
C++
637 lines
16 KiB
C++
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: vtkPixelExtenth.h
|
|
|
|
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
|
|
All rights reserved.
|
|
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY; without even
|
|
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
PURPOSE. See the above copyright notice for more information.
|
|
|
|
=========================================================================*/
|
|
/**
|
|
* @class vtkPixelExtent
|
|
*
|
|
* Representation of a cartesian pixel plane and common operations
|
|
* on it. The implementation is intended to be fast and light
|
|
* so that it may be used in place of int[4] with little or no
|
|
* performance penalty.
|
|
*
|
|
* NOTE in most cases operation on an empty object produces
|
|
* incorrect results. If it an issue query Empty() first.
|
|
*/
|
|
|
|
#ifndef vtkPixelExtent_h
|
|
#define vtkPixelExtent_h
|
|
|
|
#include "vtkCommonDataModelModule.h" // for export
|
|
#include "vtkSystemIncludes.h" // for VTK's system header config
|
|
|
|
#include <algorithm> // for inline impl
|
|
#include <climits> // for inline impl
|
|
#include <deque> // for inline impl
|
|
#include <iostream> // for inline impl
|
|
|
|
class VTKCOMMONDATAMODEL_EXPORT vtkPixelExtent
|
|
{
|
|
public:
|
|
vtkPixelExtent();
|
|
|
|
template <typename T>
|
|
vtkPixelExtent(const T* ext);
|
|
|
|
template <typename T>
|
|
vtkPixelExtent(T ilo, T ihi, T jlo, T jhi);
|
|
|
|
template <typename T>
|
|
vtkPixelExtent(T width, T height)
|
|
{
|
|
this->SetData(T(0), width - T(1), T(0), height - T(1));
|
|
}
|
|
|
|
vtkPixelExtent(const vtkPixelExtent& other);
|
|
|
|
vtkPixelExtent& operator=(const vtkPixelExtent& other);
|
|
|
|
/**
|
|
* Element access
|
|
*/
|
|
int& operator[](int i) { return this->Data[i]; }
|
|
const int& operator[](int i) const { return this->Data[i]; }
|
|
|
|
/**
|
|
* Set the extent.
|
|
*/
|
|
void SetData(const vtkPixelExtent& ext);
|
|
|
|
template <typename T>
|
|
void SetData(const T* ext);
|
|
|
|
template <typename T>
|
|
void SetData(T ilo, T ihi, T jlo, T jhi);
|
|
void Clear();
|
|
|
|
/**
|
|
* Direct access to internal data.
|
|
*/
|
|
int* GetData() { return this->Data; }
|
|
const int* GetData() const { return this->Data; }
|
|
|
|
template <typename T>
|
|
void GetData(T data[4]) const;
|
|
|
|
unsigned int* GetDataU() { return reinterpret_cast<unsigned int*>(this->Data); }
|
|
|
|
const unsigned int* GetDataU() const { return reinterpret_cast<const unsigned int*>(this->Data); }
|
|
|
|
//@{
|
|
/**
|
|
* Get the start/end index.
|
|
*/
|
|
void GetStartIndex(int first[2]) const;
|
|
void GetStartIndex(int first[2], const int origin[2]) const;
|
|
void GetEndIndex(int last[2]) const;
|
|
//@}
|
|
|
|
/**
|
|
* Return true if empty.
|
|
*/
|
|
int Empty() const;
|
|
|
|
/**
|
|
* Test for equivalence.
|
|
*/
|
|
bool operator==(const vtkPixelExtent& other) const;
|
|
|
|
//@{
|
|
/**
|
|
* Return non-zero if this extent contains the other.
|
|
*/
|
|
int Contains(const vtkPixelExtent& other) const;
|
|
int Contains(int i, int j) const;
|
|
//@}
|
|
|
|
/**
|
|
* Return non-zero if the extent is disjoint from the other
|
|
*/
|
|
int Disjoint(vtkPixelExtent other) const;
|
|
|
|
/**
|
|
* Get the number in each direction.
|
|
*/
|
|
template <typename T>
|
|
void Size(T nCells[2]) const;
|
|
|
|
/**
|
|
* Get the total number.
|
|
*/
|
|
size_t Size() const;
|
|
|
|
/**
|
|
* In place intersection.
|
|
*/
|
|
void operator&=(const vtkPixelExtent& other);
|
|
|
|
/**
|
|
* In place union
|
|
*/
|
|
void operator|=(const vtkPixelExtent& other);
|
|
|
|
//@{
|
|
/**
|
|
* Expand the extents by n.
|
|
*/
|
|
void Grow(int n);
|
|
void Grow(int q, int n);
|
|
void GrowLow(int q, int n);
|
|
void GrowHigh(int q, int n);
|
|
//@}
|
|
|
|
//@{
|
|
/**
|
|
* Shrink the extent by n.
|
|
*/
|
|
void Shrink(int n);
|
|
void Shrink(int q, int n);
|
|
//@}
|
|
|
|
/**
|
|
* Shifts by low corner of this, moving to the origin.
|
|
*/
|
|
void Shift();
|
|
|
|
/**
|
|
* Shift by low corner of the given extent.
|
|
*/
|
|
void Shift(const vtkPixelExtent& ext);
|
|
|
|
/**
|
|
* Shift by the given amount.
|
|
*/
|
|
void Shift(int* n);
|
|
|
|
/**
|
|
* Shift by the given amount in the given direction.
|
|
*/
|
|
void Shift(int q, int n);
|
|
|
|
/**
|
|
* Divide the extent in half in the given direction. The
|
|
* operation is done in-place the other half of the split
|
|
* extent is returned. The return will be empty if the split
|
|
* could not be made.
|
|
*/
|
|
vtkPixelExtent Split(int dir);
|
|
|
|
//@{
|
|
/**
|
|
* In-place conversion from cell based to node based extent, and vise-versa.
|
|
*/
|
|
void CellToNode();
|
|
void NodeToCell();
|
|
//@}
|
|
|
|
/**
|
|
* Get the number in each direction.
|
|
*/
|
|
template <typename T>
|
|
static void Size(const vtkPixelExtent& ext, T nCells[2]);
|
|
|
|
/**
|
|
* Get the total number.
|
|
*/
|
|
static size_t Size(const vtkPixelExtent& ext);
|
|
|
|
/**
|
|
* Add or remove ghost cells. If a problem domain is
|
|
* provided then the result is clipled to be within the
|
|
* problem domain.
|
|
*/
|
|
static vtkPixelExtent Grow(const vtkPixelExtent& inputExt, int n);
|
|
|
|
static vtkPixelExtent Grow(
|
|
const vtkPixelExtent& inputExt, const vtkPixelExtent& problemDomain, int n);
|
|
|
|
static vtkPixelExtent GrowLow(const vtkPixelExtent& ext, int q, int n);
|
|
|
|
static vtkPixelExtent GrowHigh(const vtkPixelExtent& ext, int q, int n);
|
|
|
|
/**
|
|
* Remove ghost cells. If a problem domain is
|
|
* provided the input is pinned at the domain.
|
|
*/
|
|
static vtkPixelExtent Shrink(
|
|
const vtkPixelExtent& inputExt, const vtkPixelExtent& problemDomain, int n);
|
|
|
|
static vtkPixelExtent Shrink(const vtkPixelExtent& inputExt, int n);
|
|
|
|
/**
|
|
* Convert from point extent to cell extent
|
|
* while respecting the dimensionality of the data.
|
|
*/
|
|
static vtkPixelExtent NodeToCell(const vtkPixelExtent& inputExt);
|
|
|
|
/**
|
|
* Convert from cell extent to point extent
|
|
* while respecting the dimensionality of the data.
|
|
*/
|
|
static vtkPixelExtent CellToNode(const vtkPixelExtent& inputExt);
|
|
|
|
//@{
|
|
/**
|
|
* Shift by the given amount while respecting mode.
|
|
*/
|
|
static void Shift(int* ij, int n);
|
|
static void Shift(int* ij, int* n);
|
|
//@}
|
|
|
|
/**
|
|
* Split ext at i,j, resulting extents (up to 4) are appended
|
|
* to newExts. If i,j is outside ext, ext is passed through
|
|
* unmodified.
|
|
*/
|
|
static void Split(int i, int j, const vtkPixelExtent& ext, std::deque<vtkPixelExtent>& newExts);
|
|
|
|
/**
|
|
* A - B = C
|
|
* C is a set of disjoint extents such that the
|
|
* intersection of B and C is empty and the intersection
|
|
* of A and C is C.
|
|
*/
|
|
static void Subtract(
|
|
const vtkPixelExtent& A, const vtkPixelExtent& B, std::deque<vtkPixelExtent>& newExts);
|
|
|
|
/**
|
|
* Merge compatible extents in the list. Extents are compatible
|
|
* if they are directly adjacent nad have the same extent along
|
|
* the adjacent edge.
|
|
*/
|
|
static void Merge(std::deque<vtkPixelExtent>& exts);
|
|
|
|
private:
|
|
int Data[4];
|
|
};
|
|
|
|
/**
|
|
* Stream insertion operator for formatted output of pixel extents.
|
|
*/
|
|
VTKCOMMONDATAMODEL_EXPORT
|
|
std::ostream& operator<<(std::ostream& os, const vtkPixelExtent& ext);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
void vtkPixelExtent::SetData(const T* ext)
|
|
{
|
|
Data[0] = static_cast<int>(ext[0]);
|
|
Data[1] = static_cast<int>(ext[1]);
|
|
Data[2] = static_cast<int>(ext[2]);
|
|
Data[3] = static_cast<int>(ext[3]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
void vtkPixelExtent::SetData(T ilo, T ihi, T jlo, T jhi)
|
|
{
|
|
T ext[4] = { ilo, ihi, jlo, jhi };
|
|
this->SetData(ext);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::SetData(const vtkPixelExtent& other)
|
|
{
|
|
this->SetData(other.GetData());
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
void vtkPixelExtent::GetData(T data[4]) const
|
|
{
|
|
data[0] = static_cast<T>(this->Data[0]);
|
|
data[1] = static_cast<T>(this->Data[1]);
|
|
data[2] = static_cast<T>(this->Data[2]);
|
|
data[3] = static_cast<T>(this->Data[3]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::Clear()
|
|
{
|
|
this->SetData<int>(INT_MAX, INT_MIN, INT_MAX, INT_MIN);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline vtkPixelExtent::vtkPixelExtent()
|
|
{
|
|
this->Clear();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
vtkPixelExtent::vtkPixelExtent(const T* ext)
|
|
{
|
|
this->SetData(ext);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
vtkPixelExtent::vtkPixelExtent(T ilo, T ihi, T jlo, T jhi)
|
|
{
|
|
this->SetData(ilo, ihi, jlo, jhi);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline vtkPixelExtent& vtkPixelExtent::operator=(const vtkPixelExtent& other)
|
|
{
|
|
if (&other != this)
|
|
{
|
|
this->Data[0] = other.Data[0];
|
|
this->Data[1] = other.Data[1];
|
|
this->Data[2] = other.Data[2];
|
|
this->Data[3] = other.Data[3];
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline vtkPixelExtent::vtkPixelExtent(const vtkPixelExtent& other)
|
|
{
|
|
*this = other;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
void vtkPixelExtent::Size(const vtkPixelExtent& ext, T nCells[2])
|
|
{
|
|
nCells[0] = ext[1] - ext[0] + 1;
|
|
nCells[1] = ext[3] - ext[2] + 1;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline size_t vtkPixelExtent::Size(const vtkPixelExtent& ext)
|
|
{
|
|
return (ext[1] - ext[0] + 1) * (ext[3] - ext[2] + 1);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
template <typename T>
|
|
void vtkPixelExtent::Size(T nCells[2]) const
|
|
{
|
|
vtkPixelExtent::Size(*this, nCells);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline size_t vtkPixelExtent::Size() const
|
|
{
|
|
return vtkPixelExtent::Size(*this);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::GetStartIndex(int first[2]) const
|
|
{
|
|
first[0] = this->Data[0];
|
|
first[1] = this->Data[2];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::GetStartIndex(int first[2], const int origin[2]) const
|
|
{
|
|
first[0] = this->Data[0] - origin[0];
|
|
first[1] = this->Data[2] - origin[1];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::GetEndIndex(int last[2]) const
|
|
{
|
|
last[0] = this->Data[1];
|
|
last[1] = this->Data[3];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline int vtkPixelExtent::Empty() const
|
|
{
|
|
if (this->Data[0] > this->Data[1] || this->Data[2] > this->Data[3])
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline bool vtkPixelExtent::operator==(const vtkPixelExtent& other) const
|
|
{
|
|
if ((this->Data[0] == other.Data[0]) && (this->Data[1] == other.Data[1]) &&
|
|
(this->Data[2] == other.Data[2]) && (this->Data[3] == other.Data[3]))
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline int vtkPixelExtent::Contains(const vtkPixelExtent& other) const
|
|
{
|
|
if ((this->Data[0] <= other.Data[0]) && (this->Data[1] >= other.Data[1]) &&
|
|
(this->Data[2] <= other.Data[2]) && (this->Data[3] >= other.Data[3]))
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline int vtkPixelExtent::Contains(int i, int j) const
|
|
{
|
|
if ((this->Data[0] <= i) && (this->Data[1] >= i) && (this->Data[2] <= j) && (this->Data[3] >= j))
|
|
{
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::operator&=(const vtkPixelExtent& other)
|
|
{
|
|
if (this->Empty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (other.Empty())
|
|
{
|
|
this->Clear();
|
|
return;
|
|
}
|
|
|
|
this->Data[0] = std::max(this->Data[0], other.Data[0]);
|
|
this->Data[1] = std::min(this->Data[1], other.Data[1]);
|
|
this->Data[2] = std::max(this->Data[2], other.Data[2]);
|
|
this->Data[3] = std::min(this->Data[3], other.Data[3]);
|
|
|
|
if (this->Empty())
|
|
{
|
|
this->Clear();
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::operator|=(const vtkPixelExtent& other)
|
|
{
|
|
if (other.Empty())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (this->Empty())
|
|
{
|
|
this->SetData(other.GetData());
|
|
return;
|
|
}
|
|
|
|
this->Data[0] = std::min(this->Data[0], other.Data[0]);
|
|
this->Data[1] = std::max(this->Data[1], other.Data[1]);
|
|
this->Data[2] = std::min(this->Data[2], other.Data[2]);
|
|
this->Data[3] = std::max(this->Data[3], other.Data[3]);
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline int vtkPixelExtent::Disjoint(vtkPixelExtent other) const
|
|
{
|
|
other &= *this;
|
|
return other.Empty();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::Grow(int n)
|
|
{
|
|
this->Data[0] -= n;
|
|
this->Data[1] += n;
|
|
this->Data[2] -= n;
|
|
this->Data[3] += n;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::Grow(int q, int n)
|
|
{
|
|
q *= 2;
|
|
|
|
this->Data[q] -= n;
|
|
this->Data[q + 1] += n;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::GrowLow(int q, int n)
|
|
{
|
|
this->Data[2 * q] -= n;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::GrowHigh(int q, int n)
|
|
{
|
|
this->Data[2 * q + 1] += n;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::Shrink(int n)
|
|
{
|
|
this->Data[0] += n;
|
|
this->Data[1] -= n;
|
|
this->Data[2] += n;
|
|
this->Data[3] -= n;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::Shrink(int q, int n)
|
|
{
|
|
q *= 2;
|
|
this->Data[q] += n;
|
|
this->Data[q + 1] -= n;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::Shift(int* n)
|
|
{
|
|
this->Data[0] += n[0];
|
|
this->Data[1] += n[0];
|
|
this->Data[2] += n[1];
|
|
this->Data[3] += n[1];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::Shift(int q, int n)
|
|
{
|
|
q *= 2;
|
|
this->Data[q] += n;
|
|
this->Data[q + 1] += n;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::Shift(const vtkPixelExtent& other)
|
|
{
|
|
for (int q = 0; q < 2; ++q)
|
|
{
|
|
int qq = q * 2;
|
|
int n = -other[qq];
|
|
|
|
this->Data[qq] += n;
|
|
this->Data[qq + 1] += n;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::Shift()
|
|
{
|
|
for (int q = 0; q < 2; ++q)
|
|
{
|
|
int qq = q * 2;
|
|
int n = -this->Data[qq];
|
|
|
|
this->Data[qq] += n;
|
|
this->Data[qq + 1] += n;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline vtkPixelExtent vtkPixelExtent::Split(int dir)
|
|
{
|
|
vtkPixelExtent half;
|
|
|
|
int q = 2 * dir;
|
|
int l = this->Data[q + 1] - this->Data[q] + 1;
|
|
int s = l / 2;
|
|
|
|
if (s)
|
|
{
|
|
s += this->Data[q];
|
|
half = *this;
|
|
half.Data[q] = s;
|
|
this->Data[q + 1] = s - 1;
|
|
}
|
|
|
|
return half;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::CellToNode()
|
|
{
|
|
++this->Data[1];
|
|
++this->Data[3];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline void vtkPixelExtent::NodeToCell()
|
|
{
|
|
--this->Data[1];
|
|
--this->Data[3];
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
inline bool operator<(const vtkPixelExtent& l, const vtkPixelExtent& r)
|
|
{
|
|
return l.Size() < r.Size();
|
|
}
|
|
|
|
#endif
|
|
// VTK-HeaderTest-Exclude: vtkPixelExtent.h
|