1 /***************************************************************************
2                              qgsbox3d.cpp
3                              ------------
4     begin                : April 2017
5     copyright            : (C) 2017 by Nyall Dawson
6     email                : nyall dot dawson at gmail dot com
7 ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "qgsbox3d.h"
19 #include "qgspoint.h"
20 
QgsBox3d(double xmin,double ymin,double zmin,double xmax,double ymax,double zmax)21 QgsBox3d::QgsBox3d( double xmin, double ymin, double zmin, double xmax, double ymax, double zmax )
22   : mBounds2d( xmin, ymin, xmax, ymax )
23   , mZmin( zmin )
24   , mZmax( zmax )
25 {}
26 
QgsBox3d(const QgsPoint & p1,const QgsPoint & p2)27 QgsBox3d::QgsBox3d( const QgsPoint &p1, const QgsPoint &p2 )
28   : mBounds2d( p1.x(), p1.y(), p2.x(), p2.y() )
29   , mZmin( std::min( p1.z(), p2.z() ) )
30   , mZmax( std::max( p1.z(), p2.z() ) )
31 {
32   mBounds2d.normalize();
33 }
34 
QgsBox3d(const QgsRectangle & rect)35 QgsBox3d::QgsBox3d( const QgsRectangle &rect )
36   : mBounds2d( rect )
37 {}
38 
setXMinimum(double x)39 void QgsBox3d::setXMinimum( double x )
40 {
41   mBounds2d.setXMinimum( x );
42 }
43 
setXMaximum(double x)44 void QgsBox3d::setXMaximum( double x )
45 {
46   mBounds2d.setXMaximum( x );
47 }
48 
setYMinimum(double y)49 void QgsBox3d::setYMinimum( double y )
50 {
51   mBounds2d.setYMinimum( y );
52 }
53 
setYMaximum(double y)54 void QgsBox3d::setYMaximum( double y )
55 {
56   mBounds2d.setYMaximum( y );
57 }
58 
setZMinimum(double z)59 void QgsBox3d::setZMinimum( double z )
60 {
61   mZmin = z;
62 }
63 
setZMaximum(double z)64 void QgsBox3d::setZMaximum( double z )
65 {
66   mZmax = z;
67 }
68 
normalize()69 void QgsBox3d::normalize()
70 {
71   mBounds2d.normalize();
72   const double z1 = std::min( mZmin, mZmax );
73   const double z2 = std::max( mZmin, mZmax );
74   mZmin = z1;
75   mZmax = z2;
76 }
77 
intersect(const QgsBox3d & other) const78 QgsBox3d QgsBox3d::intersect( const QgsBox3d &other ) const
79 {
80   const QgsRectangle intersect2d = mBounds2d.intersect( other.mBounds2d );
81   const double zMin = std::max( mZmin, other.mZmin );
82   const double zMax = std::min( mZmax, other.mZmax );
83   return QgsBox3d( intersect2d.xMinimum(), intersect2d.yMinimum(), zMin,
84                    intersect2d.xMaximum(), intersect2d.yMaximum(), zMax );
85 }
86 
is2d() const87 bool QgsBox3d::is2d() const
88 {
89   return qgsDoubleNear( mZmin, mZmax ) || ( mZmin > mZmax );
90 }
91 
intersects(const QgsBox3d & other) const92 bool QgsBox3d::intersects( const QgsBox3d &other ) const
93 {
94   if ( !mBounds2d.intersects( other.mBounds2d ) )
95     return false;
96 
97   const double z1 = ( mZmin > other.mZmin ? mZmin : other.mZmin );
98   const double z2 = ( mZmax < other.mZmax ? mZmax : other.mZmax );
99   return z1 <= z2;
100 }
101 
contains(const QgsBox3d & other) const102 bool QgsBox3d::contains( const QgsBox3d &other ) const
103 {
104   if ( !mBounds2d.contains( other.mBounds2d ) )
105     return false;
106 
107   return ( other.mZmin >= mZmin && other.mZmax <= mZmax );
108 }
109 
contains(const QgsPoint & p) const110 bool QgsBox3d::contains( const QgsPoint &p ) const
111 {
112   if ( !mBounds2d.contains( p.x(), p.y() ) )
113     return false;
114 
115   if ( p.is3D() )
116     return mZmin <= p.z() && p.z() <= mZmax;
117   else
118     return true;
119 }
120 
distanceTo(const QVector3D & point) const121 double QgsBox3d::distanceTo( const  QVector3D &point ) const
122 {
123   const double dx = std::max( mBounds2d.xMinimum() - point.x(), std::max( 0., point.x() - mBounds2d.xMaximum() ) );
124   const double dy = std::max( mBounds2d.yMinimum() - point.y(), std::max( 0., point.y() - mBounds2d.yMaximum() ) );
125   const double dz = std::max( mZmin - point.z(), std::max( 0., point.z() - mZmax ) );
126   return sqrt( dx * dx + dy * dy + dz * dz );
127 }
128 
129 
operator ==(const QgsBox3d & other) const130 bool QgsBox3d::operator==( const QgsBox3d &other ) const
131 {
132   return mBounds2d == other.mBounds2d &&
133          qgsDoubleNear( mZmin, other.mZmin ) &&
134          qgsDoubleNear( mZmax, other.mZmax );
135 }
136