$treeview $search $mathjax
Palabos  Version 1.1
$projectbrief
$projectbrief
$searchbox

geometry3D.h

Go to the documentation of this file.
00001 /* This file is part of the Palabos library.
00002  *
00003  * Copyright (C) 2011 FlowKit Sarl
00004  * Avenue de Chailly 23
00005  * 1012 Lausanne, Switzerland
00006  * E-mail contact: contact@flowkit.com
00007  *
00008  * The most recent release of Palabos can be downloaded at 
00009  * <http://www.palabos.org/>
00010  *
00011  * The library Palabos is free software: you can redistribute it and/or
00012  * modify it under the terms of the GNU Affero General Public License as
00013  * published by the Free Software Foundation, either version 3 of the
00014  * License, or (at your option) any later version.
00015  *
00016  * The library is distributed in the hope that it will be useful,
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  * GNU Affero General Public License for more details.
00020  *
00021  * You should have received a copy of the GNU Affero General Public License
00022  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
00023 */
00024 
00025 
00026 #ifndef GEOMETRY_3D_H
00027 #define GEOMETRY_3D_H
00028 
00029 #include "core/globalDefs.h"
00030 #include "core/plbDebug.h"
00031 #include "core/util.h"
00032 #include "core/array.h"
00033 #include "latticeBoltzmann/geometricOperationTemplates.h"
00034 #include <algorithm>
00035 #include <iterator>
00036 #include <vector>
00037 #include <cmath>
00038 
00039 namespace plb {
00040 
00042 struct Box3D {
00043     Box3D() : x0(), x1(), y0(), y1(), z0(), z1() { }
00044     Box3D(plint x0_, plint x1_, plint y0_, plint y1_, plint z0_, plint z1_)
00045         : x0(x0_), x1(x1_), y0(y0_), y1(y1_), z0(z0_), z1(z1_)
00046     { }
00048     Box3D shift(plint deltaX, plint deltaY, plint deltaZ) const {
00049         return Box3D(x0+deltaX, x1+deltaX, y0+deltaY, y1+deltaY, z0+deltaZ, z1+deltaZ);
00050     }
00052     Box3D multiply(plint scaling) const {
00053         return Box3D(scaling*x0, scaling*x1, scaling*y0,
00054                      scaling*y1, scaling*z0, scaling*z1);
00055     }
00057     Box3D divide(plint scaling) const {
00058         return Box3D(x0/scaling, x1/scaling, y0/scaling,
00059                      y1/scaling, z0/scaling, z1/scaling);
00060     }
00062 
00070     Box3D divideAndFitSmaller(plint scaling) const {
00071         return Box3D (util::roundUp(x0,scaling)/scaling, util::roundDown(x1,scaling)/scaling,
00072                       util::roundUp(y0,scaling)/scaling, util::roundDown(y1,scaling)/scaling,
00073                       util::roundUp(z0,scaling)/scaling, util::roundDown(z1,scaling)/scaling);
00074     }
00075 
00077 
00085     Box3D divideAndFitLarger(plint scaling) const {
00086         return Box3D (util::roundDown(x0,scaling)/scaling, util::roundUp(x1,scaling)/scaling,
00087                       util::roundDown(y0,scaling)/scaling, util::roundUp(y1,scaling)/scaling,
00088                       util::roundDown(z0,scaling)/scaling, util::roundUp(z1,scaling)/scaling);
00089     }
00090 
00092     Box3D enlarge(plint nCells) const {
00093         return Box3D(x0-nCells, x1+nCells, y0-nCells, y1+nCells, z0-nCells, z1+nCells);
00094     }
00096     plint getNx()  const { return (x1-x0+1); }
00098     plint getNy()  const { return (y1-y0+1); }
00100     plint getNz()  const { return (z1-z0+1); }
00102     plint nCells() const { return getNx()*getNy()*getNz(); }
00104     plint getMaxWidth() const { return std::max(std::max(getNx(), getNy()), getNz()); }
00106     Array<plint,6> to_plbArray() const {
00107         Array<plint,6> array;
00108         array[0] = x0; array[1] = x1;
00109         array[2] = y0; array[3] = y1;
00110         array[4] = z0; array[5] = z1;
00111         return array;
00112     }
00114     void from_plbArray(Array<plint,6> const& array) {
00115         x0 = array[0]; x1 = array[1];
00116         y0 = array[2]; y1 = array[3];
00117         z0 = array[4]; z1 = array[5];
00118     }
00119 
00120     bool operator==(Box3D const& rhs) {
00121         return x0 == rhs.x0 && y0 == rhs.y0 && z0 == rhs.z0 &&
00122                x1 == rhs.x1 && y1 == rhs.y1 && z1 == rhs.z1;
00123     }
00124 
00125     plint x0, x1, y0, y1, z0, z1;
00126 };
00127 
00129 struct Dot3D {
00130     Dot3D() : x(), y(), z() { }
00131     Dot3D(plint x_, plint y_, plint z_) : x(x_), y(y_), z(z_) { }
00132     Dot3D& operator+=(Dot3D const& rhs) {
00133         x += rhs.x;
00134         y += rhs.y;
00135         z += rhs.z;
00136         return *this;
00137     }
00138     Dot3D& operator-=(Dot3D const& rhs) {
00139         x -= rhs.x;
00140         y -= rhs.y;
00141         z -= rhs.z;
00142         return *this;
00143     }
00144     
00145     template<typename T>
00146     Array<T,3> to_plbArray() const { return Array<T,3>((T)x,(T)y,(T)z); }
00147     
00148     plint x, y, z;
00149 };
00150 
00151 inline Dot3D operator+(Dot3D const& dot1, Dot3D const& dot2) {
00152     return Dot3D(dot1) += dot2;
00153 }
00154 
00155 inline Dot3D operator-(Dot3D const& dot1, Dot3D const& dot2) {
00156     return Dot3D(dot1) -= dot2;
00157 }
00158 
00160 inline bool operator<(Dot3D const& dot1, Dot3D const& dot2) {
00161     return (dot1.x < dot2.x) || (
00162                (dot1.x == dot2.x) && (
00163                    (dot1.y < dot2.y) || (
00164                        (dot1.y == dot2.y) && (dot1.z < dot2.z) ) ) );
00165 }
00166 
00167 inline bool operator==(Dot3D const& dot1, Dot3D const& dot2) {
00168     return (dot1.x == dot2.x) && (dot1.y == dot2.y) &&
00169            (dot1.z == dot2.z);
00170 }
00171 
00174 inline bool operator<(Box3D const& box1, Box3D const& box2) {
00175     return ( Dot3D(box1.x0,box1.y0,box1.z0) < Dot3D(box2.x0,box2.y0,box2.z0) ) || (
00176                 ( Dot3D(box1.x0,box1.y0,box1.z0) == Dot3D(box2.x0,box2.y0,box2.z0) ) &&
00177                 ( Dot3D(box1.x1,box1.y1,box1.z1) <  Dot3D(box2.x1,box2.y1,box2.z1) ) );
00178 }
00179 
00181 struct DotList3D {
00182     DotList3D() { }
00183     DotList3D(std::vector<Dot3D> const& dots_) : dots(dots_) { }
00185     void addDot(Dot3D dot) {
00186         dots.push_back(dot);
00187     }
00189     void addDots(std::vector<Dot3D> const& dots_) {
00190         dots.insert(dots.end(), dots_.begin(), dots_.end());
00191     }
00193     Dot3D const& getDot(plint whichDot) const {
00194         PLB_PRECONDITION( whichDot<getN() );
00195         return dots[whichDot];
00196     }
00198     Dot3D& getDot(plint whichDot) {
00199         PLB_PRECONDITION( whichDot<getN() );
00200         return dots[whichDot];
00201     }
00203     DotList3D shift(plint deltaX, plint deltaY, plint deltaZ) const {
00204         std::vector<Dot3D> newDots;
00205         std::vector<Dot3D>::const_iterator it = dots.begin();
00206         for (; it!=dots.end(); ++it) {
00207             newDots.push_back( Dot3D(it->x+deltaX, it->y+deltaY, it->z+deltaZ) );
00208         }
00209         return DotList3D(newDots);
00210     }
00212     DotList3D multiply(plint scaling) const {
00213         std::vector<Dot3D> newDots;
00214         std::vector<Dot3D>::const_iterator it = dots.begin();
00215         for (; it!=dots.end(); ++it) {
00216             newDots.push_back( Dot3D(it->x*scaling, it->y*scaling, it->z*scaling) );
00217         }
00218         return DotList3D(newDots);
00219     }
00221     DotList3D divide(plint scaling) const {
00222         std::vector<Dot3D> newDots;
00223         std::vector<Dot3D>::const_iterator it = dots.begin();
00224         for (; it!=dots.end(); ++it) {
00225             newDots.push_back( Dot3D(it->x/scaling, it->y/scaling, it->z/scaling) );
00226         }
00227         return DotList3D(newDots);
00228 
00229     }
00231     plint getN() const {
00232         return dots.size();
00233     }
00234 
00235     std::vector<Dot3D> dots;
00236 };
00237 
00239 inline bool contained(plint x, plint y, plint z, Box3D const& box) {
00240     return x>=box.x0 && x<=box.x1 &&
00241            y>=box.y0 && y<=box.y1 &&
00242            z>=box.z0 && z<=box.z1;
00243 }
00244 
00246 inline bool contained(Dot3D dot, Box3D const& box) {
00247     return contained(dot.x, dot.y, dot.z, box);
00248 }
00249 
00251 inline bool contained(Box3D const& box1, Box3D const& box2) {
00252     return box1.x0>=box2.x0 && box1.x1<=box2.x1 &&
00253            box1.y0>=box2.y0 && box1.y1<=box2.y1 &&
00254            box1.z0>=box2.z0 && box1.z1<=box2.z1;
00255 }
00256 
00258 
00260 inline bool intersect(Box3D const& box1, Box3D const& box2, Box3D& inters) {
00261     inters.x0 = std::max(box1.x0,box2.x0);
00262     inters.y0 = std::max(box1.y0,box2.y0);
00263     inters.z0 = std::max(box1.z0,box2.z0);
00264 
00265     inters.x1 = std::min(box1.x1,box2.x1);
00266     inters.y1 = std::min(box1.y1,box2.y1);
00267     inters.z1 = std::min(box1.z1,box2.z1);
00268 
00269     return inters.x1>=inters.x0 && inters.y1>=inters.y0 && inters.z1>=inters.z0;
00270 }
00271 
00273 inline bool doesIntersect(Box3D const& box1, Box3D const& box2) {
00274     return (std::min(box1.x1,box2.x1) >= std::max(box1.x0,box2.x0)) &&
00275            (std::min(box1.y1,box2.y1) >= std::max(box1.y0,box2.y0)) &&
00276            (std::min(box1.z1,box2.z1) >= std::max(box1.z0,box2.z0));
00277 }
00278 
00281 inline bool merge(Box3D& box1, Box3D const& box2) {
00282     if (box1.x0==box2.x0 && box1.x1==box2.x1 &&
00283         box1.y0==box2.y0 && box1.y1==box2.y1) {
00284         if (box2.z0==box1.z1+1) {
00285             box1.z1=box2.z1;
00286             return true;
00287         }
00288         if (box2.z1+1==box1.z0) {
00289             box1.z0=box2.z0;
00290             return true;
00291         }
00292     }
00293     if (box1.x0==box2.x0 && box1.x1==box2.x1 &&
00294         box1.z0==box2.z0 && box1.z1==box2.z1) {
00295         if (box2.y0==box1.y1+1) {
00296             box1.y1=box2.y1;
00297             return true;
00298         }
00299         if (box2.y1+1==box1.y0) {
00300             box1.y0=box2.y0;
00301             return true;
00302         }
00303     }
00304     if (box1.y0==box2.y0 && box1.y1==box2.y1 &&
00305         box1.z0==box2.z0 && box1.z1==box2.z1) {
00306         if (box2.x0==box1.x1+1) {
00307             box1.x1=box2.x1;
00308             return true;
00309         }
00310         if (box2.x1+1==box1.x0) {
00311             box1.x0=box2.x0;
00312             return true;
00313         }
00314     }
00315     return false;
00316 }
00317 
00319 
00321 inline bool intersect(Box3D const& box, DotList3D const& dotlist, DotList3D& inters) {
00322     inters = DotList3D();
00323     std::vector<Dot3D>::const_iterator it = dotlist.dots.begin();
00324     for (; it != dotlist.dots.end(); ++it) {
00325         if ( contained(it->x,it->y,it->z, box) ) {
00326             inters.addDot(*it);
00327         }
00328     }
00329     return !inters.dots.empty();
00330 }
00331 
00333 
00335 inline void except(Box3D const& originalBox, Box3D const& toExcept, std::vector<Box3D>& result)
00336 {
00337     Box3D intersection;
00338     bool doesIntersect = intersect(originalBox, toExcept, intersection);
00339     if (!doesIntersect) {
00340         result.push_back(originalBox);
00341     }
00342     else {
00343         if (intersection.x0 != originalBox.x0) {
00344             result.push_back(Box3D(originalBox.x0, intersection.x0-1, originalBox.y0, originalBox.y1, originalBox.z0, originalBox.z1));
00345         }
00346         if (intersection.x1 != originalBox.x1) {
00347             result.push_back(Box3D(intersection.x1+1, originalBox.x1, originalBox.y0, originalBox.y1, originalBox.z0, originalBox.z1));
00348         }
00349         if (intersection.y0 != originalBox.y0) {
00350             result.push_back(Box3D(intersection.x0, intersection.x1, originalBox.y0, intersection.y0-1, originalBox.z0, originalBox.z1));
00351         }
00352         if (intersection.y1 != originalBox.y1) {
00353             result.push_back(Box3D(intersection.x0, intersection.x1, intersection.y1+1, originalBox.y1, originalBox.z0, originalBox.z1));
00354         }
00355         if (intersection.z0 != originalBox.z0) {
00356             result.push_back(Box3D(intersection.x0, intersection.x1, intersection.y0, intersection.y1, originalBox.z0, intersection.z0-1));
00357         }
00358         if (intersection.z1 != originalBox.z1) {
00359             result.push_back(Box3D(intersection.x0, intersection.x1, intersection.y0, intersection.y1, intersection.z1+1, originalBox.z1));
00360         }
00361     }
00362 }
00363 
00364 
00366 inline Box3D bound(Box3D const& box1, Box3D const& box2) {
00367     return Box3D (
00368             std::min(box1.x0, box2.x0), std::max(box1.x1, box2.x1),
00369             std::min(box1.y0, box2.y0), std::max(box1.y1, box2.y1),
00370             std::min(box1.z0, box2.z0), std::max(box1.z1, box2.z1) );
00371 }
00372 
00374 inline void adjustEqualSize(Box3D& fromDomain, Box3D& toDomain)
00375 {
00376     plint deltaX = fromDomain.x0 - toDomain.x0;
00377     plint deltaY = fromDomain.y0 - toDomain.y0;
00378     plint deltaZ = fromDomain.z0 - toDomain.z0;
00379     Box3D intersection;
00380     intersect(fromDomain, toDomain.shift(deltaX,deltaY,deltaZ), intersection);
00381     fromDomain = intersection;
00382     toDomain = intersection.shift(-deltaX,-deltaY,-deltaZ);
00383 }
00384 
00386 template<typename T>
00387 struct Plane {
00388     Array<T,3> point;
00389     Array<T,3> normal;
00390 };
00391 
00393 template<typename T>
00394 struct Cuboid {
00395     Array<T,3> lowerLeftCorner;
00396     Array<T,3> upperRightCorner;
00397 };
00398 
00406 template<typename T>
00407 inline int lineIntersectionWithPlane (
00408         Plane<T> const& plane, Array<T,3> const& point1,
00409         Array<T,3> const& point2, Precision precision, Array<T,3>& intersection )
00410 {
00411     T epsilon = getEpsilon<T>(precision);
00412 
00413     Array<T,3> direction = point2 - point1;
00414 
00415     T num = dot(plane.point, plane.normal) - dot(point1, plane.normal);
00416     T denom = dot(direction, plane.normal);
00417 
00418     if (fabs(denom) <=  epsilon) {
00419         return -1; // Line belongs to the plane or does not intersect it.
00420     }
00421 
00422     T t = num / denom;
00423 
00424     if ((t < 0.0 && !(fabs(t) <= epsilon)) ||
00425         (t > 1.0 && !(fabs(t - 1.0) <= epsilon))) {
00426         return 0;
00427     }
00428 
00429     intersection = point1 + direction * t; // Intersection point with the plane.
00430 
00431     return 1;
00432 }
00433 } // namespace plb
00434 
00435 #endif  // GEOMETRY_3D_H