6 #include "errmessages.h"
14 template<
class Po
intType=Coordinate>
class Box :
public Range{
16 enum Dimension{dim0=0, dimX=1, dimY=2, dimZ=4};
18 Box() : _min_corner(PointType(0,0,0)), _max_corner(PointType(0,0,0)){
21 Box(
const PointType& pMin,
const PointType& pMax) : _min_corner(pMin), _max_corner(pMax){
25 Box(
const Box<PointType>& bx) : _min_corner(bx.min_corner()), _max_corner(bx.max_corner()) {
29 Box(Box<PointType>&& box) :
30 _min_corner(std::move(box._min_corner)),
31 _max_corner(std::move(box._max_corner))
33 box._min_corner = box._max_corner = PointType();
36 Box(
const QSize& sz) : _min_corner(PointType(0,0,0)),_max_corner(PointType(sz.width()-1, sz.height()-1),0){
39 template<
typename T> Box(
const Size<T>& sz) : _min_corner(PointType(0,0,0)),_max_corner(PointType(sz.xsize()-1, sz.ysize()-1,sz.zsize()-1)){
46 Box(
const QString& envelope) : _min_corner(PointType(0,0)), _max_corner(PointType(0,0)){
47 int index1 = envelope.indexOf(
"(");
49 int index2 = envelope.indexOf(
")") ;
54 QString coords = envelope.mid(index1+1, index2 - index1 - 1);
55 coords = coords.trimmed();
56 QStringList parts = coords.split(
",");
57 if ( parts.size() != 2){
60 QStringList p1 = parts[0].trimmed().split(
' ');
63 this->min_corner().x = p1[0].trimmed().toDouble();
64 this->min_corner().y = p1[1].trimmed().toDouble();
66 this->min_corner().z = p1[2].trimmed().toDouble();
68 QStringList p2 = parts[1].trimmed().split(
' ');
70 this->min_corner().x = 0;
71 this->min_corner().y = 0;
72 this->min_corner().z = 0;
75 this->max_corner().x = p2[0].trimmed().toDouble();
76 this->max_corner().y = p2[1].trimmed().toDouble();
78 this->max_corner().z = p2[2].trimmed().toDouble();
83 return max_corner().valuetype();
91 PointType min_corner()
const {
95 PointType max_corner()
const {
99 PointType& min_corner() {
103 PointType& max_corner() {
107 double xlength()
const {
108 return std::abs(this->min_corner().x - this->max_corner().x) + 1;
111 double ylength()
const {
112 return std::abs(this->min_corner().y - this->max_corner().y) + 1;
115 double zlength()
const {
116 return std::abs(this->min_corner().z - this->max_corner().z) + 1;
119 template<
typename T=qu
int32> Size<T> size()
const {
120 return Size<T>(xlength(), ylength(), zlength());
124 return this->min_corner().is3D() && this->max_corner().is3D();
126 quint64 area()
const {
129 return xlength() * ylength();
132 quint64 volume()
const {
135 return xlength() * ylength() * zlength();
138 bool contains(
const PointType& p)
const {
144 const PointType& pmin = this->min_corner();
145 const PointType& pmax = this->max_corner();
146 bool ok = p.x >= pmin.x && p.x <= pmax.x &&
147 p.y >= pmin.y && p.y <= pmax.y;
148 if ( is3D() && p.is3D()) {
149 ok = p.z >= pmin.z && p.z <= pmax.z;
154 bool contains(Box<PointType>& box)
const{
155 return contains(box.min_corner()) && contains(box.max_corner());
158 bool contains(
const QVariant& value,
bool inclusive =
true)
const {
163 bool equals(Box<PointType>& box,
double delta=0)
const {
169 const PointType& pmin = box.min_corner();
170 const PointType& pmax = box.max_corner();
172 if ( std::abs( min_corner.x - pmin.x) > delta)
174 if ( std::abs( min_corner.y - pmin.y) > delta)
176 if ( std::abs( max_corner.x - pmax.x) > delta)
178 if ( std::abs( max_corner.y - pmax.y) > delta)
180 if ( is3D() && box.is3D()) {
181 if ( std::abs( min_corner.z - pmin.z) > delta)
183 if ( std::abs( max_corner.z - pmax.z) > delta)
190 return this->min_corner().isValid() && this->max_corner().isValid();
193 bool isNull()
const {
194 bool ok = this->min_corner().x == 0 && this->min_corner().y == 0 &&
195 this->max_corner().x == 0 && this->max_corner().y == 0;
197 ok &= this->min_corner().z == 0 && this->max_corner().z == 0;
202 Box<PointType>& operator=(Box<PointType>&& box) {
203 _min_corner = std::move(box._min_corner);
204 _max_corner = std::move(box._max_corner);
206 box._min_corner = box._max_corner = PointType();
210 Box<PointType>& operator=(
const Box<PointType>& box) {
211 _min_corner = std::move(box._min_corner);
212 _max_corner = std::move(box._max_corner);
216 Box<PointType>& operator +=(
const double& v) {
217 if ( isNumericalUndef(v))
220 PointType& pmin = this->min_corner();
221 PointType& pmax = this->max_corner();
227 Box<PointType>& operator *=(
const double& v) {
228 if ( isNumericalUndef(v))
230 PointType& pmin = this->min_corner();
231 PointType& pmax = this->max_corner();
232 double deltaX = xlength() * v / 2;
233 double deltaY = ylength() * v / 2;
236 deltaZ = zlength() * v / 2;
237 pmin *= {deltaX, deltaY, deltaZ};
238 pmax *= {deltaX, deltaY, deltaZ};
242 Box<PointType>& operator +=(
const PointType& pnew) {
243 if ( !pnew.isValid())
248 PointType& pmin = this->min_corner();
249 PointType& pmax = this->max_corner();
258 if ( pmin.x > pnew.x)
260 if ( pmin.y > pnew.y)
262 if ( pmax.x < pnew.x)
264 if ( pmax.y < pnew.y)
266 if ( is3D() && pnew.is3D()){
267 if ( pmin.z > pnew.z)
269 if ( pmax.z < pnew.z)
278 Box<PointType>& operator -=(
const PointType& pnew) {
279 if ( !pnew.isValid())
282 PointType& pmin = this->min_corner();
283 PointType& pmax = this->max_corner();
291 if ( !contains(pnew))
293 if ( pmin.x() < pnew.x())
295 if ( pmin.y < pnew.y)
297 if ( pmax.x > pnew.x)
299 if ( pmax.y > pnew.y)
301 if ( is3D() && pnew.is3D()){
302 if ( pmin.z < pnew.z)
304 if ( pmax.z > pnew.z)
313 template<
class T> Box<PointType>& operator +=(
const std::vector<T>& vec) {
314 int size = vec.size();
315 if ( size == 2 || size == 3) {
316 this->min_corner() += vec;
317 this->max_corner() += vec;
324 Box<PointType>& operator +=(
const Box<PointType>& box) {
328 operator+=(box.min_corner());
329 operator+=(box.max_corner());
333 bool operator==(
const Box<PointType>& box )
const {
337 return box.max_corner() == this->max_corner() && this->min_corner() == box.min_corner();
340 bool operator!=(
const Box<PointType>& box )
const {
341 return !(operator==(box));
344 QVariant impliedValue(
const QVariant& v)
const{
345 QString type = v.typeName();
346 bool ok = type ==
"Ilwis::Box<Pixel>" || type ==
"Ilwis::Box<Coordinate>" ||
347 type ==
"Ilwis::Box<Pixeld>" ;
351 if ( type ==
"Ilwis::Box<Coordinate>"){
352 Box<Coordinate> box = v.value<Box<Coordinate>>();
353 return box.toString();
355 if ( type ==
"Ilwis::Box<Pixel>"){
356 Box<Pixel> box = v.value<Box<Pixel>>();
357 return box.toString();
359 if ( type ==
"Ilwis::Box<Pixeld>"){
360 Box<Pixeld> box = v.value<Box<Pixeld>>();
361 return box.toString();
367 template<
typename T>
void ensure(
const Size<T>& sz) {
368 if ( xlength() > sz.xsize()) {
369 this->max_corner().x = sz.xsize() - 1 ;
371 if ( ylength() > sz.ysize()) {
372 this->max_corner().y = sz.ysize() - 1 ;
374 if ( zlength() > sz.zsize()) {
375 this->max_corner().z = sz.zsize() - 1 ;
379 void copyFrom(
const Box<PointType>& box, quint32 dimensions=dimX | dimY | dimZ) {
380 if ( dimensions & dimX) {
381 this->min_corner().x = box.min_corner().x;
382 this->max_corner().x =box.max_corner().x;
384 if ( dimensions & dimY) {
385 this->min_corner().y = box.min_corner().y;
386 this->max_corner().y = box.max_corner().y;
388 if ( dimensions & dimZ) {
389 this->min_corner().z = box.min_corner().z;
390 this->max_corner().z = box.max_corner().z;
397 if (this->min_corner().valuetype() == itDOUBLE)
398 return QString(
"POLYGON(%1 %2 %3,%4 %5 %6)").
399 arg((
double)this->min_corner().x,0,
'g').
400 arg((
double)this->min_corner().y,0,
'g').
401 arg((
double)this->min_corner().z,0,
'g').
402 arg((
double)this->max_corner().x,0,
'g').
403 arg((
double)this->max_corner().y,0,
'g').
404 arg((
double)this->max_corner().z,0,
'g');
406 return QString(
"POLYGON(%1 %2 %3,%4 %5 %6)").arg(this->min_corner().x).
407 arg(this->min_corner().y).
408 arg(this->min_corner().z).
409 arg(this->max_corner().x).
410 arg(this->max_corner().y).
411 arg(this->max_corner().z);
415 if (this->min_corner().valuetype() == itDOUBLE)
416 return QString(
"POLYGON(%1 %2,%3 %4)").
417 arg((
double)this->min_corner().x,0,
'g').
418 arg((
double)this->min_corner().y,0,
'g').
419 arg((
double)this->max_corner().x,0,
'g').
420 arg((
double)this->max_corner().y,0,
'g');
422 return QString(
"POLYGON(%1 %2,%3 %4)").
423 arg(this->min_corner().x).
424 arg(this->min_corner().y).
425 arg(this->max_corner().x).
426 arg(this->max_corner().y);
432 PointType _min_corner;
433 PointType _max_corner;
437 PointType& pmin = this->min_corner();
438 PointType& pmax = this->max_corner();
439 if ( pmin.x > pmax.x) {
447 if ( pmin.y > pmax.y) {
454 if ( pmin.z > pmax.z) {
467 template<
typename Po
intType> Box<PointType> operator *(
const Box<PointType>& box,
const double& v) {
468 PointType pmin = box.min_corner();
469 PointType pmax = box.max_corner();
470 double deltaX = box.xlength() * v / 2;
471 double deltaY = box.ylength() * v / 2;
472 double deltaZ = box.is3d() ? box.zlength() * v / 2 : 0;
473 pmin -= {deltaX, deltaY, deltaZ};
474 pmax += {deltaX, deltaY, deltaZ};
475 return Box<PointType>(pmin, pmax);
485 Q_DECLARE_METATYPE(Ilwis::Box<Ilwis::Pixeld>)
486 Q_DECLARE_METATYPE(Ilwis::Envelope)