diff --git a/.gitignore b/.gitignore index 3fb3f818..62cc7dd5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +*.sw* *.sdf *.suo /Obj/ diff --git a/Makefile b/Makefile index f71afaf5..8cfb102e 100644 --- a/Makefile +++ b/Makefile @@ -5,14 +5,22 @@ PR_SOURCE=CmdLineParser.cpp Factor.cpp Geometry.cpp MarchingCubes.cpp PlyFile.cp SR_SOURCE=CmdLineParser.cpp Factor.cpp Geometry.cpp MarchingCubes.cpp PlyFile.cpp SSDRecon.cpp ST_SOURCE=CmdLineParser.cpp Factor.cpp Geometry.cpp MarchingCubes.cpp PlyFile.cpp SurfaceTrimmer.cpp -CFLAGS += -fopenmp -Wno-deprecated -Wno-write-strings -std=c++11 -LFLAGS += -lgomp -lstdc++ +CFLAGS += -Wno-deprecated -Wno-write-strings -std=c++11 +LFLAGS += -lstdc++ + +# +# OpenMP +# +ifndef NO_OPENMP +CFLAGS += -fopenmp +LFLAGS += -lgomp +endif CFLAGS_DEBUG = -DDEBUG -g3 LFLAGS_DEBUG = CFLAGS_RELEASE = -O3 -DRELEASE -funroll-loops -ffast-math -LFLAGS_RELEASE = -O3 +LFLAGS_RELEASE = -O3 SRC = Src/ BIN = Bin/Linux/ diff --git a/PoissonRecon.vcxproj b/PoissonRecon.vcxproj index e5d1740e..02dd6f82 100644 --- a/PoissonRecon.vcxproj +++ b/PoissonRecon.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -30,23 +30,23 @@ Application MultiByte true - v140 + v141 Application MultiByte - v140 + v141 Application MultiByte true - v140 + v141 Application MultiByte - v140 + v141 true @@ -108,7 +108,7 @@ Disabled - WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + WIN32;NOMINMAX;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -157,7 +157,7 @@ %(AdditionalIncludeDirectories) - WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) + WIN32;NOMINMAX;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) MultiThreadedDLL diff --git a/SSDRecon.vcxproj b/SSDRecon.vcxproj index 5ddf8894..243a5bcf 100644 --- a/SSDRecon.vcxproj +++ b/SSDRecon.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -30,23 +30,23 @@ Application MultiByte true - v140 + v141 Application MultiByte - v140 + v141 Application MultiByte true - v140 + v141 Application MultiByte - v140 + v141 true diff --git a/Src/Allocator.h b/Src/Allocator.h index 3ba23d9d..6c840216 100644 --- a/Src/Allocator.h +++ b/Src/Allocator.h @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -148,7 +148,7 @@ class Allocator if( elements>blockSize ) fprintf( stderr , "[ERROR] Allocator: elements bigger than block-size: %d>%d\n" , elements , blockSize ) , exit( 0 ); if( remains #include #ifdef _WIN64 @@ -51,7 +52,8 @@ void* aligned_malloc( size_t size , size_t align ) // Add align-1 to the start of the address and then zero out at most of the first align-1 bits. amem = ( char* )( ( (size_t)( ( (char*)amem ) + (align-1) ) ) & ~( align-1 ) ); // Pre-write the actual address - ( ( void** ) amem )[-1] = mem; + void **vmem = reinterpret_cast(amem); + vmem[-1] = mem; return amem; } void aligned_free( void* mem ) { free( ( ( void** )mem )[-1] ); } diff --git a/Src/CmdLineParser.cpp b/Src/CmdLineParser.cpp index 9061b4a8..b1aee92d 100644 --- a/Src/CmdLineParser.cpp +++ b/Src/CmdLineParser.cpp @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -162,26 +162,25 @@ void cmdLineStrings::writeValue(char* str) } -char* GetFileExtension(char* fileName){ +std::string GetFileExtension(const std::string& fileName) +{ char* fileNameCopy; - char* ext=NULL; char* temp; + std::string ext; - fileNameCopy=new char[strlen(fileName)+1]; + fileNameCopy=new char[fileName.size() + 1]; assert(fileNameCopy); - strcpy(fileNameCopy,fileName); + strcpy(fileNameCopy,fileName.data()); temp=strtok(fileNameCopy,"."); while(temp!=NULL) { - if(ext!=NULL){delete[] ext;} - ext=new char[strlen(temp)+1]; - assert(ext); - strcpy(ext,temp); + ext = temp; temp=strtok(NULL,"."); } delete[] fileNameCopy; return ext; } + char* GetLocalFileName(char* fileName){ char* fileNameCopy; char* name=NULL; diff --git a/Src/CmdLineParser.h b/Src/CmdLineParser.h index 6d8b1759..e30df621 100644 --- a/Src/CmdLineParser.h +++ b/Src/CmdLineParser.h @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -28,9 +28,9 @@ DAMAGE. #ifndef CMD_LINE_PARSER_INCLUDED #define CMD_LINE_PARSER_INCLUDED +#include +#include #include -#include - #ifdef WIN32 int strcasecmp(char* c1,char* c2); @@ -112,7 +112,7 @@ class cmdLineStringArray : public cmdLineReadable { // the values of "r" appropriately. Parameters start with "--" void cmdLineParse(int argc, char **argv,int num,cmdLineReadable** r,int dumpError=1); -char* GetFileExtension(char* fileName); +std::string GetFileExtension(const std::string& fileName); char* GetLocalFileName(char* fileName); char** ReadWords(const char* fileName,int& cnt); diff --git a/Src/CmdLineParser.inl b/Src/CmdLineParser.inl index eeded680..e95db8f0 100644 --- a/Src/CmdLineParser.inl +++ b/Src/CmdLineParser.inl @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -44,7 +44,7 @@ int cmdLineIntArray::read(char** argv,int argc) { if(argc>=Dim) { - for(int i=0;i::read(char** argv,int argc) { if(argc>=Dim) { - for(int i=0;i + operator XForm3x3<_Real>() const + { + XForm3x3<_Real> out; + for( int i=0 ; i<3 ; i++ ) + for( int j=0 ; j<3 ; j++ ) + out.coords[i][j] = static_cast<_Real>(coords[i][j]); + return out; + } template< class _Real > Point3D< _Real > operator * ( const Point3D< _Real >& p ) const { Point3D< _Real > q; @@ -135,6 +144,15 @@ struct XForm4x4 } return q; } + template + operator XForm4x4<_Real>() const + { + XForm4x4<_Real> out; + for( int i=0 ; i<4 ; i++ ) + for( int j=0 ; j<4 ; j++ ) + out.coords[i][j] = static_cast<_Real>(coords[i][j]); + return out; + } XForm4x4 operator * ( const XForm4x4& m ) const { XForm4x4 n; @@ -258,7 +276,7 @@ class Triangle{ } return Area()/d; } - + }; class CoredPointIndex { diff --git a/Src/Geometry.inl b/Src/Geometry.inl index b38f0e6b..a960eefe 100644 --- a/Src/Geometry.inl +++ b/Src/Geometry.inl @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -462,7 +462,7 @@ template< class Vertex > int CoredVectorMeshData< Vertex >::addPolygon_s( const std::vector< CoredVertexIndex >& vertices ) { std::vector< int > polygon( vertices.size() ); - for( int i=0 ; i<(int)vertices.size() ; i++ ) + for( int i=0 ; i<(int)vertices.size() ; i++ ) if( vertices[i].inCore ) polygon[i] = vertices[i].idx; else polygon[i] = -vertices[i].idx-1; return addPolygon_s( polygon ); @@ -503,7 +503,7 @@ template< class Vertex > CoredFileMeshData< Vertex >::CoredFileMeshData( void ) { oocPoints = polygons = 0; - + oocPointFile = new BufferedReadWriteFile(); polygonFile = new BufferedReadWriteFile(); } @@ -555,7 +555,7 @@ template< class Vertex > int CoredFileMeshData< Vertex >::addPolygon_s( const std::vector< CoredVertexIndex >& vertices ) { std::vector< int > polygon( vertices.size() ); - for( int i=0 ; i<(int)vertices.size() ; i++ ) + for( int i=0 ; i<(int)vertices.size() ; i++ ) if( vertices[i].inCore ) polygon[i] = vertices[i].idx; else polygon[i] = -vertices[i].idx-1; return addPolygon_s( polygon ); diff --git a/Src/MAT.inl b/Src/MAT.inl index 5106659f..3f33d76c 100644 --- a/Src/MAT.inl +++ b/Src/MAT.inl @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -143,10 +143,12 @@ void MinimalAreaTriangulation::GetTriangulation(const size_t& i,const size size_t ii=i; if( i=ii ) + if( j+1>=(size_t)ii ) return; ii=midPoint[i*eCount+j]; +#ifdef BRUNO_LEVY_FIX // Always true when type of ii is size_t if( ii>=0 ) +#endif { tIndex.idx[0] = int( i ); tIndex.idx[1] = int( j ); @@ -160,7 +162,8 @@ void MinimalAreaTriangulation::GetTriangulation(const size_t& i,const size template Real MinimalAreaTriangulation::GetArea(const size_t& i,const size_t& j,const std::vector >& vertices) { - Real a=FLT_MAX,temp; + Real a(std::numeric_limits::max()); + Real temp; size_t eCount=vertices.size(); size_t idx=i*eCount+j; size_t ii=i; diff --git a/Src/MarchingCubes.cpp b/Src/MarchingCubes.cpp index 4973835b..7e6a704c 100644 --- a/Src/MarchingCubes.cpp +++ b/Src/MarchingCubes.cpp @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -145,9 +145,9 @@ bool Cube::IsEdgeCorner( int cIndex , int e ) FactorEdgeIndex( e , o , i , j ); switch( o ) { - case 0: return (cIndex && 2)==(i<<1) && (cIndex && 4)==(j<<2); - case 1: return (cIndex && 1)==(i<<0) && (cIndex && 4)==(j<<2); - case 2: return (cIndex && 4)==(i<<2) && (cIndex && 2)==(j<<1); + case 0: return (cIndex & 2)==(i<<1) && (cIndex & 4)==(j<<2); + case 1: return (cIndex & 1)==(i<<0) && (cIndex & 4)==(j<<2); + case 2: return (cIndex & 4)==(i<<2) && (cIndex & 2)==(j<<1); default: return false; } } @@ -309,7 +309,7 @@ bool MarchingSquares::HasEdgeRoots( unsigned char mcIndex , int edgeIndex ) { int c1 , c2; Square::EdgeCorners( edgeIndex , c1 , c2 ); - return !( + return !( ( ( mcIndex&(1< -> -> - 9, // 1 -> 0 -> (0,0) -> 0,3 -> 9 + 9, // 1 -> 0 -> (0,0) -> 0,3 -> 9 3, // 2 -> 1 -> (1,0) -> 0,1 -> 3 10, // 3 -> 0,1 -> (0,0) (1,0) -> 1,3 -> 10 12, // 4 -> 2 -> (0,1) -> 2,3 -> 12 @@ -333,13 +333,13 @@ const int MarchingSquares::edgeMask[1< 1,2 -> (1,0) (0,1) -> 0,1,2,3 -> 15 6, // 7 -> 0,1,2 -> (0,0) (1,0) (0,1) -> 1,2 -> 6 6, // 8 -> 3 -> (1,1) -> 1,2 -> 6 - 15, // 9 -> 0,3 -> (0,0) (1,1) -> 0,1,2,3 -> 15 + 15, // 9 -> 0,3 -> (0,0) (1,1) -> 0,1,2,3 -> 15 5, // 10 -> 1,3 -> (1,0) (1,1) -> 0,2 -> 5 12, // 11 -> 0,1,3 -> (0,0) (1,0) (1,1) -> 2,3 -> 12 10, // 12 -> 2,3 -> (0,1) (1,1) -> 1,3 -> 10 3, // 13 -> 0,2,3 -> (0,0) (0,1) (1,1) -> 0,1 -> 3 9, // 14 -> 1,2,3 -> (1,0) (0,1) (1,1) -> 0,3 -> 9 - 0, // 15 -> 0,1,2,3 -> (0,0) (1,0) (0,1) (1,1) -> + 0, // 15 -> 0,1,2,3 -> (0,0) (1,0) (0,1) (1,1) -> }; #if NEW_ORDERING /* @@ -950,7 +950,7 @@ bool MarchingCubes::HasEdgeRoots( unsigned char mcIndex , int edgeIndex ) { int c1 , c2; Cube::EdgeCorners( edgeIndex , c1 , c2 ); - return !( + return !( ( ( mcIndex&(1< m_polys; + int m_polyIter; + int m_pointIter; + +public: + BaseMemMesh() : m_polyIter(0), m_pointIter(0) + {} + + virtual int polygonCount() const + { return (int)m_polys.size(); } + virtual void newPolygon(std::vector& poly) + { +#pragma omp critical(MESH_POLY) + m_polys.push_back(poly); + } + + virtual void resetIterator() + { + m_polyIter = 0; + m_pointIter = 0; + } + + virtual bool nextPolygon(Polygon& p) + { + p = m_polys[m_polyIter++]; + return m_polyIter < m_polys.size(); + } +}; + +class MemMesh : public BaseMemMesh +{ + struct Point + { + double m_x; + double m_y; + double m_z; + }; + + std::vector m_points; + +public: + virtual int pointCount() const + { return (int)m_points.size(); } + virtual int newPoint(const std::array& position) + { +#pragma omp critical(MESH_POINT) + m_points.push_back(Point({position[0], position[1], position[2]})); + return (int)m_points.size() - 1; + } + + virtual bool nextPoint(Kazhdan::Point& p) + { + p.m_position[0] = m_points[m_pointIter].m_x; + p.m_position[1] = m_points[m_pointIter].m_y; + p.m_position[2] = m_points[m_pointIter].m_z; + return ++m_pointIter < m_points.size(); + } +}; + +class ColorMemMesh : public MemMesh +{ + struct Point + { + double m_x; + double m_y; + double m_z; + uint8_t m_red; + uint8_t m_green; + uint8_t m_blue; + }; + + std::vector m_points; + +public: + virtual int pointCount() const + { return (int)m_points.size(); } + virtual int newPoint(const std::array& position, + const std::array& color) + { +#pragma omp critical( MESH_POINT ) + m_points.push_back( + Point({position[0], position[1], position[2], + color[0], color[1], color[2]})); + return (int)m_points.size() - 1; + } + + virtual bool nextPoint(Kazhdan::Point& p) + { + p.m_position[0] = m_points[m_pointIter].m_x; + p.m_position[1] = m_points[m_pointIter].m_y; + p.m_position[2] = m_points[m_pointIter].m_z; + p.m_color[0] = m_points[m_pointIter].m_red; + p.m_color[1] = m_points[m_pointIter].m_green; + p.m_color[2] = m_points[m_pointIter].m_blue; + return ++m_pointIter < m_points.size(); + } +}; + +class DensityMemMesh : public MemMesh +{ + struct Point + { + double m_x; + double m_y; + double m_z; + double m_density; + }; + + std::vector m_points; + +public: + virtual int pointCount() const + { return (int)m_points.size(); } + virtual int newPoint(const std::array& position, + double density) + { +#pragma omp critical( MESH_POINT ) + m_points.push_back( + Point({position[0], position[1], position[2], density})); + return (int)m_points.size() - 1; + } + + virtual bool nextPoint(Kazhdan::Point& p) + { + p.m_position[0] = m_points[m_pointIter].m_x; + p.m_position[1] = m_points[m_pointIter].m_y; + p.m_position[2] = m_points[m_pointIter].m_z; + p.m_density = m_points[m_pointIter].m_density; + return ++m_pointIter < m_points.size(); + } +}; + +class CompleteMemMesh : public MemMesh +{ + struct Point + { + double m_x; + double m_y; + double m_z; + double m_density; + uint8_t m_red; + uint8_t m_green; + uint8_t m_blue; + }; + + std::vector m_points; + +public: + virtual int pointCount() const + { return (int)m_points.size(); } + virtual int newPoint(const std::array& position, + const std::array& color, double density) + { +#pragma omp critical( MESH_POINT ) + m_points.push_back( + Point({position[0], position[1], position[2], density, + color[0], color[1], color[2]})); + return (int)m_points.size(); + } + + virtual bool nextPoint(Kazhdan::Point& p) + { + p.m_position[0] = m_points[m_pointIter].m_x; + p.m_position[1] = m_points[m_pointIter].m_y; + p.m_position[2] = m_points[m_pointIter].m_z; + p.m_color[0] = m_points[m_pointIter].m_red; + p.m_color[1] = m_points[m_pointIter].m_green; + p.m_color[2] = m_points[m_pointIter].m_blue; + p.m_density = m_points[m_pointIter].m_density; + return ++m_pointIter < m_points.size(); + } +}; + +} // namespace diff --git a/Src/Mesh.h b/Src/Mesh.h new file mode 100644 index 00000000..361dd917 --- /dev/null +++ b/Src/Mesh.h @@ -0,0 +1,82 @@ +/* +Copyright (c) 2017, Andrew Bell +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior writften permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#pragma once + +#include +#include + +namespace Kazhdan +{ + +struct Point +{ + std::array m_position; + std::array m_color; + double m_density; +}; + +using Polygon = std::vector; + +class Mesh +{ +public: + virtual int pointCount() const = 0; + virtual int polygonCount() const = 0; + virtual void newPolygon(std::vector& poly) = 0; + virtual int newPoint(const std::array& position) = 0; + virtual int newPoint(const std::array& position, + const std::array& color) + { + throw std::runtime_error("Mesh doesn't support color data."); + } + + virtual int newPoint(const std::array& position, + double density) + { + throw std::runtime_error("Mesh doesn't support density data."); + } + + virtual int newPoint(const std::array& position, + const std::array& color, double density) + { + throw std::runtime_error("Mesh doesn't support color " + "and density data."); + } + + virtual bool hasColor() const + { return false; } + virtual bool hasDensity() const + { return false; } + + virtual void resetIterator() = 0; + virtual bool nextPolygon(Polygon& poly) = 0; + virtual bool nextPoint(Point& point) = 0; +}; + +} // namespace diff --git a/Src/MultiGridOctreeData.Evaluation.inl b/Src/MultiGridOctreeData.Evaluation.inl index c965effb..37bb9898 100644 --- a/Src/MultiGridOctreeData.Evaluation.inl +++ b/Src/MultiGridOctreeData.Evaluation.inl @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -55,7 +55,7 @@ void Octree< Real >::_Evaluator< FEMDegree , BType >::set( LocalDepth depth ) } //// The face stencil - for( int f=0 ; f::_Evaluator< FEMDegree , BType >::set( LocalDepth depth ) } //// The edge stencil - for( int e=0 ; e::_Evaluator< FEMDegree , BType >::set( LocalDepth depth ) } //// The corner stencil - for( int c=0 ; c::_Evaluator< FEMDegree , BType >::set( LocalDepth depth ) } //// The face stencil - for( int f=0 ; f::_Evaluator< FEMDegree , BType >::set( LocalDepth depth ) } //// The edge stencil - for( int e=0 ; e::_Evaluator< FEMDegree , BType >::set( LocalDepth depth ) } //// The corner stencil - for( int c=0 ; c::_Evaluator< FEMDegree , BType >::set( LocalDepth depth ) } template< class Real > template< class V , int FEMDegree , BoundaryType BType > -V Octree< Real >::_getValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , Point3D< Real > p , const DenseNodeData< V , FEMDegree >& solution , const DenseNodeData< V , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator ) const +V Octree< Real >::_getValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , Point3D< Real > p , const DenseNodeData< V >& solution , const DenseNodeData< V >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator ) const { static const int SupportSize = BSplineSupportSizes< FEMDegree >::SupportSize; static const int LeftSupportRadius = -BSplineSupportSizes< FEMDegree >::SupportStart; @@ -290,7 +290,7 @@ V Octree< Real >::_getValue( const ConstPointSupportKey< FEMDegree >& neighborKe int _fIdx[3]; functionIndex< FEMDegree , BType >( _n , _fIdx ); for( int dd=0 ; dd<3 ; dd++ ) _pIdx[dd] = std::max< int >( 0 , std::min< int >( SupportSize-1 , LeftSupportRadius + (int)floor( ( p[dd]-_s[dd] ) / _w ) ) ); - value += + value += solution[ _n->nodeData.nodeIndex ] * (Real) ( @@ -323,7 +323,7 @@ V Octree< Real >::_getValue( const ConstPointSupportKey< FEMDegree >& neighborKe int _fIdx[3]; functionIndex< FEMDegree , BType >( _n , _fIdx ); for( int dd=0 ; dd<3 ; dd++ ) _pIdx[dd] = std::max< int >( 0 , std::min< int >( SupportSize-1 , LeftSupportRadius + (int)floor( ( p[dd]-_s[dd] ) / _w ) ) ); - value += + value += solution[ _n->nodeData.nodeIndex ] * (Real) ( @@ -347,7 +347,7 @@ V Octree< Real >::_getValue( const ConstPointSupportKey< FEMDegree >& neighborKe int _fIdx[3]; functionIndex< FEMDegree , BType >( _n , _fIdx ); for( int dd=0 ; dd<3 ; dd++ ) _pIdx[dd] = std::max< int >( 0 , std::min< int >( SupportSize-1 , LeftSupportRadius + (int)floor( ( p[dd]-_s[dd] ) / _w ) ) ); - value += + value += coarseSolution[ _n->nodeData.nodeIndex ] * (Real) ( @@ -363,7 +363,7 @@ V Octree< Real >::_getValue( const ConstPointSupportKey< FEMDegree >& neighborKe } template< class Real > template< int FEMDegree , BoundaryType BType > -std::pair< Real , Point3D< Real > > Octree< Real >::_getValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , Point3D< Real > p , const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator ) const +std::pair< Real , Point3D< Real > > Octree< Real >::_getValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , Point3D< Real > p , const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator ) const { static const int SupportSize = BSplineSupportSizes< FEMDegree >::SupportSize; static const int LeftSupportRadius = -BSplineSupportSizes< FEMDegree >::SupportStart; @@ -391,13 +391,13 @@ std::pair< Real , Point3D< Real > > Octree< Real >::_getValueAndGradient( const int _fIdx[3]; functionIndex< FEMDegree , BType >( _n , _fIdx ); for( int dd=0 ; dd<3 ; dd++ ) _pIdx[dd] = std::max< int >( 0 , std::min< int >( SupportSize-1 , LeftSupportRadius + (int)floor( ( p[dd]-_s[dd] ) / _w ) ) ); - value += + value += solution[ _n->nodeData.nodeIndex ] * (Real) ( evaluator._bsData->baseBSplines[ _fIdx[0] ][ _pIdx[0] ]( p[0] ) * evaluator._bsData->baseBSplines[ _fIdx[1] ][ _pIdx[1] ]( p[1] ) * evaluator._bsData->baseBSplines[ _fIdx[2] ][ _pIdx[2] ]( p[2] ) ); - gradient += + gradient += Point3D< Real > ( evaluator._bsData->dBaseBSplines[ _fIdx[0] ][ _pIdx[0] ]( p[0] ) * evaluator._bsData-> baseBSplines[ _fIdx[1] ][ _pIdx[1] ]( p[1] ) * evaluator._bsData-> baseBSplines[ _fIdx[2] ][ _pIdx[2] ]( p[2] ) , @@ -431,13 +431,13 @@ std::pair< Real , Point3D< Real > > Octree< Real >::_getValueAndGradient( const int _fIdx[3]; functionIndex< FEMDegree , BType >( _n , _fIdx ); for( int dd=0 ; dd<3 ; dd++ ) _pIdx[dd] = std::max< int >( 0 , std::min< int >( SupportSize-1 , LeftSupportRadius + (int)floor( ( p[dd]-_s[dd] ) / _w ) ) ); - value += + value += solution[ _n->nodeData.nodeIndex ] * (Real) ( evaluator._bsData->baseBSplines[ _fIdx[0] ][ _pIdx[0] ]( p[0] ) * evaluator._bsData->baseBSplines[ _fIdx[1] ][ _pIdx[1] ]( p[1] ) * evaluator._bsData->baseBSplines[ _fIdx[2] ][ _pIdx[2] ]( p[2] ) ); - gradient += + gradient += Point3D< Real > ( evaluator._bsData->dBaseBSplines[ _fIdx[0] ][ _pIdx[0] ]( p[0] ) * evaluator._bsData-> baseBSplines[ _fIdx[1] ][ _pIdx[1] ]( p[1] ) * evaluator._bsData-> baseBSplines[ _fIdx[2] ][ _pIdx[2] ]( p[2] ) , @@ -461,13 +461,13 @@ std::pair< Real , Point3D< Real > > Octree< Real >::_getValueAndGradient( const int _fIdx[3]; functionIndex< FEMDegree , BType >( _n , _fIdx ); for( int dd=0 ; dd<3 ; dd++ ) _pIdx[dd] = std::max< int >( 0 , std::min< int >( SupportSize-1 , LeftSupportRadius + (int)floor( ( p[dd]-_s[dd] ) / _w ) ) ); - value += + value += coarseSolution[ _n->nodeData.nodeIndex ] * (Real) ( evaluator._bsData->baseBSplines[ _fIdx[0] ][ _pIdx[0] ]( p[0] ) * evaluator._bsData->baseBSplines[ _fIdx[1] ][ _pIdx[1] ]( p[1] ) * evaluator._bsData->baseBSplines[ _fIdx[2] ][ _pIdx[2] ]( p[2] ) ); - gradient += + gradient += Point3D< Real > ( evaluator._bsData->dBaseBSplines[ _fIdx[0] ][ _pIdx[0] ]( p[0] ) * evaluator._bsData-> baseBSplines[ _fIdx[1] ][ _pIdx[1] ]( p[1] ) * evaluator._bsData-> baseBSplines[ _fIdx[2] ][ _pIdx[2] ]( p[2] ) , @@ -482,7 +482,7 @@ std::pair< Real , Point3D< Real > > Octree< Real >::_getValueAndGradient( const } template< class Real > template< class V , int FEMDegree , BoundaryType BType > -V Octree< Real >::_getCenterValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const DenseNodeData< V , FEMDegree >& solution , const DenseNodeData< V , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const +V Octree< Real >::_getCenterValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const DenseNodeData< V >& solution , const DenseNodeData< V >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const { static const int SupportSize = BSplineEvaluationData< FEMDegree , BType >::SupportSize; static const int LeftPointSupportRadius = BSplineEvaluationData< FEMDegree , BType >::SupportEnd; @@ -559,7 +559,7 @@ V Octree< Real >::_getCenterValue( const ConstPointSupportKey< FEMDegree >& neig } template< class Real > template< int FEMDegree , BoundaryType BType > -std::pair< Real , Point3D< Real > > Octree< Real >::_getCenterValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const +std::pair< Real , Point3D< Real > > Octree< Real >::_getCenterValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const { static const int SupportSize = BSplineEvaluationData< FEMDegree , BType >::SupportSize; static const int LeftPointSupportRadius = BSplineEvaluationData< FEMDegree , BType >::SupportEnd; @@ -616,7 +616,7 @@ std::pair< Real , Point3D< Real > > Octree< Real >::_getCenterValueAndGradient( ( evaluator.evaluator.centerValue( fIdx[0] , cIdx[0] , false ) * evaluator.evaluator.centerValue( fIdx[1] , cIdx[1] , false ) * evaluator.evaluator.centerValue( fIdx[2] , cIdx[2] , false ) ) * solution[ n->nodeData.nodeIndex ]; - gradient += + gradient += Point3D< Real > ( evaluator.evaluator.centerValue( fIdx[0] , cIdx[0] , true ) * evaluator.evaluator.centerValue( fIdx[1] , cIdx[1] , false ) * evaluator.evaluator.centerValue( fIdx[2] , cIdx[2] , false ) , @@ -655,7 +655,7 @@ std::pair< Real , Point3D< Real > > Octree< Real >::_getCenterValueAndGradient( } template< class Real > template< class V , int FEMDegree , BoundaryType BType > -V Octree< Real >::_getEdgeValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int edge , const DenseNodeData< V , FEMDegree >& solution , const DenseNodeData< V , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const +V Octree< Real >::_getEdgeValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int edge , const DenseNodeData< V >& solution , const DenseNodeData< V >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const { static const int SupportSize = BSplineEvaluationData< FEMDegree , BType >::SupportSize; static const int LeftPointSupportRadius = BSplineEvaluationData< FEMDegree , BType >::SupportEnd; @@ -802,7 +802,7 @@ V Octree< Real >::_getEdgeValue( const ConstPointSupportKey< FEMDegree >& neighb } template< class Real > template< int FEMDegree , BoundaryType BType > -std::pair< Real , Point3D< Real > > Octree< Real >::_getEdgeValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int edge , const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const +std::pair< Real , Point3D< Real > > Octree< Real >::_getEdgeValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int edge , const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const { static const int SupportSize = BSplineEvaluationData< FEMDegree , BType >::SupportSize; static const int LeftPointSupportRadius = BSplineEvaluationData< FEMDegree , BType >::SupportEnd; @@ -960,7 +960,7 @@ std::pair< Real , Point3D< Real > > Octree< Real >::_getEdgeValueAndGradient( co template< class Real > template< class V , int FEMDegree , BoundaryType BType > -V Octree< Real >::_getCornerValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int corner , const DenseNodeData< V , FEMDegree >& solution , const DenseNodeData< V , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const +V Octree< Real >::_getCornerValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int corner , const DenseNodeData< V >& solution , const DenseNodeData< V >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const { static const int SupportSize = BSplineSupportSizes< FEMDegree >::SupportSize; static const int LeftPointSupportRadius = BSplineSupportSizes< FEMDegree >::SupportEnd; @@ -1045,7 +1045,7 @@ V Octree< Real >::_getCornerValue( const ConstPointSupportKey< FEMDegree >& neig } template< class Real > template< int FEMDegree , BoundaryType BType > -std::pair< Real , Point3D< Real > > Octree< Real >::_getCornerValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int corner , const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const +std::pair< Real , Point3D< Real > > Octree< Real >::_getCornerValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int corner , const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const { static const int SupportSize = BSplineSupportSizes< FEMDegree >::SupportSize; static const int LeftPointSupportRadius = BSplineSupportSizes< FEMDegree >::SupportEnd; @@ -1123,7 +1123,7 @@ std::pair< Real , Point3D< Real > > Octree< Real >::_getCornerValueAndGradient( } template< class Real > template< int Degree , BoundaryType BType > -Octree< Real >::MultiThreadedEvaluator< Degree , BType >::MultiThreadedEvaluator( const Octree< Real >* tree , const DenseNodeData< Real , Degree >& coefficients , int threads ) : _coefficients( coefficients ) , _tree( tree ) +Octree< Real >::MultiThreadedEvaluator< Degree , BType >::MultiThreadedEvaluator( const Octree< Real >* tree , const DenseNodeData< Real >& coefficients , int threads ) : _tree(tree), _coefficients( coefficients ) { _threads = std::max< int >( 1 , threads ); _neighborKeys.resize( _threads ); diff --git a/Src/MultiGridOctreeData.IsoSurface.inl b/Src/MultiGridOctreeData.IsoSurface.inl index 2be26dc5..81b32b8a 100644 --- a/Src/MultiGridOctreeData.IsoSurface.inl +++ b/Src/MultiGridOctreeData.IsoSurface.inl @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -26,10 +26,14 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S DAMAGE. */ +#include + #include "Octree.h" #include "MyTime.h" #include "MemoryUsage.h" #include "MAT.h" +#include "Mesh.h" +#include "Ply.h" template< class Real > template< class Vertex > @@ -88,7 +92,7 @@ void Octree< Real >::_SliceValues< Vertex >::reset( bool nonLinearFit ) faceEdges = AllocPointer< _FaceEdges >( _oldFCount ); faceSet = AllocPointer< char >( _oldFCount ); } - + if( sliceData.cCount>0 ) memset( cornerSet , 0 , sizeof( char ) * sliceData.cCount ); if( sliceData.eCount>0 ) memset( edgeSet , 0 , sizeof( char ) * sliceData.eCount ); if( sliceData.fCount>0 ) memset( faceSet , 0 , sizeof( char ) * sliceData.fCount ); @@ -135,13 +139,13 @@ void Octree< Real >::_XSliceValues< Vertex >::reset( void ) template< class Real > template< int FEMDegree , BoundaryType BType , int WeightDegree , int ColorDegree , class Vertex > -void Octree< Real >::getMCIsoSurface( const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , const DenseNodeData< Real , FEMDegree >& solution , Real isoValue , CoredMeshData< Vertex >& mesh , bool nonLinearFit , bool addBarycenter , bool polygonMesh ) +void Octree< Real >::getMCIsoSurface( const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , const DenseNodeData< Real >& solution , Real isoValue , Kazhdan::Mesh& mesh , bool nonLinearFit , bool addBarycenter , bool polygonMesh ) { if( FEMDegree==1 && nonLinearFit ) fprintf( stderr , "[WARNING] First order B-Splines do not support non-linear interpolation\n" ) , nonLinearFit = false; BSplineData< ColorDegree , BOUNDARY_NEUMANN >* colorBSData = NULL; if( colorData ) colorBSData = new BSplineData< ColorDegree , BOUNDARY_NEUMANN >( _maxDepth ); - DenseNodeData< Real , FEMDegree > coarseSolution( _sNodesEnd(_maxDepth-1) ); + DenseNodeData< Real > coarseSolution( _sNodesEnd(_maxDepth-1) ); memset( &coarseSolution[0] , 0 , sizeof(Real)*_sNodesEnd( _maxDepth-1) ); #pragma omp parallel for num_threads( threads ) for( int i=_sNodesBegin(0) ; i<_sNodesEnd(_maxDepth-1) ; i++ ) coarseSolution[i] = solution[i]; @@ -223,14 +227,14 @@ void Octree< Real >::getMCIsoSurface( const DensityEstimator< WeightDegree >* de template< class Real > template< class Vertex , int FEMDegree , BoundaryType BType > -void Octree< Real >::_setSliceIsoCorners( const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , Real isoValue , LocalDepth depth , int slice , std::vector< _SlabValues< Vertex > >& slabValues , const _Evaluator< FEMDegree , BType >& evaluator , int threads ) +void Octree< Real >::_setSliceIsoCorners( const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , Real isoValue , LocalDepth depth , int slice , std::vector< _SlabValues< Vertex > >& slabValues , const _Evaluator< FEMDegree , BType >& evaluator , int threads ) { if( slice>0 ) _setSliceIsoCorners( solution , coarseSolution , isoValue , depth , slice , 1 , slabValues , evaluator , threads ); if( slice<(1< template< class Vertex , int FEMDegree , BoundaryType BType > -void Octree< Real >::_setSliceIsoCorners( const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , Real isoValue , LocalDepth depth , int slice , int z , std::vector< _SlabValues< Vertex > >& slabValues , const struct _Evaluator< FEMDegree , BType >& evaluator , int threads ) +void Octree< Real >::_setSliceIsoCorners( const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , Real isoValue , LocalDepth depth , int slice , int z , std::vector< _SlabValues< Vertex > >& slabValues , const struct _Evaluator< FEMDegree , BType >& evaluator , int threads ) { typename Octree::template _SliceValues< Vertex >& sValues = slabValues[depth].sliceValues( slice ); std::vector< ConstPointSupportKey< FEMDegree > > neighborKeys( std::max< int >( 1 , threads ) ); @@ -283,16 +287,45 @@ void Octree< Real >::_setSliceIsoCorners( const DenseNodeData< Real , FEMDegree } } +inline int addPoint(Kazhdan::Mesh& mesh, const PlyVertex& v) +{ + std::array p {{v.point.coords[0], v.point.coords[1], + v.point.coords[2]}}; + return mesh.newPoint(p); +} + +inline int addPoint(Kazhdan::Mesh& mesh, const PlyValueVertex& v) +{ + std::array p {{v.point.coords[0], v.point.coords[1], + v.point.coords[2]}}; + return mesh.newPoint(p, (double)v.value); +} + +inline int addPoint(Kazhdan::Mesh& mesh, const PlyColorVertex& v) +{ + return mesh.newPoint( + {{v.point.coords[0], v.point.coords[1], v.point.coords[2]}}, + {{v.color[0], v.color[1], v.color[2]}}); +} + +inline int addPoint(Kazhdan::Mesh& mesh, const PlyColorAndValueVertex& v) +{ + return mesh.newPoint( + {{v.point.coords[0], v.point.coords[1], v.point.coords[2]}}, + {{v.color[0], v.color[1], v.color[2]}}, + (double)v.value); +} + template< class Real > template< int WeightDegree , int ColorDegree , BoundaryType BType , class Vertex > -void Octree< Real >::_setSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , Real isoValue , LocalDepth depth , int slice , int& vOffset , CoredMeshData< Vertex >& mesh , std::vector< _SlabValues< Vertex > >& slabValues , int threads ) +void Octree< Real >::_setSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , Real isoValue , LocalDepth depth , int slice , int& vOffset , Kazhdan::Mesh& mesh , std::vector< _SlabValues< Vertex > >& slabValues , int threads ) { if( slice>0 ) _setSliceIsoVertices< WeightDegree , ColorDegree >( colorBSData , densityWeights , colorData , isoValue , depth , slice , 1 , vOffset , mesh , slabValues , threads ); if( slice<(1<( colorBSData , densityWeights , colorData , isoValue , depth , slice , 0 , vOffset , mesh , slabValues , threads ); } template< class Real > template< int WeightDegree , int ColorDegree , BoundaryType BType , class Vertex > -void Octree< Real >::_setSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , Real isoValue , LocalDepth depth , int slice , int z , int& vOffset , CoredMeshData< Vertex >& mesh , std::vector< _SlabValues< Vertex > >& slabValues , int threads ) +void Octree< Real >::_setSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , Real isoValue , LocalDepth depth , int slice , int z , int& vOffset , Kazhdan::Mesh& mesh , std::vector< _SlabValues< Vertex > >& slabValues , int threads ) { typename Octree::template _SliceValues< Vertex >& sValues = slabValues[depth].sliceValues( slice ); // [WARNING] In the case Degree=2, these two keys are the same, so we don't have to maintain them separately. @@ -316,7 +349,7 @@ void Octree< Real >::_setSliceIsoVertices( const BSplineData< ColorDegree , BTyp neighborKey.getNeighbors( leaf ); if( densityWeights ) weightKey.getNeighbors( leaf ); if( colorData ) colorKey.getNeighbors( leaf ); - for( int e=0 ; e::_setSliceIsoVertices( const BSplineData< ColorDegree , BTyp { if( !sValues.edgeSet[vIndex] ) { - mesh.addOutOfCorePoint( vertex ); +// mesh.addOutOfCorePoint( vertex ); + addPoint(mesh, vertex); sValues.edgeSet[ vIndex ] = 1; sValues.edgeKeys[ vIndex ] = key; sValues.edgeVertexMap[key] = hashed_vertex = std::pair< int , Vertex >( vOffset , vertex ); @@ -383,7 +417,7 @@ void Octree< Real >::_setSliceIsoVertices( const BSplineData< ColorDegree , BTyp } template< class Real > template< int WeightDegree , int ColorDegree , BoundaryType BType , class Vertex > -void Octree< Real >::_setXSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , Real isoValue , LocalDepth depth , int slab , int& vOffset , CoredMeshData< Vertex >& mesh , std::vector< _SlabValues< Vertex > >& slabValues , int threads ) +void Octree< Real >::_setXSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , Real isoValue , LocalDepth depth , int slab , int& vOffset , Kazhdan::Mesh& mesh , std::vector< _SlabValues< Vertex > >& slabValues , int threads ) { typename Octree::template _SliceValues< Vertex >& bValues = slabValues[depth].sliceValues ( slab ); typename Octree::template _SliceValues< Vertex >& fValues = slabValues[depth].sliceValues ( slab+1 ); @@ -428,7 +462,8 @@ void Octree< Real >::_setXSliceIsoVertices( const BSplineData< ColorDegree , BTy { if( !xValues.edgeSet[vIndex] ) { - mesh.addOutOfCorePoint( vertex ); +// mesh.addOutOfCorePoint( vertex ); + addPoint(mesh, vertex); xValues.edgeSet[ vIndex ] = 1; xValues.edgeKeys[ vIndex ] = key; xValues.edgeVertexMap[key] = hashed_vertex = std::pair< int , Vertex >( vOffset , vertex ); @@ -746,7 +781,7 @@ void Octree< Real >::_setXSliceIsoEdges( LocalDepth depth , int slab , std::vect } template< class Real > template< class Vertex > -void Octree< Real >::_setIsoSurface( LocalDepth depth , int offset , const _SliceValues< Vertex >& bValues , const _SliceValues< Vertex >& fValues , const _XSliceValues< Vertex >& xValues , CoredMeshData< Vertex >& mesh , bool polygonMesh , bool addBarycenter , int& vOffset , int threads ) +void Octree< Real >::_setIsoSurface( LocalDepth depth , int offset , const _SliceValues< Vertex >& bValues , const _SliceValues< Vertex >& fValues , const _XSliceValues< Vertex >& xValues , Kazhdan::Mesh& mesh , bool polygonMesh , bool addBarycenter , int& vOffset , int threads ) { std::vector< std::pair< int , Vertex > > polygon; std::vector< std::vector< _IsoEdge > > edgess( std::max< int >( 1 , threads ) ); @@ -766,7 +801,7 @@ void Octree< Real >::_setIsoSurface( LocalDepth depth , int offset , const _Slic // [WARNING] Just because the node looks empty doesn't mean it doesn't get eges from finer neighbors { // Gather the edges from the faces (with the correct orientation) - for( int f=0 ; f::_setIsoSurface( LocalDepth depth , int offset , const _Slic { int idx; for( idx=0 ; idx<(int)edges.size() ; idx++ ) if( edges[idx][0]==current ) break; - if( idx==edges.size() ) + if( idx==(int)edges.size() ) { typename std::unordered_map< long long, long long >::const_iterator iter; if ( (iter=bValues.vertexPairMap.find(current))!=bValues.vertexPairMap.end() ) loops.back().push_back( current ) , current = iter->second; @@ -882,7 +917,7 @@ template< class Real > void SetIsoVertex( PlyColorAndValueVertex< double >& vert template< class Real > template< int WeightDegree , int ColorDegree , BoundaryType BType , class Vertex > -bool Octree< Real >::_getIsoVertex( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , Real isoValue , ConstPointSupportKey< WeightDegree >& weightKey , ConstPointSupportKey< ColorDegree >& colorKey , const TreeOctNode* node , int edgeIndex , int z , const _SliceValues< Vertex >& sValues , Vertex& vertex ) +bool Octree< Real >::_getIsoVertex( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , Real isoValue , ConstPointSupportKey< WeightDegree >& weightKey , ConstPointSupportKey< ColorDegree >& colorKey , const TreeOctNode* node , int edgeIndex , int z , const _SliceValues< Vertex >& sValues , Vertex& vertex ) { Point3D< Real > position; int c0 , c1; @@ -914,7 +949,7 @@ bool Octree< Real >::_getIsoVertex( const BSplineData< ColorDegree , BType >* co if( nonLinearFit ) { double dx0 = sValues.cornerGradients[idx[c0]][o] * width , dx1 = sValues.cornerGradients[idx[c1]][o] * width; - + // The scaling will turn the Hermite Spline into a quadratic double scl = (x1-x0) / ( (dx1+dx0 ) / 2 ); dx0 *= scl , dx1 *= scl; @@ -924,7 +959,7 @@ bool Octree< Real >::_getIsoVertex( const BSplineData< ColorDegree , BType >* co P.coefficients[0] = x0; P.coefficients[1] = dx0; P.coefficients[2] = 3*(x1-x0)-dx1-2*dx0; - + double roots[2]; int rCount = 0 , rootCount = P.getSolutions( isoValue , roots , 0 ); averageRoot = 0; @@ -954,7 +989,7 @@ bool Octree< Real >::_getIsoVertex( const BSplineData< ColorDegree , BType >* co if( densityWeights ) { Real weight; - _getSampleDepthAndWeight( *densityWeights , node , position , weightKey , depth , weight ); + _getSampleDepthAndWeight( *densityWeights , node , position , weightKey , depth , weight ); } if( colorData ) color = Point3D< Real >( _evaluate< ProjectiveData< Point3D< Real > , Real > >( *colorData , position , *colorBSData , colorKey ) ); SetIsoVertex( vertex , color , depth ); @@ -962,7 +997,7 @@ bool Octree< Real >::_getIsoVertex( const BSplineData< ColorDegree , BType >* co } template< class Real > template< int WeightDegree , int ColorDegree , BoundaryType BType , class Vertex > -bool Octree< Real >::_getIsoVertex( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , Real isoValue , ConstPointSupportKey< WeightDegree >& weightKey , ConstPointSupportKey< ColorDegree >& colorKey , const TreeOctNode* node , int cornerIndex , const _SliceValues< Vertex >& bValues , const _SliceValues< Vertex >& fValues , Vertex& vertex ) +bool Octree< Real >::_getIsoVertex( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , Real isoValue , ConstPointSupportKey< WeightDegree >& weightKey , ConstPointSupportKey< ColorDegree >& colorKey , const TreeOctNode* node , int cornerIndex , const _SliceValues< Vertex >& bValues , const _SliceValues< Vertex >& fValues , Vertex& vertex ) { Point3D< Real > position; @@ -1026,7 +1061,7 @@ bool Octree< Real >::_getIsoVertex( const BSplineData< ColorDegree , BType >* co if( densityWeights ) { Real weight; - _getSampleDepthAndWeight( *densityWeights , node , position , weightKey , depth , weight ); + _getSampleDepthAndWeight( *densityWeights , node , position , weightKey , depth , weight ); } if( colorData ) color = Point3D< Real >( _evaluate< ProjectiveData< Point3D< Real > , Real > >( *colorData , position , *colorBSData , colorKey ) ); SetIsoVertex( vertex , color , depth ); @@ -1035,13 +1070,13 @@ bool Octree< Real >::_getIsoVertex( const BSplineData< ColorDegree , BType >* co template< class Real > template< class Vertex > -int Octree< Real >::_addIsoPolygons( CoredMeshData< Vertex >& mesh , std::vector< std::pair< int , Vertex > >& polygon , bool polygonMesh , bool addBarycenter , int& vOffset ) +int Octree< Real >::_addIsoPolygons( Kazhdan::Mesh& mesh , std::vector< std::pair< int , Vertex > >& polygon , bool polygonMesh , bool addBarycenter , int& vOffset ) { if( polygonMesh ) { std::vector< int > vertices( polygon.size() ); for( int i=0 ; i<(int)polygon.size() ; i++ ) vertices[i] = polygon[polygon.size()-1-i].first; - mesh.addPolygon_s( vertices ); + mesh.newPolygon(vertices); return 1; } if( polygon.size()>3 ) @@ -1052,7 +1087,7 @@ int Octree< Real >::_addIsoPolygons( CoredMeshData< Vertex >& mesh , std::vector if( addBarycenter ) for( int i=0 ; i<(int)polygon.size() ; i++ ) for( int j=0 ; j::_addIsoPolygons( CoredMeshData< Vertex >& mesh , std::vector int cIdx; #pragma omp critical (add_barycenter_point_access) { - cIdx = mesh.addOutOfCorePoint( c ); + cIdx = addPoint(mesh, c); vOffset++; } for( int i=0 ; i<(int)polygon.size() ; i++ ) @@ -1076,7 +1111,7 @@ int Octree< Real >::_addIsoPolygons( CoredMeshData< Vertex >& mesh , std::vector triangle[0] = polygon[ i ].first; triangle[1] = cIdx; triangle[2] = polygon[(i+1)%polygon.size()].first; - mesh.addPolygon_s( triangle ); + mesh.newPolygon( triangle ); } return (int)polygon.size(); } @@ -1092,7 +1127,7 @@ int Octree< Real >::_addIsoPolygons( CoredMeshData< Vertex >& mesh , std::vector for( int i=0 ; i<(int)triangles.size() ; i++ ) { for( int j=0 ; j<3 ; j++ ) triangle[2-j] = polygon[ triangles[i].idx[j] ].first; - mesh.addPolygon_s( triangle ); + mesh.newPolygon( triangle ); } } } @@ -1100,7 +1135,7 @@ int Octree< Real >::_addIsoPolygons( CoredMeshData< Vertex >& mesh , std::vector { std::vector< int > vertices( 3 ); for( int i=0 ; i<3 ; i++ ) vertices[2-i] = polygon[i].first; - mesh.addPolygon_s( vertices ); + mesh.newPolygon( vertices ); } return (int)polygon.size()-2; } diff --git a/Src/MultiGridOctreeData.SortedTreeNodes.inl b/Src/MultiGridOctreeData.SortedTreeNodes.inl index 7efc9f87..a3f39816 100644 --- a/Src/MultiGridOctreeData.SortedTreeNodes.inl +++ b/Src/MultiGridOctreeData.SortedTreeNodes.inl @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -81,7 +81,7 @@ void SortedTreeNodes::set( TreeOctNode& root ) for( int l=0 ; l<_levels ; l++ ) { _sliceStart[l][0] = levelOffset; - for( int s=0 ; s<((size_t)1<::template ConstNeighborKey< 1 , 1 > ConstAdjacenctNodeKey; - if( offset<0 || offset>((size_t)1<(int)((size_t)1< span( _sliceStart[depth][ std::max< int >( 0 , offset-1 ) ] , _sliceStart[depth][ std::min< int >( (size_t)1<::template ConstNeighborKey< 1 , 1 > ConstAdjacenctNodeKey; - if( offset<0 || offset>=((size_t)1<=(int)((size_t)1< span( _sliceStart[depth][offset] , _sliceStart[depth][offset+1] ); @@ -298,7 +298,7 @@ void SortedTreeNodes::setXSliceTableData( XSliceTableData& sData , int depth , i bool edgeOwner = true; int ac = Square::AntipodalCornerIndex( Square::CornerIndex( x , y ) ); - for( int cc=0 ; cc { #if POINT_DATA_RES Real constraint = 0; - for( int c=0 ; c::SAMPLES ; c++ ) if( p[c].weight ) + for( int c=0 ; c::SAMPLES ; c++ ) if( p[c].weight ) { const Point3D< Real > q = p[c].position; constraint += (Real)( px( q[0] ) * py( q[1] ) * pz( q[2] ) * p[c].weight * p[c].value ); @@ -60,7 +60,7 @@ struct _ConstraintCalculator_< Real , Degree , false > { #if POINT_DATA_RES Real constraint = 0; - for( int c=0 ; c::SAMPLES ; c++ ) if( p[c].weight ) + for( int c=0 ; c::SAMPLES ; c++ ) if( p[c].weight ) { const Point3D< Real > q = p[c].position; constraint += (Real)( px( q[0] ) * py( q[1] ) * pz( q[2] ) * p[c]._value ); @@ -84,7 +84,7 @@ struct _ConstraintCalculator_< Real , Degree , true > { #if POINT_DATA_RES Real constraint = 0; - for( int c=0 ; c::SAMPLES ; c++ ) if( p[c].weight ) + for( int c=0 ; c::SAMPLES ; c++ ) if( p[c].weight ) { const Point3D< Real > q = p[c].position; double _px = px( q[0] ) , _py = py( q[1] ) , _pz = pz( q[2] ); @@ -109,7 +109,7 @@ struct _ConstraintCalculator_< Real , Degree , true > { #if POINT_DATA_RES Real constraint = 0; - for( int c=0 ; c::SAMPLES ; c++ ) if( p[c].weight ) + for( int c=0 ; c::SAMPLES ; c++ ) if( p[c].weight ) { const Point3D< Real > q = p[c].position; double _px = px( q[0] ) , _py = py( q[1] ) , _pz = pz( q[2] ); @@ -178,7 +178,7 @@ double FEMSystemFunctor< 1 , BOUNDARY_FREE >::_integrate( const I& integrator , return ( d00[0] * d00[1] * d00[2] - ) * massWeight + ) * massWeight + ( d11[0] * d00[1] * d00[2] + @@ -196,7 +196,7 @@ double FEMSystemFunctor< 1 , BOUNDARY_NEUMANN >::_integrate( const I& integrator return ( d00[0] * d00[1] * d00[2] - ) * massWeight + ) * massWeight + ( d11[0] * d00[1] * d00[2] + @@ -214,7 +214,7 @@ double FEMSystemFunctor< 1 , BOUNDARY_DIRICHLET >::_integrate( const I& integrat return ( d00[0] * d00[1] * d00[2] - ) * massWeight + ) * massWeight + ( d11[0] * d00[1] * d00[2] + @@ -233,7 +233,7 @@ double FEMSystemFunctor< FEMDegree , BType >::_integrate( const I& integrator , return ( d00[0] * d00[1] * d00[2] - ) * massWeight + ) * massWeight + ( d11[0] * d00[1] * d00[2] + @@ -259,11 +259,11 @@ double FEMSFConstraintFunctor< SFDegree , SFBType , FEMDegree , FEMBType >::_int double d00[] = D_DOT( 0 , 0 ) , d02[] = D_DOT( 0 , 2 ) , d20[] = D_DOT( 2 , 0 ) , d22[] = D_DOT( 2 , 2 ) , d11[] = D_DOT( 1 , 1 ); if( SFDegree==0 || FEMDegree==0 ) return d00[0] * d00[1] * d00[2] * massWeight; - else if( SFDegree<=1 || FEMDegree<=1 ) + else if( SFDegree<=1 || FEMDegree<=1 ) return ( d00[0] * d00[1] * d00[2] - ) * massWeight + ) * massWeight + ( d11[0] * d00[1] * d00[2] + @@ -274,7 +274,7 @@ double FEMSFConstraintFunctor< SFDegree , SFBType , FEMDegree , FEMBType >::_int return ( d00[0] * d00[1] * d00[2] - ) * massWeight + ) * massWeight + ( d11[0] * d00[1] * d00[2] + @@ -322,8 +322,8 @@ Point3D< double > FEMVFConstraintFunctor< VFDegree , VFBType , FEMDegree , FEMBT + Point3D< double > ( - d12[0] * d00[1] * d00[2] + d10[0] * ( d00[1] * d02[2] + d02[1] * d00[2] ) , - d12[1] * d00[2] * d00[0] + d10[1] * ( d00[2] * d02[0] + d02[2] * d00[0] ) , + d12[0] * d00[1] * d00[2] + d10[0] * ( d00[1] * d02[2] + d02[1] * d00[2] ) , + d12[1] * d00[2] * d00[0] + d10[1] * ( d00[2] * d02[0] + d02[2] * d00[0] ) , d12[2] * d00[0] * d00[1] + d10[2] * ( d00[0] * d02[1] + d02[0] * d00[1] ) ) * biLapWeight; } @@ -454,7 +454,7 @@ void Octree< Real >::_setMultiColorIndices( int start , int end , std::vector< s template< class Real > template< class C , int FEMDegree , BoundaryType BType > -void Octree< Real >::_downSample( LocalDepth highDepth , DenseNodeData< C , FEMDegree >& constraints ) const +void Octree< Real >::_downSample( LocalDepth highDepth , DenseNodeData< C >& constraints ) const { typedef typename TreeOctNode::NeighborKey< -BSplineSupportSizes< FEMDegree >::UpSampleStart , BSplineSupportSizes< FEMDegree >::UpSampleEnd > UpSampleKey; @@ -526,7 +526,7 @@ void Octree< Real >::_downSample( LocalDepth highDepth , DenseNodeData< C , FEMD } template< class Real > template< class C , int FEMDegree , BoundaryType BType > -void Octree< Real >::_upSample( LocalDepth highDepth , DenseNodeData< C , FEMDegree >& coefficients ) const +void Octree< Real >::_upSample( LocalDepth highDepth , DenseNodeData< C >& coefficients ) const { static const int LeftDownSampleRadius = -( ( BSplineSupportSizes< FEMDegree >::DownSample0Start < BSplineSupportSizes< FEMDegree >::DownSample1Start ) ? BSplineSupportSizes< FEMDegree >::DownSample0Start : BSplineSupportSizes< FEMDegree >::DownSample1Start ); static const int RightDownSampleRadius = ( ( BSplineSupportSizes< FEMDegree >::DownSample0End > BSplineSupportSizes< FEMDegree >::DownSample1End ) ? BSplineSupportSizes< FEMDegree >::DownSample0End : BSplineSupportSizes< FEMDegree >::DownSample1End ); @@ -539,18 +539,18 @@ void Octree< Real >::_upSample( LocalDepth highDepth , DenseNodeData< C , FEMDeg BSplineEvaluationData< FEMDegree , BType >::SetUpSampleEvaluator( upSampleEvaluator , lowDepth ); std::vector< DownSampleKey > neighborKeys( std::max< int >( 1 , threads ) ); for( size_t i=0 ; i::DownSample0Size > BSplineSupportSizes< FEMDegree >::DownSample1Size ? BSplineSupportSizes< FEMDegree >::DownSample0Size : BSplineSupportSizes< FEMDegree >::DownSample1Size; Stencil< double , DownSampleSize > downSampleStencils[ Cube::CORNERS ]; int lowCenter = ( 1<>1; - for( int c=0 ; c::DownSampleSize[cx] ; ii++ ) for( int jj=0 ; jj::DownSampleSize[cy] ; jj++ ) for( int kk=0 ; kk::DownSampleSize[cz] ; kk++ ) - downSampleStencils[c]( ii , jj , kk ) = + downSampleStencils[c]( ii , jj , kk ) = upSampleEvaluator.value( lowCenter + ii + BSplineSupportSizes< FEMDegree >::DownSampleStart[cx] , 2*lowCenter + cx ) * upSampleEvaluator.value( lowCenter + jj + BSplineSupportSizes< FEMDegree >::DownSampleStart[cy] , 2*lowCenter + cy ) * upSampleEvaluator.value( lowCenter + kk + BSplineSupportSizes< FEMDegree >::DownSampleStart[cz] , 2*lowCenter + cz ) ; @@ -632,7 +632,7 @@ void Octree< Real >::_UpSample( LocalDepth highDepth , ConstPointer( C ) lowCoef static const int DownSampleSize = BSplineSupportSizes< FEMDegree >::DownSample0Size > BSplineSupportSizes< FEMDegree >::DownSample1Size ? BSplineSupportSizes< FEMDegree >::DownSample0Size : BSplineSupportSizes< FEMDegree >::DownSample1Size; Stencil< double , DownSampleSize > downSampleStencils[ Cube::CORNERS ]; int lowCenter = ( 1<>1; - for( int c=0 ; c::_UpSample( LocalDepth highDepth , ConstPointer( C ) lowCoef for( int ii=0 ; ii::DownSampleSize[cx] ; ii++ ) for( int jj=0 ; jj::DownSampleSize[cy] ; jj++ ) for( int kk=0 ; kk::DownSampleSize[cz] ; kk++ ) - downSampleStencils[c]( ii , jj , kk ) = + downSampleStencils[c]( ii , jj , kk ) = upSampleEvaluator.value( lowCenter + ii + BSplineSupportSizes< FEMDegree >::DownSampleStart[cx] , 2*lowCenter + cx ) * upSampleEvaluator.value( lowCenter + jj + BSplineSupportSizes< FEMDegree >::DownSampleStart[cy] , 2*lowCenter + cy ) * upSampleEvaluator.value( lowCenter + kk + BSplineSupportSizes< FEMDegree >::DownSampleStart[cz] , 2*lowCenter + cz ) ; @@ -705,9 +705,9 @@ void Octree< Real >::_UpSample( LocalDepth highDepth , ConstPointer( C ) lowCoef template< class Real > template< class C , int FEMDegree , BoundaryType BType > -DenseNodeData< C , FEMDegree > Octree< Real >::coarseCoefficients( const DenseNodeData< C , FEMDegree >& coefficients ) const +DenseNodeData< C > Octree< Real >::coarseCoefficients( const DenseNodeData< C >& coefficients ) const { - DenseNodeData< Real , FEMDegree > coarseCoefficients( _sNodesEnd(_maxDepth-1) ); + DenseNodeData< Real > coarseCoefficients( _sNodesEnd(_maxDepth-1) ); memset( &coarseCoefficients[0] , 0 , sizeof(Real)*_sNodesEnd(_maxDepth-1) ); #pragma omp parallel for num_threads( threads ) for( int i=_sNodesBegin(0) ; i<_sNodesEnd(_maxDepth-1) ; i++ ) coarseCoefficients[i] = coefficients[i]; @@ -716,9 +716,9 @@ DenseNodeData< C , FEMDegree > Octree< Real >::coarseCoefficients( const DenseNo } template< class Real > template< class C , int FEMDegree , BoundaryType BType > -DenseNodeData< C , FEMDegree > Octree< Real >::coarseCoefficients( const SparseNodeData< C , FEMDegree >& coefficients ) const +DenseNodeData< C > Octree< Real >::coarseCoefficients( const SparseNodeData< C >& coefficients ) const { - DenseNodeData< Real , FEMDegree > coarseCoefficients( _sNodesEnd(_maxDepth-1) ); + DenseNodeData< Real > coarseCoefficients( _sNodesEnd(_maxDepth-1) ); memset( &coarseCoefficients[0] , 0 , sizeof(Real)*_sNodesEnd(_maxDepth-1) ); #pragma omp parallel for num_threads( threads ) for( int i=_sNodesBegin(0) ; i<_sNodesEnd(_maxDepth-1) ; i++ ) @@ -732,7 +732,7 @@ DenseNodeData< C , FEMDegree > Octree< Real >::coarseCoefficients( const SparseN template< class Real > template< int FEMDegree , BoundaryType BType > -Real Octree< Real >::_coarserFunctionValue( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* pointNode , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real , FEMDegree >& upSampledCoefficients ) const +Real Octree< Real >::_coarserFunctionValue( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* pointNode , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real >& upSampledCoefficients ) const { static const int SupportSize = BSplineSupportSizes< FEMDegree >::SupportSize; static const int LeftSupportRadius = - BSplineSupportSizes< FEMDegree >::SupportStart; @@ -777,7 +777,7 @@ Real Octree< Real >::_coarserFunctionValue( Point3D< Real > p , const PointSuppo } template< class Real > template< int FEMDegree , BoundaryType BType > -Point3D< Real > Octree< Real >::_coarserFunctionGradient( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* pointNode , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real , FEMDegree >& upSampledCoefficients ) const +Point3D< Real > Octree< Real >::_coarserFunctionGradient( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* pointNode , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real >& upSampledCoefficients ) const { static const int SupportSize = BSplineSupportSizes< FEMDegree >::SupportSize; static const int LeftSupportRadius = - BSplineSupportSizes< FEMDegree >::SupportStart; @@ -835,7 +835,7 @@ Point3D< Real > Octree< Real >::_coarserFunctionGradient( Point3D< Real > p , co template< class Real > template< int FEMDegree , BoundaryType BType > -Real Octree< Real >::_finerFunctionValue( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* pointNode , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real , FEMDegree >& finerCoefficients ) const +Real Octree< Real >::_finerFunctionValue( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* pointNode , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real >& finerCoefficients ) const { typename TreeOctNode::Neighbors< BSplineSupportSizes< FEMDegree >::SupportSize > childNeighbors; static const int LeftPointSupportRadius = BSplineSupportSizes< FEMDegree >::SupportEnd; @@ -855,7 +855,7 @@ Real Octree< Real >::_finerFunctionValue( Point3D< Real > p , const PointSupport { int fIdx[3]; functionIndex< FEMDegree , BType >( _node , fIdx ); - pointValue += + pointValue += bsData.baseBSplines[ fIdx[0] ][LeftSupportRadius-j]( p[0] ) * bsData.baseBSplines[ fIdx[1] ][LeftSupportRadius-k]( p[1] ) * bsData.baseBSplines[ fIdx[2] ][LeftSupportRadius-l]( p[2] ) * @@ -866,7 +866,7 @@ Real Octree< Real >::_finerFunctionValue( Point3D< Real > p , const PointSupport } template< class Real > template< int FEMDegree , BoundaryType BType > -Point3D< Real > Octree< Real >::_finerFunctionGradient( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* pointNode , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real , FEMDegree >& finerCoefficients ) const +Point3D< Real > Octree< Real >::_finerFunctionGradient( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* pointNode , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real >& finerCoefficients ) const { typename TreeOctNode::Neighbors< BSplineSupportSizes< FEMDegree >::SupportSize > childNeighbors; static const int LeftPointSupportRadius = BSplineSupportSizes< FEMDegree >::SupportEnd; @@ -896,7 +896,7 @@ Point3D< Real > Octree< Real >::_finerFunctionGradient( Point3D< Real > p , cons template< class Real > template< int FEMDegree , BoundaryType BType , bool HasGradients > -void Octree< Real >::_setPointValuesFromCoarser( InterpolationInfo< HasGradients >& interpolationInfo , LocalDepth highDepth , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real , FEMDegree >& upSampledCoefficients ) +void Octree< Real >::_setPointValuesFromCoarser( InterpolationInfo< HasGradients >& interpolationInfo , LocalDepth highDepth , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real >& upSampledCoefficients ) { LocalDepth lowDepth = highDepth-1; if( lowDepth<0 ) return; @@ -918,7 +918,7 @@ void Octree< Real >::_setPointValuesFromCoarser( InterpolationInfo< HasGradients c , *pData , _coarserFunctionValue( (*pData)[c].position , neighborKey , _sNodes.treeNodes[i] , bsData , upSampledCoefficients ) , HasGradients ? _coarserFunctionGradient( (*pData)[c].position , neighborKey , _sNodes.treeNodes[i] , bsData , upSampledCoefficients ) : Point3D< Real >() , - interpolationInfo.valueWeight , interpolationInfo.gradientWeight + interpolationInfo.valueWeight , interpolationInfo.gradientWeight ); #else // !POINT_DATA_RES _ConstraintCalculator_< Real , FEMDegree , HasGradients >::_CalculateCoarser_ @@ -926,7 +926,7 @@ void Octree< Real >::_setPointValuesFromCoarser( InterpolationInfo< HasGradients *pData , _coarserFunctionValue( pData->position , neighborKey , _sNodes.treeNodes[i] , bsData , upSampledCoefficients ) , HasGradients ? _coarserFunctionGradient( pData->position , neighborKey , _sNodes.treeNodes[i] , bsData , upSampledCoefficients ) : Point3D< Real >() , - interpolationInfo.valueWeight , interpolationInfo.gradientWeight + interpolationInfo.valueWeight , interpolationInfo.gradientWeight ); #endif // POINT_DATA_RES } @@ -935,7 +935,7 @@ void Octree< Real >::_setPointValuesFromCoarser( InterpolationInfo< HasGradients template< class Real > template< int FEMDegree , BoundaryType BType , bool HasGradients > -void Octree< Real >::_updateCumulativeInterpolationConstraintsFromFiner( const InterpolationInfo< HasGradients >& interpolationInfo , const BSplineData< FEMDegree , BType >& bsData , LocalDepth highDepth , const DenseNodeData< Real , FEMDegree >& finerCoefficients , DenseNodeData< Real , FEMDegree >& coarserConstraints ) const +void Octree< Real >::_updateCumulativeInterpolationConstraintsFromFiner( const InterpolationInfo< HasGradients >& interpolationInfo , const BSplineData< FEMDegree , BType >& bsData , LocalDepth highDepth , const DenseNodeData< Real >& finerCoefficients , DenseNodeData< Real >& coarserConstraints ) const { static const int SupportSize = BSplineSupportSizes< FEMDegree >::SupportSize; static const int LeftPointSupportRadius = BSplineSupportSizes< FEMDegree >::SupportEnd; @@ -1118,7 +1118,7 @@ int Octree< Real >::_setMatrixRow( const FEMSystemFunctor& F , const Interpolati if( interpolationInfo ) { memset( pointValues , 0 , sizeof(Real) * OverlapSize * OverlapSize * OverlapSize ); - // Iterate over all supported neighbors that could have a point constraint + // Iterate over all supported neighbors that could have a point constraint for( int i=-LeftSupportRadius ; i<=RightSupportRadius ; i++ ) if( hasYZPoints[i+LeftSupportRadius] ) for( int j=-LeftSupportRadius ; j<=RightSupportRadius ; j++ ) if( hasZPoints[i+LeftSupportRadius][j+LeftSupportRadius] ) for( int k=-LeftSupportRadius ; k<=RightSupportRadius ; k++ ) @@ -1208,7 +1208,7 @@ int Octree< Real >::_setMatrixRow( const FEMSystemFunctor& F , const Interpolati template< class Real > template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > -int Octree< Real >::_getMatrixAndUpdateConstraints( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , SparseMatrix< Real >& matrix , DenseNodeData< Real , FEMDegree >& constraints , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template Integrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& integrator , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const BSplineData< FEMDegree , BType >& bsData , LocalDepth depth , const DenseNodeData< Real , FEMDegree >& metSolution , bool coarseToFine ) +int Octree< Real >::_getMatrixAndUpdateConstraints( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , SparseMatrix< Real >& matrix , DenseNodeData< Real >& constraints , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template Integrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& integrator , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const BSplineData< FEMDegree , BType >& bsData , LocalDepth depth , const DenseNodeData< Real >& metSolution , bool coarseToFine ) { static const int OverlapRadius = - BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapStart; static const int OverlapSize = BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize; @@ -1250,7 +1250,7 @@ int Octree< Real >::_getMatrixAndUpdateConstraints( const FEMSystemFunctor& F , template< class Real > template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > -int Octree< Real >::_getSliceMatrixAndUpdateConstraints( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , SparseMatrix< Real >& matrix , DenseNodeData< Real , FEMDegree >& constraints , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template Integrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& integrator , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const BSplineData< FEMDegree , BType >& bsData , LocalDepth depth , int slice , const DenseNodeData< Real , FEMDegree >& metSolution , bool coarseToFine ) +int Octree< Real >::_getSliceMatrixAndUpdateConstraints( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , SparseMatrix< Real >& matrix , DenseNodeData< Real >& constraints , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template Integrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& integrator , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const BSplineData< FEMDegree , BType >& bsData , LocalDepth depth , int slice , const DenseNodeData< Real >& metSolution , bool coarseToFine ) { static const int OverlapSize = BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize; static const int OverlapRadius = -BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapStart; @@ -1290,10 +1290,12 @@ int Octree< Real >::_getSliceMatrixAndUpdateConstraints( const FEMSystemFunctor& _updateConstraintsFromCoarser( F , interpolationInfo , neighbors , pNeighbors , node , constraints , metSolution , childIntegrator , stencils[x][y][z] , bsData ); } } +/** #if !defined( _WIN32 ) && !defined( _WIN64 ) #pragma message( "[WARNING] I'm not sure how expensive this system call is on non-Windows system. (You may want to comment this out.)" ) #endif // !_WIN32 && !_WIN64 memoryUsage(); +**/ return 1; } @@ -1302,7 +1304,7 @@ int Octree< Real >::_getSliceMatrixAndUpdateConstraints( const FEMSystemFunctor& #endif // MOD template< class Real > template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > -int Octree< Real >::_solveSystemGS( const FEMSystemFunctor& F , const BSplineData< FEMDegree , BType >& bsData , InterpolationInfo< HasGradients >* interpolationInfo , LocalDepth depth , DenseNodeData< Real , FEMDegree >& solution , DenseNodeData< Real , FEMDegree >& constraints , DenseNodeData< Real , FEMDegree >& metSolutionConstraints , int iters , bool coarseToFine , _SolverStats& stats , bool computeNorms ) +int Octree< Real >::_solveSystemGS( const FEMSystemFunctor& F , const BSplineData< FEMDegree , BType >& bsData , InterpolationInfo< HasGradients >* interpolationInfo , LocalDepth depth , DenseNodeData< Real >& solution , DenseNodeData< Real >& constraints , DenseNodeData< Real >& metSolutionConstraints , int iters , bool coarseToFine , _SolverStats& stats , bool computeNorms ) { const int OverlapRadius = -BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapStart; typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template Integrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) > integrator; @@ -1310,8 +1312,8 @@ int Octree< Real >::_solveSystemGS( const FEMSystemFunctor& F , const BSplineDat BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::SetIntegrator( integrator , depth ); if( depth>0 ) BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::SetChildIntegrator( childIntegrator , depth-1 ); - DenseNodeData< Real , FEMDegree >& metSolution = metSolutionConstraints; // This stores the up-sampled solution up to depth-2 - DenseNodeData< Real , FEMDegree >& metConstraints = metSolutionConstraints; // This stores the down-sampled constraints up to depth + DenseNodeData< Real >& metSolution = metSolutionConstraints; // This stores the up-sampled solution up to depth-2 + DenseNodeData< Real >& metConstraints = metSolutionConstraints; // This stores the down-sampled constraints up to depth int sliceBegin = _BSplineBegin< FEMDegree , BType >( depth ) , sliceEnd = _BSplineEnd< FEMDegree , BType >( depth ); double& systemTime = stats. systemTime; @@ -1437,15 +1439,15 @@ int Octree< Real >::_solveSystemGS( const FEMSystemFunctor& F , const BSplineDat template< class Real > template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > -int Octree< Real >::_solveSystemCG( const FEMSystemFunctor& F , const BSplineData< FEMDegree , BType >& bsData , InterpolationInfo< HasGradients >* interpolationInfo , LocalDepth depth , DenseNodeData< Real , FEMDegree >& solution , DenseNodeData< Real , FEMDegree >& constraints , DenseNodeData< Real , FEMDegree >& metSolutionConstraints , int iters , bool coarseToFine , _SolverStats& stats , bool computeNorms , double accuracy ) +int Octree< Real >::_solveSystemCG( const FEMSystemFunctor& F , const BSplineData< FEMDegree , BType >& bsData , InterpolationInfo< HasGradients >* interpolationInfo , LocalDepth depth , DenseNodeData< Real >& solution , DenseNodeData< Real >& constraints , DenseNodeData< Real >& metSolutionConstraints , int iters , bool coarseToFine , _SolverStats& stats , bool computeNorms , double accuracy ) { typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template Integrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) > integrator; typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) > childIntegrator; BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::SetIntegrator( integrator , depth ); if( depth>0 ) BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::SetChildIntegrator( childIntegrator , depth-1 ); - DenseNodeData< Real , FEMDegree >& metSolution = metSolutionConstraints; // This stores the up-sampled solution up to depth-2 - DenseNodeData< Real , FEMDegree >& metConstraints = metSolutionConstraints; // This stores the down-sampled constraints up to depth + DenseNodeData< Real >& metSolution = metSolutionConstraints; // This stores the up-sampled solution up to depth-2 + DenseNodeData< Real >& metConstraints = metSolutionConstraints; // This stores the down-sampled constraints up to depth int iter = 0; Pointer( Real ) X = GetPointer( & solution[0] + _sNodesBegin(depth) , _sNodesSize(depth) ); @@ -1573,7 +1575,7 @@ void Octree< Real >::_SetParentOverlapBounds( const TreeOctNode* node , int& sta // has already happened template< class Real > template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > -void Octree< Real >::_updateConstraintsFromCoarser( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , const typename TreeOctNode::Neighbors< BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& neighbors , const typename TreeOctNode::Neighbors< BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& pNeighbors , TreeOctNode* node , DenseNodeData< Real , FEMDegree >& constraints , const DenseNodeData< Real , FEMDegree >& metSolution , const typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const Stencil< double , BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& lapStencil , const BSplineData< FEMDegree , BType >& bsData ) const +void Octree< Real >::_updateConstraintsFromCoarser( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , const typename TreeOctNode::Neighbors< BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& neighbors , const typename TreeOctNode::Neighbors< BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& pNeighbors , TreeOctNode* node , DenseNodeData< Real >& constraints , const DenseNodeData< Real >& metSolution , const typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const Stencil< double , BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& lapStencil , const BSplineData< FEMDegree , BType >& bsData ) const { static const int LeftSupportRadius = -BSplineSupportSizes< FEMDegree >::SupportStart; static const int RightSupportRadius = BSplineSupportSizes< FEMDegree >::SupportEnd; @@ -1636,7 +1638,7 @@ void Octree< Real >::_updateConstraintsFromCoarser( const FEMSystemFunctor& F , // Given the solution @( depth ) add to the met constraints @( depth-1 ) template< class Real > template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor > -void Octree< Real >::_updateCumulativeIntegralConstraintsFromFiner( const FEMSystemFunctor& F , const BSplineData< FEMDegree , BType >& bsData , LocalDepth highDepth , const DenseNodeData< Real , FEMDegree >& fineSolution , DenseNodeData< Real , FEMDegree >& coarseConstraints ) const +void Octree< Real >::_updateCumulativeIntegralConstraintsFromFiner( const FEMSystemFunctor& F , const BSplineData< FEMDegree , BType >& bsData , LocalDepth highDepth , const DenseNodeData< Real >& fineSolution , DenseNodeData< Real >& coarseConstraints ) const { typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) > childIntegrator; BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::SetChildIntegrator( childIntegrator , highDepth-1 ); @@ -1732,28 +1734,27 @@ void Octree< Real >::setSystemMatrix( const FEMSystemFunctor& F , const Interpol template< class Real > template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > -DenseNodeData< Real , FEMDegree > Octree< Real >::solveSystem( const FEMSystemFunctor& F , InterpolationInfo< HasGradients >* interpolationInfo , DenseNodeData< Real , FEMDegree >& constraints , LocalDepth maxSolveDepth , const typename Octree< Real >::SolverInfo& solverInfo ) +DenseNodeData< Real > Octree< Real >::solveSystem( const FEMSystemFunctor& F , InterpolationInfo< HasGradients >* interpolationInfo , DenseNodeData< Real >& constraints , LocalDepth maxSolveDepth , const typename Octree< Real >::SolverInfo& solverInfo ) { BSplineData< FEMDegree , BType > bsData( maxSolveDepth ); maxSolveDepth = std::min< LocalDepth >( maxSolveDepth , _maxDepth ); - int iter = 0; const int _iters = std::max< int >( 0 , solverInfo.iters ); - DenseNodeData< Real , FEMDegree > solution( _sNodesEnd( _maxDepth ) ); + DenseNodeData< Real > solution( _sNodesEnd( _maxDepth ) ); memset( &solution[0] , 0 , sizeof(Real) * _sNodesEnd( _maxDepth ) ); - DenseNodeData< Real , FEMDegree > metSolution( _sNodesEnd( _maxDepth-1 ) ); + DenseNodeData< Real > metSolution( _sNodesEnd( _maxDepth-1 ) ); memset( &metSolution[0] , 0 , sizeof(Real)*_sNodesEnd( _maxDepth-1 ) ); for( LocalDepth d=0 ; d<=maxSolveDepth ; d++ ) { int iters = (int)ceil( _iters * pow( solverInfo.lowResIterMultiplier , maxSolveDepth-d ) ); _SolverStats sStats; - if( !d ) iter = _solveSystemCG( F , bsData , interpolationInfo , d , solution , constraints , metSolution , _sNodesSize(d) , true , sStats , solverInfo.showResidual , 0 ); + if( !d ) _solveSystemCG( F , bsData , interpolationInfo , d , solution , constraints , metSolution , _sNodesSize(d) , true , sStats , solverInfo.showResidual , 0 ); else { - if( d>solverInfo.cgDepth ) iter = _solveSystemGS( F , bsData , interpolationInfo , d , solution , constraints , metSolution , iters , true , sStats , solverInfo.showResidual ); - else iter = _solveSystemCG( F , bsData , interpolationInfo , d , solution , constraints , metSolution , iters , true , sStats , solverInfo.showResidual , solverInfo.cgAccuracy ); + if( d>solverInfo.cgDepth ) _solveSystemGS( F , bsData , interpolationInfo , d , solution , constraints , metSolution , iters , true , sStats , solverInfo.showResidual ); + else _solveSystemCG( F , bsData , interpolationInfo , d , solution , constraints , metSolution , iters , true , sStats , solverInfo.showResidual , solverInfo.cgAccuracy ); } int femNodes = 0; #pragma omp parallel for reduction( + : femNodes ) @@ -1775,10 +1776,9 @@ DenseNodeData< Real , FEMDegree > Octree< Real >::solveSystem( const FEMSystemFu } template< class Real > -template< int FEMDegree > -DenseNodeData< Real , FEMDegree > Octree< Real >::initDenseNodeData( void ) +DenseNodeData< Real > Octree< Real >::initDenseNodeData( void ) { - DenseNodeData< Real , FEMDegree > constraints( _sNodes.size() ); + DenseNodeData< Real > constraints( _sNodes.size() ); memset( &constraints[0] , 0 , sizeof(Real)*_sNodes.size() ); return constraints; } @@ -1792,7 +1792,7 @@ template< > template< > bool Octree< float >::_IsZero( const Point3D< float >& template< > template< > bool Octree< double >::_IsZero( const Point3D< double >& p ){ return p[0]==0 && p[1]==0 && p[2]==0; } template< class Real > template< int FEMDegree , BoundaryType FEMBType , int CDegree , BoundaryType CBType , class FEMConstraintFunctor , class Coefficients , class D , class _D > -void Octree< Real >::_addFEMConstraints( const FEMConstraintFunctor& F , const Coefficients& coefficients , DenseNodeData< Real , FEMDegree >& constraints , LocalDepth maxDepth ) +void Octree< Real >::_addFEMConstraints( const FEMConstraintFunctor& F , const Coefficients& coefficients , DenseNodeData< Real >& constraints , LocalDepth maxDepth ) { typedef typename TreeOctNode::NeighborKey< -BSplineSupportSizes< FEMDegree >::SupportStart , BSplineSupportSizes< FEMDegree >::SupportEnd > SupportKey; const int CFEMOverlapSize = BSplineOverlapSizes< CDegree , FEMDegree >::OverlapSize; @@ -1805,10 +1805,10 @@ void Octree< Real >::_addFEMConstraints( const FEMConstraintFunctor& F , const C // splatted normals and compute the dot-product of the // divergence of the normal field with all the basis functions. // Within the same depth: set directly as a gather - // Coarser depths + // Coarser depths maxDepth = std::min< LocalDepth >( maxDepth , _maxDepth ); - DenseNodeData< Real , FEMDegree >* __constraints = new DenseNodeData< Real , FEMDegree >( _sNodesEnd(maxDepth-1) ); - DenseNodeData< Real , FEMDegree >& _constraints = *__constraints; + DenseNodeData< Real >* __constraints = new DenseNodeData< Real >( _sNodesEnd(maxDepth-1) ); + DenseNodeData< Real >& _constraints = *__constraints; memset( &_constraints[0] , 0 , sizeof(Real)*( _sNodesEnd(maxDepth-1) ) ); memoryUsage(); @@ -1847,14 +1847,17 @@ void Octree< Real >::_addFEMConstraints( const FEMConstraintFunctor& F , const C if( isValidFEMNode< CDegree , CBType >( _node ) ) { const D* d = coefficients( _node ); - if( d ) - if( isInterior ) constraints[i] += _Dot( (D)stencil( x , y , z ) , *d ); + if( d ) + { + if( isInterior ) + constraints[i] += _Dot( (D)stencil( x , y , z ) , *d ); else { LocalDepth _d ; LocalOffset _off; _localDepthAndOffset( _node , _d , _off ); constraints[i] += _Dot( *d , (D)F.template integrate< false >( integrator , _off , off ) ); } + } } } _SetParentOverlapBounds< CDegree , FEMDegree >( node , startX , endX , startY , endY , startZ , endZ ); @@ -1906,7 +1909,7 @@ void Octree< Real >::_addFEMConstraints( const FEMConstraintFunctor& F , const C delete __constraints; - DenseNodeData< D , CDegree > _coefficients( _sNodesEnd(maxDepth-1) ); + DenseNodeData< D > _coefficients( _sNodesEnd(maxDepth-1) ); memset( &_coefficients[0] , 0 , sizeof(D) * _sNodesEnd(maxDepth-1) ); for( LocalDepth d=maxDepth-1 ; d>=0 ; d-- ) { @@ -1976,7 +1979,7 @@ void Octree< Real >::_addFEMConstraints( const FEMConstraintFunctor& F , const C template< class Real > template< int FEMDegree , BoundaryType BType , bool HasGradients > -void Octree< Real >::addInterpolationConstraints( const InterpolationInfo< HasGradients >& interpolationInfo , DenseNodeData< Real , FEMDegree >& constraints , LocalDepth maxDepth ) +void Octree< Real >::addInterpolationConstraints( const InterpolationInfo< HasGradients >& interpolationInfo , DenseNodeData< Real >& constraints , LocalDepth maxDepth ) { typedef typename TreeOctNode::NeighborKey< -BSplineSupportSizes< FEMDegree >::SupportStart , BSplineSupportSizes< FEMDegree >::SupportEnd > SupportKey; maxDepth = std::min< LocalDepth >( maxDepth , _maxDepth ); @@ -2071,6 +2074,7 @@ double Octree< Real >::_dot( const DotFunctor& F , const InterpolationInfo< HasG const TreeOctNode* _node = neighbors.neighbors[x][y][z]; const Real* _data2; if( isValidFEMNode< FEMDegree2 , FEMBType2 >( _node ) && ( _data2=coefficients2( _node ) ) ) + { if( isInterior ) dot += (*_data1) * (*_data2 ) * stencil( x , y , z ); else { @@ -2078,6 +2082,7 @@ double Octree< Real >::_dot( const DotFunctor& F , const InterpolationInfo< HasG _localDepthAndOffset( _node , _d , _off ); dot += (*_data1) * (*_data2) * F.template integrate< false >( integrator , off , _off ); } + } } } } @@ -2090,7 +2095,7 @@ double Octree< Real >::_dot( const DotFunctor& F , const InterpolationInfo< HasG const int LeftOverlapRadius = -BSplineOverlapSizes< FEMDegree2 , FEMDegree1 >::OverlapStart; const int RightOverlapRadius = BSplineOverlapSizes< FEMDegree2 , FEMDegree1 >::OverlapEnd; - DenseNodeData< Real , FEMDegree1 > cumulative1( _sNodesEnd( _maxDepth-1 ) ); + DenseNodeData< Real > cumulative1( _sNodesEnd( _maxDepth-1 ) ); if( _maxDepth>0 ) memset( &cumulative1[0] , 0 , sizeof(Real) * _sNodesEnd( _maxDepth-1 ) ); for( LocalDepth d=1 ; d<=_maxDepth ; d++ ) @@ -2161,7 +2166,7 @@ double Octree< Real >::_dot( const DotFunctor& F , const InterpolationInfo< HasG const int LeftOverlapRadius = -BSplineOverlapSizes< FEMDegree1 , FEMDegree2 >::OverlapStart; const int RightOverlapRadius = BSplineOverlapSizes< FEMDegree1 , FEMDegree2 >::OverlapEnd; - DenseNodeData< Real , FEMDegree2 > cumulative2( _sNodesEnd( _maxDepth-1 ) ); + DenseNodeData< Real > cumulative2( _sNodesEnd( _maxDepth-1 ) ); if( _maxDepth>0 ) memset( &cumulative2[0] , 0 , sizeof(Real) * _sNodesEnd( _maxDepth-1 ) ); for( LocalDepth d=_maxDepth ; d>0 ; d-- ) @@ -2243,7 +2248,7 @@ double Octree< Real >::_dot( const DotFunctor& F , const InterpolationInfo< HasG const PointData< Real , HasGradients >& pData = *( (*iInfo)( _sNodes.treeNodes[i] ) ); #if POINT_DATA_RES - for( int c=0 ; c::SAMPLES ; c++ ) if( pData[c].weight ) + for( int c=0 ; c::SAMPLES ; c++ ) if( pData[c].weight ) { Point3D< Real > p = pData[c].position; Real w = pData[c].weight; diff --git a/Src/MultiGridOctreeData.WeightedSamples.inl b/Src/MultiGridOctreeData.WeightedSamples.inl index 279d91b9..f84e4ffc 100644 --- a/Src/MultiGridOctreeData.WeightedSamples.inl +++ b/Src/MultiGridOctreeData.WeightedSamples.inl @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -37,7 +37,7 @@ template< int Degree > double GetScaleValue( void ) } template< class Real > template< int WeightDegree > -void Octree< Real >::_addWeightContribution( DensityEstimator< WeightDegree >& densityWeights , TreeOctNode* node , Point3D< Real > position , PointSupportKey< WeightDegree >& weightKey , Real weight ) +void Octree< Real >::_addWeightContribution( DensityEstimator& densityWeights , TreeOctNode* node , Point3D< Real > position , PointSupportKey< WeightDegree >& weightKey , Real weight ) { static const double ScaleValue = GetScaleValue< WeightDegree >(); double dx[ DIMENSION ][ PointSupportKey< WeightDegree >::Size ]; @@ -60,7 +60,7 @@ void Octree< Real >::_addWeightContribution( DensityEstimator< WeightDegree >& d template< class Real > template< int WeightDegree , class PointSupportKey > -Real Octree< Real >::_getSamplesPerNode( const DensityEstimator< WeightDegree >& densityWeights , const TreeOctNode* node , Point3D< Real > position , PointSupportKey& weightKey ) const +Real Octree< Real >::_getSamplesPerNode( const DensityEstimator& densityWeights , const TreeOctNode* node , Point3D< Real > position , PointSupportKey& weightKey ) const { Real weight = 0; double dx[ DIMENSION ][ PointSupportKey::Size ]; @@ -84,12 +84,12 @@ Real Octree< Real >::_getSamplesPerNode( const DensityEstimator< WeightDegree >& return weight; } template< class Real > -template< int WeightDegree , class PointSupportKey > -void Octree< Real >::_getSampleDepthAndWeight( const DensityEstimator< WeightDegree >& densityWeights , const TreeOctNode* node , Point3D< Real > position , PointSupportKey& weightKey , Real& depth , Real& weight ) const +template< int WeightDegree, class PointSupportKey > +void Octree< Real >::_getSampleDepthAndWeight( const DensityEstimator& densityWeights , const TreeOctNode* node , Point3D< Real > position , PointSupportKey& weightKey , Real& depth , Real& weight ) const { const TreeOctNode* temp = node; while( _localDepth( temp )>densityWeights.kernelDepth() ) temp = temp->parent; - weight = _getSamplesPerNode( densityWeights , temp , position , weightKey ); + weight = _getSamplesPerNode( densityWeights , temp , position , weightKey ); if( weight>=(Real)1. ) depth = Real( _localDepth( temp ) + log( weight ) / log(double(1<<(DIMENSION-1))) ); else { @@ -99,15 +99,15 @@ void Octree< Real >::_getSampleDepthAndWeight( const DensityEstimator< WeightDeg { temp=temp->parent; oldWeight = newWeight; - newWeight = _getSamplesPerNode( densityWeights , temp , position , weightKey ); + newWeight = _getSamplesPerNode( densityWeights , temp , position , weightKey ); } depth = Real( _localDepth( temp ) + log( newWeight ) / log( newWeight / oldWeight ) ); } weight = Real( pow( double(1<<(DIMENSION-1)) , -double(depth) ) ); } template< class Real > -template< int WeightDegree , class PointSupportKey > -void Octree< Real >::_getSampleDepthAndWeight( const DensityEstimator< WeightDegree >& densityWeights , Point3D< Real > position , PointSupportKey& weightKey , Real& depth , Real& weight ) const +template< int WeightDegree, class PointSupportKey > +void Octree< Real >::_getSampleDepthAndWeight( const DensityEstimator& densityWeights , Point3D< Real > position , PointSupportKey& weightKey , Real& depth , Real& weight ) const { TreeOctNode* temp; Point3D< Real > myCenter( (Real)0.5 , (Real)0.5 , (Real)0.5 ); @@ -128,12 +128,12 @@ void Octree< Real >::_getSampleDepthAndWeight( const DensityEstimator< WeightDeg if( cIndex&4 ) myCenter[2] += myWidth/2; else myCenter[2] -= myWidth/2; } - return _getSampleDepthAndWeight( densityWeights , temp , position , weightKey , depth , weight ); + return _getSampleDepthAndWeight( densityWeights , temp , position , weightKey , depth , weight ); } template< class Real > template< bool CreateNodes , int DataDegree , class V > -void Octree< Real >::_splatPointData( TreeOctNode* node , Point3D< Real > position , V v , SparseNodeData< V , DataDegree >& dataInfo , PointSupportKey< DataDegree >& dataKey ) +void Octree< Real >::_splatPointData( TreeOctNode* node , Point3D< Real > position , V v , SparseNodeData< V >& dataInfo , PointSupportKey< DataDegree >& dataKey ) { double dx[ DIMENSION ][ PointSupportKey< DataDegree >::Size ]; typename TreeOctNode::Neighbors< PointSupportKey< DataDegree >::Size >& neighbors = dataKey.template getNeighbors< CreateNodes >( node , _NodeInitializer ); @@ -158,7 +158,7 @@ void Octree< Real >::_splatPointData( TreeOctNode* node , Point3D< Real > positi } template< class Real > template< bool CreateNodes , int WeightDegree , int DataDegree , class V > -Real Octree< Real >::_splatPointData( const DensityEstimator< WeightDegree >& densityWeights , Point3D< Real > position , V v , SparseNodeData< V , DataDegree >& dataInfo , PointSupportKey< WeightDegree >& weightKey , PointSupportKey< DataDegree >& dataKey , LocalDepth minDepth , LocalDepth maxDepth , int dim ) +Real Octree< Real >::_splatPointData( const DensityEstimator& densityWeights , Point3D< Real > position , V v , SparseNodeData< V >& dataInfo , PointSupportKey< WeightDegree >& weightKey , PointSupportKey< DataDegree >& dataKey , LocalDepth minDepth , LocalDepth maxDepth , int dim ) { double dx; V _v; @@ -183,7 +183,7 @@ Real Octree< Real >::_splatPointData( const DensityEstimator< WeightDegree >& de else myCenter[2] -= myWidth/2; } Real weight , depth; - _getSampleDepthAndWeight( densityWeights , temp , position , weightKey , depth , weight ); + _getSampleDepthAndWeight( densityWeights , temp , position , weightKey , depth , weight ); if( depthmaxDepth ) depth = Real(maxDepth); @@ -223,10 +223,11 @@ Real Octree< Real >::_splatPointData( const DensityEstimator< WeightDegree >& de } template< class Real > template< bool CreateNodes , int WeightDegree , int DataDegree , class V > -Real Octree< Real >::_multiSplatPointData( const DensityEstimator< WeightDegree >* densityWeights , TreeOctNode* node , Point3D< Real > position , V v , SparseNodeData< V , DataDegree >& dataInfo , PointSupportKey< WeightDegree >& weightKey , PointSupportKey< DataDegree >& dataKey , int dim ) +Real Octree< Real >::_multiSplatPointData( const DensityEstimator* densityWeights , TreeOctNode* node , Point3D< Real > position , V v , SparseNodeData< V >& dataInfo , PointSupportKey< WeightDegree >& weightKey , PointSupportKey< DataDegree >& dataKey , int dim ) { Real _depth , weight; - if( densityWeights ) _getSampleDepthAndWeight( *densityWeights , position , weightKey , _depth , weight ); + if( densityWeights ) + _getSampleDepthAndWeight( *densityWeights , position , weightKey , _depth , weight ); else weight = (Real)1.; V _v = v * weight; @@ -292,7 +293,7 @@ V Octree< Real >::_evaluate( const Coefficients& coefficients , Point3D< Real > template< class Real > template< class V , int DataDegree , BoundaryType BType > -Pointer( V ) Octree< Real >::voxelEvaluate( const DenseNodeData< V , DataDegree >& coefficients , int& res , Real isoValue , LocalDepth depth , bool primal ) +Pointer( V ) Octree< Real >::voxelEvaluate( const DenseNodeData< V >& coefficients , int& res , Real isoValue , LocalDepth depth , bool primal ) { int begin , end , dim; if( depth<=0 || depth>_maxDepth ) depth = _maxDepth; @@ -385,10 +386,10 @@ Pointer( V ) Octree< Real >::voxelEvaluate( const DenseNodeData< V , DataDegree } template< class Real > template< int FEMDegree , BoundaryType BType > -SparseNodeData< Real , 0 > Octree< Real >::leafValues( const DenseNodeData< Real , FEMDegree >& coefficients ) const +SparseNodeData< Real > Octree< Real >::leafValues( const DenseNodeData< Real >& coefficients ) const { - SparseNodeData< Real , 0 > values; - DenseNodeData< Real , FEMDegree > _coefficients( _sNodesEnd(_maxDepth-1) ); + SparseNodeData< Real > values; + DenseNodeData< Real > _coefficients( _sNodesEnd(_maxDepth-1) ); memset( &_coefficients[0] , 0 , sizeof(Real)*_sNodesEnd(_maxDepth-1) ); for( int i=_sNodes.begin( _localToGlobal( 0 ) ) ; i<_sNodesEnd(_maxDepth-1) ; i++ ) _coefficients[i] = coefficients[i]; for( LocalDepth d=1 ; d<_maxDepth ; d++ ) _upSample( d , _coefficients ); @@ -414,10 +415,10 @@ SparseNodeData< Real , 0 > Octree< Real >::leafValues( const DenseNodeData< Real } template< class Real > template< int FEMDegree , BoundaryType BType > -SparseNodeData< Point3D< Real > , 0 > Octree< Real >::leafGradients( const DenseNodeData< Real , FEMDegree >& coefficients ) const +SparseNodeData< Point3D< Real > > Octree< Real >::leafGradients( const DenseNodeData< Real >& coefficients ) const { - SparseNodeData< Point3D< Real > , 0 > gradients; - DenseNodeData< Real , FEMDegree > _coefficients( _sNodesEnd(_maxDepth-1 ) ); + SparseNodeData< Point3D< Real > > gradients; + DenseNodeData< Real > _coefficients( _sNodesEnd(_maxDepth-1 ) ); memset( &_coefficients[0] , 0 , sizeof(Real)*_sNodesEnd(_maxDepth-1) ); for( int i=_sNodesBegin(0) ; i<_sNodesEnd(_maxDepth-1) ; i++ ) _coefficients[i] = coefficients[i]; for( LocalDepth d=1 ; d<_maxDepth ; d++ ) _upSample( d , _coefficients ); diff --git a/Src/MultiGridOctreeData.h b/Src/MultiGridOctreeData.h index 595ebdc7..29de8c2c 100644 --- a/Src/MultiGridOctreeData.h +++ b/Src/MultiGridOctreeData.h @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -37,7 +37,7 @@ DAMAGE. // [TODO] // -- Currently, the implementation assumes that the boundary constraints are the same for vector fields and scalar fields -// -- Modify the setting of the flags so that only the subset of the broods that are needed +// -- Modify the setting of the flags so that only the subset of the broods that are needed #ifndef MULTI_GRID_OCTREE_DATA_INCLUDED #define MULTI_GRID_OCTREE_DATA_INCLUDED @@ -54,12 +54,15 @@ DAMAGE. #define MAX_MEMORY_GB 0 #include +#ifdef _OPENMP // Assume that we have the header file if we're compiling with the openmp option. #include +#endif #include "BSplineData.h" -#include "PointStream.h" +#include "Mesh.h" #include "Geometry.h" #include "Octree.h" #include "SparseMatrix.h" +#include "point_source/PointSource.h" #ifndef _OPENMP int omp_get_num_procs( void ){ return 1; } @@ -284,7 +287,7 @@ struct PointData template< class Real , bool HasGradients > using PointData = SinglePointData< Real , HasGradients >; #endif // POINT_DATA_RES -template< class Data , int Degree > +template< class Data> struct SparseNodeData { size_t size( void ) const { return _data.size(); } @@ -311,15 +314,15 @@ struct SparseNodeData if( map[i]<(int)temp.size() ) _indices[i] = temp[ map[i] ]; else _indices[i] = -1; } - template< class _Data , int _Degree > friend struct SparseNodeData; - template< class _Data , int _Degree > - void init( const SparseNodeData< _Data , _Degree >& snd ){ _indices = snd._indices , _data.resize( snd._data.size() ); } + template< class _Data> friend struct SparseNodeData; + template< class _Data> + void init( const SparseNodeData< _Data>& snd ){ _indices = snd._indices , _data.resize( snd._data.size() ); } void remove( const OctNode< TreeNodeData >* node ){ if( node->nodeData.nodeIndex<(int)_indices.size() && node->nodeData.nodeIndex>=0 ) _indices[ node->nodeData.nodeIndex ] = -1; } protected: std::vector< int > _indices; std::vector< Data > _data; }; -template< class Data , int Degree > +template< class Data > struct DenseNodeData { DenseNodeData( void ){ _data = NullPointer( Data ) ; _sz = 0; } @@ -336,7 +339,7 @@ struct DenseNodeData Data& operator[]( const OctNode< TreeNodeData >* node ) { return _data[ node->nodeData.nodeIndex ]; } Data* operator()( const OctNode< TreeNodeData >* node ) { return ( node==NULL || node->nodeData.nodeIndex>=(int)_sz ) ? NULL : &_data[ node->nodeData.nodeIndex ]; } const Data* operator()( const OctNode< TreeNodeData >* node ) const { return ( node==NULL || node->nodeData.nodeIndex>=(int)_sz ) ? NULL : &_data[ node->nodeData.nodeIndex ]; } - int index( const OctNode< TreeNodeData >* node ) const { return ( !node || node->nodeData.nodeIndex<0 || node->nodeData.nodeIndex>=(int)_data.size() ) ? -1 : node->nodeData.nodeIndex; } + int index( const OctNode< TreeNodeData >* node ) const { return ( !node || node->nodeData.nodeIndex<0 || node->nodeData.nodeIndex>=_sz ) ? -1 : node->nodeData.nodeIndex; } protected: size_t _sz; void _resize( size_t sz ){ DeletePointer( _data ) ; if( sz ) _data = NewPointer< Data >( sz ) ; else _data = NullPointer( Data ) ; _sz = sz; } @@ -461,7 +464,7 @@ class Octree template< bool HasGradients > struct InterpolationInfo { - SparseNodeData< PointData< Real , HasGradients > , 0 > iData; + SparseNodeData< PointData< Real , HasGradients > > iData; Real valueWeight , gradientWeight; InterpolationInfo( const class Octree< Real >& tree , const std::vector< PointSample >& samples , Real pointValue , int adaptiveExponent , Real v , Real g ) : valueWeight(v) , gradientWeight(g) { iData = tree._densifyInterpolationInfo< HasGradients >( samples , pointValue , adaptiveExponent ); } @@ -469,7 +472,7 @@ class Octree const PointData< Real , HasGradients >* operator()( const OctNode< TreeNodeData >* node ) const { return iData(node); } }; - template< int DensityDegree > struct DensityEstimator : public SparseNodeData< Real , DensityDegree > + struct DensityEstimator : public SparseNodeData< Real> { DensityEstimator( int kernelDepth ) : _kernelDepth( kernelDepth ){ ; } int kernelDepth( void ) const { return _kernelDepth; } @@ -608,9 +611,9 @@ class Octree double bNorm2 , inRNorm2 , outRNorm2; }; template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > - int _solveSystemGS( const FEMSystemFunctor& F , const BSplineData< FEMDegree , BType >& bsData , InterpolationInfo< HasGradients >* interpolationInfo , LocalDepth depth , DenseNodeData< Real , FEMDegree >& solution , DenseNodeData< Real , FEMDegree >& constraints , DenseNodeData< Real , FEMDegree >& metSolutionConstraints , int iters , bool coarseToFine , _SolverStats& stats , bool computeNorms ); + int _solveSystemGS( const FEMSystemFunctor& F , const BSplineData< FEMDegree , BType >& bsData , InterpolationInfo< HasGradients >* interpolationInfo , LocalDepth depth , DenseNodeData< Real >& solution , DenseNodeData< Real >& constraints , DenseNodeData< Real >& metSolutionConstraints , int iters , bool coarseToFine , _SolverStats& stats , bool computeNorms ); template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > - int _solveSystemCG( const FEMSystemFunctor& F , const BSplineData< FEMDegree , BType >& bsData , InterpolationInfo< HasGradients >* interpolationInfo , LocalDepth depth , DenseNodeData< Real , FEMDegree >& solution , DenseNodeData< Real , FEMDegree >& constraints , DenseNodeData< Real , FEMDegree >& metSolutionConstraints , int iters , bool coarseToFine , _SolverStats& stats , bool computeNorms , double accuracy ); + int _solveSystemCG( const FEMSystemFunctor& F , const BSplineData< FEMDegree , BType >& bsData , InterpolationInfo< HasGradients >* interpolationInfo , LocalDepth depth , DenseNodeData< Real >& solution , DenseNodeData< Real >& constraints , DenseNodeData< Real >& metSolutionConstraints , int iters , bool coarseToFine , _SolverStats& stats , bool computeNorms , double accuracy ); template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > int _setMatrixRow( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , const typename TreeOctNode::Neighbors< BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& neighbors , Pointer( MatrixEntry< Real > ) row , int offset , const typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template Integrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& integrator , const Stencil< double , BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& stencil , const BSplineData< FEMDegree , BType >& bsData ) const; template< int FEMDegree , BoundaryType BType > @@ -620,42 +623,42 @@ class Octree // Updates the constraints @(depth) based on the solution coefficients @(depth-1) template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > - void _updateConstraintsFromCoarser( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , const typename TreeOctNode::Neighbors< BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& neighbors , const typename TreeOctNode::Neighbors< BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& pNeighbors , TreeOctNode* node , DenseNodeData< Real , FEMDegree >& constraints , const DenseNodeData< Real , FEMDegree >& metSolution , const typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const Stencil< double , BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& stencil , const BSplineData< FEMDegree , BType >& bsData ) const; + void _updateConstraintsFromCoarser( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , const typename TreeOctNode::Neighbors< BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& neighbors , const typename TreeOctNode::Neighbors< BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& pNeighbors , TreeOctNode* node , DenseNodeData< Real >& constraints , const DenseNodeData< Real >& metSolution , const typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const Stencil< double , BSplineOverlapSizes< FEMDegree , FEMDegree >::OverlapSize >& stencil , const BSplineData< FEMDegree , BType >& bsData ) const; // evaluate the points @(depth) using coefficients @(depth-1) template< int FEMDegree , BoundaryType BType , bool HasGradients > - void _setPointValuesFromCoarser( InterpolationInfo< HasGradients >& interpolationInfo , LocalDepth highDepth , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real , FEMDegree >& upSampledCoefficients ); + void _setPointValuesFromCoarser( InterpolationInfo< HasGradients >& interpolationInfo , LocalDepth highDepth , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real >& upSampledCoefficients ); // Updates the cumulative integral constraints @(depth-1) based on the change in solution coefficients @(depth) template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor > - void _updateCumulativeIntegralConstraintsFromFiner( const FEMSystemFunctor& F , - const BSplineData< FEMDegree , BType >& bsData , LocalDepth highDepth , const DenseNodeData< Real , FEMDegree >& fineSolution , DenseNodeData< Real , FEMDegree >& cumulativeConstraints ) const; + void _updateCumulativeIntegralConstraintsFromFiner( const FEMSystemFunctor& F , + const BSplineData< FEMDegree , BType >& bsData , LocalDepth highDepth , const DenseNodeData< Real >& fineSolution , DenseNodeData< Real >& cumulativeConstraints ) const; // Updates the cumulative interpolation constraints @(depth-1) based on the change in solution coefficient @(depth) template< int FEMDegree , BoundaryType BType , bool HasGradients > void _updateCumulativeInterpolationConstraintsFromFiner( const InterpolationInfo< HasGradients >& interpolationInfo , - const BSplineData< FEMDegree , BType >& bsData , LocalDepth highDepth , const DenseNodeData< Real , FEMDegree >& fineSolution , DenseNodeData< Real , FEMDegree >& cumulativeConstraints ) const; + const BSplineData< FEMDegree , BType >& bsData , LocalDepth highDepth , const DenseNodeData< Real >& fineSolution , DenseNodeData< Real >& cumulativeConstraints ) const; template< int FEMDegree , BoundaryType BType > - Real _coarserFunctionValue( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real , FEMDegree >& upSampledCoefficients ) const; + Real _coarserFunctionValue( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real >& upSampledCoefficients ) const; template< int FEMDegree , BoundaryType BType > - Point3D< Real > _coarserFunctionGradient( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real , FEMDegree >& upSampledCoefficients ) const; + Point3D< Real > _coarserFunctionGradient( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real >& upSampledCoefficients ) const; template< int FEMDegree , BoundaryType BType > - Real _finerFunctionValue( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real , FEMDegree >& coefficients ) const; + Real _finerFunctionValue( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real >& coefficients ) const; template< int FEMDegree , BoundaryType BType > - Point3D< Real > _finerFunctionGradient( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real , FEMDegree >& coefficients ) const; + Point3D< Real > _finerFunctionGradient( Point3D< Real > p , const PointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const BSplineData< FEMDegree , BType >& bsData , const DenseNodeData< Real >& coefficients ) const; template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > - int _getSliceMatrixAndUpdateConstraints( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , SparseMatrix< Real >& matrix , DenseNodeData< Real , FEMDegree >& constraints , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template Integrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& integrator , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const BSplineData< FEMDegree , BType >& bsData , LocalDepth depth , int slice , const DenseNodeData< Real , FEMDegree >& metSolution , bool coarseToFine ); + int _getSliceMatrixAndUpdateConstraints( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , SparseMatrix< Real >& matrix , DenseNodeData< Real >& constraints , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template Integrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& integrator , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const BSplineData< FEMDegree , BType >& bsData , LocalDepth depth , int slice , const DenseNodeData< Real >& metSolution , bool coarseToFine ); template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > - int _getMatrixAndUpdateConstraints( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , SparseMatrix< Real >& matrix , DenseNodeData< Real , FEMDegree >& constraints , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template Integrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& integrator , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const BSplineData< FEMDegree , BType >& bsData , LocalDepth depth , const DenseNodeData< Real , FEMDegree >& metSolution , bool coarseToFine ); + int _getMatrixAndUpdateConstraints( const FEMSystemFunctor& F , const InterpolationInfo< HasGradients >* interpolationInfo , SparseMatrix< Real >& matrix , DenseNodeData< Real >& constraints , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template Integrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& integrator , typename BSplineIntegrationData< FEMDegree , BType , FEMDegree , BType >::FunctionIntegrator::template ChildIntegrator< DERIVATIVES( FEMDegree ) , DERIVATIVES( FEMDegree ) >& childIntegrator , const BSplineData< FEMDegree , BType >& bsData , LocalDepth depth , const DenseNodeData< Real >& metSolution , bool coarseToFine ); // Down samples constraints @(depth) to constraints @(depth-1) - template< class C , int FEMDegree , BoundaryType BType > void _downSample( LocalDepth highDepth , DenseNodeData< C , FEMDegree >& constraints ) const; + template< class C , int FEMDegree , BoundaryType BType > void _downSample( LocalDepth highDepth , DenseNodeData< C >& constraints ) const; // Up samples coefficients @(depth-1) to coefficients @(depth) - template< class C , int FEMDegree , BoundaryType BType > void _upSample( LocalDepth highDepth , DenseNodeData< C , FEMDegree >& coefficients ) const; + template< class C , int FEMDegree , BoundaryType BType > void _upSample( LocalDepth highDepth , DenseNodeData< C >& coefficients ) const; template< class C , int FEMDegree , BoundaryType BType > static void _UpSample( LocalDepth highDepth , ConstPointer( C ) lowCoefficients , Pointer( C ) highCoefficients , int threads ); public: - template< class C , int FEMDegree , BoundaryType BType > DenseNodeData< C , FEMDegree > coarseCoefficients( const DenseNodeData< C , FEMDegree >& coefficients ) const; - template< class C , int FEMDegree , BoundaryType BType > DenseNodeData< C , FEMDegree > coarseCoefficients( const SparseNodeData< C , FEMDegree >& coefficients ) const; + template< class C , int FEMDegree , BoundaryType BType > DenseNodeData< C > coarseCoefficients( const DenseNodeData< C >& coefficients ) const; + template< class C , int FEMDegree , BoundaryType BType > DenseNodeData< C > coarseCoefficients( const SparseNodeData< C >& coefficients ) const; protected: ///////////////////////////////////////////// @@ -663,25 +666,25 @@ class Octree // MultiGridOctreeData.WeightedSamples.inl // ///////////////////////////////////////////// template< int WeightDegree > - void _addWeightContribution( DensityEstimator< WeightDegree >& densityWeights , TreeOctNode* node , Point3D< Real > position , PointSupportKey< WeightDegree >& weightKey , Real weight=Real(1.0) ); - template< int WeightDegree , class PointSupportKey > - Real _getSamplesPerNode( const DensityEstimator< WeightDegree >& densityWeights , const TreeOctNode* node , Point3D< Real > position , PointSupportKey& weightKey ) const; - template< int WeightDegree , class PointSupportKey > - void _getSampleDepthAndWeight( const DensityEstimator< WeightDegree >& densityWeights , const TreeOctNode* node , Point3D< Real > position , PointSupportKey& weightKey , Real& depth , Real& weight ) const; + void _addWeightContribution( DensityEstimator& densityWeights , TreeOctNode* node , Point3D< Real > position , PointSupportKey< WeightDegree >& weightKey , Real weight=Real(1.0) ); template< int WeightDegree , class PointSupportKey > - void _getSampleDepthAndWeight( const DensityEstimator< WeightDegree >& densityWeights , Point3D< Real > position , PointSupportKey& weightKey , Real& depth , Real& weight ) const; - template< bool CreateNodes , int DataDegree , class V > void _splatPointData( TreeOctNode* node , Point3D< Real > point , V v , SparseNodeData< V , DataDegree >& data , PointSupportKey< DataDegree >& dataKey ); - template< bool CreateNodes , int WeightDegree , int DataDegree , class V > Real _splatPointData( const DensityEstimator< WeightDegree >& densityWeights , Point3D< Real > point , V v , SparseNodeData< V , DataDegree >& data , PointSupportKey< WeightDegree >& weightKey , PointSupportKey< DataDegree >& dataKey , LocalDepth minDepth , LocalDepth maxDepth , int dim=DIMENSION ); - template< bool CreateNodes , int WeightDegree , int DataDegree , class V > Real _multiSplatPointData( const DensityEstimator< WeightDegree >* densityWeights , TreeOctNode* node , Point3D< Real > point , V v , SparseNodeData< V , DataDegree >& data , PointSupportKey< WeightDegree >& weightKey , PointSupportKey< DataDegree >& dataKey , int dim=DIMENSION ); + Real _getSamplesPerNode( const DensityEstimator& densityWeights , const TreeOctNode* node , Point3D< Real > position , PointSupportKey& weightKey ) const; + template< int WeightDegree, class PointSupportKey > + void _getSampleDepthAndWeight( const DensityEstimator& densityWeights , const TreeOctNode* node , Point3D< Real > position , PointSupportKey& weightKey , Real& depth , Real& weight ) const; + template< int WeightDegree, class PointSupportKey > + void _getSampleDepthAndWeight( const DensityEstimator& densityWeights , Point3D< Real > position , PointSupportKey& weightKey , Real& depth , Real& weight ) const; + template< bool CreateNodes , int DataDegree , class V > void _splatPointData( TreeOctNode* node , Point3D< Real > point , V v , SparseNodeData< V >& data , PointSupportKey< DataDegree >& dataKey ); + template< bool CreateNodes , int WeightDegree , int DataDegree , class V > Real _splatPointData( const DensityEstimator& densityWeights , Point3D< Real > point , V v , SparseNodeData< V >& data , PointSupportKey< WeightDegree >& weightKey , PointSupportKey< DataDegree >& dataKey , LocalDepth minDepth , LocalDepth maxDepth , int dim=DIMENSION ); + template< bool CreateNodes , int WeightDegree , int DataDegree , class V > Real _multiSplatPointData( const DensityEstimator* densityWeights , TreeOctNode* node , Point3D< Real > point , V v , SparseNodeData< V >& data , PointSupportKey< WeightDegree >& weightKey , PointSupportKey< DataDegree >& dataKey , int dim=DIMENSION ); template< class V , int DataDegree , BoundaryType BType , class Coefficients > V _evaluate( const Coefficients& coefficients , Point3D< Real > p , const BSplineData< DataDegree , BType >& bsData , const ConstPointSupportKey< DataDegree >& dataKey ) const; public: - template< class V , int DataDegree , BoundaryType BType > Pointer( V ) voxelEvaluate( const DenseNodeData< V , DataDegree >& coefficients , int& res , Real isoValue=0.f , LocalDepth depth=-1 , bool primal=false ); + template< class V , int DataDegree , BoundaryType BType > Pointer( V ) voxelEvaluate( const DenseNodeData< V >& coefficients , int& res , Real isoValue=0.f , LocalDepth depth=-1 , bool primal=false ); template< int NormalDegree > struct HasNormalDataFunctor { - const SparseNodeData< Point3D< Real > , NormalDegree >& normalInfo; - HasNormalDataFunctor( const SparseNodeData< Point3D< Real > , NormalDegree >& ni ) : normalInfo( ni ){ ; } + const SparseNodeData< Point3D< Real > >& normalInfo; + HasNormalDataFunctor( const SparseNodeData< Point3D< Real > >& ni ) : normalInfo( ni ){ ; } bool operator() ( const TreeOctNode* node ) const { const Point3D< Real >* n = normalInfo( node ); @@ -690,21 +693,24 @@ class Octree const Point3D< Real >& normal = *n; if( normal[0]!=0 || normal[1]!=0 || normal[2]!=0 ) return true; } - if( node->children ) for( int c=0 ; cchildren + c ) ) return true; + if( node->children ) + for( int c=0 ; c<(int)Cube::CORNERS ; c++ ) + if( (*this)( node->children + c ) ) + return true; return false; } }; struct TrivialHasDataFunctor{ bool operator() ( const TreeOctNode* node ) const{ return true; } }; // [NOTE] The input/output for this method is pre-scaled by weight - template< bool HasGradients > bool _setInterpolationInfoFromChildren( TreeOctNode* node , SparseNodeData< PointData< Real , HasGradients > , 0 >& iInfo ) const; - template< bool HasGradients > SparseNodeData< PointData< Real , HasGradients > , 0 > _densifyInterpolationInfo( const std::vector< PointSample >& samples , Real pointValue , int adaptiveExponent ) const; + template< bool HasGradients > bool _setInterpolationInfoFromChildren( TreeOctNode* node , SparseNodeData< PointData< Real, HasGradients > >& iInfo ) const; + template< bool HasGradients > SparseNodeData< PointData< Real, HasGradients > > _densifyInterpolationInfo( const std::vector< PointSample >& samples , Real pointValue , int adaptiveExponent ) const; template< int FEMDegree , BoundaryType BType > void _setValidityFlags( void ); template< class HasDataFunctor > void _clipTree( const HasDataFunctor& f ); - template< int FEMDegree , BoundaryType BType > SparseNodeData< Real , 0 > leafValues ( const DenseNodeData< Real , FEMDegree >& coefficients ) const; - template< int FEMDegree , BoundaryType BType > SparseNodeData< Point3D< Real > , 0 > leafGradients( const DenseNodeData< Real , FEMDegree >& coefficients ) const; + template< int FEMDegree , BoundaryType BType > SparseNodeData< Real > leafValues ( const DenseNodeData< Real >& coefficients ) const; + template< int FEMDegree , BoundaryType BType > SparseNodeData< Point3D< Real > > leafGradients( const DenseNodeData< Real >& coefficients ) const; //////////////////////////////////// // Evaluation Methods // @@ -742,22 +748,22 @@ class Octree friend Octree; }; template< class V , int FEMDegree , BoundaryType BType > - V _getCenterValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const DenseNodeData< V , FEMDegree >& solution , const DenseNodeData< V , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; + V _getCenterValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const DenseNodeData< V >& solution , const DenseNodeData< V >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; template< class V , int FEMDegree , BoundaryType BType > - V _getCornerValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int corner , const DenseNodeData< V , FEMDegree >& solution , const DenseNodeData< V , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; + V _getCornerValue( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int corner , const DenseNodeData< V >& solution , const DenseNodeData< V >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; template< class V , int FEMDegree , BoundaryType BType > - V _getEdgeValue ( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int edge , const DenseNodeData< V , FEMDegree >& solution , const DenseNodeData< V , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; + V _getEdgeValue ( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int edge , const DenseNodeData< V >& solution , const DenseNodeData< V >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; template< class V , int FEMDegree , BoundaryType BType > - V _getValue ( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , Point3D< Real > p , const DenseNodeData< V , FEMDegree >& solution , const DenseNodeData< V , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator ) const; + V _getValue ( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , Point3D< Real > p , const DenseNodeData< V >& solution , const DenseNodeData< V >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator ) const; template< int FEMDegree , BoundaryType BType > - std::pair< Real , Point3D< Real > > _getCenterValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; + std::pair< Real , Point3D< Real > > _getCenterValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; template< int FEMDegree , BoundaryType BType > - std::pair< Real , Point3D< Real > > _getCornerValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int corner , const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; + std::pair< Real , Point3D< Real > > _getCornerValueAndGradient( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int corner , const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; template< int FEMDegree , BoundaryType BType > - std::pair< Real , Point3D< Real > > _getEdgeValueAndGradient ( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int edge , const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; + std::pair< Real , Point3D< Real > > _getEdgeValueAndGradient ( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , int edge , const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator , bool isInterior ) const; template< int FEMDegree , BoundaryType BType > - std::pair< Real , Point3D< Real > > _getValueAndGradient ( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , Point3D< Real > p , const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator ) const; + std::pair< Real , Point3D< Real > > _getValueAndGradient ( const ConstPointSupportKey< FEMDegree >& neighborKey , const TreeOctNode* node , Point3D< Real > p , const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , const _Evaluator< FEMDegree , BType >& evaluator ) const; public: template< int Degree , BoundaryType BType > @@ -767,10 +773,10 @@ class Octree int _threads; std::vector< ConstPointSupportKey< Degree > > _neighborKeys; _Evaluator< Degree , BType > _evaluator; - const DenseNodeData< Real , Degree >& _coefficients; - DenseNodeData< Real , Degree > _coarseCoefficients; + const DenseNodeData< Real >& _coefficients; + DenseNodeData< Real > _coarseCoefficients; public: - MultiThreadedEvaluator( const Octree* tree , const DenseNodeData< Real , Degree >& coefficients , int threads=1 ); + MultiThreadedEvaluator( const Octree* tree , const DenseNodeData< Real >& coefficients , int threads=1 ); Real value( Point3D< Real > p , int thread=0 , const TreeOctNode* node=NULL ); std::pair< Real , Point3D< Real > > valueAndGradient( Point3D< Real > , int thread=0 , const TreeOctNode* node=NULL ); }; @@ -840,15 +846,15 @@ class Octree const _XSliceValues< Vertex >& xSliceValues( int idx ) const { return _xSliceValues[idx&1]; } }; template< class Vertex , int FEMDegree , BoundaryType BType > - void _setSliceIsoCorners( const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , Real isoValue , LocalDepth depth , int slice , std::vector< _SlabValues< Vertex > >& sValues , const _Evaluator< FEMDegree , BType >& evaluator , int threads ); + void _setSliceIsoCorners( const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , Real isoValue , LocalDepth depth , int slice , std::vector< _SlabValues< Vertex > >& sValues , const _Evaluator< FEMDegree , BType >& evaluator , int threads ); template< class Vertex , int FEMDegree , BoundaryType BType > - void _setSliceIsoCorners( const DenseNodeData< Real , FEMDegree >& solution , const DenseNodeData< Real , FEMDegree >& coarseSolution , Real isoValue , LocalDepth depth , int slice , int z , std::vector< _SlabValues< Vertex > >& sValues , const _Evaluator< FEMDegree , BType >& evaluator , int threads ); + void _setSliceIsoCorners( const DenseNodeData< Real >& solution , const DenseNodeData< Real >& coarseSolution , Real isoValue , LocalDepth depth , int slice , int z , std::vector< _SlabValues< Vertex > >& sValues , const _Evaluator< FEMDegree , BType >& evaluator , int threads ); template< int WeightDegree , int ColorDegree , BoundaryType BType , class Vertex > - void _setSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , Real isoValue , LocalDepth depth , int slice , int& vOffset , CoredMeshData< Vertex >& mesh , std::vector< _SlabValues< Vertex > >& sValues , int threads ); + void _setSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , Real isoValue , LocalDepth depth , int slice , int& vOffset , Kazhdan::Mesh& mesh , std::vector< _SlabValues< Vertex > >& sValues , int threads ); template< int WeightDegree , int ColorDegree , BoundaryType BType , class Vertex > - void _setSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , Real isoValue , LocalDepth depth , int slice , int z , int& vOffset , CoredMeshData< Vertex >& mesh , std::vector< _SlabValues< Vertex > >& sValues , int threads ); + void _setSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , Real isoValue , LocalDepth depth , int slice , int z , int& vOffset , Kazhdan::Mesh& mesh , std::vector< _SlabValues< Vertex > >& sValues , int threads ); template< int WeightDegree , int ColorDegree , BoundaryType BType , class Vertex > - void _setXSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , Real isoValue , LocalDepth depth , int slab , int& vOffset , CoredMeshData< Vertex >& mesh , std::vector< _SlabValues< Vertex > >& sValues , int threads ); + void _setXSliceIsoVertices( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , Real isoValue , LocalDepth depth , int slab , int& vOffset , Kazhdan::Mesh& mesh , std::vector< _SlabValues< Vertex > >& sValues , int threads ); template< class Vertex > void _setSliceIsoEdges( LocalDepth depth , int slice , std::vector< _SlabValues< Vertex > >& slabValues , int threads ); template< class Vertex > @@ -863,15 +869,15 @@ class Octree void _copyFinerXSliceIsoEdgeKeys( LocalDepth depth , int slab , std::vector< _SlabValues< Vertex > >& sValues , int threads ); template< class Vertex > - void _setIsoSurface( LocalDepth depth , int offset , const _SliceValues< Vertex >& bValues , const _SliceValues< Vertex >& fValues , const _XSliceValues< Vertex >& xValues , CoredMeshData< Vertex >& mesh , bool polygonMesh , bool addBarycenter , int& vOffset , int threads ); + void _setIsoSurface( LocalDepth depth , int offset , const _SliceValues< Vertex >& bValues , const _SliceValues< Vertex >& fValues , const _XSliceValues< Vertex >& xValues , Kazhdan::Mesh& mesh , bool polygonMesh , bool addBarycenter , int& vOffset , int threads ); template< class Vertex > - static int _addIsoPolygons( CoredMeshData< Vertex >& mesh , std::vector< std::pair< int , Vertex > >& polygon , bool polygonMesh , bool addBarycenter , int& vOffset ); + static int _addIsoPolygons( Kazhdan::Mesh& mesh , std::vector< std::pair< int , Vertex > >& polygon , bool polygonMesh , bool addBarycenter , int& vOffset ); template< int WeightDegree , int ColorDegree , BoundaryType BType , class Vertex > - bool _getIsoVertex( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , Real isoValue , ConstPointSupportKey< WeightDegree >& weightKey , ConstPointSupportKey< ColorDegree >& colorKey , const TreeOctNode* node , int edgeIndex , int z , const _SliceValues< Vertex >& sValues , Vertex& vertex ); + bool _getIsoVertex( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , Real isoValue , ConstPointSupportKey< WeightDegree >& weightKey , ConstPointSupportKey< ColorDegree >& colorKey , const TreeOctNode* node , int edgeIndex , int z , const _SliceValues< Vertex >& sValues , Vertex& vertex ); template< int WeightDegree , int ColorDegree , BoundaryType BType , class Vertex > - bool _getIsoVertex( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , Real isoValue , ConstPointSupportKey< WeightDegree >& weightKey , ConstPointSupportKey< ColorDegree >& colorKey , const TreeOctNode* node , int cornerIndex , const _SliceValues< Vertex >& bValues , const _SliceValues< Vertex >& fValues , Vertex& vertex ); + bool _getIsoVertex( const BSplineData< ColorDegree , BType >* colorBSData , const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , Real isoValue , ConstPointSupportKey< WeightDegree >& weightKey , ConstPointSupportKey< ColorDegree >& colorKey , const TreeOctNode* node , int cornerIndex , const _SliceValues< Vertex >& bValues , const _SliceValues< Vertex >& fValues , Vertex& vertex ); void _init( TreeOctNode* node , LocalDepth maxDepth , bool (*Refine)( LocalDepth d , LocalOffset off ) ); @@ -887,49 +893,49 @@ class Octree void init( LocalDepth maxDepth , bool (*Refine)( LocalDepth d , LocalOffset off ) ); template< class Data > - int init( OrientedPointStream< Real >& pointStream , LocalDepth maxDepth , bool useConfidence , std::vector< PointSample >& samples , std::vector< ProjectiveData< Data , Real > >* sampleData ); + int init(PointSource& pointSource , LocalDepth maxDepth , bool useConfidence , std::vector< PointSample >& samples , std::vector< ProjectiveData< Data , Real > >* sampleData ); template< int DensityDegree > - typename Octree::template DensityEstimator< DensityDegree >* setDensityEstimator( const std::vector< PointSample >& samples , LocalDepth splatDepth , Real samplesPerNode ); + typename Octree::DensityEstimator* setDensityEstimator( const std::vector< PointSample >& samples , LocalDepth splatDepth , Real samplesPerNode ); template< int NormalDegree , int DensityDegree > - SparseNodeData< Point3D< Real > , NormalDegree > setNormalField( const std::vector< PointSample >& samples , const DensityEstimator< DensityDegree >& density , Real& pointWeightSum , bool forceNeumann ); + SparseNodeData< Point3D< Real > > setNormalField( const std::vector< PointSample >& samples , const DensityEstimator& density , Real& pointWeightSum , bool forceNeumann ); template< int DataDegree , bool CreateNodes , int DensityDegree , class Data > - SparseNodeData< ProjectiveData< Data , Real > , DataDegree > setDataField( const std::vector< PointSample >& samples , std::vector< ProjectiveData< Data , Real > >& sampleData , const DensityEstimator< DensityDegree >* density ); + SparseNodeData< ProjectiveData< Data , Real > > setDataField( const std::vector< PointSample >& samples , std::vector< ProjectiveData< Data , Real > >& sampleData , const DensityEstimator* density ); template< int MaxDegree , int FEMDegree , BoundaryType FEMBType , class HasDataFunctor > void inalizeForBroodedMultigrid( LocalDepth fullDepth , const HasDataFunctor& F , std::vector< int >* map=NULL ); // Generate an empty set of constraints - template< int FEMDegree > DenseNodeData< Real , FEMDegree > initDenseNodeData( void ); + DenseNodeData< Real > initDenseNodeData( void ); // Add finite-elements constraints (derived from a sparse scalar field) - template< int FEMDegree , BoundaryType FEMBType , int SFDegree , BoundaryType SFBType , class FEMSFConstraintFunctor > void addFEMConstraints( const FEMSFConstraintFunctor& F , const SparseNodeData< Real , SFDegree >& sfCoefficients , DenseNodeData< Real , FEMDegree >& constraints , LocalDepth maxDepth ) - { return _addFEMConstraints< FEMDegree , FEMBType , SFDegree , SFBType , FEMSFConstraintFunctor , const SparseNodeData< Real , SFDegree > , Real , double >( F , sfCoefficients , constraints , maxDepth ); } + template< int FEMDegree , BoundaryType FEMBType , int SFDegree , BoundaryType SFBType , class FEMSFConstraintFunctor > void addFEMConstraints( const FEMSFConstraintFunctor& F , const SparseNodeData< Real >& sfCoefficients , DenseNodeData< Real >& constraints , LocalDepth maxDepth ) + { return _addFEMConstraints< FEMDegree , FEMBType , SFDegree , SFBType , FEMSFConstraintFunctor , const SparseNodeData< Real > , Real , double >( F , sfCoefficients , constraints , maxDepth ); } // Add finite-elements constraints (derived from a dense scalar field) - template< int FEMDegree , BoundaryType FEMBType , int SFDegree , BoundaryType SFBType , class FEMSFConstraintFunctor > void addFEMConstraints( const FEMSFConstraintFunctor& F , const DenseNodeData< Real , SFDegree >& sfCoefficients , DenseNodeData< Real , FEMDegree >& constraints , LocalDepth maxDepth ) - { return _addFEMConstraints< FEMDegree , FEMBType , SFDegree , SFBType , FEMSFConstraintFunctor , const DenseNodeData< Real , SFDegree > , Real , double >( F , sfCoefficients , constraints , maxDepth ); } + template< int FEMDegree , BoundaryType FEMBType , int SFDegree , BoundaryType SFBType , class FEMSFConstraintFunctor > void addFEMConstraints( const FEMSFConstraintFunctor& F , const DenseNodeData< Real >& sfCoefficients , DenseNodeData< Real >& constraints , LocalDepth maxDepth ) + { return _addFEMConstraints< FEMDegree , FEMBType , SFDegree , SFBType , FEMSFConstraintFunctor , const DenseNodeData< Real > , Real , double >( F , sfCoefficients , constraints , maxDepth ); } // Add finite-elements constraints (derived from a sparse vector field) - template< int FEMDegree , BoundaryType FEMBType , int VFDegree , BoundaryType VFBType , class FEMVFConstraintFunctor > void addFEMConstraints( const FEMVFConstraintFunctor& F , const SparseNodeData< Point3D< Real > , VFDegree >& vfCoefficients , DenseNodeData< Real , FEMDegree >& constraints , LocalDepth maxDepth ) - { return _addFEMConstraints< FEMDegree , FEMBType , VFDegree , VFBType , FEMVFConstraintFunctor , const SparseNodeData< Point3D< Real > , VFDegree > , Point3D< Real > , Point3D< double > >( F , vfCoefficients , constraints , maxDepth ); } + template< int FEMDegree , BoundaryType FEMBType , int VFDegree , BoundaryType VFBType , class FEMVFConstraintFunctor > void addFEMConstraints( const FEMVFConstraintFunctor& F , const SparseNodeData< Point3D< Real > >& vfCoefficients , DenseNodeData< Real >& constraints , LocalDepth maxDepth ) + { return _addFEMConstraints< FEMDegree , FEMBType , VFDegree , VFBType , FEMVFConstraintFunctor , const SparseNodeData< Point3D< Real > > , Point3D< Real > , Point3D< double > >( F , vfCoefficients , constraints , maxDepth ); } // Add finite-elements constraints (derived from a dense vector field) - template< int FEMDegree , BoundaryType FEMBType , int VFDegree , BoundaryType VFBType , class FEMVFConstraintFunctor > void addFEMConstraints( const FEMVFConstraintFunctor& F , const DenseNodeData< Point3D< Real > , VFDegree >& vfCoefficients , DenseNodeData< Real , FEMDegree >& constraints , LocalDepth maxDepth ) - { return _addFEMConstraints< FEMDegree , FEMBType , VFDegree , VFBType , FEMVFConstraintFunctor , const DenseNodeData< Point3D< Real > , VFDegree > , Point3D< Real > , Point3D< double > >( F , vfCoefficients , constraints , maxDepth ); } + template< int FEMDegree , BoundaryType FEMBType , int VFDegree , BoundaryType VFBType , class FEMVFConstraintFunctor > void addFEMConstraints( const FEMVFConstraintFunctor& F , const DenseNodeData< Point3D< Real > >& vfCoefficients , DenseNodeData< Real >& constraints , LocalDepth maxDepth ) + { return _addFEMConstraints< FEMDegree , FEMBType , VFDegree , VFBType , FEMVFConstraintFunctor , const DenseNodeData< Point3D< Real > > , Point3D< Real > , Point3D< double > >( F , vfCoefficients , constraints , maxDepth ); } // Add interpolation constraints - template< int FEMDegree , BoundaryType FEMBType , bool HasGradients > void addInterpolationConstraints( const InterpolationInfo< HasGradients >& interpolationInfo , DenseNodeData< Real , FEMDegree >& constraints , LocalDepth maxDepth ); + template< int FEMDegree , BoundaryType FEMBType , bool HasGradients > void addInterpolationConstraints( const InterpolationInfo< HasGradients >& interpolationInfo , DenseNodeData< Real >& constraints , LocalDepth maxDepth ); - template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor > double dot( const DotFunctor& F , const SparseNodeData< Real , Degree1 >& coefficients1 , const SparseNodeData< Real , Degree2 >& coefficients2 ) const + template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor > double dot( const DotFunctor& F , const SparseNodeData< Real >& coefficients1 , const SparseNodeData< Real >& coefficients2 ) const { return _dot< Degree1 , BType1 , Degree2 , BType2 , DotFunctor , false >( F , (const InterpolationInfo< false >*)NULL , coefficients1 , coefficients2 ); } - template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor > double dot( const DotFunctor& F , const SparseNodeData< Real , Degree1 >& coefficients1 , const DenseNodeData< Real , Degree2 >& coefficients2 ) const + template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor > double dot( const DotFunctor& F , const SparseNodeData< Real >& coefficients1 , const DenseNodeData< Real >& coefficients2 ) const { return _dot< Degree1 , BType1 , Degree2 , BType2 , DotFunctor , false >( F , (const InterpolationInfo< false >*)NULL , coefficients1 , coefficients2 ); } - template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor > double dot( const DotFunctor& F , const DenseNodeData< Real , Degree1 >& coefficients1 , const SparseNodeData< Real , Degree2 >& coefficients2 ) const + template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor > double dot( const DotFunctor& F , const DenseNodeData< Real >& coefficients1 , const SparseNodeData< Real >& coefficients2 ) const { return _dot< Degree1 , BType1 , Degree2 , BType2 , DotFunctor , false >( F , (const InterpolationInfo< false >*)NULL , coefficients1 , coefficients2 ); } - template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor > double dot( const DotFunctor& F , const DenseNodeData< Real , Degree1 >& coefficients1 , const DenseNodeData< Real , Degree2 >& coefficients2 ) const + template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor > double dot( const DotFunctor& F , const DenseNodeData< Real >& coefficients1 , const DenseNodeData< Real >& coefficients2 ) const { return _dot< Degree1 , BType1 , Degree2 , BType2 , DotFunctor , false >( F , (const InterpolationInfo< false >*)NULL , coefficients1 , coefficients2 ); } - template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor , bool HasGradients > double dot( const DotFunctor& F , const InterpolationInfo< HasGradients >* iInfo , const SparseNodeData< Real , Degree1 >& coefficients1 , const SparseNodeData< Real , Degree2 >& coefficients2 ) const + template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor , bool HasGradients > double dot( const DotFunctor& F , const InterpolationInfo< HasGradients >* iInfo , const SparseNodeData< Real >& coefficients1 , const SparseNodeData< Real >& coefficients2 ) const { return _dot< Degree1 , BType1 , Degree2 , BType2 , DotFunctor , HasGradients >( F , iInfo , coefficients1 , coefficients2 ); } - template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor , bool HasGradients > double dot( const DotFunctor& F , const InterpolationInfo< HasGradients >* iInfo , const SparseNodeData< Real , Degree1 >& coefficients1 , const DenseNodeData< Real , Degree2 >& coefficients2 ) const + template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor , bool HasGradients > double dot( const DotFunctor& F , const InterpolationInfo< HasGradients >* iInfo , const SparseNodeData< Real >& coefficients1 , const DenseNodeData< Real >& coefficients2 ) const { return _dot< Degree1 , BType1 , Degree2 , BType2 , DotFunctor , HasGradients >( F , iInfo , coefficients1 , coefficients2 ); } - template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor , bool HasGradients > double dot( const DotFunctor& F , const InterpolationInfo< HasGradients >* iInfo , const DenseNodeData< Real , Degree1 >& coefficients1 , const SparseNodeData< Real , Degree2 >& coefficients2 ) const + template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor , bool HasGradients > double dot( const DotFunctor& F , const InterpolationInfo< HasGradients >* iInfo , const DenseNodeData< Real >& coefficients1 , const SparseNodeData< Real >& coefficients2 ) const { return _dot< Degree1 , BType1 , Degree2 , BType2 , DotFunctor , HasGradients >( F , iInfo , coefficients1 , coefficients2 ); } - template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor , bool HasGradients > double dot( const DotFunctor& F , const InterpolationInfo< HasGradients >* iInfo , const DenseNodeData< Real , Degree1 >& coefficients1 , const DenseNodeData< Real , Degree2 >& coefficients2 ) const + template< int Degree1 , BoundaryType BType1 , int Degree2 , BoundaryType BType2 , class DotFunctor , bool HasGradients > double dot( const DotFunctor& F , const InterpolationInfo< HasGradients >* iInfo , const DenseNodeData< Real >& coefficients1 , const DenseNodeData< Real >& coefficients2 ) const { return _dot< Degree1 , BType1 , Degree2 , BType2 , DotFunctor , HasGradients >( F , iInfo , coefficients1 , coefficients2 ); } template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > @@ -948,10 +954,10 @@ class Octree SolverInfo( void ) : cgDepth(0) , iters(1), cgAccuracy(0) , lowResIterMultiplier(0) , verbose(false) , showResidual(false) { ; } }; template< int FEMDegree , BoundaryType BType , class FEMSystemFunctor , bool HasGradients > - DenseNodeData< Real , FEMDegree > solveSystem( const FEMSystemFunctor& F , InterpolationInfo< HasGradients >* iData , DenseNodeData< Real , FEMDegree >& constraints , LocalDepth maxSolveDepth , const SolverInfo& solverInfo ); + DenseNodeData< Real > solveSystem( const FEMSystemFunctor& F , InterpolationInfo< HasGradients >* iData , DenseNodeData< Real >& constraints , LocalDepth maxSolveDepth , const SolverInfo& solverInfo ); template< int FEMDegree , BoundaryType BType , int WeightDegree , int ColorDegree , class Vertex > - void getMCIsoSurface( const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > , ColorDegree >* colorData , const DenseNodeData< Real , FEMDegree >& solution , Real isoValue , CoredMeshData< Vertex >& mesh , bool nonLinearFit=true , bool addBarycenter=false , bool polygonMesh=false ); + void getMCIsoSurface( const DensityEstimator* densityWeights , const SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData , const DenseNodeData< Real >& solution , Real isoValue , Kazhdan::Mesh& mesh , bool nonLinearFit=true , bool addBarycenter=false , bool polygonMesh=false ); const TreeOctNode& tree( void ) const{ return *_tree; } @@ -969,7 +975,7 @@ class Octree template< class D > static bool _IsZero( const D& d ); template< class D > static Real _Dot( const D& d1 , const D& d2 ); template< int FEMDegree , BoundaryType FEMBType , int CDegree , BoundaryType CBType , class FEMConstraintFunctor , class Coefficients , class D , class _D > - void _addFEMConstraints( const FEMConstraintFunctor& F , const Coefficients& coefficients , DenseNodeData< Real , FEMDegree >& constraints , LocalDepth maxDepth ); + void _addFEMConstraints( const FEMConstraintFunctor& F , const Coefficients& coefficients , DenseNodeData< Real >& constraints , LocalDepth maxDepth ); template< int FEMDegree1 , BoundaryType FEMBType1 , int FEMDegree2 , BoundaryType FEMBType2 , class DotFunctor , bool HasGradients , class Coefficients1 , class Coefficients2 > double _dot( const DotFunctor& F , const InterpolationInfo< HasGradients >* iInfo , const Coefficients1& coefficients1 , const Coefficients2& coefficients2 ) const; }; diff --git a/Src/MultiGridOctreeData.inl b/Src/MultiGridOctreeData.inl index 72195b9d..6d424f70 100644 --- a/Src/MultiGridOctreeData.inl +++ b/Src/MultiGridOctreeData.inl @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -29,7 +29,9 @@ DAMAGE. #include #endif // FAST_SET_UP #include -#include "PointStream.h" + +#include "MemoryUsage.h" +#include "MyTime.h" #define MEMORY_ALLOCATOR_BLOCK_SIZE 1<<12 //#define MEMORY_ALLOCATOR_BLOCK_SIZE 0 @@ -57,8 +59,7 @@ double Octree< Real >::memoryUsage( void ) return mem; } -template< class Real > Octree< Real >::Octree( void ) : threads(1) , _maxMemoryUsage(0) , _localMemoryUsage(0) -{ +template< class Real > Octree< Real >::Octree( void ) : _maxMemoryUsage(0) , _localMemoryUsage(0), threads(1) { _tree = TreeOctNode::NewBrood( _NodeInitializer ); _tree->initChildren( _NodeInitializer ) , _spaceRoot = _tree->children; _depthOffset = 1; @@ -144,13 +145,16 @@ void Octree< Real >::_setFullDepth( TreeOctNode* node , LocalDepth depth ) const LocalDepth d ; LocalOffset off; _localDepthAndOffset( node , d , off ); if( d( node ) ) refine = true; else if( !BSplineSupportSizes< Degree >::OutOfBounds( d , off[0] ) && !BSplineSupportSizes< Degree >::OutOfBounds( d , off[1] ) && !BSplineSupportSizes< Degree >::OutOfBounds( d , off[2] ) ) refine = true; + } if( refine ) { if( !node->children ) node->initChildren( _NodeInitializer ); - for( int c=0 ; c( node->children+c , depth ); + for( int c=0 ; c<(int)Cube::CORNERS ; c++ ) _setFullDepth< Degree , BType >( node->children+c , depth ); } } template< class Real > @@ -158,7 +162,7 @@ template< int Degree , BoundaryType BType > void Octree< Real >::_setFullDepth( LocalDepth depth ) { if( !_tree->children ) _tree->initChildren( _NodeInitializer ); - for( int c=0 ; c( _tree->children+c , depth ); + for( int c=0 ; c<(int)Cube::CORNERS ; c++ ) _setFullDepth< Degree , BType >( _tree->children+c , depth ); } template< class Real , bool HasGradients > @@ -203,29 +207,74 @@ void Octree< Real >::_init( TreeOctNode* node , LocalDepth maxDepth , bool (*Ref } } } -template< class Real > void Octree< Real >::init( LocalDepth maxDepth , bool (*Refine)( LocalDepth , LocalOffset ) ){ _init( _spaceRoot , maxDepth , Refine ); } template< class Real > -template< class Data > -int Octree< Real >::init( OrientedPointStream< Real >& pointStream , LocalDepth maxDepth , bool useConfidence , std::vector< PointSample >& samples , std::vector< ProjectiveData< Data , Real > >* sampleData ) +void Octree< Real >::init( LocalDepth maxDepth , + bool (*Refine)( LocalDepth , LocalOffset ) ) { - OrientedPointStreamWithData< Real , Data >& pointStreamWithData = ( OrientedPointStreamWithData< Real , Data >& )pointStream; + _init( _spaceRoot , maxDepth , Refine ); +} +template< class Real > +template< class Data > +int Octree< Real >::init(PointSource& source , LocalDepth maxDepth , + bool useConfidence , std::vector< PointSample >& samples , + std::vector< ProjectiveData< Data , Real > >* sampleData ) +{ // Add the point data - int outOfBoundPoints = 0 , zeroLengthNormals = 0 , undefinedNormals = 0 , pointCount = 0; + int outOfBoundPoints = 0; + int zeroLengthNormals = 0; + int undefinedNormals = 0; + int pointCount = 0; { std::vector< int > nodeToIndexMap; Point3D< Real > p , n; - OrientedPoint3D< Real > _p; - Data _d; - while( ( sampleData ? pointStreamWithData.nextPoint( _p , _d ) : pointStream.nextPoint( _p ) ) ) - { - p = Point3D< Real >(_p.p) , n = Point3D< Real >(_p.n); + OrientedPoint3D _p; + Point3D _d; + + while (true) + { + //ABELL - Doing this every loop is stupid, but it's proof of + // concept at this point. + try + { + ColorPointSource& colorSource = + dynamic_cast(source); + if (!colorSource.nextPoint(_p, _d)) + break; + } + catch (std::bad_cast) + { + if (!source.nextPoint(_p)) + break; + } + + p = Point3D< Real >(_p.p); + n = Point3D< Real >(_p.n); Real len = (Real)Length( n ); - if( !_InBounds(p) ){ outOfBoundPoints++ ; continue; } - if( !len ){ zeroLengthNormals++ ; continue; } - if( len!=len ){ undefinedNormals++ ; continue; } + + //ABELL - Not sure how this would happen. Points should + // be normalized when read. + if (!_InBounds(p)) + { + outOfBoundPoints++; + continue; + } + if( !len ) + { + zeroLengthNormals++; + continue; + } + if( std::isnan(len)) + { + undefinedNormals++; + continue; + } + + // Make a unit normal vector. n /= len; - Point3D< Real > center = Point3D< Real >( Real(0.5) , Real(0.5) , Real(0.5) ); + + Point3D center = + Point3D(Real(0.5) , Real(0.5) , Real(0.5)); Real width = Real(1.0); TreeOctNode* temp = _spaceRoot; LocalDepth depth = _localDepth( temp ); @@ -245,7 +294,7 @@ int Octree< Real >::init( OrientedPointStream< Real >& pointStream , LocalDepth } Real weight = (Real)( useConfidence ? len : 1. ); int nodeIndex = temp->nodeData.nodeIndex; - if( nodeIndex>=nodeToIndexMap.size() ) nodeToIndexMap.resize( nodeIndex+1 , -1 ); + if( nodeIndex>=(int)nodeToIndexMap.size() ) nodeToIndexMap.resize( nodeIndex+1 , -1 ); int idx = nodeToIndexMap[ nodeIndex ]; if( idx==-1 ) { @@ -258,7 +307,7 @@ int Octree< Real >::init( OrientedPointStream< Real >& pointStream , LocalDepth if( sampleData ) (*sampleData)[ idx ] += ProjectiveData< Data , Real >( _d * weight , weight ); pointCount++; } - pointStream.reset(); + source.reset(); } if( outOfBoundPoints ) fprintf( stderr , "[WARNING] Found out-of-bound points: %d\n" , outOfBoundPoints ); if( zeroLengthNormals ) fprintf( stderr , "[WARNING] Found zero-length normals: %d\n" , zeroLengthNormals ); @@ -267,28 +316,31 @@ int Octree< Real >::init( OrientedPointStream< Real >& pointStream , LocalDepth memoryUsage(); return pointCount; } + template< class Real > template< int DensityDegree > -typename Octree< Real >::template DensityEstimator< DensityDegree >* Octree< Real >::setDensityEstimator( const std::vector< PointSample >& samples , LocalDepth splatDepth , Real samplesPerNode ) +typename Octree< Real >::DensityEstimator* Octree< Real >::setDensityEstimator( const std::vector< PointSample >& samples , LocalDepth splatDepth , Real samplesPerNode ) { LocalDepth maxDepth = _localMaxDepth( _tree ); splatDepth = std::max< LocalDepth >( 0 , std::min< LocalDepth >( splatDepth , maxDepth ) ); - DensityEstimator< DensityDegree >* _density = new DensityEstimator< DensityDegree >( splatDepth ); - DensityEstimator< DensityDegree >& density = *_density; + DensityEstimator* _density = new DensityEstimator( splatDepth ); + DensityEstimator& density = *_density; PointSupportKey< DensityDegree > densityKey; densityKey.set( _localToGlobal( splatDepth ) ); #ifdef FAST_SET_UP std::vector< int > sampleMap( NodeCount() , -1 ); #pragma omp parallel for num_threads( threads ) - for( int i=0 ; i0 ) sampleMap[ samples[i].node->nodeData.nodeIndex ] = i; + for( int i=0 ; i<(int)samples.size() ; i++ ) + if( samples[i].sample.weight>0 ) + sampleMap[ samples[i].node->nodeData.nodeIndex ] = i; std::function< ProjectiveData< OrientedPoint3D< Real > , Real > ( TreeOctNode* ) > SetDensity = [&] ( TreeOctNode* node ) { ProjectiveData< OrientedPoint3D< Real > , Real > sample; LocalDepth d = _localDepth( node ); int idx = node->nodeData.nodeIndex; if( node->children ) - for( int c=0 ; c , Real > s = SetDensity( node->children + c ); if( d<=splatDepth && s.weight>0 ) @@ -299,7 +351,7 @@ typename Octree< Real >::template DensityEstimator< DensityDegree >* Octree< Rea } sample += s; } - else if( idx0 ) @@ -331,7 +383,7 @@ typename Octree< Real >::template DensityEstimator< DensityDegree >* Octree< Rea } template< class Real > template< int NormalDegree , int DensityDegree > -SparseNodeData< Point3D< Real > , NormalDegree > Octree< Real >::setNormalField( const std::vector< PointSample >& samples , const DensityEstimator< DensityDegree >& density , Real& pointWeightSum , bool forceNeumann ) +SparseNodeData< Point3D< Real > > Octree< Real >::setNormalField( const std::vector< PointSample >& samples , const DensityEstimator& density , Real& pointWeightSum , bool forceNeumann ) { LocalDepth maxDepth = _localMaxDepth( _tree ); PointSupportKey< DensityDegree > densityKey; @@ -340,8 +392,8 @@ SparseNodeData< Point3D< Real > , NormalDegree > Octree< Real >::setNormalField( Real weightSum = 0; pointWeightSum = 0; - SparseNodeData< Point3D< Real > , NormalDegree > normalField; - for( int i=0 ; i > normalField; + for( int i=0 ; i<(int)samples.size() ; i++ ) { const ProjectiveData< OrientedPoint3D< Real > , Real >& sample = samples[i].sample; if( sample.weight>0 ) @@ -359,15 +411,15 @@ SparseNodeData< Point3D< Real > , NormalDegree > Octree< Real >::setNormalField( } template< class Real > template< int DataDegree , bool CreateNodes , int DensityDegree , class Data > -SparseNodeData< ProjectiveData< Data , Real > , DataDegree > Octree< Real >::setDataField( const std::vector< PointSample >& samples , std::vector< ProjectiveData< Data , Real > >& sampleData , const DensityEstimator< DensityDegree >* density ) +SparseNodeData< ProjectiveData< Data , Real > > Octree< Real >::setDataField( const std::vector< PointSample >& samples , std::vector< ProjectiveData< Data , Real > >& sampleData , const DensityEstimator* density ) { LocalDepth maxDepth = _localMaxDepth( _tree ); PointSupportKey< DensityDegree > densityKey; PointSupportKey< DataDegree > dataKey; densityKey.set( _localToGlobal( maxDepth ) ) , dataKey.set( _localToGlobal( maxDepth ) ); - SparseNodeData< ProjectiveData< Data , Real > , DataDegree > dataField; - for( int i=0 ; i > dataField; + for( int i=0 ; i<(int)samples.size() ; i++ ) { const ProjectiveData< OrientedPoint3D< Real > , Real >& sample = samples[i].sample; const ProjectiveData< Data , Real >& data = sampleData[i]; @@ -408,7 +460,7 @@ void Octree< Real >::inalizeForBroodedMultigrid( LocalDepth fullDepth , const Ha int corner = _depthOffset<=1 ? Cube::CORNERS-1 : 0; newSpaceRootParent[corner].children = _spaceRoot; oldSpaceRootParent->children = newSpaceRootParent; - for( int c=0 ; c::_clipTree( const HasDataFunctor& f ) for( TreeOctNode* temp=_tree->nextNode() ; temp ; temp=_tree->nextNode(temp) ) if( temp->children && _localDepth( temp )>=_fullDepth ) { bool hasData = false; - for( int c=0 ; cchildren + c ); - for( int c=0 ; cchildren+c , !hasData ); + for( int c=0 ; c<(int)Cube::CORNERS && !hasData ; c++ ) hasData |= f( temp->children + c ); + for( int c=0 ; c<(int)Cube::CORNERS ; c++ ) SetGhostFlag( temp->children+c , !hasData ); } } template< class Real > template< bool HasGradients > -bool Octree< Real >::_setInterpolationInfoFromChildren( TreeOctNode* node , SparseNodeData< PointData< Real , HasGradients > , 0 >& interpolationInfo ) const +bool Octree< Real >::_setInterpolationInfoFromChildren( TreeOctNode* node , SparseNodeData< PointData< Real , HasGradients > >& interpolationInfo ) const { if( IsActiveNode( node->children ) ) { @@ -494,7 +546,7 @@ bool Octree< Real >::_setInterpolationInfoFromChildren( TreeOctNode* node , Spar hasChildData = true; } #else // !POINT_DATA_RES - for( int c=0 ; cchildren + c , interpolationInfo ) ) { pData += interpolationInfo[ node->children + c ]; @@ -508,10 +560,10 @@ bool Octree< Real >::_setInterpolationInfoFromChildren( TreeOctNode* node , Spar } template< class Real > template< bool HasGradients > -SparseNodeData< PointData< Real , HasGradients > , 0 > Octree< Real >::_densifyInterpolationInfo( const std::vector< PointSample >& samples , Real pointValue , int adaptiveExponent ) const +SparseNodeData< PointData< Real , HasGradients > > Octree< Real >::_densifyInterpolationInfo( const std::vector< PointSample >& samples , Real pointValue , int adaptiveExponent ) const { - SparseNodeData< PointData< Real , HasGradients > , 0 > iInfo; - for( int i=0 ; i > iInfo; + for( int i=0 ; i<(int)samples.size() ; i++ ) { const TreeOctNode* node = samples[i].node; const ProjectiveData< OrientedPoint3D< Real > , Real >& pData = samples[i].sample; diff --git a/Src/Octree.h b/Src/Octree.h index 83733965..31b4d697 100644 --- a/Src/Octree.h +++ b/Src/Octree.h @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -67,7 +67,7 @@ class OctNode ~OctNode( void ); int initChildren( void (*Initializer)( OctNode& )=NULL ); - void depthAndOffset( int& depth , int offset[DIMENSION] ) const; + void depthAndOffset( int& depth , int offset[DIMENSION] ) const; void centerIndex( int index[DIMENSION] ) const; int depth( void ) const; static inline void DepthAndOffset( const long long& index , int& depth , int offset[DIMENSION] ); @@ -149,7 +149,7 @@ class OctNode template< bool CreateNodes , unsigned int _LeftRadius , unsigned int _RightRadius > void getNeighbors( OctNode* node , Neighbors< _LeftRadius + _RightRadius + 1 >& neighbors , void (*Initializer)( OctNode& )=NULL ); template< bool CreateNodes > bool getChildNeighbors( int cIdx , int d , Neighbors< Width >& childNeighbors , void (*Initializer)( OctNode& )=NULL ) const; template< bool CreateNodes , class Real > bool getChildNeighbors( Point3D< Real > p , int d , Neighbors< Width >& childNeighbors , void (*Initializer)( OctNode& )=NULL ) const; - typename OctNode< NodeData >::template Neighbors< LeftRadius+RightRadius+1 >& getNeighbors( const OctNode* node ) { return getNeighbors< false >( (OctNode*)node , NULL ); } + typename OctNode< NodeData >::template Neighbors< LeftRadius+RightRadius+1 >& getNeighbors( const OctNode* node ) { return getNeighbors< false >( const_cast(node), NULL ); } template< unsigned int _LeftRadius , unsigned int _RightRadius > void getNeighbors( const OctNode* node , Neighbors< _LeftRadius + _RightRadius + 1 >& neighbors ){ return getNeighbors< false , _LeftRadius , _RightRadius >( (OctNode*)node , NULL ); } bool getChildNeighbors( int cIdx , int d , Neighbors< Width >& childNeighbors ) const { return getChildNeighbors< false >( cIdx , d , childNeighbors , NULL ); } template< class Real > bool getChildNeighbors( Point3D< Real > p , int d , Neighbors< Width >& childNeighbors ) const { return getChildNeighbors< false , Real >( p , d , childNeighbors , NULL ); } diff --git a/Src/Octree.inl b/Src/Octree.inl index 40202f97..bdbabd16 100644 --- a/Src/Octree.inl +++ b/Src/Octree.inl @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -268,7 +268,7 @@ int OctNode< NodeData >::maxDepth(void) const{ if(!children){return 0;} else{ int c,d; - for(int i=0;ic){c=d;} } @@ -644,7 +644,13 @@ template< unsigned int Width > OctNode< NodeData >::Neighbors< Width >::Neighbors( void ){ clear(); } template< class NodeData > template< unsigned int Width > -void OctNode< NodeData >::Neighbors< Width >::clear( void ){ for( int i=0 ; i::Neighbors< Width >::clear( void ) +{ + for( int i=0 ; i<(int)Width ; i++ ) + for( int j=0 ; j<(int)Width ; j++ ) + for( int k=0 ; k<(int)Width ; k++ ) + neighbors[i][j][k]=NULL; +} ///////////////////////////// // OctNode::ConstNeighbors // @@ -654,7 +660,11 @@ template< unsigned int Width > OctNode< NodeData >::ConstNeighbors< Width >::ConstNeighbors( void ){ clear(); } template< class NodeData > template< unsigned int Width > -void OctNode< NodeData >::ConstNeighbors< Width >::clear( void ){ for( int i=0 ; i::ConstNeighbors< Width >::clear( void ) +{ for( int i=0 ; i<(int)Width ; i++ ) + for( int j=0 ; j<(int)Width ; j++ ) + for( int k=0 ; k<(int)Width ; k++ ) neighbors[i][j][k]=NULL; +} ////////////////////////// // OctNode::NeighborKey // @@ -696,7 +706,7 @@ bool OctNode< NodeData >::NeighborKey< LeftRadius , RightRadius >::getChildNeigh Neighbors< Width >& pNeighbors = neighbors[d]; // Check that we actuall have a center node if( !pNeighbors.neighbors[LeftRadius][LeftRadius][LeftRadius] ) return false; - + // Get the indices of the child node that would contain the point (and its antipode) int cx , cy , cz; Cube::FactorCornerIndex( cIdx , cx , cy , cz ); @@ -1038,7 +1048,7 @@ void OctNode< NodeData >::ConstNeighborKey< LeftRadius , RightRadius >::getNeigh for( int x=-(int)_LeftRadius ; x<=(int)_RightRadius ; x++ ) { int _x = (x+cx) + (_LeftRadius<<1) , px = ( _x>>1 ) - _LeftRadius + LeftRadius , xx = x + _LeftRadius; - if( pNeighbors.neighbors[px][py][pz] && pNeighbors.neighbors[px][py][pz]->children ) + if( pNeighbors.neighbors[px][py][pz] && pNeighbors.neighbors[px][py][pz]->children ) neighbors.neighbors[xx][yy][zz] = pNeighbors.neighbors[px][py][pz]->children + ( cornerIndex | (_x&1) ); else neighbors.neighbors[xx][yy][zz] = NULL; @@ -1124,7 +1134,7 @@ int OctNode< NodeData >::read( FILE* fp , void (*Initializer)( OctNode& ) ) template< class NodeData > int OctNode< NodeData >::width(int maxDepth) const { int d=depth(); - return 1<<(maxDepth-d); + return 1<<(maxDepth-d); } template< class NodeData > void OctNode< NodeData >::centerIndex(int maxDepth,int index[DIMENSION]) const diff --git a/Src/Ply.h b/Src/Ply.h index 699381ff..c45ee354 100644 --- a/Src/Ply.h +++ b/Src/Ply.h @@ -1,33 +1,33 @@ /* Header for PLY polygon files. - + - Greg Turk, March 1994 - + A PLY file contains a single polygonal _object_. - + An object is composed of lists of _elements_. Typical elements are vertices, faces, edges and materials. - + Each type of element for a given object has one or more _properties_ associated with the element type. For instance, a vertex element may have as properties three floating-point values x,y,z and three unsigned chars for red, green and blue. - + --------------------------------------------------------------- - + Copyright (c) 1994 The Board of Trustees of The Leland Stanford - Junior University. All rights reserved. - - Permission to use, copy, modify and distribute this software and its - documentation for any purpose is hereby granted without fee, provided - that the above copyright notice and this permission notice appear in - all copies of this software and that you do not sell the software. - - THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, - EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - + Junior University. All rights reserved. + + Permission to use, copy, modify and distribute this software and its + documentation for any purpose is hereby granted without fee, provided + that the above copyright notice and this permission notice appear in + all copies of this software and that you do not sell the software. + + THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, + EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + */ #ifndef __PLY_H__ @@ -42,22 +42,22 @@ #ifdef __cplusplus extern "C" { #endif - + #include #include #include #include - + #define PLY_ASCII 1 /* ascii PLY file */ #define PLY_BINARY_BE 2 /* binary PLY file, big endian */ #define PLY_BINARY_LE 3 /* binary PLY file, little endian */ #define PLY_BINARY_NATIVE 4 /* binary PLY file, same endianness as current architecture */ - + #define PLY_OKAY 0 /* ply routine worked okay */ #define PLY_ERROR -1 /* error in ply routine */ - + /* scalar data types supported by PLY format */ - + #define PLY_START_TYPE 0 #define PLY_CHAR 1 #define PLY_SHORT 2 @@ -75,26 +75,26 @@ extern "C" { #define PLY_UINT_32 14 #define PLY_FLOAT_32 15 #define PLY_FLOAT_64 16 - + #define PLY_END_TYPE 17 - + #define PLY_SCALAR 0 #define PLY_LIST 1 - + #define PLY_STRIP_COMMENT_HEADER 0 typedef struct PlyProperty { /* description of a property */ - + char *name; /* property name */ int external_type; /* file's data type */ int internal_type; /* program's data type */ int offset; /* offset bytes of prop in a struct */ - + int is_list; /* 1 = list, 0 = scalar */ int count_external; /* file's count type */ int count_internal; /* program's count type */ int count_offset; /* offset byte for list count */ - + } PlyProperty; typedef struct PlyElement { /* description of an element */ @@ -144,7 +144,7 @@ typedef struct PlyFile { /* description of PLY file */ PlyElement *which_elem; /* which element we're currently writing */ PlyOtherElems *other_elems; /* "other" elements from a PLY file */ } PlyFile; - + /* memory allocation */ extern char *my_alloc(); #define myalloc(mem_size) my_alloc((mem_size), __LINE__, __FILE__) @@ -220,6 +220,7 @@ extern int equal_strings(const char *, const char *); } #endif #include "Geometry.h" +#include "Mesh.h" #include template< class Real > int PLYType( void ); @@ -241,7 +242,6 @@ static PlyProperty face_props[] = { _strdup( "vertex_indices" ) , PLY_INT , PLY_INT , offsetof( PlyFace , vertices ) , 1 , PLY_UCHAR, PLY_UCHAR , offsetof(PlyFace,nr_vertices) }, }; - /////////////////// // PlyVertexType // /////////////////// @@ -262,6 +262,12 @@ class PlyVertex PlyVertex( void ) { ; } PlyVertex( Point3D< Real > p ) { point=p; } + PlyVertex( Kazhdan::Point& p ) + { + point.coords[0] = (Real)p.m_position[0]; + point.coords[1] = (Real)p.m_position[1]; + point.coords[2] = (Real)p.m_position[2]; + } PlyVertex operator + ( PlyVertex p ) const { return PlyVertex( point+p.point ); } PlyVertex operator - ( PlyVertex p ) const { return PlyVertex( point-p.point ); } template< class _Real > PlyVertex operator * ( _Real s ) const { return PlyVertex( point*s ); } @@ -300,6 +306,13 @@ class PlyValueVertex PlyValueVertex( void ) : value( Real(0) ) { ; } PlyValueVertex( Point3D< Real > p , Real v ) : point(p) , value(v) { ; } + PlyValueVertex( Kazhdan::Point& p ) + { + point.coords[0] = (Real)p.m_position[0]; + point.coords[1] = (Real)p.m_position[1]; + point.coords[2] = (Real)p.m_position[2]; + value = (Real)p.m_density; + } PlyValueVertex operator + ( PlyValueVertex p ) const { return PlyValueVertex( point+p.point , value+p.value ); } PlyValueVertex operator - ( PlyValueVertex p ) const { return PlyValueVertex( point-p.value , value-p.value ); } template< class _Real > PlyValueVertex operator * ( _Real s ) const { return PlyValueVertex( point*s , Real(value*s) ); } @@ -410,7 +423,17 @@ class PlyColorVertex PlyColorVertex( void ) { point.coords[0] = point.coords[1] = point.coords[2] = 0 , color[0] = color[1] = color[2] = 0; } PlyColorVertex( const Point3D& p ) { point=p; } PlyColorVertex( const Point3D< Real >& p , const unsigned char c[3] ) { point = p , color[0] = c[0] , color[1] = c[1] , color[2] = c[2]; } + PlyColorVertex( Kazhdan::Point& p ) + { + point.coords[0] = (Real)p.m_position[0]; + point.coords[1] = (Real)p.m_position[1]; + point.coords[2] = (Real)p.m_position[2]; + color[0] = p.m_color[0]; + color[1] = p.m_color[1]; + color[2] = p.m_color[2]; + } }; + template< class Real , class _Real > PlyColorVertex< Real > operator * ( XForm4x4< _Real > xForm , PlyColorVertex< Real > v ) { return PlyColorVertex< Real >( xForm * v.point , v.color ); } template< class Real > PlyProperty PlyColorVertex< Real >::ReadProperties[]= @@ -480,7 +503,18 @@ class PlyColorAndValueVertex PlyColorAndValueVertex( void ) { point.coords[0] = point.coords[1] = point.coords[2] = (Real)0 , color[0] = color[1] = color[2] = 0 , value = (Real)0; } PlyColorAndValueVertex( const Point3D< Real >& p ) { point=p; } PlyColorAndValueVertex( const Point3D< Real >& p , const unsigned char c[3] , Real v) { point = p , color[0] = c[0] , color[1] = c[1] , color[2] = c[2] , value = v; } + PlyColorAndValueVertex( Kazhdan::Point& p ) + { + point.coords[0] = (Real)p.m_position[0]; + point.coords[1] = (Real)p.m_position[1]; + point.coords[2] = (Real)p.m_position[2]; + color[0] = p.m_color[0]; + color[1] = p.m_color[1]; + color[2] = p.m_color[2]; + value = (Real)p.m_density; + } }; + template< class Real , class _Real > PlyColorAndValueVertex< Real > operator * ( XForm4x4< _Real > xForm , PlyColorAndValueVertex< Real > v ) { return PlyColorAndValueVertex< Real >( xForm * v.point , v.color , v.value ); } template< class Real > PlyProperty PlyColorAndValueVertex< Real >::ReadProperties[]= { @@ -507,10 +541,10 @@ template< class Real > PlyProperty PlyColorAndValueVertex< Real >::WriteProperti }; template< class Vertex , class Real > -int PlyWritePolygons( char* fileName , CoredMeshData< Vertex >* mesh , int file_type , const Point3D< float >& translate , float scale , char** comments=NULL , int commentNum=0 , XForm4x4< Real > xForm=XForm4x4< Real >::Identity() ); +int PlyWritePolygons( char* fileName , Kazhdan::Mesh& mesh , int file_type , const Point3D< float >& translate , float scale , char** comments=NULL , int commentNum=0 , XForm4x4< Real > xForm=XForm4x4< Real >::Identity() ); template< class Vertex , class Real > -int PlyWritePolygons( char* fileName , CoredMeshData< Vertex >* mesh , int file_type , char** comments=NULL , int commentNum=0 , XForm4x4< Real > xForm=XForm4x4< Real >::Identity() ); +int PlyWritePolygons( char* fileName , Kazhdan::Mesh& mesh, int file_type , char** comments=NULL , int commentNum=0 , XForm4x4< Real > xForm=XForm4x4< Real >::Identity() ); inline bool PlyReadHeader( char* fileName , PlyProperty* properties , int propertyNum , bool* readFlags , int& file_type ) { @@ -550,12 +584,12 @@ inline bool PlyReadHeader( char* fileName , PlyProperty* properties , int proper for( int i=0 ; inum_obj_info ; i++ ) free( ply->obj_info[i] ); free( ply->obj_info ); ply_free_other_elements( ply->other_elems ); - + for( int i=0 ; ielems[i]->name ); @@ -586,8 +620,8 @@ inline bool PlyReadHeader( char* fileName , PlyProperty* properties , int proper for( int i=0 ; inum_obj_info ; i++ ) free( ply->obj_info[i] ); free( ply->obj_info ); ply_free_other_elements(ply->other_elems); - - + + for( int i=0 ; inum_obj_info;i++){free(ply->obj_info[i]);} free(ply->obj_info); ply_free_other_elements (ply->other_elems); - + for(i=0;ielems[i]->name); free(ply->elems[i]->store_prop); @@ -778,8 +812,8 @@ int PlyReadPolygons(char* fileName, for(i=0;inum_obj_info;i++){free(ply->obj_info[i]);} free(ply->obj_info); ply_free_other_elements (ply->other_elems); - - + + for(i=0;i -int PlyWritePolygons( char* fileName , CoredMeshData< Vertex >* mesh , int file_type , const Point3D& translate , float scale , char** comments , int commentNum , XForm4x4< Real > xForm ) +int PlyWritePolygons( char* fileName , Kazhdan::Mesh& mesh, int file_type , const Point3D& translate , float scale , char** comments , int commentNum , XForm4x4< Real > xForm ) { int i; - int nr_vertices=int(mesh->outOfCorePointCount()+mesh->inCorePoints.size()); - int nr_faces=mesh->polygonCount(); + int nr_vertices=mesh.pointCount(); + int nr_faces=mesh.polygonCount(); float version; const char *elem_names[] = { "vertex" , "face" }; PlyFile *ply = ply_open_for_writing( fileName , 2 , elem_names , file_type , &version ); if( !ply ) return 0; - mesh->resetIterator(); - + mesh.resetIterator(); + // // describe vertex and face properties // ply_element_count( ply , "vertex" , nr_vertices ); for( int i=0 ; iinCorePoints.size() ) ; i++ ) + for( i=0; iinCorePoints[i] * scale + translate ); - ply_put_element(ply, (void *) &vertex); - } - for( i=0; ioutOfCorePointCount() ; i++ ) - { - Vertex vertex; - mesh->nextOutOfCorePoint( vertex ); + Kazhdan::Point p; + mesh.nextPoint(p); + Vertex vertex(p); vertex = xForm * ( vertex * scale +translate ); - ply_put_element(ply, (void *) &vertex); + ply_put_element(ply, (void *) &vertex); } // for, write vertices - + // write faces - std::vector< CoredVertexIndex > polygon; + Kazhdan::Polygon polygon; ply_put_element_setup( ply , "face" ); for( i=0 ; i* mesh , int file_ // create and fill a struct that the ply code can handle // PlyFace ply_face; - mesh->nextPolygon( polygon ); + mesh.nextPolygon( polygon ); ply_face.nr_vertices = int( polygon.size() ); ply_face.vertices = new int[ polygon.size() ]; for( int i=0 ; iinCorePoints.size() ); + ply_face.vertices[i] = polygon[i]; ply_put_element( ply, (void *) &ply_face ); delete[] ply_face.vertices; } // for, write faces - + ply_close( ply ); return 1; } template< class Vertex , class Real > -int PlyWritePolygons( char* fileName , CoredMeshData< Vertex >* mesh , int file_type , char** comments , int commentNum , XForm4x4< Real > xForm ) +int PlyWritePolygons( char* fileName , Kazhdan::Mesh& mesh, int file_type , char** comments , int commentNum , XForm4x4< Real > xForm ) { int i; - int nr_vertices=int(mesh->outOfCorePointCount()+mesh->inCorePoints.size()); - int nr_faces=mesh->polygonCount(); + int nr_vertices=int(mesh.pointCount()); + int nr_faces=mesh.polygonCount(); float version; const char *elem_names[] = { "vertex" , "face" }; PlyFile *ply = ply_open_for_writing( fileName , 2 , elem_names , file_type , &version ); if( !ply ) return 0; - mesh->resetIterator(); - + mesh.resetIterator(); + // // describe vertex and face properties // ply_element_count( ply , "vertex" , nr_vertices ); for( int i=0 ; iinCorePoints.size() ) ; i++ ) - { - Vertex vertex = xForm * mesh->inCorePoints[i]; - ply_put_element(ply, (void *) &vertex); - } - for( i=0; ioutOfCorePointCount() ; i++ ) + for( i=0; inextOutOfCorePoint( vertex ); + Kazhdan::Point p; + mesh.nextPoint(p); + Vertex vertex(p); vertex = xForm * ( vertex ); - ply_put_element(ply, (void *) &vertex); + ply_put_element(ply, (void *) &vertex); } // for, write vertices - + // write faces - std::vector< CoredVertexIndex > polygon; + Kazhdan::Polygon polygon; ply_put_element_setup( ply , "face" ); for( i=0 ; i* mesh , int file_ // create and fill a struct that the ply code can handle // PlyFace ply_face; - mesh->nextPolygon( polygon ); + mesh.nextPolygon(polygon); ply_face.nr_vertices = int( polygon.size() ); ply_face.vertices = new int[ polygon.size() ]; for( int i=0 ; iinCorePoints.size() ); + ply_face.vertices[i] = polygon[i]; ply_put_element( ply, (void *) &ply_face ); delete[] ply_face.vertices; } // for, write faces - + ply_close( ply ); return 1; } diff --git a/Src/PlyFile.cpp b/Src/PlyFile.cpp index 9d3f37c9..dae72f15 100644 --- a/Src/PlyFile.cpp +++ b/Src/PlyFile.cpp @@ -1,35 +1,35 @@ /* The interface routines for reading and writing PLY polygon files. - + Greg Turk, February 1994 - + --------------------------------------------------------------- - + A PLY file contains a single polygonal _object_. - + An object is composed of lists of _elements_. Typical elements are vertices, faces, edges and materials. - + Each type of element for a given object has one or more _properties_ associated with the element type. For instance, a vertex element may have as properties the floating-point values x,y,z and the three unsigned chars representing red, green and blue. - + --------------------------------------------------------------- - + Copyright (c) 1994 The Board of Trustees of The Leland Stanford - Junior University. All rights reserved. - - Permission to use, copy, modify and distribute this software and its - documentation for any purpose is hereby granted without fee, provided - that the above copyright notice and this permission notice appear in - all copies of this software and that you do not sell the software. - - THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, - EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY - WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. - + Junior University. All rights reserved. + + Permission to use, copy, modify and distribute this software and its + documentation for any purpose is hereby granted without fee, provided + that the above copyright notice and this permission notice appear in + all copies of this software and that you do not sell the software. + + THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, + EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY + WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. + */ #include @@ -130,24 +130,24 @@ void add_obj_info(PlyFile *, char *); void copy_property(PlyProperty *, PlyProperty *); /* store a value into where a pointer and a type specify */ -void store_item(char *, int, int, unsigned int, double); +void store_item(void *, int, int, unsigned int, double); /* return the value of a stored item */ void get_stored_item( void *, int, int *, unsigned int *, double *); /* return the value stored in an item, given ptr to it and its type */ -double get_item_value(char *, int); +double get_item_value(void *, int); /* get binary or ascii item and store it according to ptr and type */ void get_ascii_item(char *, int, int *, unsigned int *, double *); void get_binary_item(FILE *, int, int, int *, unsigned int *, double *); /* get a bunch of elements from a file */ -void ascii_get_element(PlyFile *, char *); -void binary_get_element(PlyFile *, char *); +void ascii_get_element(PlyFile *, void *); +void binary_get_element(PlyFile *, void *); /* memory allocation */ -char *my_alloc(int, int, const char *); +void *my_alloc(int, int, const char *); /* byte ordering */ void get_native_binary_type(); @@ -168,7 +168,7 @@ Given a file pointer, get ready to write PLY data to the file. nelems - number of elements in object elem_names - list of element names file_type - file type, either ascii or binary - + Exit: returns a pointer to a PlyFile, used to refer to this file, or NULL if error ******************************************************************************/ @@ -183,18 +183,18 @@ PlyFile *ply_write( int i; PlyFile *plyfile; PlyElement *elem; - + /* check for NULL file pointer */ if (fp == NULL) return (NULL); - + if (native_binary_type == -1) get_native_binary_type(); if (!types_checked) check_types(); - + /* create a record for this object */ - + plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); if (file_type == PLY_BINARY_NATIVE) plyfile->file_type = native_binary_type; @@ -206,9 +206,9 @@ PlyFile *ply_write( plyfile->version = 1.0; plyfile->fp = fp; plyfile->other_elems = NULL; - + /* tuck aside the names of the elements */ - + plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *) * nelems); for (i = 0; i < nelems; i++) { elem = (PlyElement *) myalloc (sizeof (PlyElement)); @@ -217,7 +217,7 @@ PlyFile *ply_write( elem->num = 0; elem->nprops = 0; } - + /* return pointer to the file descriptor */ return (plyfile); } @@ -231,7 +231,7 @@ Open a polygon file for writing. nelems - number of elements in object elem_names - list of element names file_type - file type, either ascii or binary - + Exit: version - version number of PLY file returns a file identifier, used to refer to this file, or NULL if error @@ -248,32 +248,32 @@ PlyFile *ply_open_for_writing( PlyFile *plyfile; char *name; FILE *fp; - + /* tack on the extension .ply, if necessary */ - + name = (char *) myalloc (int(sizeof (char) * (strlen (filename)) + 5)); strcpy (name, filename); if (strlen (name) < 4 || strcmp (name + strlen (name) - 4, ".ply") != 0) strcat (name, ".ply"); - + /* open the file for writing */ - + fp = fopen (name, "wb"); free(name); if (fp == NULL) { return (NULL); } - + /* create the actual PlyFile structure */ - + plyfile = ply_write (fp, nelems, elem_names, file_type); if (plyfile == NULL) return (NULL); - + /* say what PLY file version number we're writing */ *version = plyfile->version; - + /* return pointer to the file descriptor */ return (plyfile); } @@ -302,22 +302,22 @@ void ply_describe_element( int i; PlyElement *elem; PlyProperty *prop; - + /* look for appropriate element */ elem = find_element (plyfile, elem_name); if (elem == NULL) { fprintf(stderr,"ply_describe_element: can't find element '%s'\n",elem_name); exit (-1); } - + elem->num = nelems; - + /* copy the list of properties */ - + elem->nprops = nprops; elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * nprops); elem->store_prop = (char *) myalloc (sizeof (char) * nprops); - + for (i = 0; i < nprops; i++) { prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); elem->props[i] = prop; @@ -344,7 +344,7 @@ void ply_describe_property( { PlyElement *elem; PlyProperty *elem_prop; - + /* look for appropriate element */ elem = find_element (plyfile, elem_name); if (elem == NULL) { @@ -352,9 +352,9 @@ void ply_describe_property( elem_name); return; } - + /* create room for new property */ - + if (elem->nprops == 0) { elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); elem->store_prop = (char *) myalloc (sizeof (char)); @@ -367,9 +367,9 @@ void ply_describe_property( elem->store_prop = (char *) realloc (elem->store_prop, sizeof (char) * elem->nprops); } - + /* copy the new property */ - + elem_prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); elem->props[elem->nprops - 1] = elem_prop; elem->store_prop[elem->nprops - 1] = NAMED_PROP; @@ -391,7 +391,7 @@ void ply_describe_other_properties( int i; PlyElement *elem; PlyProperty *prop; - + /* look for appropriate element */ elem = find_element (plyfile, other->name); if (elem == NULL) { @@ -399,9 +399,9 @@ void ply_describe_other_properties( other->name); return; } - + /* create room for other properties */ - + if (elem->nprops == 0) { elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *) * other->nprops); @@ -416,9 +416,9 @@ void ply_describe_other_properties( elem->store_prop = (char *) realloc (elem->store_prop, sizeof (char) * newsize); } - + /* copy the other properties */ - + for (i = 0; i < other->nprops; i++) { prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); copy_property (prop, other->props[i]); @@ -426,7 +426,7 @@ void ply_describe_other_properties( elem->store_prop[elem->nprops] = OTHER_PROP; elem->nprops++; } - + /* save other info about other properties */ elem->other_size = other->size; elem->other_offset = offset; @@ -449,14 +449,14 @@ void ply_element_count( ) { PlyElement *elem; - + /* look for appropriate element */ elem = find_element (plyfile, elem_name); if (elem == NULL) { fprintf(stderr,"ply_element_count: can't find element '%s'\n",elem_name); exit (-1); } - + elem->num = nelems; } @@ -475,9 +475,9 @@ void ply_header_complete(PlyFile *plyfile) FILE *fp = plyfile->fp; PlyElement *elem; PlyProperty *prop; - + fprintf (fp, "ply\n"); - + switch (plyfile->file_type) { case PLY_ASCII: fprintf (fp, "format ascii 1.0\n"); @@ -493,24 +493,24 @@ void ply_header_complete(PlyFile *plyfile) plyfile->file_type); exit (-1); } - + /* write out the comments */ - + for (i = 0; i < plyfile->num_comments; i++) fprintf (fp, "comment %s\n", plyfile->comments[i]); - + /* write out object information */ - + for (i = 0; i < plyfile->num_obj_info; i++) fprintf (fp, "obj_info %s\n", plyfile->obj_info[i]); - + /* write out information about each element */ - + for (i = 0; i < plyfile->nelems; i++) { - + elem = plyfile->elems[i]; fprintf (fp, "element %s %d\n", elem->name, elem->num); - + /* write out each property */ for (j = 0; j < elem->nprops; j++) { prop = elem->props[j]; @@ -528,7 +528,7 @@ void ply_header_complete(PlyFile *plyfile) } } } - + fprintf (fp, "end_header\n"); } @@ -545,13 +545,13 @@ before a call to the routine ply_put_element(). void ply_put_element_setup(PlyFile *plyfile, const char *elem_name) { PlyElement *elem; - + elem = find_element (plyfile, elem_name); if (elem == NULL) { fprintf(stderr, "ply_elements_setup: can't find element '%s'\n", elem_name); exit (-1); } - + plyfile->which_elem = elem; } @@ -572,93 +572,93 @@ void ply_put_element(PlyFile *plyfile, void *elem_ptr) FILE *fp = plyfile->fp; PlyElement *elem; PlyProperty *prop; - char *elem_data,*item; - char **item_ptr; + void *elem_data,*item; + void *item_ptr; int list_count; int item_size; int int_val; unsigned int uint_val; double double_val; - char **other_ptr; - + void *other_ptr; + elem = plyfile->which_elem; - elem_data = (char *)elem_ptr; - other_ptr = (char **) (((char *) elem_ptr) + elem->other_offset); - + elem_data = elem_ptr; + other_ptr = reinterpret_cast(elem_ptr) + elem->other_offset; + /* write out either to an ascii or binary file */ - + if (plyfile->file_type == PLY_ASCII) { - + /* write an ascii file */ - + /* write out each property of the element */ for (j = 0; j < elem->nprops; j++) { prop = elem->props[j]; if (elem->store_prop[j] == OTHER_PROP) - elem_data = *other_ptr; + memcpy(&elem_data, other_ptr, sizeof(void *)); else - elem_data = (char *)elem_ptr; + memcpy(&elem_data, &elem_ptr, sizeof(void *)); if (prop->is_list) { - item = elem_data + prop->count_offset; - get_stored_item ((void *) item, prop->count_internal, + item = reinterpret_cast(elem_data) + prop->count_offset; + get_stored_item (item, prop->count_internal, &int_val, &uint_val, &double_val); write_ascii_item (fp, int_val, uint_val, double_val, prop->count_external); list_count = uint_val; - item_ptr = (char **) (elem_data + prop->offset); - item = item_ptr[0]; + item_ptr = reinterpret_cast(elem_data) + prop->offset; + memcpy(&item, item_ptr, sizeof(void *)); item_size = ply_type_size[prop->internal_type]; for (k = 0; k < list_count; k++) { - get_stored_item ((void *) item, prop->internal_type, + get_stored_item (item, prop->internal_type, &int_val, &uint_val, &double_val); write_ascii_item (fp, int_val, uint_val, double_val, prop->external_type); - item += item_size; + item = reinterpret_cast(item) + item_size; } } else { - item = elem_data + prop->offset; + item = reinterpret_cast(elem_data) + prop->offset; get_stored_item ((void *) item, prop->internal_type, &int_val, &uint_val, &double_val); write_ascii_item (fp, int_val, uint_val, double_val, prop->external_type); } } - + fprintf (fp, "\n"); } else { - + /* write a binary file */ - + /* write out each property of the element */ for (j = 0; j < elem->nprops; j++) { prop = elem->props[j]; if (elem->store_prop[j] == OTHER_PROP) - elem_data = *other_ptr; + elem_data = other_ptr; else elem_data = (char *)elem_ptr; if (prop->is_list) { - item = elem_data + prop->count_offset; + item = reinterpret_cast(elem_data) + prop->count_offset; item_size = ply_type_size[prop->count_internal]; get_stored_item ((void *) item, prop->count_internal, &int_val, &uint_val, &double_val); write_binary_item (fp, plyfile->file_type, int_val, uint_val, double_val, prop->count_external); list_count = uint_val; - item_ptr = (char **) (elem_data + prop->offset); - item = item_ptr[0]; + item_ptr = reinterpret_cast(elem_data) + prop->offset; + memcpy(&item, item_ptr, sizeof(void *)); item_size = ply_type_size[prop->internal_type]; for (k = 0; k < list_count; k++) { get_stored_item ((void *) item, prop->internal_type, &int_val, &uint_val, &double_val); write_binary_item (fp, plyfile->file_type, int_val, uint_val, double_val, prop->external_type); - item += item_size; + item = reinterpret_cast(item) + item_size; } } else { - item = elem_data + prop->offset; + item = reinterpret_cast(elem_data) + prop->offset; item_size = ply_type_size[prop->internal_type]; get_stored_item ((void *) item, prop->internal_type, &int_val, &uint_val, &double_val); @@ -666,7 +666,7 @@ void ply_put_element(PlyFile *plyfile, void *elem_ptr) double_val, prop->external_type); } } - + } } @@ -678,7 +678,7 @@ Specify a comment that will be written in the header. plyfile - file identifier comment - the comment to be written ******************************************************************************/ - + void ply_put_comment(PlyFile *plyfile, char *comment) { /* (re)allocate space for new comment */ @@ -687,22 +687,22 @@ Specify a comment that will be written in the header. else plyfile->comments = (char **) realloc (plyfile->comments, sizeof (char *) * (plyfile->num_comments + 1)); - + /* add comment to list */ plyfile->comments[plyfile->num_comments] = _strdup (comment); plyfile->num_comments++; } - - + + /****************************************************************************** Specify a piece of object information (arbitrary text) that will be written in the header. - + Entry: plyfile - file identifier obj_info - the text information to be written ******************************************************************************/ - + void ply_put_obj_info(PlyFile *plyfile, char *obj_info) { /* (re)allocate space for new info */ @@ -711,36 +711,36 @@ Specify a comment that will be written in the header. else plyfile->obj_info = (char **) realloc (plyfile->obj_info, sizeof (char *) * (plyfile->num_obj_info + 1)); - + /* add info to list */ plyfile->obj_info[plyfile->num_obj_info] = _strdup (obj_info); plyfile->num_obj_info++; } - - - - - - - + + + + + + + /*************/ /* Reading */ /*************/ - - - + + + /****************************************************************************** Given a file pointer, get ready to read PLY data from the file. - + Entry: fp - the given file pointer - + Exit: nelems - number of elements in object elem_names - list of element names returns a pointer to a PlyFile, used to refer to this file, or NULL if error ******************************************************************************/ - + PlyFile *ply_read(FILE *fp, int *nelems, char ***elem_names) { int i,j; @@ -753,13 +753,13 @@ Specify a comment that will be written in the header. /* check for NULL file pointer */ if (fp == NULL) return (NULL); - + if (native_binary_type == -1) get_native_binary_type(); if (!types_checked) check_types(); /* create record for this object */ - + plyfile = (PlyFile *) myalloc (sizeof (PlyFile)); plyfile->nelems = 0; plyfile->comments = NULL; @@ -768,9 +768,9 @@ Specify a comment that will be written in the header. plyfile->num_obj_info = 0; plyfile->fp = fp; plyfile->other_elems = NULL; - + /* read and parse the file's header */ - + words = get_words (plyfile->fp, &nwords, &orig_line); if (!words || !equal_strings (words[0], "ply")) { @@ -780,7 +780,7 @@ Specify a comment that will be written in the header. } while (words) { /* parse words */ - + if (equal_strings (words[0], "format")) { if (nwords != 3) { free(words); @@ -810,16 +810,16 @@ Specify a comment that will be written in the header. free(words); break; } - + /* free up words space */ free (words); - + words = get_words (plyfile->fp, &nwords, &orig_line); } - + /* create tags for each property of each element, to be used */ /* later to say whether or not to store each property for the user */ - + for (i = 0; i < plyfile->nelems; i++) { elem = plyfile->elems[i]; elem->store_prop = (char *) myalloc (sizeof (char) * elem->nprops); @@ -827,18 +827,18 @@ Specify a comment that will be written in the header. elem->store_prop[j] = DONT_STORE_PROP; elem->other_offset = NO_OTHER_PROPS; /* no "other" props by default */ } - + /* set return values about the elements */ - + elist = (char **) myalloc (sizeof (char *) * plyfile->nelems); for (i = 0; i < plyfile->nelems; i++) elist[i] = _strdup (plyfile->elems[i]->name); - + *elem_names = elist; *nelems = plyfile->nelems; - + /* return a pointer to the file's information */ - + return (plyfile); } @@ -848,7 +848,7 @@ Open a polygon file for reading. Entry: filename - name of file to read from - + Exit: nelems - number of elements in object elem_names - list of element names @@ -856,7 +856,7 @@ Open a polygon file for reading. version - version number of PLY file returns a file identifier, used to refer to this file, or NULL if error ******************************************************************************/ - + PlyFile *ply_open_for_reading( char *filename, int *nelems, @@ -868,50 +868,50 @@ Open a polygon file for reading. FILE *fp; PlyFile *plyfile; char *name; - + /* tack on the extension .ply, if necessary */ - + name = (char *) myalloc (int(sizeof (char) * (strlen (filename) + 5))); strcpy (name, filename); if (strlen (name) < 4 || strcmp (name + strlen (name) - 4, ".ply") != 0) strcat (name, ".ply"); - + /* open the file for reading */ - + fp = fopen (name, "rb"); free(name); if (fp == NULL) return (NULL); - + /* create the PlyFile data structure */ - + plyfile = ply_read (fp, nelems, elem_names); - + /* determine the file type and version */ - + *file_type = plyfile->file_type; *version = plyfile->version; - + /* return a pointer to the file's information */ - + return (plyfile); } - - + + /****************************************************************************** Get information about a particular element. - + Entry: plyfile - file identifier elem_name - name of element to get information about - + Exit: nelems - number of elements of this type in the file nprops - number of properties returns a list of properties, or NULL if the file doesn't contain that elem ******************************************************************************/ - + PlyProperty **ply_get_element_description( PlyFile *plyfile, char *elem_name, @@ -923,15 +923,15 @@ Open a polygon file for reading. PlyElement *elem; PlyProperty *prop; PlyProperty **prop_list; - + /* find information about the element */ elem = find_element (plyfile, elem_name); if (elem == NULL) return (NULL); - + *nelems = elem->num; *nprops = elem->nprops; - + /* make a copy of the element's property list */ prop_list = (PlyProperty **) myalloc (sizeof (PlyProperty *) * elem->nprops); for (i = 0; i < elem->nprops; i++) { @@ -939,23 +939,23 @@ Open a polygon file for reading. copy_property (prop, elem->props[i]); prop_list[i] = prop; } - + /* return this duplicate property list */ return (prop_list); } - - + + /****************************************************************************** Specify which properties of an element are to be returned. This should be called before a call to the routine ply_get_element(). - + Entry: plyfile - file identifier elem_name - which element we're talking about nprops - number of properties prop_list - list of properties ******************************************************************************/ - + void ply_get_element_setup( PlyFile *plyfile, char *elem_name, @@ -967,14 +967,14 @@ Open a polygon file for reading. PlyElement *elem; PlyProperty *prop; int index; - + /* find information about the element */ elem = find_element (plyfile, elem_name); plyfile->which_elem = elem; - + /* deposit the property information into the element's description */ for (i = 0; i < nprops; i++) { - + /* look for actual property */ prop = find_property (elem, prop_list[i].name, &index); if (prop == NULL) { @@ -982,31 +982,31 @@ Open a polygon file for reading. prop_list[i].name, elem_name); continue; } - + /* store its description */ prop->internal_type = prop_list[i].internal_type; prop->offset = prop_list[i].offset; prop->count_internal = prop_list[i].count_internal; prop->count_offset = prop_list[i].count_offset; - + /* specify that the user wants this property */ elem->store_prop[index] = STORE_PROP; } } - - + + /****************************************************************************** Specify a property of an element that is to be returned. This should be called (usually multiple times) before a call to the routine ply_get_element(). This routine should be used in preference to the less flexible old routine called ply_get_element_setup(). - + Entry: plyfile - file identifier elem_name - which element we're talking about prop - property to add to those that will be returned ******************************************************************************/ - + int ply_get_property( PlyFile *plyfile, char *elem_name, @@ -1016,13 +1016,13 @@ Open a polygon file for reading. PlyElement *elem; PlyProperty *prop_ptr; int index; - + /* find information about the element */ elem = find_element (plyfile, elem_name); plyfile->which_elem = elem; - + /* deposit the property information into the element's description */ - + prop_ptr = find_property (elem, prop->name, &index); if (prop_ptr == NULL) { // fprintf (stderr, "Warning: Can't find property '%s' in element '%s'\n", @@ -1034,117 +1034,117 @@ Open a polygon file for reading. prop_ptr->offset = prop->offset; prop_ptr->count_internal = prop->count_internal; prop_ptr->count_offset = prop->count_offset; - + /* specify that the user wants this property */ elem->store_prop[index] = STORE_PROP; return 1; } - - + + /****************************************************************************** Read one element from the file. This routine assumes that we're reading the type of element specified in the last call to the routine ply_get_element_setup(). - + Entry: plyfile - file identifier elem_ptr - pointer to location where the element information should be put ******************************************************************************/ - + void ply_get_element(PlyFile *plyfile, void *elem_ptr) { if (plyfile->file_type == PLY_ASCII) - ascii_get_element (plyfile, (char *) elem_ptr); + ascii_get_element (plyfile, elem_ptr); else - binary_get_element (plyfile, (char *) elem_ptr); + binary_get_element (plyfile, elem_ptr); } - - + + /****************************************************************************** Extract the comments from the header information of a PLY file. - + Entry: plyfile - file identifier - + Exit: num_comments - number of comments returned returns a pointer to a list of comments ******************************************************************************/ - + char **ply_get_comments(PlyFile *plyfile, int *num_comments) { *num_comments = plyfile->num_comments; return (plyfile->comments); } - - + + /****************************************************************************** Extract the object information (arbitrary text) from the header information of a PLY file. - + Entry: plyfile - file identifier - + Exit: num_obj_info - number of lines of text information returned returns a pointer to a list of object info lines ******************************************************************************/ - + char **ply_get_obj_info(PlyFile *plyfile, int *num_obj_info) { *num_obj_info = plyfile->num_obj_info; return (plyfile->obj_info); } - - + + /****************************************************************************** Make ready for "other" properties of an element-- those properties that the user has not explicitly asked for, but that are to be stashed away in a special structure to be carried along with the element's other information. - + Entry: plyfile - file identifier elem - element for which we want to save away other properties ******************************************************************************/ - + void setup_other_props(PlyElement *elem) { int i; PlyProperty *prop; int size = 0; int type_size; - + /* Examine each property in decreasing order of size. */ /* We do this so that all data types will be aligned by */ /* word, half-word, or whatever within the structure. */ - + for (type_size = 8; type_size > 0; type_size /= 2) { - + /* add up the space taken by each property, and save this information */ /* away in the property descriptor */ - + for (i = 0; i < elem->nprops; i++) { - + /* don't bother with properties we've been asked to store explicitly */ if (elem->store_prop[i]) continue; - + prop = elem->props[i]; - + /* internal types will be same as external */ prop->internal_type = prop->external_type; prop->count_internal = prop->count_external; - + /* check list case */ if (prop->is_list) { - + /* pointer to list */ if (type_size == sizeof (void *)) { prop->offset = size; size += sizeof (void *); /* always use size of a pointer here */ } - + /* count of number of list elements */ if (type_size == ply_type_size[prop->count_external]) { prop->count_offset = size; @@ -1157,28 +1157,28 @@ Open a polygon file for reading. size += ply_type_size[prop->external_type]; } } - + } - + /* save the size for the other_props structure */ elem->other_size = size; } - - + + /****************************************************************************** Specify that we want the "other" properties of an element to be tucked away within the user's structure. The user needn't be concerned for how these properties are stored. - + Entry: plyfile - file identifier elem_name - name of element that we want to store other_props in offset - offset to where other_props will be stored inside user's structure - + Exit: returns pointer to structure containing description of other_props ******************************************************************************/ - + PlyOtherProp *ply_get_other_properties( PlyFile *plyfile, char *elem_name, @@ -1190,7 +1190,7 @@ Open a polygon file for reading. PlyOtherProp *other; PlyProperty *prop; int nprops; - + /* find information about the element */ elem = find_element (plyfile, elem_name); if (elem == NULL) { @@ -1198,22 +1198,22 @@ Open a polygon file for reading. elem_name); return (NULL); } - + /* remember that this is the "current" element */ plyfile->which_elem = elem; - + /* save the offset to where to store the other_props */ elem->other_offset = offset; - + /* place the appropriate pointers, etc. in the element's property list */ setup_other_props (elem); - + /* create structure for describing other_props */ other = (PlyOtherProp *) myalloc (sizeof (PlyOtherProp)); other->name = _strdup (elem_name); other->size = elem->other_size; other->props = (PlyProperty **) myalloc (sizeof(PlyProperty) * elem->nprops); - + /* save descriptions of each "other" property */ nprops = 0; for (i = 0; i < elem->nprops; i++) { @@ -1225,39 +1225,39 @@ Open a polygon file for reading. nprops++; } other->nprops = nprops; - + /* set other_offset pointer appropriately if there are NO other properties */ if (other->nprops == 0) { elem->other_offset = NO_OTHER_PROPS; } - + /* return structure */ return (other); } - - - - + + + + /*************************/ /* Other Element Stuff */ /*************************/ - - - - + + + + /****************************************************************************** Grab all the data for an element that a user does not want to explicitly read in. - + Entry: plyfile - pointer to file elem_name - name of element whose data is to be read in elem_count - number of instances of this element stored in the file - + Exit: returns pointer to ALL the "other" element data for this PLY file ******************************************************************************/ - + PlyOtherElems *ply_get_other_element ( PlyFile *plyfile, char *elem_name, @@ -1268,7 +1268,7 @@ Open a polygon file for reading. PlyElement *elem; PlyOtherElems *other_elems; OtherElem *other; - + /* look for appropriate element */ elem = find_element (plyfile, elem_name); if (elem == NULL) { @@ -1276,10 +1276,10 @@ Open a polygon file for reading. "ply_get_other_element: can't find element '%s'\n", elem_name); exit (-1); } - + /* create room for the new "other" element, initializing the */ /* other data structure if necessary */ - + if (plyfile->other_elems == NULL) { plyfile->other_elems = (PlyOtherElems *) myalloc (sizeof (PlyOtherElems)); other_elems = plyfile->other_elems; @@ -1294,42 +1294,42 @@ Open a polygon file for reading. other = &(other_elems->other_list[other_elems->num_elems]); other_elems->num_elems++; } - + /* count of element instances in file */ other->elem_count = elem_count; - + /* save name of element */ other->elem_name = _strdup (elem_name); - + /* create a list to hold all the current elements */ other->other_data = (OtherData **) malloc (sizeof (OtherData *) * other->elem_count); - + /* set up for getting elements */ other->other_props = ply_get_other_properties (plyfile, elem_name, offsetof(OtherData,other_props)); - + /* grab all these elements */ for (i = 0; i < other->elem_count; i++) { /* grab and element from the file */ other->other_data[i] = (OtherData *) malloc (sizeof (OtherData)); ply_get_element (plyfile, (void *) other->other_data[i]); } - + /* return pointer to the other elements data */ return (other_elems); } - - + + /****************************************************************************** Pass along a pointer to "other" elements that we want to save in a given PLY file. These other elements were presumably read from another PLY file. - + Entry: plyfile - file pointer in which to store this other element info other_elems - info about other elements that we want to store ******************************************************************************/ - + void ply_describe_other_elements ( PlyFile *plyfile, PlyOtherElems *other_elems @@ -1338,18 +1338,18 @@ Open a polygon file for reading. int i; OtherElem *other; PlyElement *elem; - + /* ignore this call if there is no other element */ if (other_elems == NULL) return; - + /* save pointer to this information */ plyfile->other_elems = other_elems; - + /* describe the other properties of this element */ /* store them in the main element list as elements with only other properties */ - + REALLOCN(plyfile->elems, PlyElement *, plyfile->nelems, plyfile->nelems + other_elems->num_elems); for (i = 0; i < other_elems->num_elems; i++) { @@ -1363,172 +1363,173 @@ Open a polygon file for reading. offsetof(OtherData,other_props)); } } - - + + /****************************************************************************** Write out the "other" elements specified for this PLY file. - + Entry: plyfile - pointer to PLY file to write out other elements for ******************************************************************************/ - + void ply_put_other_elements (PlyFile *plyfile) { int i,j; OtherElem *other; - + /* make sure we have other elements to write */ if (plyfile->other_elems == NULL) return; - + /* write out the data for each "other" element */ - + for (i = 0; i < plyfile->other_elems->num_elems; i++) { - + other = &(plyfile->other_elems->other_list[i]); ply_put_element_setup (plyfile, other->elem_name); - + /* write out each instance of the current element */ for (j = 0; j < other->elem_count; j++) ply_put_element (plyfile, (void *) other->other_data[j]); } } - - + + /****************************************************************************** Free up storage used by an "other" elements data structure. - + (No-op) + Entry: other_elems - data structure to free up ******************************************************************************/ - + void ply_free_other_elements (PlyOtherElems *other_elems) { - other_elems = other_elems; + (void)other_elems; } - - - + + + /*******************/ /* Miscellaneous */ /*******************/ - - - + + + /****************************************************************************** Close a PLY file. - + Entry: plyfile - identifier of file to close ******************************************************************************/ - + void ply_close(PlyFile *plyfile) { fclose (plyfile->fp); - + /* free up memory associated with the PLY file */ free (plyfile); } - - + + /****************************************************************************** Get version number and file type of a PlyFile. - + Entry: ply - pointer to PLY file - + Exit: version - version of the file file_type - PLY_ASCII, PLY_BINARY_BE, or PLY_BINARY_LE ******************************************************************************/ - + void ply_get_info(PlyFile *ply, float *version, int *file_type) { if (ply == NULL) return; - + *version = ply->version; *file_type = ply->file_type; } - - + + /****************************************************************************** Compare two strings. Returns 1 if they are the same, 0 if not. ******************************************************************************/ - + int equal_strings(const char *s1, const char *s2) { - + while (*s1 && *s2) if (*s1++ != *s2++) return (0); - + if (*s1 != *s2) return (0); else return (1); } - - + + /****************************************************************************** Find an element from the element list of a given PLY object. - + Entry: plyfile - file id for PLY file element - name of element we're looking for - + Exit: returns the element, or NULL if not found ******************************************************************************/ - + PlyElement *find_element(PlyFile *plyfile, const char *element) { int i; - + for (i = 0; i < plyfile->nelems; i++) if (equal_strings (element, plyfile->elems[i]->name)) return (plyfile->elems[i]); - + return (NULL); } - - + + /****************************************************************************** Find a property in the list of properties of a given element. - + Entry: elem - pointer to element in which we want to find the property prop_name - name of property to find - + Exit: index - index to position in list returns a pointer to the property, or NULL if not found ******************************************************************************/ - + PlyProperty *find_property(PlyElement *elem, const char *prop_name, int *index) { int i; - + for (i = 0; i < elem->nprops; i++) if (equal_strings (prop_name, elem->props[i]->name)) { *index = i; return (elem->props[i]); } - + *index = -1; return (NULL); } - - + + /****************************************************************************** Read an element from an ascii file. - + Entry: plyfile - file identifier elem_ptr - pointer to element ******************************************************************************/ - - void ascii_get_element(PlyFile *plyfile, char *elem_ptr) + + void ascii_get_element(PlyFile *plyfile, void *elem_ptr) { int j,k; PlyElement *elem; @@ -1536,83 +1537,87 @@ Open a polygon file for reading. char **words; int nwords; int which_word; - char *elem_data,*item=NULL; - char *item_ptr; + void *elem_data,*item(nullptr); + void *item_ptr; int item_size; int int_val; unsigned int uint_val; double double_val; int list_count; int store_it; - char **store_array; + void *store_array; char *orig_line; - char *other_data=NULL; + void *other_data(nullptr); int other_flag; - + /* the kind of element we're reading currently */ elem = plyfile->which_elem; - + /* do we need to setup for other_props? */ - + if (elem->other_offset != NO_OTHER_PROPS) { - char **ptr; + void *ptr; other_flag = 1; /* make room for other_props */ - other_data = (char *) myalloc (elem->other_size); + other_data = myalloc (elem->other_size); /* store pointer in user's structure to the other_props */ - ptr = (char **) (elem_ptr + elem->other_offset); - *ptr = other_data; + ptr = reinterpret_cast(elem_ptr) + elem->other_offset; + memcpy(ptr, &other_data, sizeof(other_data)); } else other_flag = 0; - + /* read in the element */ - + words = get_words (plyfile->fp, &nwords, &orig_line); if (words == NULL) { fprintf (stderr, "ply_get_element: unexpected end of file\n"); exit (-1); } - + which_word = 0; - + for (j = 0; j < elem->nprops; j++) { - + prop = elem->props[j]; store_it = (elem->store_prop[j] | other_flag); - + /* store either in the user's structure or in other_props */ if (elem->store_prop[j]) elem_data = elem_ptr; else elem_data = other_data; - + if (prop->is_list) { /* a list */ - + /* get and store the number of items in the list */ get_ascii_item (words[which_word++], prop->count_external, &int_val, &uint_val, &double_val); if (store_it) { - item = elem_data + prop->count_offset; + item = reinterpret_cast(elem_data) + + prop->count_offset; store_item(item, prop->count_internal, int_val, uint_val, double_val); } - + /* allocate space for an array of items and store a ptr to the array */ list_count = int_val; item_size = ply_type_size[prop->internal_type]; - store_array = (char **) (elem_data + prop->offset); - + store_array = reinterpret_cast(elem_data) + prop->offset; + if (list_count == 0) { if (store_it) - *store_array = NULL; + { + void *empty(nullptr); + memcpy(store_array, &empty, sizeof(empty)); + } } else { if (store_it) { - item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); + item_ptr = myalloc (sizeof (char) * item_size * list_count); item = item_ptr; - *store_array = item_ptr; + memcpy(store_array, &item_ptr, sizeof(item_ptr)); } - + /* read items and store them into the array */ for (k = 0; k < list_count; k++) { get_ascii_item (words[which_word++], prop->external_type, @@ -1620,23 +1625,24 @@ Open a polygon file for reading. if (store_it) { store_item (item, prop->internal_type, int_val, uint_val, double_val); - item += item_size; + item = reinterpret_cast(item) + item_size; } } } - + } else { /* not a list */ get_ascii_item (words[which_word++], prop->external_type, &int_val, &uint_val, &double_val); if (store_it) { - item = elem_data + prop->offset; - store_item (item, prop->internal_type, int_val, uint_val, double_val); + item = reinterpret_cast(elem_data) + prop->offset; + store_item (item, prop->internal_type, int_val, uint_val, + double_val); } } - + } - + free (words); } @@ -1648,80 +1654,84 @@ Read an element from a binary file. plyfile - file identifier elem_ptr - pointer to an element ******************************************************************************/ - - void binary_get_element(PlyFile *plyfile, char *elem_ptr) + + void binary_get_element(PlyFile *plyfile, void *elem_ptr) { int j,k; PlyElement *elem; PlyProperty *prop; FILE *fp = plyfile->fp; - char *elem_data,*item=NULL; - char *item_ptr; + void *elem_data,*item(nullptr); + void *item_ptr; int item_size; int int_val; unsigned int uint_val; double double_val; int list_count; int store_it; - char **store_array; - char *other_data=NULL; + void *store_array; + void *other_data(nullptr); int other_flag; - + /* the kind of element we're reading currently */ elem = plyfile->which_elem; - + /* do we need to setup for other_props? */ - + if (elem->other_offset != NO_OTHER_PROPS) { - char **ptr; + void *ptr; other_flag = 1; /* make room for other_props */ - other_data = (char *) myalloc (elem->other_size); + other_data = myalloc (elem->other_size); /* store pointer in user's structure to the other_props */ - ptr = (char **) (elem_ptr + elem->other_offset); - *ptr = other_data; + ptr = reinterpret_cast(elem_ptr) + elem->other_offset; + memcpy(ptr, &other_data, sizeof(other_data)); } else other_flag = 0; - + /* read in a number of elements */ - + for (j = 0; j < elem->nprops; j++) { - + prop = elem->props[j]; store_it = (elem->store_prop[j] | other_flag); - + /* store either in the user's structure or in other_props */ if (elem->store_prop[j]) elem_data = elem_ptr; else elem_data = other_data; - + if (prop->is_list) { /* a list */ - + /* get and store the number of items in the list */ get_binary_item (fp, plyfile->file_type, prop->count_external, &int_val, &uint_val, &double_val); if (store_it) { - item = elem_data + prop->count_offset; + item = reinterpret_cast(elem_data) + + prop->count_offset; store_item(item, prop->count_internal, int_val, uint_val, double_val); } - + /* allocate space for an array of items and store a ptr to the array */ list_count = int_val; item_size = ply_type_size[prop->internal_type]; - store_array = (char **) (elem_data + prop->offset); + store_array = reinterpret_cast(elem_data) + prop->offset; if (list_count == 0) { if (store_it) - *store_array = NULL; + { + void *empty(nullptr); + memcpy(store_array, &empty, sizeof(empty)); + } } else { if (store_it) { - item_ptr = (char *) myalloc (sizeof (char) * item_size * list_count); + item_ptr = myalloc (sizeof (char) * item_size * list_count); item = item_ptr; - *store_array = item_ptr; + memcpy(store_array, &item_ptr, sizeof(item_ptr)); } - + /* read items and store them into the array */ for (k = 0; k < list_count; k++) { get_binary_item (fp, plyfile->file_type, prop->external_type, @@ -1729,61 +1739,61 @@ Read an element from a binary file. if (store_it) { store_item (item, prop->internal_type, int_val, uint_val, double_val); - item += item_size; + item = reinterpret_cast(item) + item_size; } } } - + } else { /* not a list */ get_binary_item (fp, plyfile->file_type, prop->external_type, &int_val, &uint_val, &double_val); if (store_it) { - item = elem_data + prop->offset; + item = reinterpret_cast(elem_data) + prop->offset; store_item (item, prop->internal_type, int_val, uint_val, double_val); } } - + } } - - + + /****************************************************************************** Write to a file the word that represents a PLY data type. - + Entry: fp - file pointer code - code for type ******************************************************************************/ - + void write_scalar_type (FILE *fp, int code) { /* make sure this is a valid code */ - + if (code <= PLY_START_TYPE || code >= PLY_END_TYPE) { fprintf (stderr, "write_scalar_type: bad data code = %d\n", code); exit (-1); } - + /* write the code to a file */ - + fprintf (fp, "%s", type_names[code]); } - + /****************************************************************************** Reverse the order in an array of bytes. This is the conversion from big endian to little endian and vice versa - + Entry: bytes - array of bytes to reverse (in place) num_bytes - number of bytes in array ******************************************************************************/ - + void swap_bytes(char *bytes, int num_bytes) { int i; char temp; - + for (i=0; i < num_bytes/2; i++) { temp = bytes[i]; @@ -1791,20 +1801,20 @@ Read an element from a binary file. bytes[(num_bytes-1)-i] = temp; } } - + /****************************************************************************** Find out if this machine is big endian or little endian - + Exit: set global variable, native_binary_type = either PLY_BINARY_BE or PLY_BINARY_LE - + ******************************************************************************/ - + void get_native_binary_type() { endian_test_type test; - + test.int_value = 0; test.int_value = 1; if (test.byte_values[0] == 1) @@ -1818,47 +1828,47 @@ Read an element from a binary file. exit(1); } } - + /****************************************************************************** Verify that all the native types are the sizes we need - - + + ******************************************************************************/ - + void check_types() { if ((ply_type_size[PLY_CHAR] != sizeof(char)) || - (ply_type_size[PLY_SHORT] != sizeof(short)) || - (ply_type_size[PLY_INT] != sizeof(int)) || - (ply_type_size[PLY_UCHAR] != sizeof(unsigned char)) || - (ply_type_size[PLY_USHORT] != sizeof(unsigned short)) || - (ply_type_size[PLY_UINT] != sizeof(unsigned int)) || - (ply_type_size[PLY_FLOAT] != sizeof(float)) || + (ply_type_size[PLY_SHORT] != sizeof(short)) || + (ply_type_size[PLY_INT] != sizeof(int)) || + (ply_type_size[PLY_UCHAR] != sizeof(unsigned char)) || + (ply_type_size[PLY_USHORT] != sizeof(unsigned short)) || + (ply_type_size[PLY_UINT] != sizeof(unsigned int)) || + (ply_type_size[PLY_FLOAT] != sizeof(float)) || (ply_type_size[PLY_DOUBLE] != sizeof(double))) { fprintf(stderr, "ply: Type sizes do not match built-in types\n"); fprintf(stderr, "ply: Exiting...\n"); exit(1); } - + types_checked = 1; } - + /****************************************************************************** Get a text line from a file and break it up into words. - + IMPORTANT: The calling routine call "free" on the returned pointer once finished with it. - + Entry: fp - file to read from - + Exit: nwords - number of words returned orig_line - the original line of characters returns a list of words from the line, or NULL if end-of-file ******************************************************************************/ - + char **get_words(FILE *fp, int *nwords, char **orig_line) { #define BIG_STRING 4096 @@ -1869,9 +1879,9 @@ Read an element from a binary file. int num_words = 0; char *ptr,*ptr2; char *result; - + words = (char **) myalloc (sizeof (char *) * max_words); - + /* read in a line */ result = fgets (str, BIG_STRING, fp); if (result == NULL) { @@ -1883,10 +1893,10 @@ Read an element from a binary file. /* convert line-feed and tabs into spaces */ /* (this guarentees that there will be a space before the */ /* null character at the end of the string) */ - + str[BIG_STRING-2] = ' '; str[BIG_STRING-1] = '\0'; - + for (ptr = str, ptr2 = str_copy; *ptr != '\0'; ptr++, ptr2++) { *ptr2 = *ptr; // Added line here to manage carriage returns @@ -1900,54 +1910,54 @@ Read an element from a binary file. break; } } - + /* find the words in the line */ - + ptr = str; while (*ptr != '\0') { - + /* jump over leading spaces */ while (*ptr == ' ') ptr++; - + /* break if we reach the end */ if (*ptr == '\0') break; - + /* save pointer to beginning of word */ if (num_words >= max_words) { max_words += 10; words = (char **) realloc (words, sizeof (char *) * max_words); } words[num_words++] = ptr; - + /* jump over non-spaces */ while (*ptr != ' ') ptr++; - + /* place a null character here to mark the end of the word */ *ptr++ = '\0'; } - + /* return the list of words */ *nwords = num_words; *orig_line = str_copy; return (words); } - - + + /****************************************************************************** Return the value of an item, given a pointer to it and its type. - + Entry: item - pointer to item type - data type that "item" points to - + Exit: returns a double-precision float that contains the value of the item ******************************************************************************/ - - double get_item_value(char *item, int type) + + double get_item_value(void *item, int type) { unsigned char *puchar; char *pchar; @@ -1960,7 +1970,7 @@ Read an element from a binary file. int int_value; unsigned int uint_value; double double_value; - + switch (type) { case PLY_CHAR: case PLY_INT_8: @@ -2007,11 +2017,11 @@ Read an element from a binary file. exit (-1); } } - - + + /****************************************************************************** Write out an item to a file as raw binary bytes. - + Entry: fp - file to write to int_val - integer version of item @@ -2019,7 +2029,7 @@ Read an element from a binary file. double_val - double-precision float version of item type - data type to write out ******************************************************************************/ - + void write_binary_item( FILE *fp, int file_type, @@ -2035,7 +2045,7 @@ Read an element from a binary file. short short_val; float float_val; void *value; - + switch (type) { case PLY_CHAR: case PLY_INT_8: @@ -2079,21 +2089,21 @@ Read an element from a binary file. exit (-1); } - + if ((file_type != native_binary_type) && (ply_type_size[type] > 1)) swap_bytes((char *)value, ply_type_size[type]); - + if (fwrite (value, ply_type_size[type], 1, fp) != 1) { fprintf(stderr, "PLY ERROR: fwrite() failed -- aborting.\n"); exit(1); } } - - + + /****************************************************************************** Write out an item to a file as ascii characters. - + Entry: fp - file to write to int_val - integer version of item @@ -2101,7 +2111,7 @@ Read an element from a binary file. double_val - double-precision float version of item type - data type to write out ******************************************************************************/ - + void write_ascii_item( FILE *fp, int int_val, @@ -2151,104 +2161,75 @@ Read an element from a binary file. exit (-1); } } - - + + /****************************************************************************** Write out an item to a file as ascii characters. - + Entry: fp - file to write to item - pointer to item to write type - data type that "item" points to - + Exit: returns a double-precision float that contains the value of the written item ******************************************************************************/ - - double old_write_ascii_item(FILE *fp, char *item, int type) + template + double writeCast(FILE *fp, void *item, const char *format) + { + T t = *reinterpret_cast(item); + fprintf(fp, format, t); + return static_cast(t); + } + + double old_write_ascii_item(FILE *fp, void *item, int type) { - unsigned char *puchar; - char *pchar; - short int *pshort; - unsigned short int *pushort; - int *pint; - unsigned int *puint; - float *pfloat; - double *pdouble; - int int_value; - unsigned int uint_value; - double double_value; - switch (type) { case PLY_CHAR: case PLY_INT_8: - pchar = (char *) item; - int_value = *pchar; - fprintf (fp, "%d ", int_value); - return ((double) int_value); + return writeCast(fp, item, "%d "); case PLY_UCHAR: case PLY_UINT_8: - puchar = (unsigned char *) item; - int_value = *puchar; - fprintf (fp, "%d ", int_value); - return ((double) int_value); + return writeCast(fp, item, "%d "); case PLY_SHORT: case PLY_INT_16: - pshort = (short int *) item; - int_value = *pshort; - fprintf (fp, "%d ", int_value); - return ((double) int_value); + return writeCast(fp, item, "%d "); case PLY_USHORT: case PLY_UINT_16: - pushort = (unsigned short int *) item; - int_value = *pushort; - fprintf (fp, "%d ", int_value); - return ((double) int_value); + return writeCast(fp, item, "%d "); case PLY_INT: case PLY_INT_32: - pint = (int *) item; - int_value = *pint; - fprintf (fp, "%d ", int_value); - return ((double) int_value); + return writeCast(fp, item, "%d "); case PLY_UINT: case PLY_UINT_32: - puint = (unsigned int *) item; - uint_value = *puint; - fprintf (fp, "%u ", uint_value); - return ((double) uint_value); + return writeCast(fp, item, "%u "); case PLY_FLOAT: case PLY_FLOAT_32: - pfloat = (float *) item; - double_value = *pfloat; - fprintf (fp, "%g ", double_value); - return (double_value); + return writeCast(fp, item, "%g "); case PLY_DOUBLE: case PLY_FLOAT_64: - pdouble = (double *) item; - double_value = *pdouble; - fprintf (fp, "%g ", double_value); - return (double_value); + return writeCast(fp, item, "%g "); default: fprintf (stderr, "old_write_ascii_item: bad type = %d\n", type); exit (-1); } } - - + + /****************************************************************************** Get the value of an item that is in memory, and place the result into an integer, an unsigned integer and a double. - + Entry: ptr - pointer to the item type - data type supposedly in the item - + Exit: int_val - integer value uint_val - unsigned integer value double_val - double-precision floating point value ******************************************************************************/ - + void get_stored_item( void *ptr, int type, @@ -2311,22 +2292,22 @@ Read an element from a binary file. exit (-1); } } - - + + /****************************************************************************** Get the value of an item from a binary file, and place the result into an integer, an unsigned integer and a double. - + Entry: fp - file to get item from type - data type supposedly in the word - + Exit: int_val - integer value uint_val - unsigned integer value double_val - double-precision floating point value ******************************************************************************/ - + void get_binary_item( FILE *fp, int file_type, @@ -2338,19 +2319,19 @@ Read an element from a binary file. { char c[8]; void *ptr; - + ptr = (void *) c; - + if (fread (ptr, ply_type_size[type], 1, fp) != 1) { fprintf(stderr, "PLY ERROR: fread() failed -- aborting.\n"); exit(1); } - - + + if ((file_type != native_binary_type) && (ply_type_size[type] > 1)) swap_bytes((char *)ptr, ply_type_size[type]); - + switch (type) { case PLY_CHAR: case PLY_INT_8: @@ -2405,22 +2386,22 @@ Read an element from a binary file. exit (-1); } } - - + + /****************************************************************************** Extract the value of an item from an ascii word, and place the result into an integer, an unsigned integer and a double. - + Entry: word - word to extract value from type - data type supposedly in the word - + Exit: int_val - integer value uint_val - unsigned integer value double_val - double-precision floating point value ******************************************************************************/ - + void get_ascii_item( char *word, int type, @@ -2444,14 +2425,14 @@ Read an element from a binary file. *uint_val = (unsigned int) *int_val; *double_val = (double) *int_val; break; - + case PLY_UINT: case PLY_UINT_32: *uint_val = strtol (word, (char **) NULL, 10); *int_val = (int) *uint_val; *double_val = (double) *uint_val; break; - + case PLY_FLOAT: case PLY_FLOAT_32: case PLY_DOUBLE: @@ -2460,165 +2441,155 @@ Read an element from a binary file. *int_val = (int) *double_val; *uint_val = (unsigned int) *double_val; break; - + default: fprintf (stderr, "get_ascii_item: bad type = %d\n", type); exit (-1); } } - - + + /****************************************************************************** Store a value into a place being pointed to, guided by a data type. - + Entry: item - place to store value type - data type int_val - integer version of value uint_val - unsigned integer version of value double_val - double version of value - + Exit: item - pointer to stored value ******************************************************************************/ - + + template + void castAssign(void *loc, const T t) + { + *reinterpret_cast(loc) = t; + } + void store_item ( - char *item, + void *item, int type, int int_val, unsigned int uint_val, double double_val ) { - unsigned char *puchar; - short int *pshort; - unsigned short int *pushort; - int *pint; - unsigned int *puint; - float *pfloat; - double *pdouble; - - switch (type) { case PLY_CHAR: case PLY_INT_8: - *item = char(int_val); + castAssign(item, (char)int_val); break; case PLY_UCHAR: case PLY_UINT_8: - puchar = (unsigned char *) item; - *puchar = (unsigned char)(uint_val); + castAssign(item, (unsigned char)uint_val); break; case PLY_SHORT: case PLY_INT_16: - pshort = (short *) item; - *pshort = short(int_val); + castAssign(item, (short)int_val); break; case PLY_USHORT: case PLY_UINT_16: - pushort = (unsigned short *) item; - *pushort = (unsigned short)(uint_val); + castAssign(item, (unsigned short)uint_val); break; case PLY_INT: case PLY_INT_32: - pint = (int *) item; - *pint = int_val; + castAssign(item, int_val); break; case PLY_UINT: case PLY_UINT_32: - puint = (unsigned int *) item; - *puint = uint_val; + castAssign(item, uint_val); break; case PLY_FLOAT: case PLY_FLOAT_32: - pfloat = (float *) item; - *pfloat = (float)double_val; + castAssign(item, (float)double_val); break; case PLY_DOUBLE: case PLY_FLOAT_64: - pdouble = (double *) item; - *pdouble = double_val; + castAssign(item, double_val); break; default: fprintf (stderr, "store_item: bad type = %d\n", type); exit (-1); } } - - + + /****************************************************************************** Add an element to a PLY file descriptor. - + Entry: plyfile - PLY file descriptor words - list of words describing the element nwords - number of words in the list ******************************************************************************/ - + void add_element (PlyFile *plyfile, char **words) { PlyElement *elem; - + /* create the new element */ elem = (PlyElement *) myalloc (sizeof (PlyElement)); elem->name = _strdup (words[1]); elem->num = atoi (words[2]); elem->nprops = 0; - + /* make room for new element in the object's list of elements */ if (plyfile->nelems == 0) plyfile->elems = (PlyElement **) myalloc (sizeof (PlyElement *)); else plyfile->elems = (PlyElement **) realloc (plyfile->elems, sizeof (PlyElement *) * (plyfile->nelems + 1)); - + /* add the new element to the object's list */ plyfile->elems[plyfile->nelems] = elem; plyfile->nelems++; } - - + + /****************************************************************************** Return the type of a property, given the name of the property. - + Entry: name - name of property type - + Exit: returns integer code for property, or 0 if not found ******************************************************************************/ - + int get_prop_type(char *type_name) { int i; - + for (i = PLY_START_TYPE + 1; i < PLY_END_TYPE; i++) if (equal_strings (type_name, type_names[i])) return (i); - + /* if we get here, we didn't find the type */ return (0); } - - + + /****************************************************************************** Add a property to a PLY file descriptor. - + Entry: plyfile - PLY file descriptor words - list of words describing the property nwords - number of words in the list ******************************************************************************/ - + void add_property (PlyFile *plyfile, char **words) { PlyProperty *prop; PlyElement *elem; - + /* create the new property */ - + prop = (PlyProperty *) myalloc (sizeof (PlyProperty)); - + if (equal_strings (words[1], "list")) { /* is a list */ prop->count_external = get_prop_type (words[2]); prop->external_type = get_prop_type (words[3]); @@ -2630,101 +2601,101 @@ Read an element from a binary file. prop->name = _strdup (words[2]); prop->is_list = 0; } - + /* add this property to the list of properties of the current element */ - + elem = plyfile->elems[plyfile->nelems - 1]; - + if (elem->nprops == 0) elem->props = (PlyProperty **) myalloc (sizeof (PlyProperty *)); else elem->props = (PlyProperty **) realloc (elem->props, sizeof (PlyProperty *) * (elem->nprops + 1)); - + elem->props[elem->nprops] = prop; elem->nprops++; } - - + + /****************************************************************************** Add a comment to a PLY file descriptor. - + Entry: plyfile - PLY file descriptor line - line containing comment ******************************************************************************/ - + void add_comment (PlyFile *plyfile, char *line) { int i; - + /* skip over "comment" and leading spaces and tabs */ i = 7; while (line[i] == ' ' || line[i] == '\t') i++; - + ply_put_comment (plyfile, &line[i]); } - - + + /****************************************************************************** Add a some object information to a PLY file descriptor. - + Entry: plyfile - PLY file descriptor line - line containing text info ******************************************************************************/ - + void add_obj_info (PlyFile *plyfile, char *line) { int i; - + /* skip over "obj_info" and leading spaces and tabs */ i = 8; while (line[i] == ' ' || line[i] == '\t') i++; - + ply_put_obj_info (plyfile, &line[i]); } - - + + /****************************************************************************** Copy a property. ******************************************************************************/ - + void copy_property(PlyProperty *dest, PlyProperty *src) { dest->name = _strdup (src->name); dest->external_type = src->external_type; dest->internal_type = src->internal_type; dest->offset = src->offset; - + dest->is_list = src->is_list; dest->count_external = src->count_external; dest->count_internal = src->count_internal; dest->count_offset = src->count_offset; } - - + + /****************************************************************************** Allocate some memory. - + Entry: size - amount of memory requested (in bytes) lnum - line number from which memory was requested fname - file name from which memory was requested ******************************************************************************/ - - char *my_alloc(int size, int lnum, const char *fname) + + void *my_alloc(int size, int lnum, const char *fname) { - char *ptr; - - ptr = (char *) malloc (size); - + void *ptr; + + ptr = malloc (size); + if (ptr == 0) { fprintf(stderr, "Memory allocation bombed on line %d in %s\n", lnum, fname); } - + return (ptr); } - + diff --git a/Src/PoissonRecon.cpp b/Src/PoissonRecon.cpp index 13ff3eca..8914d90e 100644 --- a/Src/PoissonRecon.cpp +++ b/Src/PoissonRecon.cpp @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -31,86 +31,17 @@ DAMAGE. #define BRUNO_LEVY_FIX #define FOR_RELEASE -#include -#include -#include -#include #if defined( _WIN32 ) || defined( _WIN64 ) #include #include #endif // _WIN32 || _WIN64 -#include "MyTime.h" -#include "MarchingCubes.h" -#include "Octree.h" -#include "SparseMatrix.h" -#include "CmdLineParser.h" -#include "PPolynomial.h" -#include "Ply.h" -#include "MemoryUsage.h" -#ifdef _OPENMP -#include "omp.h" -#endif // _OPENMP -void DumpOutput( const char* format , ... ); -void DumpOutput2( std::vector< char* >& comments , const char* format , ... ); -#include "MultiGridOctreeData.h" - -#define DEFAULT_FULL_DEPTH 5 - -#define XSTR(x) STR(x) -#define STR(x) #x -#if DEFAULT_FULL_DEPTH -#pragma message ( "[WARNING] Setting default full depth to " XSTR(DEFAULT_FULL_DEPTH) ) -#endif // DEFAULT_FULL_DEPTH - -#include -char* outputFile=NULL; -int echoStdout=0; -void DumpOutput( const char* format , ... ) -{ - if( outputFile ) - { - FILE* fp = fopen( outputFile , "a" ); - va_list args; - va_start( args , format ); - vfprintf( fp , format , args ); - fclose( fp ); - va_end( args ); - } - if( echoStdout ) - { - va_list args; - va_start( args , format ); - vprintf( format , args ); - va_end( args ); - } -} -void DumpOutput2( std::vector< char* >& comments , const char* format , ... ) -{ - if( outputFile ) - { - FILE* fp = fopen( outputFile , "a" ); - va_list args; - va_start( args , format ); - vfprintf( fp , format , args ); - fclose( fp ); - va_end( args ); - } - if( echoStdout ) - { - va_list args; - va_start( args , format ); - vprintf( format , args ); - va_end( args ); - } - comments.push_back( new char[1024] ); - char* str = comments.back(); - va_list args; - va_start( args , format ); - vsprintf( str , format , args ); - va_end( args ); - if( str[strlen(str)-1]=='\n' ) str[strlen(str)-1] = 0; -} +#include "CmdLineParser.h" +#include "PoissonRecon.h" +#include "point_source/AsciiPointSource.h" +#include "point_source/BinaryPointSource.h" +#include "point_source/PlyPointSource.h" +#include "MemMesh.h" cmdLineString In( "in" ) , @@ -139,7 +70,7 @@ cmdLineReadable cmdLineInt #ifndef FAST_COMPILE - Degree( "degree" , 2 ) , + //Degree( "degree" , 2 ) , #endif // !FAST_COMPILE Depth( "depth" , 8 ) , CGDepth( "cgDepth" , 0 ) , @@ -149,7 +80,7 @@ cmdLineInt VoxelDepth( "voxelDepth" , -1 ) , FullDepth( "fullDepth" , DEFAULT_FULL_DEPTH ) , #ifndef FAST_COMPILE - BType( "bType" , BOUNDARY_NEUMANN+1 ) , +// BType( "bType" , BOUNDARY_NEUMANN+1 ) , #endif // !FAST_COMPILE MaxSolveDepth( "maxSolveDepth" ) , Threads( "threads" , omp_get_num_procs() ); @@ -159,14 +90,16 @@ cmdLineFloat SamplesPerNode( "samplesPerNode" , 1.5f ) , Scale( "scale" , 1.1f ) , CGSolverAccuracy( "cgAccuracy" , float(1e-3) ) , - LowResIterMultiplier( "iterMultiplier" , 1.f ) , + LowResIterMultiplier( "iterMultiplier" , 1.f ) , PointWeight( "pointWeight" , 4.f ); cmdLineReadable* params[] = { #ifndef FAST_COMPILE - &Degree , &Double , &BType , +// &Degree , +&Double , +// &BType , #endif // !FAST_COMPILE &In , &Depth , &Out , &XForm , &Scale , &Verbose , &CGSolverAccuracy , &NoComments , &LowResIterMultiplier , @@ -195,9 +128,9 @@ void ShowUsage(char* ex) printf( "\t[--%s ]\n" , VoxelGrid.name ); #ifndef FAST_COMPILE - printf( "\t[--%s =%d]\n" , Degree.name , Degree.value ); +// printf( "\t[--%s =%d]\n" , Degree.name , Degree.value ); - printf( "\t[--%s =%d]\n" , BType.name , BType.value ); +// printf( "\t[--%s =%d]\n" , BType.name , BType.value ); for( int i=0 ; i -struct ColorInfo -{ - static Point3D< Real > ReadASCII( FILE* fp ) - { - Point3D< unsigned char > c; - if( fscanf( fp , " %c %c %c " , &c[0] , &c[1] , &c[2] )!=3 ) fprintf( stderr , "[ERROR] Failed to read color\n" ) , exit( 0 ); - return Point3D< Real >( (Real)c[0] , (Real)c[1] , (Real)c[2] ); - }; - static bool ValidPlyProperties( const bool* props ){ return ( props[0] || props[3] ) && ( props[1] || props[4] ) && ( props[2] || props[5] ); } - const static PlyProperty PlyProperties[]; -}; -template<> -const PlyProperty ColorInfo< float >::PlyProperties[] = -{ - { "r" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "g" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[1] ) ) , 0 , 0 , 0 , 0 } , - { "b" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[2] ) ) , 0 , 0 , 0 , 0 } , - { "red" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "green" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[1] ) ) , 0 , 0 , 0 , 0 } , - { "blue" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[2] ) ) , 0 , 0 , 0 , 0 } -}; -template<> -const PlyProperty ColorInfo< double >::PlyProperties[] = -{ - { "r" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "g" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[1] ) ) , 0 , 0 , 0 , 0 } , - { "b" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[2] ) ) , 0 , 0 , 0 , 0 } , - { "red" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[0] ) ) , 0 , 0 , 0 , 0 } , - { "green" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[1] ) ) , 0 , 0 , 0 , 0 } , - { "blue" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[2] ) ) , 0 , 0 , 0 , 0 } -}; - -double Weight( double v , double start , double end ) -{ - v = ( v - start ) / ( end - start ); - if ( v<0 ) return 1.; - else if( v>1 ) return 0.; - else - { - // P(x) = a x^3 + b x^2 + c x + d - // P (0) = 1 , P (1) = 0 , P'(0) = 0 , P'(1) = 0 - // => d = 1 , a + b + c + d = 0 , c = 0 , 3a + 2b + c = 0 - // => c = 0 , d = 1 , a + b = -1 , 3a + 2b = 0 - // => a = 2 , b = -3 , c = 0 , d = 1 - // => P(x) = 2 x^3 - 3 x^2 + 1 - return 2. * v * v * v - 3. * v * v + 1.; - } -} #if defined( _WIN32 ) || defined( _WIN64 ) double PeakMemoryUsageMB( void ) @@ -360,7 +244,8 @@ struct OctreeProfiler else DumpOutput( "%9.1f (s), %9.1f (MB) / %9.1f (MB) / %9.1f (MB)\n" , Time()-t , tree.localMemoryUsage() , tree.maxMemoryUsage() ); #endif // _WIN32 || _WIN64 } - void dumpOutput2( std::vector< char* >& comments , const char* header ) const + + void dumpOutput2( std::vector& comments , const char* header ) const { tree.memoryUsage(); #if defined( _WIN32 ) || defined( _WIN64 ) @@ -373,408 +258,143 @@ struct OctreeProfiler } }; -template< class Real > -XForm4x4< Real > GetPointXForm( OrientedPointStream< Real >& stream , Real scaleFactor ) +using MeshPtr = std::unique_ptr; + +template +void writeOutput(PoissonRecon& recon, Kazhdan::Mesh& mesh) { - Point3D< Real > min , max; - stream.boundingBox( min , max ); - Point3D< Real > center = ( max + min ) / 2; - Real scale = std::max< Real >( max[0]-min[0] , std::max< Real >( max[1]-min[1] , max[2]-min[2] ) ); - scale *= scaleFactor; - for( int i=0 ; i<3 ; i++ ) center[i] -= scale/2; - XForm4x4< Real > tXForm = XForm4x4< Real >::Identity() , sXForm = XForm4x4< Real >::Identity(); - for( int i=0 ; i<3 ; i++ ) sXForm(i,i) = (Real)(1./scale ) , tXForm(3,i) = -center[i]; - return sXForm * tXForm; + std::cerr << "Vertices / Polygons: " << mesh.pointCount() << " / " << + mesh.polygonCount() << std::endl; + + std::vector comments(recon.comments()); + std::unique_ptr buf(new char *[comments.size()]); + for (size_t i = 0; i < comments.size(); ++i) + *(buf.get() + i) = (char *)comments[i].data(); + PlyWritePolygons(Out.value, mesh, + (ASCII.set ? PLY_ASCII : PLY_BINARY_NATIVE), buf.get(), (int)comments.size(), + recon.inverseTransform()); } -template< class Real , int Degree , BoundaryType BType , class Vertex > -int _Execute( int argc , char* argv[] ) +template +void extractMesh(PoissonRecon& recon, bool color, bool density) { - typedef typename Octree< Real >::template DensityEstimator< WEIGHT_DEGREE > DensityEstimator; - typedef typename Octree< Real >::template InterpolationInfo< false > InterpolationInfo; - typedef OrientedPointStream< Real > PointStream; - typedef OrientedPointStreamWithData< Real , Point3D< Real > > PointStreamWithData; - typedef TransformedOrientedPointStream< Real > XPointStream; - typedef TransformedOrientedPointStreamWithData< Real , Point3D< Real > > XPointStreamWithData; - Reset< Real >(); - int paramNum = sizeof(params)/sizeof(cmdLineReadable*); - std::vector< char* > comments; - - if( Verbose.set ) echoStdout=1; - - XForm4x4< Real > xForm , iXForm; - if( XForm.set ) - { - FILE* fp = fopen( XForm.value , "r" ); - if( !fp ) - { - fprintf( stderr , "[WARNING] Could not read x-form from: %s\n" , XForm.value ); - xForm = XForm4x4< Real >::Identity(); - } - else - { - for( int i=0 ; i<4 ; i++ ) for( int j=0 ; j<4 ; j++ ) - { - float f; - if( fscanf( fp , " %f " , &f )!=1 ) fprintf( stderr , "[ERROR] Execute: Failed to read xform\n" ) , exit( 0 ); - xForm(i,j) = (Real)f; - } - fclose( fp ); - } - } - else xForm = XForm4x4< Real >::Identity(); - - DumpOutput2( comments , "Running Screened Poisson Reconstruction (Version 9.01)\n" ); - char str[1024]; - for( int i=0 ; iset ) - { - params[i]->writeValue( str ); - if( strlen( str ) ) DumpOutput2( comments , "\t--%s %s\n" , params[i]->name , str ); - else DumpOutput2( comments , "\t--%s\n" , params[i]->name ); - } - - double startTime = Time(); - Real isoValue = 0; - - Octree< Real > tree; - OctreeProfiler< Real > profiler( tree ); - tree.threads = Threads.value; - if( !In.set ) - { - ShowUsage( argv[0] ); - return 0; - } - if( !MaxSolveDepth.set ) MaxSolveDepth.value = Depth.value; - - OctNode< TreeNodeData >::SetAllocator( MEMORY_ALLOCATOR_BLOCK_SIZE ); - - int kernelDepth = KernelDepth.set ? KernelDepth.value : Depth.value-2; - if( kernelDepth>Depth.value ) - { - fprintf( stderr,"[WARNING] %s can't be greater than %s: %d <= %d\n" , KernelDepth.name , Depth.name , KernelDepth.value , Depth.value ); - kernelDepth = Depth.value; - } + MeshPtr mesh; + if (color && density) + { + mesh.reset(new Kazhdan::CompleteMemMesh); + recon.extractMesh(*mesh); + writeOutput, Real>(recon, *mesh); + } + else if (color) + { + mesh.reset(new Kazhdan::ColorMemMesh); + recon.extractMesh(*mesh); + writeOutput, Real>(recon, *mesh); + } + else if (density) + { + mesh.reset(new Kazhdan::DensityMemMesh); + recon.extractMesh(*mesh); + writeOutput, Real>(recon, *mesh); + } + else + { + mesh.reset(new Kazhdan::MemMesh); + recon.extractMesh(*mesh); + writeOutput, Real>(recon, *mesh); + } +} - int pointCount; +PointSourcePtr createPointSource(const std::string& filename, bool color) +{ + std::string ext = GetFileExtension(filename); + for (auto& c : ext) + c = tolower(c); + + PointSource *pointSource; + if (color) + { + if (ext == "bnpts") + pointSource = new ColorBinaryPointSource(filename); + else if (ext == "ply") + pointSource = new ColorPLYPointSource(filename); + else + pointSource = new ColorASCIIPointSource(filename); + } + else + { + if (ext == "bnpts") + pointSource = new BinaryPointSource(filename); + else if (ext == "ply") + pointSource = new PLYPointSource(filename); + else + pointSource = new ASCIIPointSource(filename); + } + return PointSourcePtr(pointSource); +} - Real pointWeightSum; - std::vector< typename Octree< Real >::PointSample >* samples = new std::vector< typename Octree< Real >::PointSample >(); - std::vector< ProjectiveData< Point3D< Real > , Real > >* sampleData = NULL; - DensityEstimator* density = NULL; - SparseNodeData< Point3D< Real > , NORMAL_DEGREE >* normalInfo = NULL; - Real targetValue = (Real)0.5; - // Read in the samples (and color data) - { - profiler.start(); - PointStream* pointStream; - char* ext = GetFileExtension( In.value ); - if( Color.set && Color.value>0 ) - { - sampleData = new std::vector< ProjectiveData< Point3D< Real > , Real > >(); - if ( !strcasecmp( ext , "bnpts" ) ) pointStream = new BinaryOrientedPointStreamWithData< Real , Point3D< Real > , float , Point3D< unsigned char > >( In.value ); - else if( !strcasecmp( ext , "ply" ) ) pointStream = new PLYOrientedPointStreamWithData< Real , Point3D< Real > >( In.value , ColorInfo< Real >::PlyProperties , 6 , ColorInfo< Real >::ValidPlyProperties ); - else pointStream = new ASCIIOrientedPointStreamWithData< Real , Point3D< Real > >( In.value , ColorInfo< Real >::ReadASCII ); - } - else - { - if ( !strcasecmp( ext , "bnpts" ) ) pointStream = new BinaryOrientedPointStream< Real , float >( In.value ); - else if( !strcasecmp( ext , "ply" ) ) pointStream = new PLYOrientedPointStream< Real >( In.value ); - else pointStream = new ASCIIOrientedPointStream< Real >( In.value ); - } - delete[] ext; - XPointStream _pointStream( xForm , *pointStream ); - xForm = GetPointXForm( _pointStream , (Real)Scale.value ) * xForm; - if( sampleData ) - { - XPointStreamWithData _pointStream( xForm , ( PointStreamWithData& )*pointStream ); - pointCount = tree.template init< Point3D< Real > >( _pointStream , Depth.value , Confidence.set , *samples , sampleData ); - } - else - { - XPointStream _pointStream( xForm , *pointStream ); - pointCount = tree.template init< Point3D< Real > >( _pointStream , Depth.value , Confidence.set , *samples , sampleData ); - } - iXForm = xForm.inverse(); - delete pointStream; -#pragma omp parallel for num_threads( Threads.value ) - for( int i=0 ; i<(int)samples->size() ; i++ ) (*samples)[i].sample.data.n *= (Real)-1; - - DumpOutput( "Input Points / Samples: %d / %d\n" , pointCount , samples->size() ); - profiler.dumpOutput2( comments , "# Read input into tree:" ); - } - DenseNodeData< Real , Degree > solution; +int main(int argc, char *argv[]) +{ + using Real = float; + + cmdLineParse(argc-1, &argv[1] ,sizeof(params)/sizeof(params[0]), + params , 1); + + PoissonOpts opts; + //Right now we only care about some options. + + if (!In.set) + { + std::cerr << "Must supply input file!\n"; + ShowUsage(argv[0]); + return 0; + } + if (!Out.set) + { + std::cerr << "Must supply output file!\n"; + return 0; + } + if (Depth.set) + opts.m_depth = Depth.value; + if (Color.set) + { + opts.m_color = Color.value; + opts.m_hasColor = (Color.value > 0); + } + opts.m_density = Density.set; + if (PointWeight.set) + opts.m_pointWeight = PointWeight.value; + opts.m_primalVoxel = PrimalVoxel.set; + opts.m_verbose = Verbose.set; + opts.m_confidence = Confidence.set; + opts.m_showResidual = ShowResidual.set; + opts.m_linearFit = LinearFit.set; + opts.m_nonManifold = NonManifold.set; + opts.m_polygonMesh = PolygonMesh.set; + +//ABELL +// m_startTime = Time()); + if( !MaxSolveDepth.set ) + MaxSolveDepth.value = Depth.value; + + opts.m_solveDepth = MaxSolveDepth.value; + opts.m_kernelDepth = KernelDepth.set ? KernelDepth.value : Depth.value-2; + if (opts.m_kernelDepth > opts.m_depth) { - DenseNodeData< Real , Degree > constraints; - InterpolationInfo* iInfo = NULL; - int solveDepth = MaxSolveDepth.value; - - tree.resetNodeIndices(); - - // Get the kernel density estimator [If discarding, compute anew. Otherwise, compute once.] - { - profiler.start(); - density = tree.template setDensityEstimator< WEIGHT_DEGREE >( *samples , kernelDepth , SamplesPerNode.value ); - profiler.dumpOutput2( comments , "# Got kernel density:" ); - } - - // Transform the Hermite samples into a vector field [If discarding, compute anew. Otherwise, compute once.] - { - profiler.start(); - normalInfo = new SparseNodeData< Point3D< Real > , NORMAL_DEGREE >(); - *normalInfo = tree.template setNormalField< NORMAL_DEGREE >( *samples , *density , pointWeightSum , BType==BOUNDARY_NEUMANN ); - profiler.dumpOutput2( comments , "# Got normal field:" ); - } - - if( !Density.set ) delete density , density = NULL; - - // Trim the tree and prepare for multigrid - { - profiler.start(); - std::vector< int > indexMap; - - constexpr int MAX_DEGREE = NORMAL_DEGREE > Degree ? NORMAL_DEGREE : Degree; - tree.template inalizeForBroodedMultigrid< MAX_DEGREE , Degree , BType >( FullDepth.value , typename Octree< Real >::template HasNormalDataFunctor< NORMAL_DEGREE >( *normalInfo ) , &indexMap ); - - if( normalInfo ) normalInfo->remapIndices( indexMap ); - if( density ) density->remapIndices( indexMap ); - profiler.dumpOutput2( comments , "# Finalized tree:" ); - } - - // Add the FEM constraints - { - profiler.start(); - constraints = tree.template initDenseNodeData< Degree >( ); - tree.template addFEMConstraints< Degree , BType , NORMAL_DEGREE , BType >( FEMVFConstraintFunctor< NORMAL_DEGREE , BType , Degree , BType >( 1. , 0. ) , *normalInfo , constraints , solveDepth ); - profiler.dumpOutput2( comments , "# Set FEM constraints:" ); - } - - // Free up the normal info [If we don't need it for subseequent iterations.] - delete normalInfo , normalInfo = NULL; - - // Add the interpolation constraints - if( PointWeight.value>0 ) - { - profiler.start(); - iInfo = new InterpolationInfo( tree , *samples , targetValue , AdaptiveExponent.value , (Real)PointWeight.value * pointWeightSum , (Real)0 ); - tree.template addInterpolationConstraints< Degree , BType >( *iInfo , constraints , solveDepth ); - profiler.dumpOutput2( comments , "#Set point constraints:" ); - } - - DumpOutput( "Leaf Nodes / Active Nodes / Ghost Nodes: %d / %d / %d\n" , (int)tree.leaves() , (int)tree.nodes() , (int)tree.ghostNodes() ); - DumpOutput( "Memory Usage: %.3f MB\n" , float( MemoryInfo::Usage())/(1<<20) ); - - // Solve the linear system - { - profiler.start(); - typename Octree< Real >::SolverInfo solverInfo; - solverInfo.cgDepth = CGDepth.value , solverInfo.iters = Iters.value , solverInfo.cgAccuracy = CGSolverAccuracy.value , solverInfo.verbose = Verbose.set , solverInfo.showResidual = ShowResidual.set , solverInfo.lowResIterMultiplier = std::max< double >( 1. , LowResIterMultiplier.value ); - solution = tree.template solveSystem< Degree , BType >( FEMSystemFunctor< Degree , BType >( 0 , 1. , 0 ) , iInfo , constraints , solveDepth , solverInfo ); - profiler.dumpOutput2( comments , "# Linear system solved:" ); - if( iInfo ) delete iInfo , iInfo = NULL; - } + std::cerr << "[WARNING] kernelDepth can't be greater than depth: " << + opts.m_kernelDepth << " <= " << opts.m_depth << "." << std::endl; + opts.m_kernelDepth = opts.m_depth; } - CoredFileMeshData< Vertex > mesh; + PointSourcePtr pointSource(createPointSource(In.value, opts.m_hasColor)); - { - profiler.start(); - double valueSum = 0 , weightSum = 0; - typename Octree< Real >::template MultiThreadedEvaluator< Degree , BType > evaluator( &tree , solution , Threads.value ); -#pragma omp parallel for num_threads( Threads.value ) reduction( + : valueSum , weightSum ) - for( int j=0 ; jsize() ; j++ ) - { - ProjectiveData< OrientedPoint3D< Real > , Real >& sample = (*samples)[j].sample; - Real w = sample.weight; - if( w>0 ) weightSum += w , valueSum += evaluator.value( sample.data.p / sample.weight , omp_get_thread_num() , (*samples)[j].node ) * w; - } - isoValue = (Real)( valueSum / weightSum ); - if( !( Color.set && Color.value>0 ) && samples ) delete samples , samples = NULL; - profiler.dumpOutput( "Got average:" ); - DumpOutput( "Iso-Value: %e\n" , isoValue ); - } + PoissonRecon recon(opts, *pointSource); + recon.execute(); + recon.evaluate(); - if( VoxelGrid.set ) - { - profiler.start(); - FILE* fp = fopen( VoxelGrid.value , "wb" ); - if( !fp ) fprintf( stderr , "Failed to open voxel file for writing: %s\n" , VoxelGrid.value ); - else - { - int res = 0; - Pointer( Real ) values = tree.template voxelEvaluate< Real , Degree , BType >( solution , res , isoValue , VoxelDepth.value , PrimalVoxel.set ); - fwrite( &res , sizeof(int) , 1 , fp ); - if( sizeof(Real)==sizeof(float) ) fwrite( values , sizeof(float) , res*res*res , fp ); - else - { - float *fValues = new float[res*res*res]; - for( int i=0 ; i , Real > , DATA_DEGREE >* colorData = NULL; - if( sampleData ) - { - colorData = new SparseNodeData< ProjectiveData< Point3D< Real > , Real > , DATA_DEGREE >(); - *colorData = tree.template setDataField< DATA_DEGREE , false >( *samples , *sampleData , (DensityEstimator*)NULL ); - delete sampleData , sampleData = NULL; - for( const OctNode< TreeNodeData >* n = tree.tree().nextNode() ; n ; n=tree.tree().nextNode( n ) ) - { - ProjectiveData< Point3D< Real > , Real >* clr = (*colorData)( n ); - if( clr ) (*clr) *= (Real)pow( Color.value , tree.depth( n ) ); - } - } - tree.template getMCIsoSurface< Degree , BType , WEIGHT_DEGREE , DATA_DEGREE >( density , colorData , solution , isoValue , mesh , !LinearFit.set , !NonManifold.set , PolygonMesh.set ); - DumpOutput( "Vertices / Polygons: %d / %d\n" , mesh.outOfCorePointCount()+mesh.inCorePoints.size() , mesh.polygonCount() ); - if( PolygonMesh.set ) profiler.dumpOutput2( comments , "# Got polygons:" ); - else profiler.dumpOutput2( comments , "# Got triangles:" ); - - if( colorData ) delete colorData , colorData = NULL; - - if( NoComments.set ) - { - if( ASCII.set ) PlyWritePolygons( Out.value , &mesh , PLY_ASCII , NULL , 0 , iXForm ); - else PlyWritePolygons( Out.value , &mesh , PLY_BINARY_NATIVE , NULL , 0 , iXForm ); - } - else - { - if( ASCII.set ) PlyWritePolygons( Out.value , &mesh , PLY_ASCII , &comments[0] , (int)comments.size() , iXForm ); - else PlyWritePolygons( Out.value , &mesh , PLY_BINARY_NATIVE , &comments[0] , (int)comments.size() , iXForm ); - } - } - if( density ) delete density , density = NULL; - DumpOutput2( comments , "# Total Solve: %9.1f (s), %9.1f (MB)\n" , Time()-startTime , tree.maxMemoryUsage() ); + extractMesh(recon, opts.m_hasColor, opts.m_density); - return 1; + return 0; } -#if defined( _WIN32 ) || defined( _WIN64 ) -inline double to_seconds( const FILETIME& ft ) -{ - const double low_to_sec=100e-9; // 100 nanoseconds - const double high_to_sec=low_to_sec*4294967296.0; - return ft.dwLowDateTime*low_to_sec+ft.dwHighDateTime*high_to_sec; -} -#endif // _WIN32 || _WIN64 - -#ifndef FAST_COMPILE -template< class Real , class Vertex > -int Execute( int argc , char* argv[] ) -{ - switch( BType.value ) - { - case BOUNDARY_FREE+1: - { - switch( Degree.value ) - { - case 1: return _Execute< Real , 1 , BOUNDARY_FREE , Vertex >( argc , argv ); - case 2: return _Execute< Real , 2 , BOUNDARY_FREE , Vertex >( argc , argv ); - case 3: return _Execute< Real , 3 , BOUNDARY_FREE , Vertex >( argc , argv ); - case 4: return _Execute< Real , 4 , BOUNDARY_FREE , Vertex >( argc , argv ); - default: fprintf( stderr , "[ERROR] Only B-Splines of degree 1 - 4 are supported" ) ; return EXIT_FAILURE; - } - } - case BOUNDARY_NEUMANN+1: - { - switch( Degree.value ) - { - case 1: return _Execute< Real , 1 , BOUNDARY_NEUMANN , Vertex >( argc , argv ); - case 2: return _Execute< Real , 2 , BOUNDARY_NEUMANN , Vertex >( argc , argv ); - case 3: return _Execute< Real , 3 , BOUNDARY_NEUMANN , Vertex >( argc , argv ); - case 4: return _Execute< Real , 4 , BOUNDARY_NEUMANN , Vertex >( argc , argv ); - default: fprintf( stderr , "[ERROR] Only B-Splines of degree 1 - 4 are supported" ) ; return EXIT_FAILURE; - } - } - case BOUNDARY_DIRICHLET+1: - { - switch( Degree.value ) - { - case 1: return _Execute< Real , 1 , BOUNDARY_DIRICHLET , Vertex >( argc , argv ); - case 2: return _Execute< Real , 2 , BOUNDARY_DIRICHLET , Vertex >( argc , argv ); - case 3: return _Execute< Real , 3 , BOUNDARY_DIRICHLET , Vertex >( argc , argv ); - case 4: return _Execute< Real , 4 , BOUNDARY_DIRICHLET , Vertex >( argc , argv ); - default: fprintf( stderr , "[ERROR] Only B-Splines of degree 1 - 4 are supported" ) ; return EXIT_FAILURE; - } - } - default: fprintf( stderr , "[ERROR] Not a valid boundary type: %d\n" , BType.value ) ; return EXIT_FAILURE; - } -} -#endif // !FAST_COMPILE -int main( int argc , char* argv[] ) -{ -#ifdef ARRAY_DEBUG - fprintf( stderr , "[WARNING] Running in array debugging mode\n" ); -#endif // ARRAY_DEBUG -#if defined( WIN32 ) && defined( MAX_MEMORY_GB ) - if( MAX_MEMORY_GB>0 ) - { - SIZE_T peakMemory = 1; - peakMemory <<= 30; - peakMemory *= MAX_MEMORY_GB; - printf( "Limiting memory usage to %.2f GB\n" , float( peakMemory>>30 ) ); - HANDLE h = CreateJobObject( NULL , NULL ); - AssignProcessToJobObject( h , GetCurrentProcess() ); - - JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = { 0 }; - jeli.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_JOB_MEMORY; - jeli.JobMemoryLimit = peakMemory; - if( !SetInformationJobObject( h , JobObjectExtendedLimitInformation , &jeli , sizeof( jeli ) ) ) - fprintf( stderr , "Failed to set memory limit\n" ); - } -#endif // defined( WIN32 ) && defined( MAX_MEMORY_GB ) - double t = Time(); - - cmdLineParse( argc-1 , &argv[1] , sizeof(params)/sizeof(cmdLineReadable*) , params , 1 ); -#ifdef FAST_COMPILE - static const int Degree = 2; - static const BoundaryType BType = BOUNDARY_NEUMANN; - fprintf( stderr , "[WARNING] Compiling for degree-%d, boundary-%s, single-precision _only_\n" , Degree , BoundaryNames[ BType ] ); - if( Density.set ) - if( Color.set && Color.value>0 ) return _Execute< float , Degree , BType , PlyColorAndValueVertex< float > >( argc , argv ); - else return _Execute< float , Degree , BType , PlyValueVertex< float > >( argc , argv ); - else - if( Color.set && Color.value>0 ) return _Execute< float , Degree , BType , PlyColorVertex< float > >( argc , argv ); - else return _Execute< float , Degree , BType , PlyVertex< float > >( argc , argv ); -#else // !FAST_COMPILE - { - if( Density.set ) - if( Color.set && Color.value>0 ) - if( Double.set ) Execute< double , PlyColorAndValueVertex< float > >( argc , argv ); - else Execute< float , PlyColorAndValueVertex< float > >( argc , argv ); - else - if( Double.set ) Execute< double , PlyValueVertex< float > >( argc , argv ); - else Execute< float , PlyValueVertex< float > >( argc , argv ); - else - if( Color.set && Color.value>0 ) - if( Double.set ) Execute< double , PlyColorVertex< float > >( argc , argv ); - else Execute< float , PlyColorVertex< float > >( argc , argv ); - else - if( Double.set ) Execute< double , PlyVertex< float > >( argc , argv ); - else Execute< float , PlyVertex< float > >( argc , argv ); - } -#endif // FAST_COMPILE -#if defined( _WIN32 ) || defined( _WIN64 ) - if( Performance.set ) - { - HANDLE cur_thread=GetCurrentThread(); - FILETIME tcreat, texit, tkernel, tuser; - if( GetThreadTimes( cur_thread , &tcreat , &texit , &tkernel , &tuser ) ) - printf( "Time (Wall/User/Kernel): %.2f / %.2f / %.2f\n" , Time()-t , to_seconds( tuser ) , to_seconds( tkernel ) ); - else printf( "Time: %.2f\n" , Time()-t ); - HANDLE h = GetCurrentProcess(); - PROCESS_MEMORY_COUNTERS pmc; - if( GetProcessMemoryInfo( h , &pmc , sizeof(pmc) ) ) printf( "Peak Memory (MB): %d\n" , (int)( pmc.PeakWorkingSetSize>>20 ) ); - } -#endif // _WIN32 || _WIN64 - return EXIT_SUCCESS; -} diff --git a/Src/PoissonRecon.h b/Src/PoissonRecon.h new file mode 100644 index 00000000..9e61b70c --- /dev/null +++ b/Src/PoissonRecon.h @@ -0,0 +1,532 @@ +/* +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#undef FAST_COMPILE +#undef ARRAY_DEBUG +#define BRUNO_LEVY_FIX +#define FOR_RELEASE + +//ABELL - Necessary? +/** +#if defined( _WIN32 ) || defined( _WIN64 ) +#include +#include +#endif // _WIN32 || _WIN64 +**/ + +#include +#include +#include +#ifdef _OPENMP +#include +#endif // _OPENMP +#include + +#include "MultiGridOctreeData.h" +#include "Mesh.h" +#include "point_source/TransformedPointSource.h" + +constexpr BoundaryType BType = BOUNDARY_NEUMANN; +constexpr int Degree = 2; + +void DumpOutput( const char* format , ... ); +void DumpOutput2( std::vector< char* >& comments , const char* format , ... ); +#include "MultiGridOctreeData.h" + +#define DEFAULT_FULL_DEPTH 5 + +#define XSTR(x) STR(x) +#define STR(x) #x +/** +#if DEFAULT_FULL_DEPTH +#pragma message ( "[WARNING] Setting default full depth to " XSTR(DEFAULT_FULL_DEPTH) ) +#endif // DEFAULT_FULL_DEPTH +**/ + +#include + +template +XForm4x4 GetPointXForm(PointSource& source, Real scaleFactor) +{ + Point3D min , max; + source.boundingBox(min, max); + Point3D center = ( max + min ) / 2; + double scale = std::max( max[0]-min[0], + std::max(max[1]-min[1], max[2]-min[2])); + scale *= scaleFactor; + for( int i=0 ; i<3 ; i++ ) + center[i] -= scale/2; + + XForm4x4 tXForm = XForm4x4::Identity(); + XForm4x4 sXForm = XForm4x4::Identity(); + for( int i=0 ; i<3 ; i++ ) + { + sXForm(i,i) = (Real)(1./scale ); + tXForm(3,i) = -(Real)center[i]; + } + return sXForm * tXForm; +} + +template +using ProjData = ProjectiveData, Real>; + +template +using DataSample = ProjData; + +template +using DataSampleVec = std::vector>; + +template +using OctreeSample = typename Octree::PointSample; + +template +using OctreeSampleVec = std::vector>; + +template +using DensityEstimator = typename Octree::DensityEstimator; + +template +using InterpolationInfo = + typename Octree::template InterpolationInfo; + +template +struct PoissonOpts +{ + int m_threads; + int m_voxelDepth; + bool m_primalVoxel; + bool m_verbose; + bool m_confidence; + bool m_hasColor; + Real m_color; + std::string m_voxelFilename; + std::string m_xformFilename; + Real m_samplesPerNode; + int m_depth; + int m_cgDepth; + int m_iterations; + bool m_showResidual; + Real m_lowResIterMult; + int m_kernelDepth; + int m_solveDepth; // MaxSolveDepth ); + Real m_solverAccuracy; + Real m_pointWeight; + int m_adaptExponent; // 1 + bool m_density; + bool m_linearFit; + bool m_nonManifold; + bool m_polygonMesh; + int m_fullDepth; + Real m_scale; + + PoissonOpts() : m_threads(omp_get_num_procs()), m_voxelDepth(-1), + m_primalVoxel(false), m_verbose(false), m_confidence(false), + m_color(16), m_samplesPerNode(1.5F), m_depth(8), m_cgDepth(0), + m_iterations(8), m_showResidual(false), m_lowResIterMult(1), + m_kernelDepth(0), m_solveDepth(0), m_solverAccuracy(1e-3F), + m_pointWeight(4), m_adaptExponent(1), m_density(false), + m_linearFit(false), m_nonManifold(false), m_polygonMesh(false), + m_fullDepth(5), m_scale(1.1F) + {} + + void dump() + { + std::cerr << "Threads = " << m_threads << "!\n"; + std::cerr << "Voxel depth = " << m_voxelDepth << "!\n"; + std::cerr << "Primal voxel = " << m_primalVoxel << "!\n"; + std::cerr << "Verbose = " << m_verbose << "!\n"; + std::cerr << "Confidence = " << m_confidence << "!\n"; + std::cerr << "Has color = " << m_hasColor << "!\n"; + std::cerr << "Color = " << m_color << "!\n"; + std::cerr << "Voxel filename = " << m_voxelFilename << "!\n"; + std::cerr << "Xform filename = " << m_xformFilename << "!\n"; + std::cerr << "Samples per node = " << m_samplesPerNode << "!\n"; + std::cerr << "Depth = " << m_depth << "!\n"; + std::cerr << "CG depth = " << m_cgDepth << "!\n"; + std::cerr << "Iterations = " << m_iterations << "!\n"; + std::cerr << "Show residual = " << m_showResidual << "!\n"; + std::cerr << "Low res multiplier = " << m_lowResIterMult << "!\n"; + std::cerr << "Kernel depth = " << m_kernelDepth << "!\n"; + std::cerr << "Solve depth = " << m_solveDepth << "!\n"; + std::cerr << "Solver accuracy = " << m_solverAccuracy << "!\n"; + std::cerr << "Point weight = " << m_pointWeight << "!\n"; + std::cerr << "Adapt exponent = " << m_adaptExponent << "!\n"; + std::cerr << "Density = " << m_density << "!\n"; + std::cerr << "Linear fit = " << m_linearFit << "!\n"; + std::cerr << "Non-manifold = " << m_nonManifold << "!\n"; + std::cerr << "Poly mesh = " << m_polygonMesh << "!\n"; + std::cerr << "Full depth = " << m_fullDepth << "!\n"; + std::cerr << "Scale = " << m_scale << "!\n"; + } +}; + +class Profiler +{ +public: + void start() + {} + void dumpOutput(const std::string& s) + { std::cerr << s << std::endl; } + void dumpOutput2(std::vector& comments, const std::string& s) + { + comments.push_back(s); + dumpOutput(s); + } +}; + +template +class PoissonRecon +{ +public: + PoissonRecon(PoissonOpts opts, PointSource& pointSource) : + m_opts(opts), m_pointSource(pointSource), + m_xForm(XForm4x4::Identity()), + m_samples(new OctreeSampleVec), m_isoValue(0) + {} + void execute(); + void evaluate(); + void extractMesh(Kazhdan::Mesh& mesh); + std::vector comments() const + { return m_comments; } + XForm4x4 inverseTransform() const + { return m_iXForm; } + +private: + void readData(); + void calcDensity(); + void calcNormalData(); + void readXForm(const std::string& filename); + void trim(); + void addFEMConstraints(); + void addInterpolationConstraints(); + void solve(); + void writeVoxels(); + + template + void writeSurface(Kazhdan::Mesh& mesh); + +private: + PoissonOpts m_opts; + PointSource& m_pointSource; + XForm4x4 m_xForm; + XForm4x4 m_iXForm; // Inverse transform. + Octree m_tree; + Profiler m_profiler; // OctreeProfiler(tree); + DataSampleVec *m_sampleData; + OctreeSampleVec *m_samples; + Real m_isoValue; + double m_startTime; + DensityEstimator *m_density; + SparseNodeData > m_normalInfo; + Real m_pointWeightSum; + DenseNodeData m_constraints; + DenseNodeData m_solution; + InterpolationInfo *m_interp; + std::vector m_comments; +}; + + +inline void writeVoxelValues(FILE *fp, size_t count, float *values) +{ + fwrite(values, sizeof(float), count * count * count, fp); +} + +inline void writeVoxelValues(FILE *fp, size_t count, double *values) +{ + while (count--) + { + float f = (float) *values++; + fwrite(&f, sizeof(float), 1, fp); + } +} + + +template +void PoissonRecon::writeVoxels() +{ + if (m_opts.m_voxelFilename.empty()) + return; + FILE* fp = fopen(m_opts.m_voxelFilename.data(), "wb" ); + if ( !fp ) + std::cerr << "Failed to open voxel file for writing: " << + m_opts.m_voxelFilename << std::endl; + else + { + int res = 0; + Pointer( Real ) values = + m_tree.template voxelEvaluate(m_solution, res, + m_isoValue, m_opts.m_voxelDepth, m_opts.m_primalVoxel); + fwrite( &res , sizeof(int) , 1 , fp ); + writeVoxelValues(fp, res * res * res, values); + fclose( fp ); + DeletePointer( values ); + } +} + +template +void PoissonRecon::extractMesh(Kazhdan::Mesh& mesh) +{ + if (m_opts.m_density && m_opts.m_hasColor) + { + writeSurface>(mesh); + } + else if (m_opts.m_density) + { + writeSurface>(mesh); + } + else if (m_opts.m_hasColor) + { + writeSurface>(mesh); + } + else + { + writeSurface>(mesh); + } +} + +template +template +void PoissonRecon::writeSurface(Kazhdan::Mesh& mesh) +{ + using ColorData = SparseNodeData, Real> >; + + m_profiler.start(); + ColorData colorData = m_tree.template setDataField( + *m_samples, *m_sampleData, (DensityEstimator *)nullptr); + for (const OctNode* n = m_tree.tree().nextNode(); n; + n = m_tree.tree().nextNode(n)) + { + ProjectiveData, Real> *color = colorData(n); + if (color) + *color *= pow(m_opts.m_color, m_tree.depth(n)); + } + + m_tree.template getMCIsoSurface + (m_density, &colorData, m_solution, m_isoValue, mesh, + !m_opts.m_linearFit, !m_opts.m_nonManifold, m_opts.m_polygonMesh); +} + +template +void PoissonRecon::readXForm(const std::string& filename) +{ + if (filename.empty()) + return; + + FILE* fp = fopen(filename.data(), "r" ); + if( !fp ) + { + fprintf( stderr , "[WARNING] Could not read x-form from: %s\n" , + filename.data()); + return; + } + for( int i=0 ; i<4 ; i++ ) + for( int j=0 ; j<4 ; j++ ) + { + float f; + if ( fscanf( fp , " %f " , &f )!= 1 ) + { + fprintf( stderr , "[ERROR] Execute: Failed to read xform\n" ); + exit( 0 ); + } + m_xForm(i,j) = (Real)f; + } + fclose( fp ); +} + +template +int loadOctTree(Octree& tree, XForm4x4& xForm, PointSource& source, + int depth, bool confidence, OctreeSampleVec *samples, + DataSampleVec *sampleData) +{ + try + { + ColorPointSource& colorSource = + dynamic_cast(source); + + ColorTransformedPointSource xsource(xForm, colorSource); + return tree.template init< Point3D< Real >>(xsource, depth, + confidence, *samples, sampleData); + } + catch (std::bad_cast) + {} + + TransformedPointSource xsource(xForm, source); + return tree.template init>(xsource, depth, + confidence, *samples, sampleData); +} + +template +void PoissonRecon::readData() +{ + m_profiler.start(); + + m_sampleData = new DataSampleVec(); + TransformedPointSource xPointSource(m_xForm, m_pointSource); + m_xForm = GetPointXForm(xPointSource, m_opts.m_scale) * m_xForm; + m_iXForm = m_xForm.inverse(); + int pointCount = loadOctTree(m_tree, m_xForm, m_pointSource, m_opts.m_depth, + m_opts.m_confidence, m_samples, m_sampleData); +#pragma omp parallel for num_threads( m_opts.m_threads) + for( int i=0 ; i<(int)m_samples->size() ; i++ ) + (*m_samples)[i].sample.data.n *= (Real)-1; + + m_profiler.dumpOutput2(m_comments , "# Read input into tree:"); + m_tree.resetNodeIndices(); +} + +template +void PoissonRecon::calcDensity() +{ + // Get the kernel density estimator [If discarding, compute anew. + // Otherwise, compute once.] + m_profiler.start(); + m_density = m_tree.template setDensityEstimator(*m_samples, + m_opts.m_kernelDepth, m_opts.m_samplesPerNode); + m_profiler.dumpOutput2(m_comments , "# Got kernel density:"); +} + +template +void PoissonRecon::calcNormalData() +{ + // Transform the Hermite samples into a vector field. + m_profiler.start(); + m_normalInfo = m_tree.template setNormalField< NORMAL_DEGREE, + WEIGHT_DEGREE >(*m_samples, *m_density , m_pointWeightSum , + BType==BOUNDARY_NEUMANN); + m_profiler.dumpOutput2(m_comments , "# Got normal field:" ); +} + +template +void PoissonRecon::trim() +{ + // Trim the tree and prepare for multigrid + m_profiler.start(); + std::vector indexMap; + + constexpr int MAX_DEGREE = NORMAL_DEGREE > Degree ? + NORMAL_DEGREE : Degree; + m_tree.template inalizeForBroodedMultigrid + (m_opts.m_fullDepth, typename Octree::template + HasNormalDataFunctor( m_normalInfo ) , &indexMap); + + m_normalInfo.remapIndices(indexMap); + if (m_density) + m_density->remapIndices( indexMap ); + m_profiler.dumpOutput2(m_comments , "# Finalized tree:" ); +} + +template +void PoissonRecon::addFEMConstraints() +{ + m_profiler.start(); + + // This just initializes a vector of data to 0. Blarf. + m_constraints = m_tree.initDenseNodeData(); +//ABELL - This is really slow! + m_tree.template addFEMConstraints( + FEMVFConstraintFunctor( 1., 0.), + m_normalInfo, m_constraints , m_opts.m_solveDepth); + m_profiler.dumpOutput2(m_comments , "# Set FEM constraints:"); +} + +template +void PoissonRecon::addInterpolationConstraints() +{ + m_profiler.start(); + if (m_opts.m_pointWeight > 0) + { + m_interp = new InterpolationInfo(m_tree, *m_samples, .5, + m_opts.m_adaptExponent, m_pointWeightSum * m_opts.m_pointWeight, 0); + m_tree.template addInterpolationConstraints(*m_interp, + m_constraints, m_opts.m_solveDepth); + } + m_profiler.dumpOutput2(m_comments, "#Set point constraints:"); +} + +template +void PoissonRecon::solve() +{ + m_profiler.start(); + typename Octree::SolverInfo solverInfo; + solverInfo.cgDepth = m_opts.m_cgDepth; + solverInfo.iters = m_opts.m_iterations; + solverInfo.cgAccuracy = m_opts.m_solverAccuracy; + solverInfo.verbose = m_opts.m_verbose; + solverInfo.showResidual = m_opts.m_showResidual; + solverInfo.lowResIterMultiplier = + std::max((Real)1.0, m_opts.m_lowResIterMult); + + m_solution = m_tree.template solveSystem( + FEMSystemFunctor(0, 1, 0), m_interp, m_constraints, + m_opts.m_solveDepth, solverInfo); +} + +template +void PoissonRecon::execute() +{ + readXForm(m_opts.m_xformFilename); + m_comments.push_back("Running Screened Poisson Reconstruction " + "(Version 9.01)"); +// m_debug.dump(m_comments.back()); + m_tree.threads = m_opts.m_threads; + OctNode< TreeNodeData >::SetAllocator( MEMORY_ALLOCATOR_BLOCK_SIZE ); + readData(); + + calcDensity(); + calcNormalData(); + trim(); + addFEMConstraints(); + addInterpolationConstraints(); + solve(); +} + +template +void PoissonRecon::evaluate() +{ + m_profiler.start(); + Real valueSum = 0; + Real weightSum = 0; + typename Octree::template MultiThreadedEvaluator + evaluator(&m_tree, m_solution, m_opts.m_threads); + for (auto & s : *m_samples) + { + ProjectiveData, Real>& sample = s.sample; + Real w = sample.weight; + if (w > 0) + { + weightSum += w; + valueSum += evaluator.value(sample.data.p / sample.weight, + omp_get_thread_num(), s.node) * w; + } + } + m_isoValue = valueSum / weightSum; + + m_profiler.dumpOutput("Got average:"); +} + diff --git a/Src/Polynomial.inl b/Src/Polynomial.inl index ea7ae504..4756ec47 100644 --- a/Src/Polynomial.inl +++ b/Src/Polynomial.inl @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -261,51 +261,60 @@ void Polynomial::printnl(void) const{ } printf("\n"); } + template -void Polynomial::getSolutions(double c,std::vector& roots,double EPS) const +void Polynomial::getSolutions(double c, + std::vector& realRoots, double EPS) const { - double r[4][2]; - int rCount=0; - roots.clear(); - switch(Degree){ - case 1: - rCount=Factor(coefficients[1],coefficients[0]-c,r,EPS); - break; - case 2: - rCount=Factor(coefficients[2],coefficients[1],coefficients[0]-c,r,EPS); - break; - case 3: - rCount=Factor(coefficients[3],coefficients[2],coefficients[1],coefficients[0]-c,r,EPS); - break; -// case 4: -// rCount=Factor(coefficients[4],coefficients[3],coefficients[2],coefficients[1],coefficients[0]-c,r,EPS); -// break; - default: - printf("Can't solve polynomial of degree: %d\n",Degree); - } - for(int i=0;i -int Polynomial::getSolutions( double c , double* roots , double EPS ) const + +template<> +int Polynomial<1>::getSolutions( double c , double* roots , double EPS ) const { - double _roots[4][2]; - int _rCount=0; - switch( Degree ) - { - case 1: _rCount = Factor( coefficients[1] , coefficients[0]-c , _roots , EPS ) ; break; - case 2: _rCount = Factor( coefficients[2] , coefficients[1] , coefficients[0]-c , _roots , EPS ) ; break; - case 3: _rCount = Factor( coefficients[3] , coefficients[2] , coefficients[1] , coefficients[0]-c , _roots , EPS ) ; break; -// case 4: _rCount = Factor( coefficients[4] , coefficients[3] , coefficients[2] , coefficients[1] , coefficients[0]-c , _roots , EPS ) ; break; - default: printf( "Can't solve polynomial of degree: %d\n" , Degree ); - } - int rCount = 0; - for( int i=0 ; i<_rCount ; i++ ) if( fabs(_roots[i][1])<=EPS ) roots[rCount++] = _roots[i][0]; - return rCount; + double _roots[1][2]; + Factor(coefficients[1] , coefficients[0]-c , _roots , EPS ); + + int realRoots = 0; + if (fabs(_roots[0][1]) <= EPS) + roots[realRoots++] = _roots[0][0]; + return realRoots; } + +template<> +int Polynomial<2>::getSolutions( double c , double* roots , double EPS ) const +{ + double _roots[2][2]; + Factor(coefficients[2] , coefficients[1] , coefficients[0]-c, _roots, EPS); + + int realRoots = 0; + if (fabs(_roots[0][1]) <= EPS) + roots[realRoots++] = _roots[0][0]; + if (fabs(_roots[1][1]) <= EPS) + roots[realRoots++] = _roots[1][0]; + return realRoots; +} + +template<> +int Polynomial<3>::getSolutions(double c, double *roots, double EPS) const +{ + double _roots[3][2]; + Factor(coefficients[3] , coefficients[2] , coefficients[1] , + coefficients[0]-c , _roots , EPS ); + + int realRoots = 0; + if (fabs(_roots[0][1]) <= EPS) + roots[realRoots++] = _roots[0][0]; + if (fabs(_roots[1][1]) <= EPS) + roots[realRoots++] = _roots[1][0]; + if (fabs(_roots[2][1]) <= EPS) + roots[realRoots++] = _roots[2][0]; + return realRoots; +} + // The 0-th order B-spline template< > Polynomial< 0 > Polynomial< 0 >::BSplineComponent( int i ) diff --git a/Src/SSDRecon.cpp b/Src/SSDRecon.cpp index 3f109c36..67e8e974 100644 --- a/Src/SSDRecon.cpp +++ b/Src/SSDRecon.cpp @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -39,6 +39,7 @@ DAMAGE. #include #include #endif // _WIN32 || _WIN64 +#include "MemMesh.h" #include "MyTime.h" #include "MarchingCubes.h" #include "Octree.h" @@ -53,6 +54,10 @@ DAMAGE. void DumpOutput( const char* format , ... ); void DumpOutput2( std::vector< char* >& comments , const char* format , ... ); #include "MultiGridOctreeData.h" +#include "point_source/AsciiPointSource.h" +#include "point_source/BinaryPointSource.h" +#include "point_source/TransformedPointSource.h" +#include "point_source/PlyPointSource.h" #define DEFAULT_FULL_DEPTH 5 @@ -62,6 +67,8 @@ void DumpOutput2( std::vector< char* >& comments , const char* format , ... ); #pragma message ( "[WARNING] Setting default full depth to " XSTR(DEFAULT_FULL_DEPTH) ) #endif // DEFAULT_FULL_DEPTH +using MeshPtr = std::unique_ptr; + #include char* outputFile=NULL; int echoStdout=0; @@ -157,8 +164,8 @@ cmdLineFloat SamplesPerNode( "samplesPerNode" , 1.5f ) , Scale( "scale" , 1.1f ) , CGSolverAccuracy( "cgAccuracy" , 1e-3f ) , - LowResIterMultiplier( "iterMultiplier" , 1.5f ) , - ValueWeight ( "valueWeight" , 4e-0f ) , + LowResIterMultiplier( "iterMultiplier" , 1.5f ) , + ValueWeight ( "valueWeight" , 4e-0f ) , GradientWeight( "gradientWeight" , 1e-3f ) , BiLapWeight ( "biLapWeight" , 1e-5f ); @@ -267,10 +274,10 @@ void ShowUsage( char* ex ) #endif // !FOR_RELEASE #ifndef FOR_RELEASE printf( "\t[--%s]\n" , ASCII.name ); - + printf( "\t[--%s]\n" , NoComments.name ); #endif // !FOR_RELEASE - + #ifndef FAST_COMPILE printf( "\t[--%s]\n" , Double.name ); #endif // !FAST_COMPILE @@ -294,7 +301,7 @@ const PlyProperty ColorInfo< float >::PlyProperties[] = { "r" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[0] ) ) , 0 , 0 , 0 , 0 } , { "g" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[1] ) ) , 0 , 0 , 0 , 0 } , { "b" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[2] ) ) , 0 , 0 , 0 , 0 } , - { "red" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[0] ) ) , 0 , 0 , 0 , 0 } , + { "red" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[0] ) ) , 0 , 0 , 0 , 0 } , { "green" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[1] ) ) , 0 , 0 , 0 , 0 } , { "blue" , PLY_UCHAR , PLY_FLOAT , int( offsetof( Point3D< float > , coords[2] ) ) , 0 , 0 , 0 , 0 } }; @@ -304,7 +311,7 @@ const PlyProperty ColorInfo< double >::PlyProperties[] = { "r" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[0] ) ) , 0 , 0 , 0 , 0 } , { "g" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[1] ) ) , 0 , 0 , 0 , 0 } , { "b" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[2] ) ) , 0 , 0 , 0 , 0 } , - { "red" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[0] ) ) , 0 , 0 , 0 , 0 } , + { "red" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[0] ) ) , 0 , 0 , 0 , 0 } , { "green" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[1] ) ) , 0 , 0 , 0 , 0 } , { "blue" , PLY_UCHAR , PLY_DOUBLE , int( offsetof( Point3D< double > , coords[2] ) ) , 0 , 0 , 0 , 0 } }; @@ -382,10 +389,10 @@ struct OctreeProfiler }; template< class Real > -XForm4x4< Real > GetPointXForm( OrientedPointStream< Real >& stream , Real scaleFactor ) +XForm4x4< Real > GetPointXForm(PointSource& source , Real scaleFactor ) { - Point3D< Real > min , max; - stream.boundingBox( min , max ); + Point3D min , max; + source.boundingBox( min , max ); Point3D< Real > center = ( max + min ) / 2; Real scale = std::max< Real >( max[0]-min[0] , std::max< Real >( max[1]-min[1] , max[2]-min[2] ) ); scale *= scaleFactor; @@ -395,15 +402,66 @@ XForm4x4< Real > GetPointXForm( OrientedPointStream< Real >& stream , Real scale return sXForm * tXForm; } +PointSourcePtr createPointSource(const char *filename, bool color) +{ + std::string ext = GetFileExtension(filename); + for (auto& c : ext) + c = std::tolower(c); + + PointSource *pointSource; + if (color) + { + if (ext == "bnpts") + pointSource = new ColorBinaryPointSource(filename); + else if (ext == "ply") + pointSource = new ColorPLYPointSource(filename); + else + pointSource = new ColorASCIIPointSource(filename); + } + else + { + if (ext == "bnpts") + pointSource = new BinaryPointSource(filename); + else if (ext == "ply") + pointSource = new PLYPointSource(filename); + else + pointSource = new ASCIIPointSource(filename); + } + return PointSourcePtr(pointSource); +} + +template +MeshPtr createMesh(); + +template<> +MeshPtr createMesh>() +{ + return MeshPtr(new Kazhdan::MemMesh); +} + +template<> +MeshPtr createMesh>() +{ + return MeshPtr(new Kazhdan::ColorMemMesh); +} + +template<> +MeshPtr createMesh>() +{ + return MeshPtr(new Kazhdan::DensityMemMesh); +} + +template<> +MeshPtr createMesh>() +{ + return MeshPtr(new Kazhdan::CompleteMemMesh); +} + template< class Real , int Degree , BoundaryType BType , class Vertex > int _Execute( int argc , char* argv[] ) { - typedef typename Octree< Real >::template DensityEstimator< WEIGHT_DEGREE > DensityEstimator; + typedef typename Octree< Real >::DensityEstimator DensityEstimator; typedef typename Octree< Real >::template InterpolationInfo< true > InterpolationInfo; - typedef OrientedPointStream< Real > PointStream; - typedef OrientedPointStreamWithData< Real , Point3D< Real > > PointStreamWithData; - typedef TransformedOrientedPointStream< Real > XPointStream; - typedef TransformedOrientedPointStreamWithData< Real , Point3D< Real > > XPointStreamWithData; Reset< Real >(); int paramNum = sizeof(params)/sizeof(cmdLineReadable*); std::vector< char* > comments; @@ -454,7 +512,7 @@ int _Execute( int argc , char* argv[] ) return 0; } if( !MaxSolveDepth.set ) MaxSolveDepth.value = Depth.value; - + OctNode< TreeNodeData >::SetAllocator( MEMORY_ALLOCATOR_BLOCK_SIZE ); int kernelDepth = KernelDepth.set ? KernelDepth.value : Depth.value-2; @@ -470,53 +528,45 @@ int _Execute( int argc , char* argv[] ) std::vector< typename Octree< Real >::PointSample >* samples = new std::vector< typename Octree< Real >::PointSample >(); std::vector< ProjectiveData< Point3D< Real > , Real > >* sampleData = NULL; DensityEstimator* density = NULL; - SparseNodeData< Point3D< Real > , NORMAL_DEGREE >* normalInfo = NULL; + SparseNodeData< Point3D< Real > >* normalInfo = NULL; Real targetValue = (Real)0.; // Read in the samples (and color data) { profiler.start(); - PointStream* pointStream; - char* ext = GetFileExtension( In.value ); - if( Color.set && Color.value>0 ) - { - sampleData = new std::vector< ProjectiveData< Point3D< Real > , Real > >(); - if ( !strcasecmp( ext , "bnpts" ) ) pointStream = new BinaryOrientedPointStreamWithData< Real , Point3D< Real > , float , Point3D< unsigned char > >( In.value ); - else if( !strcasecmp( ext , "ply" ) ) pointStream = new PLYOrientedPointStreamWithData< Real , Point3D< Real > >( In.value , ColorInfo< Real >::PlyProperties , 6 , ColorInfo< Real >::ValidPlyProperties ); - else pointStream = new ASCIIOrientedPointStreamWithData< Real , Point3D< Real > >( In.value , ColorInfo< Real >::ReadASCII ); - } - else - { - if ( !strcasecmp( ext , "bnpts" ) ) pointStream = new BinaryOrientedPointStream< Real , float >( In.value ); - else if( !strcasecmp( ext , "ply" ) ) pointStream = new PLYOrientedPointStream< Real >( In.value ); - else pointStream = new ASCIIOrientedPointStream< Real >( In.value ); - } - delete[] ext; - XPointStream _pointStream( xForm , *pointStream ); - xForm = GetPointXForm( _pointStream , (Real)Scale.value ) * xForm; - if( sampleData ) - { - XPointStreamWithData _pointStream( xForm , ( PointStreamWithData& )*pointStream ); - pointCount = tree.template init< Point3D< Real > >( _pointStream , Depth.value , Confidence.set , *samples , sampleData ); + PointSourcePtr source(createPointSource(In.value, + Color.set && Color.value > 0)); + TransformedPointSource _pointSource(xForm , *source); + xForm = GetPointXForm(_pointSource, (Real)Scale.value) * xForm; + + ColorPointSource *colorSource = + dynamic_cast(source.get()); + if (colorSource) + { + sampleData = new std::vector, Real>>(); + ColorTransformedPointSource xsource(xForm, *colorSource); + pointCount = tree.template init< Point3D< Real > >(xsource, + Depth.value, Confidence.set, *samples, sampleData); } else { - XPointStream _pointStream( xForm , *pointStream ); - pointCount = tree.template init< Point3D< Real > >( _pointStream , Depth.value , Confidence.set , *samples , sampleData ); + TransformedPointSource xsource(xForm , *source); + pointCount = tree.template init>(xsource, + Depth.value, Confidence.set, *samples, sampleData ); } iXForm = xForm.inverse(); - delete pointStream; #pragma omp parallel for num_threads( Threads.value ) - for( int i=0 ; i<(int)samples->size() ; i++ ) (*samples)[i].sample.data.n *= (Real)-1; + for( int i=0 ; i<(int)samples->size() ; i++ ) + (*samples)[i].sample.data.n *= (Real)-1; DumpOutput( "Input Points / Samples: %d / %d\n" , pointCount , samples->size() ); profiler.dumpOutput2( comments , "# Read input into tree:" ); } - DenseNodeData< Real , Degree > solution; + DenseNodeData< Real > solution; // Solve { - DenseNodeData< Real , Degree > constraints; + DenseNodeData< Real > constraints; InterpolationInfo* iInfo = NULL; int solveDepth = MaxSolveDepth.value; @@ -525,15 +575,15 @@ int _Execute( int argc , char* argv[] ) // Get the kernel density estimator { profiler.start(); - density = tree.template setDensityEstimator< WEIGHT_DEGREE >( *samples , kernelDepth , SamplesPerNode.value ); + density = tree.template setDensityEstimator( *samples , kernelDepth , SamplesPerNode.value ); profiler.dumpOutput2( comments , "# Got kernel density:" ); } // Transform the Hermite samples into a vector field { profiler.start(); - normalInfo = new SparseNodeData< Point3D< Real > , NORMAL_DEGREE >(); - *normalInfo = tree.template setNormalField< NORMAL_DEGREE >( *samples , *density , pointWeightSum , BType==BOUNDARY_NEUMANN ); + normalInfo = new SparseNodeData< Point3D< Real > >(); + *normalInfo = tree.template setNormalField< NORMAL_DEGREE, WEIGHT_DEGREE >( *samples , *density , pointWeightSum , BType==BOUNDARY_NEUMANN ); profiler.dumpOutput2( comments , "# Got normal field:" ); } @@ -560,7 +610,7 @@ int _Execute( int argc , char* argv[] ) { profiler.start(); iInfo = new InterpolationInfo( tree , *samples , targetValue , AdaptiveExponent.value , (Real)ValueWeight.value * pointWeightSum , (Real)GradientWeight.value * pointWeightSum ); - constraints = tree.template initDenseNodeData< Degree >( ); + constraints = tree.template initDenseNodeData( ); tree.template addInterpolationConstraints< Degree , BType >( *iInfo , constraints , solveDepth ); profiler.dumpOutput2( comments , "#Set point constraints:" ); } @@ -580,7 +630,7 @@ int _Execute( int argc , char* argv[] ) } } - CoredFileMeshData< Vertex > mesh; + MeshPtr mesh(createMesh()); { profiler.start(); @@ -626,11 +676,11 @@ int _Execute( int argc , char* argv[] ) if( Out.set ) { profiler.start(); - SparseNodeData< ProjectiveData< Point3D< Real > , Real > , DATA_DEGREE >* colorData = NULL; + SparseNodeData< ProjectiveData< Point3D< Real > , Real > >* colorData = NULL; if( sampleData ) { - colorData = new SparseNodeData< ProjectiveData< Point3D< Real > , Real > , DATA_DEGREE >(); - *colorData = tree.template setDataField< DATA_DEGREE , false >( *samples , *sampleData , (DensityEstimator*)NULL ); + colorData = new SparseNodeData< ProjectiveData< Point3D< Real > , Real > >(); + *colorData = tree.template setDataField< DATA_DEGREE , false, WEIGHT_DEGREE >( *samples , *sampleData , (DensityEstimator*)NULL ); delete sampleData , sampleData = NULL; for( const OctNode< TreeNodeData >* n = tree.tree().nextNode() ; n ; n=tree.tree().nextNode( n ) ) { @@ -638,8 +688,8 @@ int _Execute( int argc , char* argv[] ) if( clr ) (*clr) *= (Real)pow( Color.value , tree.depth( n ) ); } } - tree.template getMCIsoSurface< Degree , BType , WEIGHT_DEGREE , DATA_DEGREE >( density , colorData , solution , isoValue , mesh , NonLinearFit.set , !NonManifold.set , PolygonMesh.set ); - DumpOutput( "Vertices / Polygons: %d / %d\n" , mesh.outOfCorePointCount()+mesh.inCorePoints.size() , mesh.polygonCount() ); + tree.template getMCIsoSurface< Degree , BType , WEIGHT_DEGREE , DATA_DEGREE, Vertex >( density , colorData , solution , isoValue , *mesh , NonLinearFit.set , !NonManifold.set , PolygonMesh.set ); + DumpOutput( "Vertices / Polygons: %d / %d\n" , mesh->pointCount(), mesh->polygonCount() ); if( PolygonMesh.set ) profiler.dumpOutput2( comments , "# Got polygons:" ); else profiler.dumpOutput2( comments , "# Got triangles:" ); @@ -647,13 +697,13 @@ int _Execute( int argc , char* argv[] ) if( NoComments.set ) { - if( ASCII.set ) PlyWritePolygons( Out.value , &mesh , PLY_ASCII , NULL , 0 , iXForm ); - else PlyWritePolygons( Out.value , &mesh , PLY_BINARY_NATIVE , NULL , 0 , iXForm ); + if( ASCII.set ) PlyWritePolygons( Out.value , *mesh , PLY_ASCII , NULL , 0 , iXForm ); + else PlyWritePolygons( Out.value , *mesh , PLY_BINARY_NATIVE , NULL , 0 , iXForm ); } else { - if( ASCII.set ) PlyWritePolygons( Out.value , &mesh , PLY_ASCII , &comments[0] , (int)comments.size() , iXForm ); - else PlyWritePolygons( Out.value , &mesh , PLY_BINARY_NATIVE , &comments[0] , (int)comments.size() , iXForm ); + if( ASCII.set ) PlyWritePolygons( Out.value , *mesh , PLY_ASCII , &comments[0] , (int)comments.size() , iXForm ); + else PlyWritePolygons( Out.value , *mesh , PLY_BINARY_NATIVE , &comments[0] , (int)comments.size() , iXForm ); } } if( density ) delete density , density = NULL; diff --git a/Src/SparseMatrix.inl b/Src/SparseMatrix.inl index 763590ae..21372119 100644 --- a/Src/SparseMatrix.inl +++ b/Src/SparseMatrix.inl @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -345,8 +345,12 @@ SetOMPParallel \ } \ } #endif // ZERO_TESTING_JACOBI - if( forward ) for( int j=0 ; j=0 ; j-- ){ sum += int( mcIndices[j].size() ) ; ITERATE( mcIndices[j] ); } + if( forward ) + for( int j=0 ; j=0 ; j-- ) + { sum += int( mcIndices[j].size() ) ; ITERATE( mcIndices[j] ); } #undef ITERATE #undef SetOMPParallel return sum; @@ -400,7 +404,7 @@ int SparseMatrix::SolveGS( const std::vector< std::vector< int > >& mcIndices T2 _b = b[jj]; for( e=start ; e!=end ; e++ ) _b -= x[ e->N ] * e->Value; x[jj] = _b / diagonal; - } + } } } } diff --git a/Src/SurfaceTrimmer.cpp b/Src/SurfaceTrimmer.cpp index 62a8fee7..c8827a0d 100644 --- a/Src/SurfaceTrimmer.cpp +++ b/Src/SurfaceTrimmer.cpp @@ -8,14 +8,14 @@ are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the distribution. +in the documentation and/or other materials provided with the distribution. Neither the name of the Johns Hopkins University nor the names of its contributors may be used to endorse or promote products derived from this software without specific -prior written permission. +prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY -EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED @@ -28,24 +28,22 @@ DAMAGE. #undef ARRAY_DEBUG -#include -#include -#include -#ifdef _OPENMP -#include -#endif // _OPENMP -#include +#include +#include + #include "CmdLineParser.h" -#include "Geometry.h" #include "Ply.h" -#include "MAT.h" #include "MyTime.h" +#include "SurfaceTrimmer.h" + cmdLineString In( "in" ) , Out( "out" ); cmdLineInt Smooth( "smooth" , 5 ); cmdLineFloat Trim( "trim" ) , IslandAreaRatio( "aRatio" , 0.001f ); cmdLineReadable PolygonMesh( "polygonMesh" ); +typedef std::vector Polygon; + cmdLineReadable* params[] = { &In , &Out , &Trim , &PolygonMesh , &Smooth , &IslandAreaRatio @@ -57,309 +55,120 @@ void ShowUsage( char* ex ) printf( "\t --%s \n" , In.name ); printf( "\t[--%s ]\n" , Trim.name ); printf( "\t[--%s ]\n" , Out.name ); - printf( "\t[--%s =%d]\n" , Smooth.name , Smooth.value ); - printf( "\t[--%s =%f]\n" , IslandAreaRatio.name , IslandAreaRatio.value ); + printf( "\t[--%s =%d]\n" , + Smooth.name , Smooth.value ); + printf( "\t[--%s =%f]\n" , + IslandAreaRatio.name , IslandAreaRatio.value ); printf( "\t[--%s]\n" , PolygonMesh.name ); } -long long EdgeKey( int key1 , int key2 ) +template +void readData(std::vector& vertices, std::vector& polygons, + std::vector comments) { - if( key1 -Vertex InterpolateVertices( const Vertex& v1 , const Vertex& v2 , Real value ) +template +void writeData(std::vector& vertices, std::vector& polygons, + std::vector comments) { - typename Vertex::Wrapper _v1(v1) , _v2(v2); - if( _v1.value==_v2.value ) return Vertex( (_v1+_v2)/Real(2.) ); + if (!Out.set) + return; - Real dx = ( _v1.value-value ) / ( _v1.value-_v2.value ); - return Vertex( _v1*(1.f-dx) + _v2*dx ); -} -template< class Real , class Vertex > -void SmoothValues( std::vector< Vertex >& vertices , const std::vector< std::vector< int > >& polygons ) -{ - std::vector< int > count( vertices.size() ); - std::vector< Real > sums( vertices.size() , 0 ); - for( size_t i=0 ; i -void SplitPolygon - ( - const std::vector< int >& polygon , - std::vector< Vertex >& vertices , - std::vector< std::vector< int > >* ltPolygons , std::vector< std::vector< int > >* gtPolygons , - std::vector< bool >* ltFlags , std::vector< bool >* gtFlags , - std::unordered_map< long long, int >& vertexTable, - Real trimValue - ) -{ - int sz = int( polygon.size() ); - std::vector< bool > gt( sz ); - int gtCount = 0; - for( int j=0 ; jtrimValue ); - if( gt[j] ) gtCount++; - } - if ( gtCount==sz ){ if( gtPolygons ) gtPolygons->push_back( polygon ) ; if( gtFlags ) gtFlags->push_back( false ); } - else if( gtCount==0 ){ if( ltPolygons ) ltPolygons->push_back( polygon ) ; if( ltFlags ) ltFlags->push_back( false ); } - else - { - int start; - for( start=0 ; start poly; - - // Add the initial vertex - { - int j1 = (start+int(sz)-1)%sz , j2 = start; - int v1 = polygon[j1] , v2 = polygon[j2]; - int vIdx; - std::unordered_map< long long, int >::iterator iter = vertexTable.find(EdgeKey(v1, v2)); - if( iter==vertexTable.end() ) - { - vertexTable[ EdgeKey( v1 , v2 ) ] = vIdx = int( vertices.size() ); - vertices.push_back( InterpolateVertices( vertices[v1] , vertices[v2] , trimValue ) ); - } - else vIdx = iter->second; - poly.push_back( vIdx ); - } - - for( int _j=0 ; _j<=sz ; _j++ ) - { - int j1 = (_j+start+sz-1)%sz , j2 = (_j+start)%sz; - int v1 = polygon[j1] , v2 = polygon[j2]; - if( gt[j2]==gtFlag ) poly.push_back( v2 ); - else - { - int vIdx; - std::unordered_map< long long, int >::iterator iter = vertexTable.find(EdgeKey(v1, v2)); - if( iter==vertexTable.end() ) - { - vertexTable[ EdgeKey( v1 , v2 ) ] = vIdx = int( vertices.size() ); - vertices.push_back( InterpolateVertices( vertices[v1] , vertices[v2] , trimValue ) ); - } - else vIdx = iter->second; - poly.push_back( vIdx ); - if( gtFlag ){ if( gtPolygons ) gtPolygons->push_back( poly ) ; if( ltFlags ) ltFlags->push_back( true ); } - else { if( ltPolygons ) ltPolygons->push_back( poly ) ; if( gtFlags ) gtFlags->push_back( true ); } - poly.clear() , poly.push_back( vIdx ) , poly.push_back( v2 ); - gtFlag = !gtFlag; - } - } - } -} -template< class Real , class Vertex > -void Triangulate( const std::vector< Vertex >& vertices , const std::vector< std::vector< int > >& polygons , std::vector< std::vector< int > >& triangles ) -{ - triangles.clear(); - for( size_t i=0 ; i3 ) - { - MinimalAreaTriangulation< Real > mat; - std::vector< Point3D< Real > > _vertices( polygons[i].size() ); - std::vector< TriangleIndex > _triangles; - for( int j=0 ; j -double PolygonArea( const std::vector< Vertex >& vertices , const std::vector< int >& polygon ) -{ - if( polygon.size()<3 ) return 0.; - else if( polygon.size()==3 ) return TriangleArea( vertices[polygon[0]].point , vertices[polygon[1]].point , vertices[polygon[2]].point ); - else - { - Point3D< Real > center; - for( size_t i=0 ; i -void RemoveHangingVertices( std::vector< Vertex >& vertices , std::vector< std::vector< int > >& polygons ) -{ - std::unordered_map< int, int > vMap; - std::vector< bool > vertexFlags( vertices.size() , false ); - for( size_t i=0 ; i _vertices( vCount ); - for( int i=0 ; i >& polygons , std::vector< std::vector< int > >& components ) + + +void addComments(std::vector comments) { - std::vector< int > polygonRoots( polygons.size() ); - for( size_t i=0 ; i edgeTable; - for( size_t i=0 ; i::iterator iter = edgeTable.find(eKey); - if( iter==edgeTable.end() ) edgeTable[ eKey ] = int(i); - else - { - int p = iter->second; - while( polygonRoots[p]!=p ) - { - int temp = polygonRoots[p]; - polygonRoots[p] = int(i); - p = temp; - } - polygonRoots[p] = int(i); - } - } - } - for( size_t i=0 ; i vMap; - for( int i= 0 ; i -inline Point3D< Real > CrossProduct( Point3D< Real > p1 , Point3D< Real > p2 ){ return Point3D< Real >( p1[1]*p2[2]-p1[2]*p2[1] , p1[2]*p2[0]-p1[0]*p2[2] , p1[0]*p1[1]-p1[1]*p2[0] ); } -template< class Real > -double TriangleArea( Point3D< Real > v1 , Point3D< Real > v2 , Point3D< Real > v3 ) + + +template +void printVertexValues(std::vector& vertices) { - Point3D< Real > n = CrossProduct( v2-v1 , v3-v1 ); - return sqrt( n[0]*n[0] + n[1]*n[1] + n[2]*n[2] ) / 2.; + if (vertices.empty()) + return; + + float min = vertices[0].value; + float max = vertices[0].value; + + for (Vertex& v : vertices) + { + min = std::min(min, v.value); + max = std::max(min, v.value); + } + std::cout << "Value Range: [" << min << "," << max << "]\n"; } -template< class Vertex > -int Execute( void ) -{ - float min , max; - int paramNum = sizeof(params)/sizeof(cmdLineReadable*); - std::vector< Vertex > vertices; - std::vector< std::vector< int > > polygons; - - int ft , commentNum = paramNum+2; - char** comments; - PlyReadPolygons( In.value , vertices , polygons , Vertex::ReadProperties , Vertex::ReadComponents , ft , &comments , &commentNum ); - for( int i=0 ; i( vertices , polygons ); - min = max = vertices[0].value; - for( size_t i=0 ; i( min , vertices[i].value ) , max = std::max< float >( max , vertices[i].value ); - printf( "Value Range: [%f,%f]\n" , min , max ); - - std::unordered_map< long long, int > vertexTable; - std::vector< std::vector< int > > ltPolygons , gtPolygons; - std::vector< bool > ltFlags , gtFlags; - - for( int i=0 ; i0 ) - { - std::vector< std::vector< int > > _ltPolygons , _gtPolygons; - std::vector< std::vector< int > > ltComponents , gtComponents; - SetConnectedComponents( ltPolygons , ltComponents ); - SetConnectedComponents( gtPolygons , gtComponents ); - std::vector< double > ltAreas( ltComponents.size() , 0. ) , gtAreas( gtComponents.size() , 0. ); - std::vector< bool > ltComponentFlags( ltComponents.size() , false ) , gtComponentFlags( gtComponents.size() , false ); - double area = 0.; - for( size_t i=0 ; i( vertices , ltPolygons[ ltComponents[i][j] ] ); - ltComponentFlags[i] = ( ltComponentFlags[i] || ltFlags[ ltComponents[i][j] ] ); - } - area += ltAreas[i]; - } - for( size_t i=0 ; i( vertices , gtPolygons[ gtComponents[i][j] ] ); - gtComponentFlags[i] = ( gtComponentFlags[i] || gtFlags[ gtComponents[i][j] ] ); - } - area += gtAreas[i]; - } - for( size_t i=0 ; i > polys = ltPolygons; - Triangulate< float , Vertex >( vertices , ltPolygons , polys ) , ltPolygons = polys; - } - { - std::vector< std::vector< int > > polys = gtPolygons; - Triangulate< float , Vertex >( vertices , gtPolygons , polys ) , gtPolygons = polys; - } - } - RemoveHangingVertices( vertices , gtPolygons ); - sprintf( comments[commentNum++] , "#Trimmed In: %9.1f (s)" , Time()-t ); - if( Out.set ) PlyWritePolygons( Out.value , vertices , gtPolygons , Vertex::WriteProperties , Vertex::WriteComponents , ft , comments , commentNum ); - return EXIT_SUCCESS; +template +int execute() +{ + using ST = SurfaceTrimmer; + + std::vector vertices; + std::vector polygons; + std::vector comments; + + readData(vertices, polygons, comments); + addComments(comments); + + ST trimmer(vertices, polygons, Trim.value, + IslandAreaRatio.value, PolygonMesh.set); + + while (Smooth.value--) + trimmer.SmoothValues(); + printVertexValues(vertices); + + double t = Time(); + + int result = trimmer.Execute(); + + comments.push_back("#Trimmed In " + std::to_string((Time() - t)) + + " (s)"); + writeData(vertices, polygons, comments); + return result; } + + int main( int argc , char* argv[] ) { int paramNum = sizeof(params)/sizeof(cmdLineReadable*); @@ -371,12 +180,26 @@ int main( int argc , char* argv[] ) return EXIT_FAILURE; } bool readFlags[ PlyColorAndValueVertex< float >::ReadComponents ]; - if( !PlyReadHeader( In.value , PlyColorAndValueVertex< float >::ReadProperties , PlyColorAndValueVertex< float >::ReadComponents , readFlags ) ) fprintf( stderr , "[ERROR] Failed to read ply header: %s\n" , In.value ) , exit( 0 ); + if (!PlyReadHeader(In.value, PlyColorAndValueVertex::ReadProperties, + PlyColorAndValueVertex::ReadComponents, readFlags)) + { + fprintf(stderr , "[ERROR] Failed to read ply header: %s\n" , In.value); + exit( 0 ); + } bool hasValue = readFlags[3]; - bool hasColor = ( readFlags[4] || readFlags[7] ) && ( readFlags[5] || readFlags[8] ) && ( readFlags[6] || readFlags[9] ); + bool hasColor = ( readFlags[4] || readFlags[7] ) && + ( readFlags[5] || readFlags[8] ) && ( readFlags[6] || readFlags[9] ); - if( !hasValue ) fprintf( stderr , "[ERROR] Ply file does not contain values\n" ) , exit( 0 ); - if( hasColor ) return Execute< PlyColorAndValueVertex< float > >(); - else return Execute< PlyValueVertex< float > >(); + if( !hasValue ) + { + fprintf( stderr , "[ERROR] Ply file does not contain values\n" ); + exit( 0 ); + } + + if ( hasColor) + return execute>(); + else + return execute>(); } + diff --git a/Src/SurfaceTrimmer.h b/Src/SurfaceTrimmer.h new file mode 100644 index 00000000..0643078d --- /dev/null +++ b/Src/SurfaceTrimmer.h @@ -0,0 +1,424 @@ +/* +Copyright (c) 2013, Michael Kazhdan +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#undef ARRAY_DEBUG + +/** +#include +#include +#include +#ifdef _OPENMP +#include +#endif // _OPENMP +#include +#include "Geometry.h" +#include "Ply.h" +#include "MyTime.h" +**/ + +#include "MAT.h" + +long long EdgeKey( int key1 , int key2 ) +{ + if( key1 +inline Point3D< Real > CrossProduct( Point3D< Real > p1 , Point3D< Real > p2 ) +{ + return Point3D< Real >( p1[1]*p2[2]-p1[2]*p2[1] , + p1[2]*p2[0]-p1[0]*p2[2] , p1[0]*p1[1]-p1[1]*p2[0] ); +} + +template< class Real > +double TriangleArea( Point3D< Real > v1 , Point3D< Real > v2 , + Point3D< Real > v3 ) +{ + Point3D< Real > n = CrossProduct( v2-v1 , v3-v1 ); + return sqrt( n[0]*n[0] + n[1]*n[1] + n[2]*n[2] ) / 2.; +} + +template +class SurfaceTrimmer +{ +public: + typedef std::vector Polygon; + +private: + float m_trim; + float m_islandRatio; + bool m_polygonMesh; + std::vector& m_vertices; + std::vector& m_polygons; + +public: + SurfaceTrimmer(std::vector& vertices, + std::vector& polygons, Real trim, Real islandRatio = .001, + bool polygonMesh = false) : + m_trim(trim), m_islandRatio(islandRatio), m_polygonMesh(polygonMesh), + m_vertices(vertices), m_polygons(polygons) + {} + int Execute(); + void SmoothValues(); + +private: + Vertex InterpolateVertices( const Vertex& v1 , const Vertex& v2 , + Real value ); + void SplitPolygon(const Polygon& polygon, std::vector* ltPolygons, + std::vector* gtPolygons , std::vector< bool >* ltFlags, + std::vector< bool >* gtFlags , + std::unordered_map< long long, int >& vertexTable, Real trimValue); + void Triangulate( const std::vector& polygons , + std::vector< std::vector< int > >& triangles ); + double PolygonArea( const Polygon& polygon ); + void RemoveHangingVertices( std::vector& polygons ); + void SetConnectedComponents( const std::vector& polygons , + std::vector< std::vector< int > >& components ); + double calcAreas(std::vector& polygons, + std::vector>& components, std::vector& flags, + std::vector& areas); + void reSortPolygons(std::vector& ltPolygons, + std::vector>& ltComponents, std::vector& ltFlags, + std::vector& ltAreas, + std::vector& gtPolygons, + std::vector>& gtComponents, std::vector& gtFlags, + std::vector gtAreas, double islandArea); +}; + +template +Vertex SurfaceTrimmer::InterpolateVertices( const Vertex& v1 , + const Vertex& v2 , Real value ) +{ + typename Vertex::Wrapper _v1(v1) , _v2(v2); + if( _v1.value==_v2.value ) return Vertex( (_v1+_v2)/Real(2.) ); + + Real dx = ( _v1.value-value ) / ( _v1.value-_v2.value ); + return Vertex( _v1*(1.f-dx) + _v2*dx ); +} + +template +void SurfaceTrimmer::SmoothValues() +{ + std::vector< int > count( m_vertices.size() ); + std::vector< Real > sums( m_vertices.size() , 0 ); + for( size_t i=0 ; i +void SurfaceTrimmer::SplitPolygon + ( + const Polygon& polygon , + std::vector* ltPolygons , std::vector* gtPolygons , + std::vector< bool >* ltFlags , std::vector< bool >* gtFlags , + std::unordered_map< long long, int >& vertexTable, + Real trimValue + ) +{ + int sz = int( polygon.size() ); + std::vector< bool > gt( sz ); + int gtCount = 0; + for( int j=0 ; jtrimValue ); + if( gt[j] ) gtCount++; + } + if ( gtCount==sz ){ if( gtPolygons ) gtPolygons->push_back( polygon ) ; if( gtFlags ) gtFlags->push_back( false ); } + else if( gtCount==0 ){ if( ltPolygons ) ltPolygons->push_back( polygon ) ; if( ltFlags ) ltFlags->push_back( false ); } + else + { + int start; + for( start=0 ; start poly; + + // Add the initial vertex + { + int j1 = (start+int(sz)-1)%sz , j2 = start; + int v1 = polygon[j1] , v2 = polygon[j2]; + int vIdx; + std::unordered_map< long long, int >::iterator iter = vertexTable.find(EdgeKey(v1, v2)); + if( iter==vertexTable.end() ) + { + vertexTable[ EdgeKey( v1 , v2 ) ] = vIdx = int( m_vertices.size() ); + m_vertices.push_back( InterpolateVertices( m_vertices[v1] , m_vertices[v2] , trimValue ) ); + } + else vIdx = iter->second; + poly.push_back( vIdx ); + } + + for( int _j=0 ; _j<=sz ; _j++ ) + { + int j1 = (_j+start+sz-1)%sz , j2 = (_j+start)%sz; + int v1 = polygon[j1] , v2 = polygon[j2]; + if( gt[j2]==gtFlag ) poly.push_back( v2 ); + else + { + int vIdx; + std::unordered_map< long long, int >::iterator iter = vertexTable.find(EdgeKey(v1, v2)); + if( iter==vertexTable.end() ) + { + vertexTable[ EdgeKey( v1 , v2 ) ] = vIdx = int( m_vertices.size() ); + m_vertices.push_back( InterpolateVertices( m_vertices[v1] , m_vertices[v2] , trimValue ) ); + } + else vIdx = iter->second; + poly.push_back( vIdx ); + if( gtFlag ){ if( gtPolygons ) gtPolygons->push_back( poly ) ; if( ltFlags ) ltFlags->push_back( true ); } + else { if( ltPolygons ) ltPolygons->push_back( poly ) ; if( gtFlags ) gtFlags->push_back( true ); } + poly.clear() , poly.push_back( vIdx ) , poly.push_back( v2 ); + gtFlag = !gtFlag; + } + } + } +} + +template +void SurfaceTrimmer::Triangulate( + const std::vector& polygons, + std::vector< std::vector< int > >& triangles ) +{ + triangles.clear(); + for( size_t i=0 ; i3 ) + { + MinimalAreaTriangulation< Real > mat; + std::vector< Point3D< Real > > _vertices( polygons[i].size() ); + std::vector< TriangleIndex > _triangles; + for( int j=0 ; j +double SurfaceTrimmer::PolygonArea( const Polygon& polygon ) +{ + if( polygon.size()<3 ) return 0.; + else if( polygon.size()==3 ) return TriangleArea( m_vertices[polygon[0]].point , m_vertices[polygon[1]].point , m_vertices[polygon[2]].point ); + else + { + Point3D< Real > center; + for( size_t i=0 ; i +void SurfaceTrimmer::RemoveHangingVertices( + std::vector& polygons ) +{ + std::unordered_map< int, int > vMap; + std::vector< bool > vertexFlags( m_vertices.size() , false ); + for( size_t i=0 ; i _vertices( vCount ); + for( int i=0 ; i +void SurfaceTrimmer::SetConnectedComponents( + const std::vector& polygons , + std::vector< std::vector< int > >& components ) +{ + std::vector< int > polygonRoots( polygons.size() ); + for( size_t i=0 ; i edgeTable; + for( size_t i=0 ; i::iterator iter = edgeTable.find(eKey); + if( iter==edgeTable.end() ) edgeTable[ eKey ] = int(i); + else + { + int p = iter->second; + while( polygonRoots[p]!=p ) + { + int temp = polygonRoots[p]; + polygonRoots[p] = int(i); + p = temp; + } + polygonRoots[p] = int(i); + } + } + } + for( size_t i=0 ; i vMap; + for( int i= 0 ; i +double SurfaceTrimmer::calcAreas(std::vector& polygons, + std::vector>& components, std::vector& flags, + std::vector& areas) +{ + double area = 0; + for (size_t i = 0; i < components.size() ; i++) + { + for (size_t j=0 ; j +void SurfaceTrimmer::reSortPolygons( + std::vector& ltPolygons, + std::vector>& ltComponents, std::vector& ltFlags, + std::vector& ltAreas, + std::vector& gtPolygons, + std::vector>& gtComponents, std::vector& gtFlags, + std::vector gtAreas, double islandArea) +{ + std::vector _ltPolygons , _gtPolygons; + + for( size_t i=0 ; i +int SurfaceTrimmer::Execute() +{ + std::unordered_map vertexTable; + std::vector ltPolygons, gtPolygons; + std::vector ltFlags , gtFlags; + + for (Polygon& poly : m_polygons) + SplitPolygon( poly, <Polygons , >Polygons , <Flags , >Flags , + vertexTable , m_trim); + + if(m_islandRatio >0) + { + std::vector> ltComponents , gtComponents; + SetConnectedComponents( ltPolygons , ltComponents ); + SetConnectedComponents( gtPolygons , gtComponents ); + + std::vector< double > ltAreas( ltComponents.size() , 0. ); + std::vector gtAreas( gtComponents.size() , 0. ); + std::vector ltComponentFlags( ltComponents.size() , false ); + std::vector gtComponentFlags( gtComponents.size() , false ); + + double area = 0; + area += calcAreas(ltPolygons, ltComponents, ltFlags, ltAreas); + area += calcAreas(gtPolygons, gtComponents, gtFlags, gtAreas); + + reSortPolygons(ltPolygons, ltComponents, ltFlags, ltAreas, + gtPolygons, gtComponents, gtFlags, gtAreas, + area * m_islandRatio); + } + + if( !m_polygonMesh) + { + std::vector polys = ltPolygons; + Triangulate(ltPolygons , polys ); + ltPolygons = polys; + + polys = gtPolygons; + Triangulate(gtPolygons , polys ); + gtPolygons = polys; + } + + RemoveHangingVertices(gtPolygons ); + m_polygons = gtPolygons; + + return EXIT_SUCCESS; +} diff --git a/Src/SurfaceTrimmerMain.cpp b/Src/SurfaceTrimmerMain.cpp new file mode 100644 index 00000000..b4b761f6 --- /dev/null +++ b/Src/SurfaceTrimmerMain.cpp @@ -0,0 +1,220 @@ +/* +Copyright (c) 2013, Michael Kazhdan +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#undef ARRAY_DEBUG + +#include +#include + +#include "CmdLineParser.h" +#include "Ply.h" +#include "MyTime.h" + +#include "SurfaceTrimmer.h" + +/** +#include +#include +#include +#ifdef _OPENMP +#include +#endif // _OPENMP +#include +#include "Geometry.h" +#include "MAT.h" +**/ + +cmdLineString In( "in" ) , Out( "out" ); +cmdLineInt Smooth( "smooth" , 5 ); +cmdLineFloat Trim( "trim" ) , IslandAreaRatio( "aRatio" , 0.001f ); +cmdLineReadable PolygonMesh( "polygonMesh" ); + +typedef std::vector Polygon; + +cmdLineReadable* params[] = +{ + &In , &Out , &Trim , &PolygonMesh , &Smooth , &IslandAreaRatio +}; + +void ShowUsage( char* ex ) +{ + printf( "Usage: %s\n" , ex ); + printf( "\t --%s \n" , In.name ); + printf( "\t[--%s ]\n" , Trim.name ); + printf( "\t[--%s ]\n" , Out.name ); + printf( "\t[--%s =%d]\n" , + Smooth.name , Smooth.value ); + printf( "\t[--%s =%f]\n" , + IslandAreaRatio.name , IslandAreaRatio.value ); + printf( "\t[--%s]\n" , PolygonMesh.name ); +} + +template +void readData(std::vector& vertices, std::vector& polygons, + std::vector comments) +{ + int fileType = 0; + char **cComments; + int numComments = 0; + PlyReadPolygons(In.value, vertices, polygons, Vertex::ReadProperties, + Vertex::ReadComponents, fileType, &cComments, &numComments); + for (auto i = 0; i < numComments; ++i) + { + std::string c = cComments[i]; + comments.push_back(c); + free(cComments[i]); + } +} + +template +void writeData(std::vector& vertices, std::vector& polygons, + std::vector comments) +{ + if (!Out.set) + return; + + int fileType = 0; + + char **cComments = new char *[comments.size()]; + for (size_t i = 0; i < comments.size(); ++i) + cComments[i] = strdup(comments[i].data()); + + PlyWritePolygons(Out.value, vertices, polygons, Vertex::WriteProperties, + Vertex::WriteComponents, fileType, cComments, comments.size()); + + for (size_t i = 0; i < comments.size(); ++i) + free(cComments[i]); + delete [] cComments; +} + + +void addComments(std::vector comments) +{ + std::string leader("\t--"); + + comments.push_back("Running Surface Trimmer (V5)"); + if (In.set) + comments.push_back(leader + In.name + " " + In.value); + if (Out.set) + comments.push_back(leader + Out.name + " " + Out.value); + if (Trim.set) + comments.push_back(leader + Trim.name + " " + + std::to_string(Trim.value)); + if (Smooth.set) + comments.push_back(leader + IslandAreaRatio.name + " " + + std::to_string(IslandAreaRatio.value)); + if (PolygonMesh.set) + comments.push_back(leader + PolygonMesh.name); +} + + +template +void printVertexValues(std::vector& vertices) +{ + if (vertices.empty()) + return; + + float min = vertices[0].value; + float max = vertices[0].value; + + for (Vertex& v : vertices) + { + min = std::min(min, v.value); + max = std::max(min, v.value); + } + std::cout << "Value Range: [" << min << "," << max << "]\n"; +} + + +template +int execute() +{ + float min; + float max; + + using ST = SurfaceTrimmer; + + std::vector vertices; + std::vector polygons; + std::vector comments; + + readData(vertices, polygons, comments); + addComments(comments); + + ST trimmer(vertices, polygons, Trim.value, + IslandAreaRatio.value, PolygonMesh.set); + + while (Smooth.value--) + trimmer.SmoothValues(); + printVertexValues(vertices); + + double t = Time(); + + int result = trimmer.Execute(); + + comments.push_back("#Trimmed In " + std::to_string((Time() - t)) + + " (s)"); + writeData(vertices, polygons, comments); + return result; +} + + +int main( int argc , char* argv[] ) +{ + int paramNum = sizeof(params)/sizeof(cmdLineReadable*); + cmdLineParse( argc-1 , &argv[1] , paramNum , params , 0 ); + + if( !In.set || !Trim.set ) + { + ShowUsage( argv[0] ); + return EXIT_FAILURE; + } + bool readFlags[ PlyColorAndValueVertex< float >::ReadComponents ]; + if (!PlyReadHeader(In.value, PlyColorAndValueVertex::ReadProperties, + PlyColorAndValueVertex::ReadComponents, readFlags)) + { + fprintf(stderr , "[ERROR] Failed to read ply header: %s\n" , In.value); + exit( 0 ); + } + + bool hasValue = readFlags[3]; + bool hasColor = ( readFlags[4] || readFlags[7] ) && + ( readFlags[5] || readFlags[8] ) && ( readFlags[6] || readFlags[9] ); + + if( !hasValue ) + { + fprintf( stderr , "[ERROR] Ply file does not contain values\n" ); + exit( 0 ); + } + + if ( hasColor) + return execute>(); + else + return execute>(); +} + diff --git a/Src/point_source/AsciiPointSource.h b/Src/point_source/AsciiPointSource.h new file mode 100644 index 00000000..3f7811bf --- /dev/null +++ b/Src/point_source/AsciiPointSource.h @@ -0,0 +1,57 @@ +/* +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior writften permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#pragma once + +#include "PointSource.h" + +class ASCIIPointSource : public PointSource +{ +private: + FILE *m_fp; +public: + ASCIIPointSource(const std::string& filename); + ~ASCIIPointSource(); + + void reset(); + bool nextPoint(Point& p); +}; + +class ColorASCIIPointSource : public ColorPointSource +{ +private: + FILE* m_fp; +public: + ColorASCIIPointSource(const std::string& filename); + ~ColorASCIIPointSource(); + + void reset(); + bool nextPoint(Point& point, Point3D& color); +}; + +#include "AsciiPointSource.inl" diff --git a/Src/point_source/AsciiPointSource.inl b/Src/point_source/AsciiPointSource.inl new file mode 100644 index 00000000..dc42e142 --- /dev/null +++ b/Src/point_source/AsciiPointSource.inl @@ -0,0 +1,101 @@ +/* +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#include + +/////////////////////////////// +// ASCIIPointSource // +/////////////////////////////// +ASCIIPointSource::ASCIIPointSource(const std::string& filename) +{ + m_fp = fopen(filename.data(), "r"); + if (!m_fp) + { + std::cerr << "Failed to open file for reading: " << + filename << std::endl; + exit(0); + } +} + +ASCIIPointSource::~ASCIIPointSource() +{ + fclose(m_fp); +} + +void ASCIIPointSource::reset() +{ + fseek(m_fp, SEEK_SET, 0); +} + +bool ASCIIPointSource::nextPoint(Point& p) +{ + if (fscanf(m_fp , " %lf %lf %lf %lf %lf %lf ", + &p.p[0], &p.p[1], &p.p[2], &p.n[0], &p.n[1], &p.n[2]) != 6) + return false; + return true; +} + +/////////////////////////////// +// ColorASCIIPointSource // +/////////////////////////////// +ColorASCIIPointSource::ColorASCIIPointSource(const std::string& filename) +{ + m_fp = fopen(filename.data(), "r"); + if (!m_fp) + { + std::cerr << "Failed to open file for reading: " << + filename << std::endl; + exit(0); + } +} + +ColorASCIIPointSource::~ColorASCIIPointSource() +{ + fclose(m_fp); +} + +void ColorASCIIPointSource::reset() +{ + fseek(m_fp, SEEK_SET, 0); +} + +bool ColorASCIIPointSource::nextPoint(Point& p, Point3D& color) +{ + if (fscanf(m_fp , " %lf %lf %lf %lf %lf %lf ", + &p.p[0] , &p.p[1] , &p.p[2] , &p.n[0], &p.n[1], &p.n[2]) != 6) + return false; + char c[3]; + if (fscanf(m_fp, " %c %c %c ", &c[0], &c[1], &c[2]) != 3) + return false; + color.coords[0] = c[0]; + color.coords[1] = c[1]; + color.coords[2] = c[2]; + return true; +} + + diff --git a/Src/point_source/BinaryPointSource.h b/Src/point_source/BinaryPointSource.h new file mode 100644 index 00000000..4fba7d49 --- /dev/null +++ b/Src/point_source/BinaryPointSource.h @@ -0,0 +1,61 @@ +/* +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior writften permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#pragma once + +#include "PointSource.h" + +class BinaryPointSource : public PointSource +{ +private: + FILE *m_fp; + std::vector m_points; + size_t m_current; +public: + BinaryPointSource(const std::string& filename); + ~BinaryPointSource(); + + void reset(); + bool nextPoint(Point& point); +}; + +class ColorBinaryPointSource : public ColorPointSource +{ +private: + FILE *m_fp; + std::vector m_points; + size_t m_current; +public: + ColorBinaryPointSource(const std::string& filename); + ~ColorBinaryPointSource(); + + void reset(); + bool nextPoint(Point& point, Point3D& color); +}; + +#include "BinaryPointSource.inl" diff --git a/Src/point_source/BinaryPointSource.inl b/Src/point_source/BinaryPointSource.inl new file mode 100644 index 00000000..2ae70997 --- /dev/null +++ b/Src/point_source/BinaryPointSource.inl @@ -0,0 +1,129 @@ +/* +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#include + +////////////////////////// +// BinaryPointSource // +////////////////////////// +BinaryPointSource::BinaryPointSource(const std::string& filename) : m_current(0) +{ + m_fp = fopen(filename.data(), "rb"); + if (!m_fp) + { + std::cerr << "Failed to open file for reading: " << + filename << std::endl; + exit(0); + } +} + +BinaryPointSource::~BinaryPointSource() +{ + fclose(m_fp); +} + +void BinaryPointSource::reset() +{ + fseek(m_fp, SEEK_SET, 0); + m_current = 0; + m_points.clear(); +} + +bool BinaryPointSource::nextPoint(Point& p) +{ + if (m_current < m_points.size()) + { + p = m_points[m_current++]; + return true; + } + else + { + m_current = 0; + m_points.resize(1024); + size_t count = fread(m_points.data(), sizeof(Point), + m_points.size(), m_fp); + m_points.resize(count); + + if (count == 0) + return false; + else + return nextPoint(p); + } +} + +/////////////////////////////// +// ColorBinaryPointSource // +/////////////////////////////// +ColorBinaryPointSource::ColorBinaryPointSource(const std::string& filename) : + m_current(0) +{ + m_fp = fopen(filename.data(), "rb"); + if (!m_fp) + { + std::cerr << "Failed to open file for reading: " << + filename << std::endl; + exit(0); + } +} + +ColorBinaryPointSource::~ColorBinaryPointSource() +{ + fclose(m_fp); +} + +void ColorBinaryPointSource::reset() +{ + fseek(m_fp, SEEK_SET, 0); + m_current = 0; + m_points.clear(); +} + +bool ColorBinaryPointSource::nextPoint(Point& p, Point3D& color) +{ + if (m_current < m_points.size()) + { + p = m_points[m_current].first; + color = m_points[m_current].second; + m_current++; + return true; + } + else + { + m_current = 0; + m_points.resize(1024); + size_t count = fread(m_points.data(), sizeof(Point), + m_points.size(), m_fp); + m_points.resize(count); + + if (count == 0) + return false; + else + return nextPoint(p, color); + } +} + diff --git a/Src/point_source/MemoryPointSource.h b/Src/point_source/MemoryPointSource.h new file mode 100644 index 00000000..7295bcc0 --- /dev/null +++ b/Src/point_source/MemoryPointSource.h @@ -0,0 +1,84 @@ +/* +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior writften permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#pragma once + +#include "PointSource.h" + +class MemoryPointSource : public PointSource +{ +private: + const Point *m_points; + size_t m_pointCount; + size_t m_current; +public: + MemoryPointSource(size_t pointCount, const Point *points) : + m_points(points), m_pointCount(pointCount), m_current(0) + {} + + virtual void reset() + { m_current = 0; } + + virtual bool nextPoint(Point& p) + { + if (m_current >= m_pointCount) + return false; + p = m_points[m_current++]; + return true; + } +}; + +class ColorMemoryPointSource : public ColorPointSource +{ +private: + const PointPair *m_points; + size_t m_pointCount; + size_t m_current; +public: + ColorMemoryPointSource(size_t pointCount, const PointPair *points) : + m_points(points), m_pointCount(pointCount), m_current(0) + {} + + virtual bool nextPoint(Point& p, Point3D& color) + { + if (m_current >= m_pointCount) + return false; + const PointPair& pp(m_points[m_current++]); + p = pp.first; + color = pp.second; + return true; + } + + virtual void reset() + { + m_current = 0; + } +}; + + +#include "PointSource.inl" diff --git a/Src/point_source/PlyPointSource.h b/Src/point_source/PlyPointSource.h new file mode 100644 index 00000000..8c7a2e66 --- /dev/null +++ b/Src/point_source/PlyPointSource.h @@ -0,0 +1,80 @@ +/* +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior writften permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#pragma once + +#include "PointSource.h" +#include "../Ply.h" + +class PLYPointSource : public PointSource +{ + struct Vertex + { + Point3D point; + Point3D normal; + }; + + std::string m_filename; + PlyFile *m_ply; + int m_numElements; + int m_numInstances; + char **m_elements; + int m_current; + + void _free( void ); +public: + PLYPointSource(const std::string& filename); + ~PLYPointSource(); + void reset(); + bool nextPoint(Point& p); +}; + +class ColorPLYPointSource : public ColorPointSource +{ + struct Vertex + { + Point3D point; + Point3D normal; + Point3D color; + }; + + std::string m_filename; + PlyFile *m_ply; + int m_numElements; + int m_numInstances; + char **m_elements; + int m_current; + void _free( void ); +public: + ColorPLYPointSource(const std::string& namefile); + ~ColorPLYPointSource(); + void reset(); + bool nextPoint(Point& p, Point3D& color); +}; + +#include "PlyPointSource.inl" diff --git a/Src/point_source/PlyPointSource.inl b/Src/point_source/PlyPointSource.inl new file mode 100644 index 00000000..79f00d2d --- /dev/null +++ b/Src/point_source/PlyPointSource.inl @@ -0,0 +1,311 @@ +/* +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#include + +////////////////////// +// PLYPointSource // +////////////////////// +PLYPointSource::PLYPointSource(const std::string& filename) : + m_filename(filename), m_ply(nullptr) +{ + reset(); +} + +PLYPointSource::~PLYPointSource() +{ + _free(); +} + +void PLYPointSource::reset() +{ + int fileType; + float version; + + // The _strdup looks leaky, but I don't think I care. + static PlyProperty requiredProps[] = + { + { _strdup("x") , PLY_DOUBLE, PLY_DOUBLE }, + { _strdup("y") , PLY_DOUBLE, PLY_DOUBLE }, + { _strdup("z") , PLY_DOUBLE, PLY_DOUBLE }, + { _strdup("nx") , PLY_DOUBLE, PLY_DOUBLE }, + { _strdup("ny") , PLY_DOUBLE, PLY_DOUBLE }, + { _strdup("nz") , PLY_DOUBLE, PLY_DOUBLE } + }; + const int numRequiredProps = sizeof(requiredProps) / sizeof(PlyProperty); + + Vertex v; + requiredProps[0].offset = (int)((char *)&v.point.coords[0] - (char *)&v); + requiredProps[1].offset = (int)((char *)&v.point.coords[1] - (char *)&v); + requiredProps[2].offset = (int)((char *)&v.point.coords[2] - (char *)&v); + requiredProps[3].offset = (int)((char *)&v.normal.coords[0] - (char *)&v); + requiredProps[4].offset = (int)((char *)&v.normal.coords[1] - (char *)&v); + requiredProps[5].offset = (int)((char *)&v.normal.coords[2] - (char *)&v); + + if (m_ply) + _free(); + m_ply = ply_open_for_reading(const_cast(m_filename.data()), + &m_numElements, &m_elements, &fileType, &version); + if (!m_ply) + { + std::cerr << "[ERROR] Failed to open ply file for reading: " << + m_filename << std::endl; + exit(0); + } + m_current = 0; + + PlyProperty** plist; + bool foundVertices = false; + for(int i = 0; i < m_numElements; ++i) + { + int numProperties; + char* elementName = m_elements[i]; + plist = ply_get_element_description(m_ply , elementName, + &m_numInstances, &numProperties); + if (!plist) + { + std::cerr << "[ERROR] Failed to get element description: " << + elementName << std::endl; + exit(0); + } + + if (equal_strings("vertex", elementName)) + { + foundVertices = true; + for (int prop = 0; prop < numRequiredProps; ++prop) + if (!ply_get_property(m_ply, elementName, + &(requiredProps[prop]))) + { + std::cerr << "[ERROR] Failed to find property in " + "ply file: " << requiredProps[prop].name << std::endl; + exit(0); + } + } + for(size_t j = 0 ; j < numProperties; ++j) + { + free(plist[j]->name); + free(plist[j]); + } + free(plist); + if (foundVertices) + break; + } + if (!foundVertices) + { + std::cerr << "[ERROR] Could not find vertices in ply file" << std::endl; + exit(0); + } +} + +void PLYPointSource::_free() +{ + if (m_ply) + ply_close(m_ply); + m_ply = NULL; + if (m_elements) + { + for (int i =0; i < m_numElements; ++i) + free(m_elements[i]); + free(m_elements); + } +} + +bool PLYPointSource::nextPoint(Point& p) +{ + if (m_current >= m_numInstances) + return false; + + Vertex op; + ply_get_element(m_ply, (void *)&op); + p.p = op.point; + p.n = op.normal; + m_current++; + return true; +} + +/////////////////////////// +// ColorPLYPointSource // +/////////////////////////// + +ColorPLYPointSource::ColorPLYPointSource(const std::string& filename) : + m_filename(filename), m_ply(nullptr) +{ + reset(); +} + +void ColorPLYPointSource::reset() +{ + int fileType; + float version; + PlyProperty** plist; + + // The _strdup looks leaky, but I don't think I care. + static PlyProperty requiredProps[] = + { + { _strdup("x") , PLY_DOUBLE, PLY_DOUBLE }, + { _strdup("y") , PLY_DOUBLE, PLY_DOUBLE }, + { _strdup("z") , PLY_DOUBLE, PLY_DOUBLE }, + { _strdup("nx") , PLY_DOUBLE, PLY_DOUBLE }, + { _strdup("ny") , PLY_DOUBLE, PLY_DOUBLE }, + { _strdup("nz") , PLY_DOUBLE, PLY_DOUBLE } + }; + const int numRequiredProps = sizeof(requiredProps) / sizeof(PlyProperty); + + Vertex v; + requiredProps[0].offset = (int)((char *)&v.point.coords[0] - (char *)&v); + requiredProps[1].offset = (int)((char *)&v.point.coords[1] - (char *)&v); + requiredProps[2].offset = (int)((char *)&v.point.coords[2] - (char *)&v); + requiredProps[3].offset = (int)((char *)&v.normal.coords[0] - (char *)&v); + requiredProps[4].offset = (int)((char *)&v.normal.coords[1] - (char *)&v); + requiredProps[5].offset = (int)((char *)&v.normal.coords[2] - (char *)&v); + + PlyProperty reqDataProps[] = + { + { "r" , PLY_UCHAR, PLY_DOUBLE }, + { "g" , PLY_UCHAR, PLY_DOUBLE }, + { "b" , PLY_UCHAR, PLY_DOUBLE }, + { "red" , PLY_UCHAR, PLY_DOUBLE }, + { "green" ,PLY_UCHAR, PLY_DOUBLE }, + { "blue" , PLY_UCHAR, PLY_DOUBLE } + }; + const int numReqDataProps = sizeof(reqDataProps) / sizeof(PlyProperty); + + reqDataProps[0].offset = (int)((char *)&v.color.coords[0] - (char *)&v); + reqDataProps[1].offset = (int)((char *)&v.color.coords[1] - (char *)&v); + reqDataProps[2].offset = (int)((char *)&v.color.coords[2] - (char *)&v); + reqDataProps[3].offset = (int)((char *)&v.color.coords[0] - (char *)&v); + reqDataProps[4].offset = (int)((char *)&v.color.coords[1] - (char *)&v); + reqDataProps[5].offset = (int)((char *)&v.color.coords[2] - (char *)&v); + + if (m_ply) + _free(); + m_ply = ply_open_for_reading(const_cast(m_filename.data()), + &m_numElements, &m_elements, &fileType, &version); + if (!m_ply) + { + std::cerr << "[ERROR] Failed to open ply file for reading: " << + m_filename << std::endl; + exit(0); + } + + m_current = 0; + bool foundVertices = false; + for (size_t i = 0; i < m_numElements; ++i) + { + int numProperties; + char* elementName = m_elements[i]; + plist = ply_get_element_description(m_ply, elementName, + &m_numInstances, &numProperties); + if (!plist) + { + std::cerr << "[ERROR] Failed to get element description: " << + elementName << std::endl; + exit(0); + } + + if (equal_strings("vertex", elementName)) + { + foundVertices = true; + + for (int prop = 0; prop < numRequiredProps; ++prop) + if (!ply_get_property(m_ply, elementName, + &(requiredProps[prop]))) + { + std::cerr << "[ERROR] Failed to find property in " + "ply file: " << requiredProps[prop].name << std::endl; + exit( 0 ); + } + + int propIndicator = 0; + for (size_t prop = 0; prop < numReqDataProps; ++prop) + { + // The properties r g b/red green blue are represented by + // the low 3 bits. When the propIndicator is 7, we know + // we found all three. + int bit = (int)pow(2, prop % 3); + PlyProperty& property(reqDataProps[prop]); + if (ply_get_property(m_ply, elementName, &property)) + propIndicator |= bit; + } + if (propIndicator != 7) + { + std::cerr << "[ERROR] Missing at least one of red/gree/blue " + "in vertex property list." << std::endl; + exit(0); + } + } + for (int j=0; j < numProperties; ++j) + { + free(plist[j]->name); + free(plist[j]); + } + free(plist); + if (foundVertices) + break; + } + if (!foundVertices) + { + std::cerr << "[ERROR] Could not find vertices in ply file" << std::endl; + exit(0); + } +} + +void ColorPLYPointSource::_free() +{ + if (m_ply) + { + ply_close(m_ply); + m_ply = nullptr; + } + if (m_elements) + { + for(int i = 0; i< m_numElements; ++i) + free(m_elements[i]); + free(m_elements); + m_elements = nullptr; + } +} + +ColorPLYPointSource::~ColorPLYPointSource() +{ + _free(); +} + +bool ColorPLYPointSource::nextPoint(Point& p, Point3D& color) +{ + if (m_current >= m_numInstances) + return false; + + Vertex op; + ply_get_element(m_ply, (void *)&op); + p.p = op.point; + p.n = op.normal; + color = op.color; + m_current++; + return true; +} diff --git a/Src/point_source/PointSource.h b/Src/point_source/PointSource.h new file mode 100644 index 00000000..0269d6d1 --- /dev/null +++ b/Src/point_source/PointSource.h @@ -0,0 +1,77 @@ +/* +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior writften permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#pragma once + +#include "../Geometry.h" + +class PointSource +{ +protected: + using Point = OrientedPoint3D; // Contains Normals + +public: + virtual ~PointSource() + {} + + virtual void reset() = 0; + virtual bool nextPoint(Point& point) = 0; + void boundingBox(Point3D& min, Point3D& max) + { + for (int i = 0; i < 3; ++i) + { + min[i] = std::numeric_limits::max(); + max[i] = std::numeric_limits::lowest(); + } + + Point p; + while (nextPoint(p)) + { + for( int i=0 ; i<3 ; i++ ) + { + min[i] = std::min(min[i], p.p[i]); + max[i] = std::max(max[i], p.p[i]); + } + } + reset(); + } +}; +typedef std::unique_ptr PointSourcePtr; + +class ColorPointSource : public PointSource +{ +protected: + using PointPair = std::pair>; +public: + virtual bool nextPoint(Point& p, Point3D& color) = 0; + virtual bool nextPoint(Point& p) + { + Point3D color; + return nextPoint(p, color); + } +}; diff --git a/Src/point_source/TransformedPointSource.h b/Src/point_source/TransformedPointSource.h new file mode 100644 index 00000000..e46461ca --- /dev/null +++ b/Src/point_source/TransformedPointSource.h @@ -0,0 +1,88 @@ +/* +Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the distribution. + +Neither the name of the Johns Hopkins University nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior writften permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. +*/ + +#pragma once + +#include "PointSource.h" + +class TransformedPointSource : public PointSource +{ + XForm4x4 m_xForm; + XForm3x3 m_normalXForm; + PointSource& m_stream; + +public: + TransformedPointSource(const XForm4x4& xForm, PointSource& stream) : + m_xForm(xForm), m_stream(stream) + { + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + m_normalXForm(i, j) = m_xForm(i, j); + m_normalXForm = m_normalXForm.transpose().inverse(); + } + + virtual void reset() + { m_stream.reset(); } + + virtual bool nextPoint(Point& p) + { + bool ret = m_stream.nextPoint(p); + p.p = m_xForm * p.p; + p.n = m_normalXForm * p.n; + return ret; + } +}; + +class ColorTransformedPointSource : public ColorPointSource +{ +private: + XForm4x4 m_xForm; + XForm3x3 m_normalXForm; + ColorPointSource& m_stream; + +public: + ColorTransformedPointSource(const XForm4x4& xForm, + ColorPointSource& stream) : m_xForm(xForm), m_stream(stream) + { + for (int i = 0; i < 3; ++i) + for (int j = 0; j < 3; ++j) + m_normalXForm(i, j) = m_xForm(i, j); + m_normalXForm = m_normalXForm.transpose().inverse(); + } + + virtual void reset() + { m_stream.reset(); } + + virtual bool nextPoint(Point& p, Point3D& color) + { + bool ret = m_stream.nextPoint(p, color); + p.p = m_xForm * p.p; + p.n = m_normalXForm * p.n; + return ret; + } +}; diff --git a/SurfaceTrimmer.vcxproj b/SurfaceTrimmer.vcxproj index 383f6786..4f034c7c 100644 --- a/SurfaceTrimmer.vcxproj +++ b/SurfaceTrimmer.vcxproj @@ -1,5 +1,5 @@  - + Debug @@ -30,23 +30,23 @@ Application Unicode true - v140 + v141 Application Unicode true - v140 + v141 Application Unicode - v140 + v141 Application Unicode - v140 + v141 true