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

marchingCube.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 #ifndef MARCHING_CUBE_H
00026 #define MARCHING_CUBE_H
00027 
00028 #include "core/globalDefs.h"
00029 #include "offLattice/boundaryShapes3D.h"
00030 #include "offLattice/triangleSet.h"
00031 #include "offLattice/triangularSurfaceMesh.h"
00032 #include "offLattice/offLatticeBoundaryProfiles3D.h"
00033 #include "offLattice/triangleBoundary3D.h"
00034 #include <vector>
00035 
00036 namespace plb {
00037 
00038 template<typename T> class IsoSurfaceDefinition3D;
00039 
00040 
00042 
00049 template<typename T>
00050 void isoSurfaceMarchingCube (
00051         std::vector<typename TriangleSet<T>::Triangle>& triangles,
00052         std::vector<MultiBlock3D*> surfDefinitionArgs,
00053         IsoSurfaceDefinition3D<T>* isoSurfaceDefinition,
00054         Box3D const& domain, std::vector<plint> surfaceIds = std::vector<plint>() );
00055 
00057 template<typename T>
00058 void isoSurfaceMarchingCube (
00059         std::vector<typename TriangleSet<T>::Triangle>& triangles,
00060         VoxelizedDomain3D<T>& voxelizedDomain, Box3D const& domain );
00061 
00063 template<typename T>
00064 void isoSurfaceMarchingCube (
00065         std::vector<typename TriangleSet<T>::Triangle>& triangles,
00066         MultiScalarField3D<T>& scalarField, std::vector<T> const& isoLevels, Box3D const& domain );
00067 
00068 
00069 template<typename T>
00070 class IsoSurfaceDefinition3D {
00071 public:
00072     virtual ~IsoSurfaceDefinition3D() { }
00073     virtual bool isInside (
00074             plint surfaceId, Array<plint,3> const& position ) const =0;
00075     virtual bool isValid(Array<plint,3> const& position) const { return true; }
00076     virtual Array<T,3> getSurfacePosition (
00077              plint surfaceId, Array<plint,3> const& p1, Array<plint,3> const& p2 ) const =0;
00078     virtual void setArguments(std::vector<AtomicBlock3D*> const& arguments) =0;
00079     virtual IsoSurfaceDefinition3D<T>* clone() const =0;
00080     virtual plint getNumArgs() const =0;
00081     virtual std::vector<plint> getSurfaceIds() const=0;
00082 public:
00083     bool edgeIsValid(plint iX, plint iY, plint iZ, int edge) const;
00084 };
00085 
00086 template<typename T>
00087 class ScalarFieldIsoSurface3D : public IsoSurfaceDefinition3D<T> {
00088 public:
00089     ScalarFieldIsoSurface3D(std::vector<T> const& isoValues_);
00090     virtual bool isInside (
00091             plint surfaceId, Array<plint,3> const& position ) const;
00092     virtual Array<T,3> getSurfacePosition (
00093             plint surfaceId, Array<plint,3> const& p1, Array<plint,3> const& p2 ) const;
00094     virtual void setArguments(std::vector<AtomicBlock3D*> const& arguments);
00095     virtual ScalarFieldIsoSurface3D<T>* clone() const;
00096     virtual plint getNumArgs() const { return 1; }
00097     virtual std::vector<plint> getSurfaceIds() const;
00098 private:
00099     std::vector<T> isoValues;
00100     ScalarField3D<T>* scalar;
00101     Dot3D location;
00102 };
00103 
00104 
00105 
00106 template<typename T, class SurfaceData>
00107 class BoundaryShapeIsoSurface3D : public IsoSurfaceDefinition3D<T> {
00108 public:
00109     BoundaryShapeIsoSurface3D(BoundaryShape3D<T,SurfaceData>* shape_);
00110     ~BoundaryShapeIsoSurface3D();
00111     BoundaryShapeIsoSurface3D(BoundaryShapeIsoSurface3D<T,SurfaceData> const& rhs);
00112     BoundaryShapeIsoSurface3D<T,SurfaceData>& operator=(BoundaryShapeIsoSurface3D<T,SurfaceData> const& rhs);
00113     void swap(BoundaryShapeIsoSurface3D<T,SurfaceData>& rhs);
00114     virtual bool isInside (
00115             plint surfaceId, Array<plint,3> const& position ) const;
00116     virtual Array<T,3> getSurfacePosition (
00117             plint surfaceId, Array<plint,3> const& p1, Array<plint,3> const& p2 ) const;
00122     virtual void setArguments(std::vector<AtomicBlock3D*> const& arguments);
00123     virtual BoundaryShapeIsoSurface3D<T,SurfaceData>* clone() const;
00124     virtual plint getNumArgs() const { return 3; }
00125     virtual std::vector<plint> getSurfaceIds() const;
00126 private:
00127     BoundaryShape3D<T,SurfaceData>* shape;
00128 };
00129 
00130 
00131 template<typename T>
00132 class MarchingCubeSurfaces3D : public BoxProcessingFunctional3D {
00133 public:
00134     typedef typename TriangleSet<T>::Triangle Triangle;
00135 public:
00136     MarchingCubeSurfaces3D( std::vector<plint> surfaceIds_,
00137                             IsoSurfaceDefinition3D<T>* isoSurface_,
00138                             bool edgeOrientedData_=false );
00139     ~MarchingCubeSurfaces3D();
00140     MarchingCubeSurfaces3D(MarchingCubeSurfaces3D<T> const& rhs);
00141     MarchingCubeSurfaces3D<T>& operator=(MarchingCubeSurfaces3D<T> const& rhs);
00142     void swap(MarchingCubeSurfaces3D<T>& rhs);
00143     virtual void processGenericBlocks (
00144                 Box3D domain, std::vector<AtomicBlock3D*> fields );
00145     virtual void defaultImplementation (
00146                 Box3D domain, AtomicContainerBlock3D* triangleContainer );
00147     virtual void edgeOriented (
00148                 Box3D domain, AtomicContainerBlock3D* triangleContainer );
00149     virtual MarchingCubeSurfaces3D<T>* clone() const;
00150     virtual void getTypeOfModification(std::vector<modif::ModifT>& modified) const;
00151     void setEdgeOrientedEnvelope(plint edgeOrientedEnvelope_) {
00152         edgeOrientedEnvelope = edgeOrientedEnvelope_;
00153     }
00154 public:
00155     class TriangleSetData : public ContainerBlockData {
00156     public:
00157         std::vector<Triangle> triangles;
00158         virtual TriangleSetData* clone() const {
00159             return new TriangleSetData(*this);
00160         }
00161     };
00162     class EdgeOrientedTriangleSetData : public ContainerBlockData {
00163     public:
00166         struct OnEdgeTriangle {
00169             Array<plint,4> vertex1, vertex2;
00170         };
00171     public:
00172         EdgeOrientedTriangleSetData(plint nx, plint ny, plint nz)
00173             : data(nx,ny,nz)
00174         { }
00175         virtual EdgeOrientedTriangleSetData* clone() const {
00176             return new EdgeOrientedTriangleSetData(*this);
00177         }
00178         void addTriangle( plint iX, plint iY, plint iZ, int iEdge,
00179                           OnEdgeTriangle const& triangle )
00180         {
00181             switch(iEdge) {
00182                 case 0: data.get(iX,iY,iZ).edge1triangles.push_back(triangle); break;
00183                 case 1: data.get(iX,iY,iZ).edge2triangles.push_back(triangle); break;
00184                 case 2: data.get(iX,iY,iZ).edge3triangles.push_back(triangle); break;
00185                 default: PLB_ASSERT( false );
00186             }
00187         }
00188         std::vector<OnEdgeTriangle> const& getTriangles(plint iX, plint iY, plint iZ, int iEdge) const {
00189             switch(iEdge) {
00190                 case 0: return data.get(iX,iY,iZ).edge1triangles;
00191                 case 1: return data.get(iX,iY,iZ).edge2triangles;
00192                 case 2: return data.get(iX,iY,iZ).edge3triangles;
00193                 default: PLB_ASSERT( false );
00194             }
00195         }
00196         void setVertex(plint iX, plint iY, plint iZ, int iEdge, Array<T,3> const& vertex) {
00197             switch(iEdge) {
00198                 case 0:
00199                     data.get(iX,iY,iZ).edge1Vertex = vertex;
00200                     data.get(iX,iY,iZ).edge1VertexDefined = true;
00201                     break;
00202                 case 1:
00203                     data.get(iX,iY,iZ).edge2Vertex = vertex;
00204                     data.get(iX,iY,iZ).edge2VertexDefined = true;
00205                     break;
00206                 case 2:
00207                     data.get(iX,iY,iZ).edge3Vertex = vertex;
00208                     data.get(iX,iY,iZ).edge3VertexDefined = true;
00209                     break;
00210                 default: PLB_ASSERT( false );
00211             }
00212         }
00213         bool getVertex(plint iX, plint iY, plint iZ, int iEdge, Array<T,3>& vertex) const {
00214             switch(iEdge) {
00215                 case 0:
00216                     vertex = data.get(iX,iY,iZ).edge1Vertex;
00217                     return data.get(iX,iY,iZ).edge1VertexDefined;
00218                 case 1:
00219                     vertex = data.get(iX,iY,iZ).edge2Vertex;
00220                     return data.get(iX,iY,iZ).edge2VertexDefined;
00221                 case 2:
00222                     vertex = data.get(iX,iY,iZ).edge3Vertex;
00223                     return data.get(iX,iY,iZ).edge3VertexDefined;
00224                 default: PLB_ASSERT( false );
00225             }
00226         }
00227         std::vector<T> const& getScalars(plint iX, plint iY, plint iZ, int iEdge) const {
00228             switch(iEdge) {
00229                 case 0: return data.get(iX,iY,iZ).scalars1;
00230                 case 1: return data.get(iX,iY,iZ).scalars2;
00231                 case 2: return data.get(iX,iY,iZ).scalars3;
00232                 default: PLB_ASSERT( false );
00233             }
00234         }
00235         std::vector<T>& getScalars(plint iX, plint iY, plint iZ, int iEdge) {
00236             switch(iEdge) {
00237                 case 0: return data.get(iX,iY,iZ).scalars1;
00238                 case 1: return data.get(iX,iY,iZ).scalars2;
00239                 case 2: return data.get(iX,iY,iZ).scalars3;
00240                 default: PLB_ASSERT( false );
00241             }
00242         }
00243         bool isEdgeVertexDefined(plint iX, plint iY, plint iZ, int iEdge) {
00244             switch(iEdge) {
00245                 case 0: return data.get(iX,iY,iZ).edge1VertexDefined;
00246                 case 1: return data.get(iX,iY,iZ).edge2VertexDefined;
00247                 case 2: return data.get(iX,iY,iZ).edge3VertexDefined;
00248                 default: PLB_ASSERT( false );
00249             }
00250         }
00251         plint getNx() const { return data.getNx(); }
00252         plint getNy() const { return data.getNy(); }
00253         plint getNz() const { return data.getNz(); }
00254         Box3D getBoundingBox() const { return data.getBoundingBox(); }
00255     private:
00256         struct EdgeData {
00257             EdgeData()
00258                 : edge1VertexDefined(false),
00259                   edge2VertexDefined(false),
00260                   edge3VertexDefined(false)
00261             { }
00262             // Each element in the three following vectors defines the topology of
00263             // a triangle.
00264             std::vector<OnEdgeTriangle> edge1triangles;
00265             std::vector<OnEdgeTriangle> edge2triangles;
00266             std::vector<OnEdgeTriangle> edge3triangles;
00267             // Every edge has at most one vertex which is shared by all
00268             // triangles that have a vertex on this edge.
00269             Array<T,3> edge1Vertex, edge2Vertex, edge3Vertex;
00270             std::vector<T> scalars1, scalars2, scalars3;
00271             bool edge1VertexDefined, edge2VertexDefined, edge3VertexDefined;
00272         };
00273     private:
00274         ScalarField3D<EdgeData> data;
00275     };
00276 private:
00277     void marchingCubeImpl (
00278              plint iX, plint iY, plint iZ, plint surfaceId,
00279              std::vector<Triangle>& triangles,
00280              int& cubeIndex, std::vector<Array<T,3> >& vertlist );
00281     void polygonize (
00282              plint iX, plint iY, plint iZ, plint surfaceId,
00283              std::vector<Triangle>& triangles );
00286     void polygonize (
00287              plint iX, plint iY, plint iZ, plint surfaceId,
00288              std::vector<Triangle>& triangles,
00289              std::vector<Array<plint,4> >& edgeAttributions );
00290 private:
00291     std::vector<plint> surfaceIds;
00292     IsoSurfaceDefinition3D<T>* isoSurface;
00293     bool edgeOrientedData;
00294     plint edgeOrientedEnvelope;
00295 };
00296 
00297 struct MarchingCubeConstants {
00298     static const int edgeTable[256];
00299     static const int triTable[256][16];
00300     static const int edgeNeighb[12][3];
00301     static const int edgeOrient[12];
00302 };
00303 
00304 }  // namespace plb
00305 
00306 #endif  // MARCHING_CUBE_H