├── .gitignore ├── Include ├── CurvatureMetric.h ├── GradientDomain.h └── PreProcessor.h ├── LICENSE ├── Makefile ├── Misha ├── Algebra.h ├── Array.h ├── Array.inl ├── Atomic.h ├── CmdLineParser.h ├── CmdLineParser.inl ├── Exceptions.h ├── FEM.BasisInfo.inc ├── FEM.h ├── FEM.inl ├── Geometry.h ├── Geometry.inl ├── Miscellany.h ├── MultiThreading.h ├── Ply.h ├── Ply.inl ├── PlyFile.h ├── PlyFile.inl ├── PlyVertexData.h ├── PlyVertexData.inl ├── Poly34.h ├── Poly34.inl ├── Polynomial.h ├── Polynomial.inl ├── SparseMatrix.h ├── SparseMatrix.inl ├── SparseMatrixInterface.h ├── SparseMatrixInterface.inl ├── Vector.h └── Vector.inl ├── README.md ├── ShapeCurvature ├── ShapeCurvature.cpp └── ShapeCurvature.vcxproj ├── ShapeGradientDomain.sln ├── ShapeGradientDomain ├── ShapeGradientDomain.cpp └── ShapeGradientDomain.vcxproj ├── armadillo.curvature.png └── armadillo.png /.gitignore: -------------------------------------------------------------------------------- 1 | .gitignore 2 | *.suo 3 | .git/ 4 | .vs/ 5 | x64/ 6 | /Eigen/ 7 | /Obj/ 8 | /Bin/ 9 | */x64/ 10 | *.opensdf 11 | *.bat 12 | *.tlog 13 | *.exe 14 | *.user 15 | *.filters 16 | *.zip 17 | index.html -------------------------------------------------------------------------------- /Include/CurvatureMetric.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2025, Michael Kazhdan 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | #ifndef CURVATURE_METRIC_INCLUDED 30 | #define CURVATURE_METRIC_INCLUDED 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace MishaK 38 | { 39 | namespace CurvatureMetric 40 | { 41 | template< typename Real , unsigned int K > 42 | SquareMatrix< Real , K > SecondFundamentalForm( Simplex< Real , K+1 , K > s , const Point< Real , K+1 > n[K+1] , bool symmetric=true ); 43 | 44 | template< typename Real , unsigned int K > 45 | Matrix< Real , K , K+1 > PrincipalCurvatures( Simplex< Real , K+1 , K > s , const Point< Real , K+1 > n[K+1] , Real curvatureValues[K] ); 46 | 47 | template< typename Real , typename VertexFunctor /* = std::function< Point< Real , 3 > ( unsigned int ) */ , typename NormalFunctor /* = std::function< Point< Real , 3 > ( unsigned int ) */ , typename CurvatureFunctor /* = std::function< Point< Real , 2 > ( Point< Real , 2 > ) > */ > 48 | void SetCurvatureMetric( FEM::RiemannianMesh< Real > &mesh , VertexFunctor && V , NormalFunctor && N , CurvatureFunctor && F ); 49 | 50 | //////////////////// 51 | // Implementation // 52 | //////////////////// 53 | 54 | template< typename Real , unsigned int K > 55 | SquareMatrix< Real , K > SecondFundamentalForm( Simplex< Real , K+1 , K > s , const Point< Real , K+1 > n[K+1] , bool symmetric ) 56 | { 57 | SquareMatrix< Real , K > II; 58 | Point< Real , K+1 > dv[K] , dn[K]; 59 | for( unsigned int k=0 ; k::Dot( dv[i] , dn[j] ); 61 | if( symmetric ) return ( II + II.transpose() ) / (Real)2; 62 | else return II; 63 | } 64 | 65 | template< typename Real , unsigned int K > 66 | Matrix< Real , K , K+1 > PrincipalCurvatures( Simplex< Real , K+1 , K > s , const Point< Real , K+1 > n[K+1] , Real curvatureValues[K] ) 67 | { 68 | auto ToEigen = []( const SquareMatrix< Real , K > & M ) 69 | { 70 | Eigen::Matrix< Real , K , K > _M; 71 | for( unsigned int i=0 ; i & M ) 76 | { 77 | SquareMatrix< Real , K > _M; 78 | for( unsigned int i=0 ; i d[K]; 83 | for( unsigned int k=0 ; k D; 86 | for( unsigned int i=0 ; i II = SecondFundamentalForm< Real , K >( s , n , true ); 89 | 90 | Eigen::GeneralizedSelfAdjointEigenSolver< Eigen::MatrixXd > ges( ToEigen( II ) , ToEigen( D.transpose() * D ) ); 91 | for( unsigned int k=0 ; k ( unsigned int ) */ , typename NormalFunctor /* = std::function< Point< Real , 3 > ( unsigned int ) */ , typename PrincipalCurvatureFunctor /* = std::function< Point< Real , 2 > ( unsigned int , Point< Real , 2 > ) > */ > 97 | void SetCurvatureMetric( FEM::RiemannianMesh< Real > &mesh , VertexFunctor && V , NormalFunctor && N , PrincipalCurvatureFunctor && PCF ) 98 | { 99 | static const unsigned int K = 2; 100 | static const unsigned int Dim = K+1; 101 | 102 | static_assert( std::is_convertible_v< VertexFunctor , std::function< Point< Real , Dim > ( unsigned int ) > > , "[ERROR] VertexFunctor is poorly formed" ); 103 | static_assert( std::is_convertible_v< NormalFunctor , std::function< Point< Real , Dim > ( unsigned int ) > > , "[ERROR] NormalFunctor is poorly formed" ); 104 | static_assert( std::is_convertible_v< PrincipalCurvatureFunctor , std::function< Point< Real , K > ( unsigned int , Point< Real , K > ) > > , "[ERROR] PrincipalCurvatureFunctor is poorly formed" ); 105 | 106 | auto ToEigen = []( const SquareMatrix< Real , K > & M ) 107 | { 108 | Eigen::Matrix< Real , K , K > _M; 109 | for( unsigned int i=0 ; i & M ) 114 | { 115 | SquareMatrix< Real , K > _M; 116 | for( unsigned int i=0 ; i ) simplices = mesh.triangles(); 121 | unsigned int simplexNum = (unsigned int)mesh.tCount(); 122 | ThreadPool::ParallelFor 123 | ( 124 | 0 , simplexNum , 125 | [&]( unsigned int , size_t i ) 126 | { 127 | Simplex< Real , Dim , K > s; 128 | Point< Real , Dim > n[K+1]; 129 | for( unsigned int k=0 ; k<=K ; k++ ) s[k] = V( simplices[i][k] ) , n[k] = N( simplices[i][k] ); 130 | SquareMatrix< Real , K > II = SecondFundamentalForm< Real , K >( s , n ); 131 | Eigen::GeneralizedSelfAdjointEigenSolver< Eigen::MatrixXd > ges( ToEigen( II ) , ToEigen( mesh.g(i) ) ); 132 | Eigen::Matrix< Real , K , K > D( Eigen::DiagonalMatrix< Real , K >( ges.eigenvalues() ) ); 133 | Point< Real , K > pCurvatures; 134 | for( unsigned int k=0 ; k( ges.eigenvectors() * D * ges.eigenvectors().inverse() ) ); 138 | } 139 | ); 140 | } 141 | } 142 | } 143 | #endif // CURVATURE_METRIC_INCLUDED -------------------------------------------------------------------------------- /Include/GradientDomain.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2025, Michael Kazhdan 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | #ifndef GRADIENT_DOMAIN_INCLUDED 30 | #define GRADIENT_DOMAIN_INCLUDED 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | namespace MishaK 38 | { 39 | namespace GradientDomain 40 | { 41 | template< typename EigenSolver , typename Real , typename VertexFunctor /* = std::function< Point< Real , 3 >( unsigned int ) > */ , typename NormalFunctor /* = std::function< Point< Real , 3 >( unsigned int ) > */ > 42 | std::vector< Point< Real , 3 > > FitToNormals( const FEM::RiemannianMesh< Real > &mesh , Real vWeight , Real nWeight , VertexFunctor && V , NormalFunctor && N ); 43 | 44 | template< typename EigenSolver , typename T , typename Real , typename LowFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ , typename HighFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ > 45 | std::vector< T > ProcessVertexVertex( const FEM::RiemannianMesh< Real > &mesh , Real lowWeight , Real highWeight , LowFrequencyVertexFunctor && Low , HighFrequencyVertexFunctor && High ); 46 | 47 | template< typename EigenSolver , typename T , typename Real , typename LowFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ , typename HighFrequencyEdgeFunctor /* = std::function< T ( unsigned int ) > */ > 48 | std::vector< T > ProcessVertexEdge( const FEM::RiemannianMesh< Real > &mesh , Real lowWeight , Real highWeight , LowFrequencyVertexFunctor && Low , HighFrequencyEdgeFunctor && High ); 49 | 50 | ////////////////////////////////////////////////////////////////////////////////////////////////// 51 | // Variants of the above with a solver for which symbolic factorization has already been performed 52 | template< typename EigenSolver , typename Real , typename VertexFunctor /* = std::function< Point< Real , 3 >( unsigned int ) > */ , typename NormalFunctor /* = std::function< Point< Real , 3 >( unsigned int ) > */ > 53 | std::vector< Point< Real , 3 > > FitToNormals( EigenSolver & solver , const FEM::RiemannianMesh< Real > &mesh , Real vWeight , Real nWeight , VertexFunctor && V , NormalFunctor && N ); 54 | 55 | template< typename EigenSolver , typename T , typename Real , typename LowFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ , typename HighFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ > 56 | std::vector< T > ProcessVertexVertex( EigenSolver & solver , const FEM::RiemannianMesh< Real > &mesh , Real lowWeight , Real highWeight , LowFrequencyVertexFunctor && Low , HighFrequencyVertexFunctor && High ); 57 | 58 | template< typename EigenSolver , typename T , typename Real , typename LowFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ , typename HighFrequencyEdgeFunctor /* = std::function< T ( unsigned int ) > */ > 59 | std::vector< T > ProcessVertexEdge( EigenSolver & solver , const FEM::RiemannianMesh< Real > &mesh , Real lowWeight , Real highWeight , LowFrequencyVertexFunctor && Low , HighFrequencyEdgeFunctor && High ); 60 | // Variants of the above with a solver for which symbolic factorization has already been performed 61 | ////////////////////////////////////////////////////////////////////////////////////////////////// 62 | 63 | //////////////////// 64 | // Implementation // 65 | //////////////////// 66 | 67 | template< typename T > 68 | struct Array{ static const unsigned int Dim=0; }; 69 | 70 | template<> 71 | struct Array< float > 72 | { 73 | using T = float; 74 | using Real = float; 75 | static const unsigned int Dim=1; 76 | static const Real & Entry( const T &v , unsigned int ){ return v; } 77 | static Real & Entry( T &v , unsigned int ){ return v; } 78 | template< unsigned int D > static constexpr const Real & Entry( const T &v ){ static_assert( D<=Dim , "[ERROR] Bad index" ) ; return v; } 79 | template< unsigned int D > static constexpr Real & Entry( T &v ){ static_assert( D<=Dim , "[ERROR] Bad index" ) ; return v; } 80 | }; 81 | 82 | template<> 83 | struct Array< double > 84 | { 85 | using T = double; 86 | using Real = double; 87 | static const unsigned int Dim=1; 88 | static const Real & Entry( const T &v , unsigned int ){ return v; } 89 | static Real & Entry( T &v , unsigned int ){ return v; } 90 | template< unsigned int D > static constexpr const Real & Entry( const T &v ){ static_assert( D<=Dim , "[ERROR] Bad index" ) ; return v; } 91 | template< unsigned int D > static constexpr Real & Entry( T &v ){ static_assert( D<=Dim , "[ERROR] Bad index" ) ; return v; } 92 | }; 93 | 94 | template< typename _T , unsigned int _Dim , typename _Real > 95 | struct Array< Point< _T , _Dim , _Real > > 96 | { 97 | using T = Point< _T , _Dim , _Real >; 98 | using Real = _Real; 99 | static const unsigned int Dim = _Dim * Array< _T >::Dim; 100 | static const Real & Entry( const T &v , unsigned int d ){ return Array< _T >::Entry( v[ d%_Dim ] , d/_Dim ); } 101 | static Real & Entry( T &v , unsigned int d ){ return Array< _T >::Entry( v[ d%_Dim ] , d/_Dim ); } 102 | template< unsigned int D > static constexpr const Real & Entry( const T &v ){ static_assert( D<=Dim , "[ERROR] Bad index" ) ; return Array< _T >::template Entry< D/_Dim >( v[ D%_Dim ] ); } 103 | template< unsigned int D > static constexpr Real & Entry( T &v ){ static_assert( D<=Dim , "[ERROR] Bad index" ) ; return Array< _T >::template Entry< D/_Dim >( v[ D%_Dim ] ); } 104 | }; 105 | 106 | template< unsigned int D , typename T , typename Real , typename EigenSolver , typename LowFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ , typename HighFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ > 107 | void _Solve( const EigenSolver &solver , const Eigen::SparseMatrix< Real > &lowM , const Eigen::SparseMatrix< Real > &highM , LowFrequencyVertexFunctor && Low , HighFrequencyVertexFunctor && High , std::vector< T > &out ) 108 | { 109 | if constexpr( D < Array< T >::Dim ) 110 | { 111 | Eigen::Matrix< Real , Eigen::Dynamic , 1 > l , h; 112 | l.resize( lowM.cols() ) , h.resize( highM.cols() ); 113 | for( unsigned int i=0 ; i< lowM.cols() ; i++ ) l[i] = Array< T >::template Entry< D >( Low(i) ); 114 | for( unsigned int i=0 ; i::template Entry< D >( High(i) ); 115 | 116 | Eigen::Matrix< Real , Eigen::Dynamic , 1 > b = lowM * l + highM * h; 117 | Eigen::Matrix< Real , Eigen::Dynamic , 1 > x = solver.solve( b ); 118 | 119 | for( unsigned int i=0 ; i::template Entry< D >( out[i] ) = x[i]; 120 | _Solve< D+1 >( solver , lowM , highM , std::forward< LowFrequencyVertexFunctor >( Low ) , std::forward< HighFrequencyVertexFunctor >( High ) , out ); 121 | } 122 | } 123 | 124 | template< typename EigenSolver , typename T , typename Real , typename LowFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ , typename HighFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ > 125 | std::vector< T > _ProcessVertexVertex( EigenSolver & solver , const FEM::RiemannianMesh< Real > &mesh , Real lowWeight , Real highWeight , LowFrequencyVertexFunctor && Low , HighFrequencyVertexFunctor && High , bool preAnalyzed ) 126 | { 127 | static_assert( Array< T >::Dim , "[ERROR] T is not of array type" ); 128 | static_assert( std::is_convertible_v< LowFrequencyVertexFunctor , std::function< T ( unsigned int ) > > , "[ERROR] LowFrequencyVertexFunctor is poorly formed" ); 129 | static_assert( std::is_convertible_v< HighFrequencyVertexFunctor , std::function< T ( unsigned int ) > > , "[ERROR] HighFrequencyVertexFunctor is poorly formed" ); 130 | 131 | Eigen::SparseMatrix< Real > mass = mesh.template massMatrix< FEM::BASIS_0_WHITNEY , true >() * lowWeight; 132 | Eigen::SparseMatrix< Real > stiffness = mesh.template stiffnessMatrix< FEM::BASIS_0_WHITNEY , true >() * highWeight; 133 | 134 | if( preAnalyzed ) solver.factorize( mass + stiffness ); 135 | else solver.compute ( mass + stiffness ); 136 | if( solver.info()!=Eigen::Success ) MK_ERROR_OUT( "Failed to factorize matrix" ); 137 | 138 | std::vector< T > out( mesh.vCount() ); 139 | _Solve< 0 >( solver , mass , stiffness , std::forward< LowFrequencyVertexFunctor >( Low ) , std::forward< HighFrequencyVertexFunctor >( High ) , out ); 140 | return out; 141 | } 142 | 143 | template< typename EigenSolver , typename T , typename Real , typename LowFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ , typename HighFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ > 144 | std::vector< T > ProcessVertexVertex( const FEM::RiemannianMesh< Real > &mesh , Real lowWeight , Real highWeight , LowFrequencyVertexFunctor && Low , HighFrequencyVertexFunctor && High ) 145 | { 146 | EigenSolver solver; 147 | return _ProcessVertexVertex< EigenSolver , T , Real >( solver , mesh , lowWeight , highWeight , std::forward< LowFrequencyVertexFunctor >( Low ) , std::forward< HighFrequencyVertexFunctor >( High ) , false ); 148 | } 149 | 150 | template< typename EigenSolver , typename T , typename Real , typename LowFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ , typename HighFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ > 151 | std::vector< T > ProcessVertexVertex( EigenSolver & solver , const FEM::RiemannianMesh< Real > &mesh , Real lowWeight , Real highWeight , LowFrequencyVertexFunctor && Low , HighFrequencyVertexFunctor && High ) 152 | { 153 | return _ProcessVertexVertex< EigenSolver , T , Real >( solver , mesh , lowWeight , highWeight , std::forward< LowFrequencyVertexFunctor >( Low ) , std::forward< HighFrequencyVertexFunctor >( High ) , true ); 154 | } 155 | 156 | template< typename EigenSolver , typename T , typename Real , typename LowFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ , typename HighFrequencyEdgeFunctor /* = std::function< T ( unsigned int ) > */ > 157 | std::vector< T > _ProcessVertexEdge( EigenSolver & solver , const FEM::RiemannianMesh< Real > &mesh , Real lowWeight , Real highWeight , LowFrequencyVertexFunctor && Low , HighFrequencyEdgeFunctor && High , bool preAnalyzed ) 158 | { 159 | static_assert( Array< T >::Dim , "[ERROR] T is not of array type" ); 160 | static_assert( std::is_convertible_v< LowFrequencyVertexFunctor , std::function< T ( unsigned int ) > > , "[ERROR] LowFrequencyVertexFunctor is poorly formed" ); 161 | static_assert( std::is_convertible_v< HighFrequencyEdgeFunctor , std::function< T ( unsigned int ) > > , "[ERROR] HighFrequencyEdgeFunctor is poorly formed" ); 162 | 163 | Eigen::SparseMatrix< Real > mass = mesh.template massMatrix< FEM::BASIS_0_WHITNEY , true >() * lowWeight; 164 | Eigen::SparseMatrix< Real > d = mesh.template dMatrix< FEM::BASIS_0_WHITNEY , FEM::BASIS_1_WHITNEY , true >(); 165 | Eigen::SparseMatrix< Real > divergence = d.transpose() * mesh.template massMatrix< FEM::BASIS_1_WHITNEY , true >( true ) * highWeight; 166 | 167 | if( preAnalyzed ) solver.factorize( mass + divergence * d ); 168 | else solver.compute ( mass + divergence * d ); 169 | if( solver.info()!=Eigen::Success ) MK_ERROR_OUT( "Failed to factorize matrix" ); 170 | 171 | std::vector< T > out( mesh.vCount() ); 172 | _Solve< 0 >( solver , mass , divergence , std::forward< LowFrequencyVertexFunctor >( Low ) , std::forward< HighFrequencyEdgeFunctor >( High ) , out ); 173 | return out; 174 | } 175 | 176 | template< typename EigenSolver , typename T , typename Real , typename LowFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ , typename HighFrequencyEdgeFunctor /* = std::function< T ( unsigned int ) > */ > 177 | std::vector< T > ProcessVertexEdge( const FEM::RiemannianMesh< Real > &mesh , Real lowWeight , Real highWeight , LowFrequencyVertexFunctor && Low , HighFrequencyEdgeFunctor && High ) 178 | { 179 | EigenSolver solver; 180 | return _ProcessVertexEdge< EigenSolver , T , Real >( solver , mesh , lowWeight , highWeight , std::forward< LowFrequencyVertexFunctor >( Low ) , std::forward< HighFrequencyEdgeFunctor >( High ) , false ); 181 | } 182 | 183 | template< typename EigenSolver , typename T , typename Real , typename LowFrequencyVertexFunctor /* = std::function< T ( unsigned int ) > */ , typename HighFrequencyEdgeFunctor /* = std::function< T ( unsigned int ) > */ > 184 | std::vector< T > ProcessVertexEdge( EigenSolver & solver , const FEM::RiemannianMesh< Real > &mesh , Real lowWeight , Real highWeight , LowFrequencyVertexFunctor && Low , HighFrequencyEdgeFunctor && High ) 185 | { 186 | return _ProcessVertexEdge< EigenSolver , T , Real >( solver , mesh , lowWeight , highWeight , std::forward< LowFrequencyVertexFunctor >( Low ) , std::forward< HighFrequencyEdgeFunctor >( High ) , true ); 187 | } 188 | 189 | template< typename EigenSolver , typename Real , typename VertexFunctor /* = std::function< Point< Real , 3 >( unsigned int ) > */ , typename NormalFunctor /* = std::function< Point< Real , 3 >( unsigned int ) > */ > 190 | std::vector< Point< Real , 3 > > FitToNormals( const FEM::RiemannianMesh< Real > &mesh , Real vWeight , Real nWeight , VertexFunctor && V , NormalFunctor && N ) 191 | { 192 | static_assert( std::is_convertible_v< VertexFunctor , std::function< Point< Real , 3 > ( unsigned int ) > > , "[ERROR] VertexFunctor is poorly formed" ); 193 | static_assert( std::is_convertible_v< NormalFunctor , std::function< Point< Real , 3 > ( unsigned int ) > > , "[ERROR] NormalFunctor is poorly formed" ); 194 | 195 | auto LowFrequencyVertexValues = [&]( unsigned int v ){ return V(v); }; 196 | 197 | // High frequencies given projection of edge offset onto the normal plane 198 | auto HighFrequencyEdgeValues = [&]( unsigned int e ) 199 | { 200 | int v1 , v2; 201 | mesh.edgeVertices( e , v1 , v2 ); 202 | Point< Real , 3 > d = V(v2) - V(v1); 203 | Point< Real , 3 > n = N(v2) + N(v1); 204 | return d - Point< Real , 3 >::Dot( d , n ) / Point< Real , 3 >::SquareNorm( n ) * n; 205 | }; 206 | 207 | return ProcessVertexEdge< EigenSolver , Point3D< Real > , Real >( mesh , vWeight , nWeight , LowFrequencyVertexValues , HighFrequencyEdgeValues ); 208 | } 209 | 210 | template< typename EigenSolver , typename Real , typename VertexFunctor /* = std::function< Point< Real , 3 >( unsigned int ) > */ , typename NormalFunctor /* = std::function< Point< Real , 3 >( unsigned int ) > */ > 211 | std::vector< Point< Real , 3 > > FitToNormals( EigenSolver & solver , const FEM::RiemannianMesh< Real > &mesh , Real vWeight , Real nWeight , VertexFunctor && V , NormalFunctor && N ) 212 | { 213 | static_assert( std::is_convertible_v< VertexFunctor , std::function< Point< Real , 3 > ( unsigned int ) > > , "[ERROR] VertexFunctor is poorly formed" ); 214 | static_assert( std::is_convertible_v< NormalFunctor , std::function< Point< Real , 3 > ( unsigned int ) > > , "[ERROR] NormalFunctor is poorly formed" ); 215 | 216 | auto LowFrequencyVertexValues = [&]( unsigned int v ){ return V(v); }; 217 | 218 | // High frequencies given projection of edge offset onto the normal plane 219 | auto HighFrequencyEdgeValues = [&]( unsigned int e ) 220 | { 221 | int v1 , v2; 222 | mesh.edgeVertices( e , v1 , v2 ); 223 | Point< Real , 3 > d = V(v2) - V(v1); 224 | Point< Real , 3 > n = N(v2) + N(v1); 225 | return d - Point< Real , 3 >::Dot( d , n ) / Point< Real , 3 >::SquareNorm( n ) * n; 226 | }; 227 | 228 | return ProcessVertexEdge< EigenSolver , Point3D< Real > , Real >( solver , mesh , vWeight , nWeight , LowFrequencyVertexValues , HighFrequencyEdgeValues ); 229 | } 230 | 231 | } 232 | } 233 | #endif // GRADIENT_DOMAIN_INCLUDED -------------------------------------------------------------------------------- /Include/PreProcessor.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2025, Michael Kazhdan 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | #ifndef PRE_PROCESSOR_INCLUDED 30 | #define PRE_PROCESSOR_INCLUDED 31 | 32 | #if _WIN32 || _WIN64 33 | #define NOMINMAX 34 | #endif // _WIN32 || _WIN64 35 | 36 | //B#define EIGEN_USE_MKL_ALL // Accelerate Eigen performance by using the MKL 37 | 38 | 39 | #endif // PRE_PROCESSOR_INCLUDED -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2025 mkazhdan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHAPE_GRADIENT_DOMAIN_TARGET=ShapeGradientDomain 2 | SHAPE_GRADIENT_DOMAIN_SOURCE=ShapeGradientDomain/ShapeGradientDomain.cpp 3 | SHAPE_CURVATURE_TARGET=ShapeCurvature 4 | SHAPE_CURVATURE_SOURCE=ShapeCurvature/ShapeCurvature.cpp 5 | 6 | COMPILER ?= gcc 7 | #COMPILER ?= clang 8 | 9 | CFLAGS += -std=c++20 -Wno-deprecated -Wno-invalid-offsetof 10 | LFLAGS += -lstdc++ 11 | ifeq ($(COMPILER),gcc) 12 | CFLAGS += -fopenmp 13 | LFLAGS += -lgomp -lpthread 14 | CC=gcc 15 | CXX=g++ 16 | else 17 | CFLAGS += -Wno-dangling-else -Wno-null-dereference 18 | CC=clang 19 | CXX=clang++ 20 | ifeq ($(SANITIZATION),none) 21 | LFLAGS += -static 22 | else 23 | LFLAGS += -g -fsanitize=$(SANITIZATION) 24 | CFLAGS += -O1 -g -fsanitize=$(SANITIZATION) 25 | endif 26 | endif 27 | 28 | CFLAGS += -O3 -DRELEASE -funroll-loops -g 29 | LFLAGS += -O3 -g 30 | 31 | BIN = Bin/Linux/ 32 | BIN_O = Obj/Linux/ 33 | INCLUDE = /usr/include/ -I. 34 | 35 | MD=mkdir 36 | 37 | SHAPE_GRADIENT_DOMAIN_OBJECTS=$(addprefix $(BIN_O), $(addsuffix .o, $(basename $(SHAPE_GRADIENT_DOMAIN_SOURCE)))) 38 | SHAPE_GRADIENT_DOMAIN_OBJECT_DIR=$(dir $(SHAPE_GRADIENT_DOMAIN_OBJECTS)) 39 | SHAPE_CURVATURE_OBJECTS=$(addprefix $(BIN_O), $(addsuffix .o, $(basename $(SHAPE_CURVATURE_SOURCE)))) 40 | SHAPE_CURVATURE_OBJECT_DIR=$(dir $(SHAPE_CURVATURE_OBJECTS)) 41 | 42 | all: make_dirs 43 | all: $(BIN)$(SHAPE_GRADIENT_DOMAIN_TARGET) 44 | all: $(BIN)$(SHAPE_CURVATURE_TARGET) 45 | 46 | shapegradientdomain: make_dirs 47 | shapegradientdomain: $(BIN)$(SHAPE_GRADIENT_DOMAIN_TARGET) 48 | 49 | shapecurvature: make_dirs 50 | shapecurvature: $(BIN)$(SHAPE_CURVATURE_TARGET) 51 | 52 | clean: 53 | rm -rf $(BIN)$(SHAPE_GRADIENT_DOMAIN_TARGET) 54 | rm -rf $(BIN)$(SHAPE_CURVATURE_TARGET) 55 | rm -rf $(BIN_O) 56 | 57 | make_dirs: FORCE 58 | $(MD) -p $(BIN) 59 | $(MD) -p $(BIN_O) 60 | $(MD) -p $(SHAPE_GRADIENT_DOMAIN_OBJECT_DIR) 61 | $(MD) -p $(SHAPE_CURVATURE_OBJECT_DIR) 62 | 63 | 64 | $(BIN)$(SHAPE_GRADIENT_DOMAIN_TARGET): $(SHAPE_GRADIENT_DOMAIN_OBJECTS) 65 | $(CXX) -o $@ $(SHAPE_GRADIENT_DOMAIN_OBJECTS) -L$(BIN) $(LFLAGS) 66 | 67 | $(BIN)$(SHAPE_CURVATURE_TARGET): $(SHAPE_CURVATURE_OBJECTS) 68 | $(CXX) -o $@ $(SHAPE_CURVATURE_OBJECTS) -L$(BIN) $(LFLAGS) 69 | 70 | 71 | $(BIN_O)%.o: $(SRC)%.cpp 72 | $(CXX) -c -o $@ $(CFLAGS) -I$(INCLUDE) $< 73 | 74 | FORCE: -------------------------------------------------------------------------------- /Misha/Algebra.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2013, Michael Kazhdan 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | #ifndef ALGEBRA_INCLUDED 30 | #define ALGEBRA_INCLUDED 31 | 32 | #include 33 | 34 | namespace MishaK 35 | { 36 | template 37 | class Group 38 | { 39 | public: 40 | // For this to work, need to define: 41 | // void Element::SetIdentity (void); 42 | // void Element::Multiply (const Element& e) 43 | // void Element::Invert (void) 44 | 45 | static Element Identity(void) 46 | { 47 | Element out; 48 | out.SetIdentity(); 49 | return out; 50 | } 51 | Element inverse(void) const 52 | { 53 | Element out=*(Element*)this; 54 | out.Invert(); 55 | return out; 56 | } 57 | friend Element operator * (const Element& e1,const Element& e2) 58 | { 59 | Element out=e1; 60 | out.Multiply(e2); 61 | return out; 62 | } 63 | friend Element operator / (const Element& e1,const Element& e2) 64 | { 65 | Element out=e1; 66 | Element inv=e2.Invert(); 67 | out.Multiply(inv); 68 | return out; 69 | } 70 | friend Element& operator *= (Element& e1,const Element& e2) 71 | { 72 | e1.Multiply(e2); 73 | return e1; 74 | } 75 | friend Element& operator /= (Element& e1,const Element& e2) 76 | { 77 | Element inv=e2; 78 | inv.Invert(); 79 | e1.Multiply(inv); 80 | return e1; 81 | } 82 | }; 83 | 84 | template 85 | class VectorSpace 86 | { 87 | public: 88 | typedef Real R; 89 | // For this to work, need to define: 90 | // void Element::Add(const Element& e) 91 | // void Element::Scale(Real s) 92 | friend Element operator - ( const Element& e ) 93 | { 94 | Element out=e; 95 | out.Scale(-1); 96 | return out; 97 | } 98 | 99 | friend Element operator + (const Element& e1,const Element& e2) 100 | { 101 | Element out=e1; 102 | out.Add(e2); 103 | return out; 104 | }; 105 | friend Element operator - (const Element& e1,const Element& e2) 106 | { 107 | Element out=e2; 108 | out.Scale(-1); 109 | out.Add(e1); 110 | return out; 111 | } 112 | friend Element& operator += (Element& e1,const Element& e2) 113 | { 114 | e1.Add(e2); 115 | return e1; 116 | } 117 | friend Element& operator -= (Element& e1,const Element& e2) 118 | { 119 | Element neg=e2; 120 | neg.Scale(-1); 121 | return e1+=neg; 122 | } 123 | 124 | friend Element operator * (const Element& e,const Real& s) 125 | { 126 | Element out=e; 127 | out.Scale(s); 128 | return out; 129 | } 130 | friend Element operator * (const Real& s,const Element& e) 131 | { 132 | return e*s; 133 | } 134 | friend Element operator / (const Element& e,const Real& s) 135 | { 136 | return e*(Real(1)/s); 137 | } 138 | 139 | friend Element& operator *= (Element& e,const Real& s) 140 | { 141 | e.Scale(s); 142 | return e; 143 | } 144 | friend Element& operator /= (Element& e,const Real& s) 145 | { 146 | return e*=Real(1)/s; 147 | } 148 | }; 149 | 150 | template< class Real , class Element > 151 | class InnerProductSpace : public VectorSpace< Real , Element > 152 | { 153 | public: 154 | // For this to work, need to define: 155 | // Real Element::InnerProduct (const Element& e) const 156 | 157 | static Real SquareNorm (const Element& e) { return e.InnerProduct(e); } 158 | static Real Dot (const Element& e1,const Element& e2) { return e1.InnerProduct(e2); } 159 | static Real SquareDistance (const Element& e1,const Element& e2) { return SquareNorm(e1-e2); } 160 | static Real Length (const Element& e) { return Real( sqrt( e.InnerProduct(e) ) ); } 161 | Real squareNorm( void ) const { return SquareNorm( *( ( Element* )this ) ); } 162 | }; 163 | 164 | template 165 | class Algebra : public VectorSpace 166 | { 167 | public: 168 | virtual void SetIdentity (void) = 0; 169 | virtual void Multiply (const Element& e) = 0; 170 | 171 | static Element Identity(void) 172 | { 173 | Element out; 174 | out.SetIdentity(); 175 | return out; 176 | } 177 | 178 | friend Element operator * (const Element& e1,const Element& e2) 179 | { 180 | Element out=e1; 181 | out.Multiply(e2); 182 | return out; 183 | } 184 | 185 | friend Element& operator *= (Element& e1,const Element& e2) 186 | { 187 | e1.Multiply(e2); 188 | return e1; 189 | } 190 | }; 191 | 192 | template< class Element > 193 | class Field 194 | { 195 | public: 196 | typedef Element R; 197 | // For this to work, need to define: 198 | // void Element::SetAdditiveIdentity (void); 199 | // void Element::SetMultiplicativeIdentity (void); 200 | // void Element::Add (const Element& e); 201 | // void Element::Multiply (const Element& e); 202 | // void Element::Negate (void); 203 | // void Element::Invert (void); 204 | 205 | static Element AdditiveIdentity(void) 206 | { 207 | Element out; 208 | out.SetAdditiveIdentity(); 209 | return out; 210 | } 211 | static Element MultiplicativeIdentity(void) 212 | { 213 | Element out; 214 | out.SetMultiplicativeIdentity(); 215 | return out; 216 | } 217 | Element additiveInverse(void) const 218 | { 219 | Element out=*(Element*)this; 220 | out.Negate(); 221 | return out; 222 | } 223 | Element multiplicativeInverse(void) const 224 | { 225 | Element out=*(Element*)this; 226 | out.Invert(); 227 | return out; 228 | } 229 | friend Element operator + ( const Element& e1 , const Element& e2 ) 230 | { 231 | Element out=e1; 232 | out.Add(e2); 233 | return out; 234 | } 235 | friend Element operator * ( const Element& e1 , const Element& e2 ) 236 | { 237 | Element out=e1; 238 | out.Multiply(e2); 239 | return out; 240 | } 241 | friend Element operator - (const Element& e1,const Element& e2) 242 | { 243 | Element out=e1; 244 | Element inv=e2.Negate(); 245 | out.Add(inv); 246 | return out; 247 | } 248 | friend Element operator / (const Element& e1,const Element& e2) 249 | { 250 | Element out=e1; 251 | Element inv=e2.Invert(); 252 | out.Multiply(inv); 253 | return out; 254 | } 255 | friend Element& operator += (Element& e1,const Element& e2) 256 | { 257 | e1.Add(e2); 258 | return e1; 259 | } 260 | friend Element& operator *= (Element& e1,const Element& e2) 261 | { 262 | e1.Multiply(e2); 263 | return e1; 264 | } 265 | friend Element& operator -= (Element& e1,const Element& e2) 266 | { 267 | Element inv=e2; 268 | inv.Negate(); 269 | e1.Add(inv); 270 | return e1; 271 | } 272 | friend Element& operator /= (Element& e1,const Element& e2) 273 | { 274 | Element inv=e2; 275 | inv.Invert(); 276 | e1.Multiply(inv); 277 | return e1; 278 | } 279 | }; 280 | } 281 | #endif // ALGEBRA_INCLUDED 282 | -------------------------------------------------------------------------------- /Misha/Array.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2011, Michael Kazhdan and Ming Chuang 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | #ifndef ARRAY_INCLUDED 30 | #define ARRAY_INCLUDED 31 | 32 | #include 33 | #include 34 | #ifdef ARRAY_DEBUG 35 | #include 36 | #include 37 | #include 38 | #ifdef _WIN32 39 | #include 40 | #endif // _WIN32 41 | #include 42 | #endif // ARRAY_DEBUG 43 | 44 | #ifdef _WIN64 45 | #include 46 | #define MK_ASSERT( x ) { if( !( x ) ) __debugbreak(); } 47 | #else // !_WIN64 48 | #ifdef _WIN32 49 | #define MK_ASSERT( x ) { if( !( x ) ) _asm{ int 0x03 } } 50 | #else // !_WIN32 51 | #define MK_ASSERT( x ) { if( !( x ) ) exit(0); } 52 | #endif // _WIN32 53 | #endif // _WIN64 54 | 55 | namespace MishaK 56 | { 57 | // Code from http://stackoverflow.com 58 | inline void* aligned_malloc( size_t size , size_t align ) 59 | { 60 | // Align enough for the data, the alignment padding, and room to store a pointer to the actual start of the memory 61 | void* mem = malloc( size + align + sizeof( void* ) ); 62 | // The position at which we could potentially start addressing 63 | char* amem = ( (char*)mem ) + sizeof( void* ); 64 | // Add align-1 to the start of the address and then zero out at most of the first align-1 bits. 65 | amem = ( char* )( ( (size_t)( ( (char*)amem ) + (align-1) ) ) & ~( align-1 ) ); 66 | // Pre-write the actual address 67 | ( ( void** ) amem )[-1] = mem; 68 | return amem; 69 | } 70 | inline void aligned_free( void* mem ) { free( ( ( void** )mem )[-1] ); } 71 | 72 | #ifdef ARRAY_DEBUG 73 | #pragma message ( "[WARNING] Array debugging is enabled" ) 74 | #include "Array.inl" 75 | #define Pointer( ... ) Array< __VA_ARGS__ > 76 | #define ConstPointer( ... ) ConstArray< __VA_ARGS__ > 77 | template< class C > void FreePointer( Array< C >& a ){ a.Free( ); } 78 | template< class C > void AlignedFreePointer( Array< C >& a ){ a.Free( ); } 79 | template< class C > void VFreePointer( Array< C >& a ){ a.Free( ); } 80 | template< class C > void DeletePointer( Array< C >& a ){ a.Delete( ); } 81 | 82 | template< class C > Array< C > NewPointer( size_t size , const char* name=NULL ){ return Array< C >::New ( size , name ); } 83 | template< class C > Array< C > AllocPointer( size_t size , const char* name=NULL ){ return Array< C >::Alloc ( size , false , name ); } 84 | template< class C > Array< C > AlignedAllocPointer( size_t size , size_t alignment , const char* name=NULL ){ return Array< C >::AlignedAlloc( size , alignment , false , name ); } 85 | template< class C > Array< C > ReAllocPointer( Array< C >& a , size_t size , const char* name=NULL ){ return Array< C >::ReAlloc ( a , size , false , name ); } 86 | 87 | template< class C > Array< C > NullPointer( void ){ return Array< C >( ); } 88 | 89 | template< class C > Array< C > GetPointer( C& c ) { return Array< C >::FromPointer( &c , 1 ); } 90 | template< class C > ConstArray< C > GetPointer( const C& c ) { return ConstArray< C >::FromPointer( &c , 1 ); } 91 | template< class C > Array< C > GetPointer( std::vector< C >& v ){ return Array< C >::FromPointer( &v[0] , v.size() ); } 92 | template< class C > ConstArray< C > GetPointer( const std::vector< C >& v ){ return ConstArray< C >::FromPointer( &v[0] , v.size() ); } 93 | template< class C > Array< C > GetPointer( C* c , size_t sz ){ return Array< C >::FromPointer( c , sz ); } 94 | template< class C > ConstArray< C > GetPointer( const C* c , size_t sz ){ return ConstArray< C >::FromPointer( c , sz ); } 95 | //template< class C > Array< C > GetPointer( Array< C >& a ) { return a; } 96 | //template< class C > ConstArray< C > GetPointer( ConstArray< C >& a ) { return a; } 97 | 98 | template< class C > C *GetAddress( Array< C > &a ){ return a.ptr(); } 99 | template< class C > const C *GetAddress( const Array< C > &a ){ return a.ptr(); } 100 | template< class C > const C *GetAddress( ConstArray< C > &a ){ return a.ptr(); } 101 | 102 | 103 | #else // !ARRAY_DEBUG 104 | #define Pointer( ... ) __VA_ARGS__* 105 | #define ConstPointer( ... ) const __VA_ARGS__* 106 | 107 | #define FreePointer( ... ) { if( __VA_ARGS__ ) free( __VA_ARGS__ ) , __VA_ARGS__ = NULL; } 108 | #define AlignedFreePointer( ... ) { if( __VA_ARGS__ ) aligned_free( __VA_ARGS__ ) , __VA_ARGS__ = NULL; } 109 | #define DeletePointer( ... ) { if( __VA_ARGS__ ) delete[] __VA_ARGS__ , __VA_ARGS__ = NULL; } 110 | 111 | template< class C > C* NewPointer( size_t size , const char* name=NULL ){ return new C[size]; } 112 | template< class C > C* AllocPointer( size_t size , const char* name=NULL ){ return (C*) malloc( sizeof(C) * size ); } 113 | template< class C > C* AlignedAllocPointer( size_t size , size_t alignment , const char* name=NULL ){ return (C*)aligned_malloc( sizeof(C) * size , alignment ); } 114 | template< class C > C* ReAllocPointer( C* c , size_t size , const char* name=NULL ){ return (C*) realloc( c , sizeof(C) * size ); } 115 | 116 | template< class C > C* NullPointer( void ){ return NULL; } 117 | 118 | template< class C > C* GetPointer( C& c ){ return &c; } 119 | template< class C > const C* GetPointer( const C& c ){ return &c; } 120 | template< class C > C* GetPointer( std::vector< C >& v ){ return &v[0]; } 121 | template< class C > const C* GetPointer( const std::vector< C >& v ){ return &v[0]; } 122 | template< class C > C* GetPointer( C* c , size_t sz ){ return c; } 123 | template< class C > const C* GetPointer( const C* c , size_t sz ){ return c; } 124 | 125 | template< class C > C* GetAddress( C* c ) { return c; } 126 | template< class C > const C* GetAddress( const C* c ) { return c; } 127 | #endif // ARRAY_DEBUG 128 | 129 | // [WARNING] The out-of-core array uses a buffer and is not thread-safe 130 | template< class Data , size_t BufferSize=64 > 131 | class OOCArray 132 | { 133 | FILE* _fp; 134 | char _fileName[512]; 135 | size_t _currentBufferIndex; 136 | Data _buffer[BufferSize]; 137 | 138 | void _init( void ) 139 | { 140 | #ifdef _WIN32 141 | const char FileSeparator = '\\'; 142 | #else // !_WIN32 143 | const char FileSeparator = '/'; 144 | #endif // _WIN32 145 | 146 | const char prefix[] = "scratch"; 147 | const char current[] = "."; 148 | { 149 | const char* dir = NULL; 150 | if( !dir || !strlen(dir) ) dir = getenv( "TMP" ); // Try to get the scratch directory from the environment variable 151 | if( !dir || !strlen(dir) ) dir = current; // Set it to the current directory 152 | 153 | if( dir[strlen(dir)-1]!=FileSeparator ) sprintf( _fileName , "%s%c%s_XXXXXX" , dir , FileSeparator , prefix ); 154 | else sprintf( _fileName , "%s%s_XXXXXX" , dir , prefix ); 155 | } 156 | #ifdef _WIN32 157 | _mktemp( _fileName ); 158 | fopen_s( &_fp , _fileName , "w+b" ); 159 | #else // !_WIN32 160 | mktemp ( _fileName ); 161 | _fp = fopen( _fileName , "w+b" ); 162 | #endif // _WIN32 163 | if( !_fp ) fprintf( stderr , "[ERROR] Failed to open file for writing: %s\n" , _fileName ) , exit( 0 ); 164 | _currentBufferIndex = 0; 165 | } 166 | public: 167 | OOCArray( void ){ _init(); } 168 | OOCArray( size_t sz ) { _init() , resize( sz ); } 169 | 170 | ~OOCArray( void ) 171 | { 172 | fclose( _fp ); 173 | remove( _fileName ); 174 | _fp = NULL; 175 | } 176 | void resize( size_t sz ) 177 | { 178 | #ifdef _WIN32 179 | _fseeki64( _fp , sizeof( Data ) * sz , SEEK_SET ); 180 | #else // !_WIN32 181 | fseek ( _fp , sizeof( Data ) * sz , SEEK_SET ); 182 | #endif // _WIN32 183 | } 184 | Data& operator[]( size_t i ) 185 | { 186 | size_t bufferIndex = i / BufferSize; 187 | if( bufferIndex!=_currentBufferIndex ) 188 | { 189 | // Write out the previous buffer 190 | #ifdef _WIN32 191 | _fseeki64( _fp , sizeof( Data ) * _currentBufferIndex * BufferSize , SEEK_SET ); 192 | #else // !_WIN32 193 | fseek ( _fp , sizeof( Data ) * _currentBufferIndex * BufferSize , SEEK_SET ); 194 | #endif // _WIN32 195 | fwrite( &_buffer , sizeof( Data ) , BufferSize , _fp ); 196 | 197 | // Read in the current buffer 198 | _currentBufferIndex = bufferIndex; 199 | #ifdef _WIN32 200 | _fseeki64( _fp , sizeof( Data ) * _currentBufferIndex * BufferSize , SEEK_SET ); 201 | #else // !_WIN32 202 | fseek ( _fp , sizeof( Data ) * _currentBufferIndex * BufferSize , SEEK_SET ); 203 | #endif // _WIN32 204 | fread( &_buffer , sizeof( Data ) , BufferSize , _fp ); 205 | } 206 | return _buffer[ i % BufferSize ]; 207 | } 208 | }; 209 | } 210 | #endif // ARRAY_INCLUDED 211 | -------------------------------------------------------------------------------- /Misha/Atomic.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Michael Kazhdan 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | #ifndef MY_ATOMIC_INCLUDED 29 | #define MY_ATOMIC_INCLUDED 30 | 31 | #if defined( _WIN32 ) || defined( _WIN64 ) 32 | #include 33 | #include 34 | #include 35 | #else // !_WIN32 && !_WIN64 36 | #include 37 | #include 38 | #include 39 | #endif // _WIN32 || _WIN64 40 | #include 41 | 42 | namespace MishaK 43 | { 44 | template< typename Value > 45 | Value SetAtomic( volatile Value & value , Value newValue ); 46 | 47 | template< typename Value > 48 | bool SetAtomic( volatile Value & value , Value newValue , Value oldValue ); 49 | 50 | template< typename Value > 51 | void AddAtomic( volatile Value & a , Value b ); 52 | 53 | template< typename Value > 54 | Value ReadAtomic( const volatile Value & value ); 55 | 56 | template< typename Value > 57 | struct Atomic 58 | { 59 | static void Add( volatile Value &a , const Value &b ); 60 | static Value Set( volatile Value & value , Value newValue ); 61 | static bool Set( volatile Value & value , Value newValue , Value oldValue ); 62 | static Value Read( const volatile Value & value ); 63 | }; 64 | 65 | //////////////////// 66 | // Implementation // 67 | //////////////////// 68 | 69 | template< typename Value > Value ReadAtomic8_( const volatile Value * value ); 70 | template< typename Value > Value ReadAtomic32_( const volatile Value * value ); 71 | template< typename Value > Value ReadAtomic64_( const volatile Value * value ); 72 | 73 | template< typename Value > Value SetAtomic8_ ( volatile Value * value , Value newValue ); 74 | template< typename Value > Value SetAtomic32_( volatile Value * value , Value newValue ); 75 | template< typename Value > Value SetAtomic64_( volatile Value * value , Value newValue ); 76 | 77 | template< typename Value > bool SetAtomic8_ ( volatile Value * value , Value newValue , Value oldValue ); 78 | template< typename Value > bool SetAtomic32_( volatile Value * value , Value newValue , Value oldValue ); 79 | template< typename Value > bool SetAtomic64_( volatile Value * value , Value newValue , Value oldValue ); 80 | 81 | template< typename Value > void AddAtomic8_( volatile Value * a , Value b ); 82 | template< typename Value > void AddAtomic32_( volatile Value * a , Value b ); 83 | template< typename Value > void AddAtomic64_( volatile Value * a , Value b ); 84 | 85 | template< typename Value > 86 | Value SetAtomic( volatile Value & value , Value newValue ) 87 | { 88 | if constexpr( sizeof(Value)==1 ) return SetAtomic8_ ( &value , newValue ); 89 | else if constexpr( sizeof(Value)==4 ) return SetAtomic32_( &value , newValue ); 90 | else if constexpr( sizeof(Value)==8 ) return SetAtomic64_( &value , newValue ); 91 | else 92 | { 93 | MK_WARN_ONCE( "should not use this function: " , typeid(Value).name() , " , " , sizeof(Value) ); 94 | static std::mutex setAtomicMutex; 95 | std::lock_guard< std::mutex > lock( setAtomicMutex ); 96 | Value oldValue = *(Value*)&value; 97 | *(Value*)&value = newValue; 98 | return oldValue; 99 | } 100 | } 101 | 102 | template< typename Value > 103 | bool SetAtomic( volatile Value & value , Value newValue , Value oldValue ) 104 | { 105 | if constexpr( sizeof(Value)==1 ) return SetAtomic8_ ( &value , newValue , oldValue ); 106 | else if constexpr( sizeof(Value)==4 ) return SetAtomic32_( &value , newValue , oldValue ); 107 | else if constexpr( sizeof(Value)==8 ) return SetAtomic64_( &value , newValue , oldValue ); 108 | else 109 | { 110 | MK_WARN_ONCE( "should not use this function: " , typeid(Value).name() , " , " , sizeof(Value) ); 111 | static std::mutex setAtomicMutex; 112 | std::lock_guard< std::mutex > lock( setAtomicMutex ); 113 | if( value==oldValue ){ value = newValue ; return true; } 114 | else return false; 115 | } 116 | } 117 | 118 | template< typename Value > 119 | void AddAtomic( volatile Value & a , Value b ) 120 | { 121 | if constexpr( sizeof(Value)==1 ) return AddAtomic8_ ( &a , b ); 122 | else if constexpr( sizeof(Value)==4 ) return AddAtomic32_( &a , b ); 123 | else if constexpr( sizeof(Value)==8 ) return AddAtomic64_( &a , b ); 124 | else 125 | { 126 | MK_WARN_ONCE( "should not use this function: " , typeid(Value).name() , " , " , sizeof(Value) ); 127 | static std::mutex addAtomicMutex; 128 | std::lock_guard< std::mutex > lock( addAtomicMutex ); 129 | *(Value*)&a += b; 130 | } 131 | } 132 | 133 | template< typename Value > 134 | Value ReadAtomic( const volatile Value & value ) 135 | { 136 | if constexpr( sizeof(Value)==1 ) return ReadAtomic8_( &value ); 137 | else if constexpr( sizeof(Value)==4 ) return ReadAtomic32_( &value ); 138 | else if constexpr( sizeof(Value)==8 ) return ReadAtomic64_( &value ); 139 | else 140 | { 141 | MK_WARN_ONCE( "should not use this function: " , typeid(Value).name() , " , " , sizeof(Value) ); 142 | static std::mutex readAtomicMutex; 143 | std::lock_guard< std::mutex > lock( readAtomicMutex ); 144 | return *(Value*)&value; 145 | } 146 | } 147 | 148 | template< typename Value > 149 | void Atomic< Value >::Add( volatile Value &a , const Value &b ) 150 | { 151 | if constexpr( std::is_trivial_v< Value > ) AddAtomic( a , b ); 152 | else 153 | { 154 | MK_WARN_ONCE( "should not use this function: " , typeid(Value).name() ); 155 | static std::mutex addAtomicMutex; 156 | std::lock_guard< std::mutex > lock( addAtomicMutex ); 157 | *(Value*)&a += b; 158 | } 159 | } 160 | 161 | template< typename Value > 162 | Value Atomic< Value >::Set( volatile Value & value , Value newValue ) 163 | { 164 | if constexpr( std::is_trivial_v< Value > ) return SetAtomic( value , newValue ); 165 | else 166 | { 167 | MK_WARN_ONCE( "should not use this function: " , typeid(Value).name() ); 168 | static std::mutex setAtomicMutex; 169 | std::lock_guard< std::mutex > lock( setAtomicMutex ); 170 | Value oldValue = *(Value*)&value; 171 | *(Value*)&value = newValue; 172 | return oldValue; 173 | } 174 | } 175 | 176 | template< typename Value > 177 | bool Atomic< Value >::Set( volatile Value & value , Value newValue , Value oldValue ) 178 | { 179 | if constexpr( std::is_trivial_v< Value > ) return SetAtomic( value , newValue , oldValue ); 180 | else 181 | { 182 | MK_WARN_ONCE( "should not use this function: " , typeid(Value).name() , " , " , sizeof(Value) ); 183 | static std::mutex setAtomicMutex; 184 | std::lock_guard< std::mutex > lock( setAtomicMutex ); 185 | if( value==oldValue ){ value = newValue ; return true; } 186 | else return false; 187 | } 188 | } 189 | 190 | template< typename Value > 191 | Value Atomic< Value >::Read( const volatile Value & value ) 192 | { 193 | if constexpr( std::is_trivial_v< Value > ) return ReadAtomic( value ); 194 | else 195 | { 196 | MK_WARN_ONCE( "should not use this function: " , typeid(Value).name() , " , " , sizeof(Value) ); 197 | static std::mutex readAtomicMutex; 198 | std::lock_guard< std::mutex > lock( readAtomicMutex ); 199 | return *(Value*)&value; 200 | } 201 | } 202 | 203 | /////////////////////////////////////////////// 204 | /////////////////////////////////////////////// 205 | /////////////////////////////////////////////// 206 | 207 | template< typename Value > 208 | Value ReadAtomic8_( const volatile Value * value ) 209 | { 210 | #if defined( _WIN32 ) || defined( _WIN64 ) 211 | char _value = InterlockedExchangeAdd8( (char*)value , 0 ); 212 | return *(Value*)(&_value); 213 | #else // !_WIN32 && !_WIN64 214 | uint8_t _value = __atomic_load_n( (uint8_t *)value , __ATOMIC_SEQ_CST ); 215 | #endif // _WIN32 || _WIN64 216 | return *(Value*)(&_value); 217 | } 218 | 219 | template< typename Value > 220 | Value ReadAtomic32_( const volatile Value * value ) 221 | { 222 | #if defined( _WIN32 ) || defined( _WIN64 ) 223 | long _value = InterlockedExchangeAdd( (long*)value , 0 ); 224 | return *(Value*)(&_value); 225 | #else // !_WIN32 && !_WIN64 226 | uint32_t _value = __atomic_load_n( (uint32_t *)value , __ATOMIC_SEQ_CST ); 227 | #endif // _WIN32 || _WIN64 228 | return *(Value*)(&_value); 229 | } 230 | 231 | template< typename Value > 232 | Value ReadAtomic64_( const volatile Value * value ) 233 | { 234 | #if defined( _WIN32 ) || defined( _WIN64 ) 235 | __int64 _value = InterlockedExchangeAdd64( (__int64*)value , 0 ); 236 | #else // !_WIN32 && !_WIN64 237 | uint64_t _value = __atomic_load_n( (uint64_t *)value , __ATOMIC_SEQ_CST ); 238 | #endif // _WIN32 || _WIN64 239 | return *(Value*)(&_value); 240 | } 241 | 242 | template< typename Value > 243 | Value SetAtomic8_( volatile Value *value , Value newValue ) 244 | { 245 | #if defined( _WIN32 ) || defined( _WIN64 ) 246 | char *_newValue = (char *)&newValue; 247 | char oldValue = InterlockedExchange8( (char*)value , *_newValue ); 248 | #else // !_WIN32 && !_WIN64 249 | uint8_t *_newValue = (uint8_t *)&newValue; 250 | uint8_t oldValue = __atomic_exchange_n( (uint8_t *)value , *_newValue , __ATOMIC_SEQ_CST ); 251 | #endif // _WIN32 || _WIN64 252 | return *(Value*)&oldValue; 253 | } 254 | 255 | template< typename Value > 256 | Value SetAtomic32_( volatile Value *value , Value newValue ) 257 | { 258 | #if defined( _WIN32 ) || defined( _WIN64 ) 259 | long *_newValue = (long *)&newValue; 260 | long oldValue = InterlockedExchange( (long*)value , *_newValue ); 261 | #else // !_WIN32 && !_WIN64 262 | uint32_t *_newValue = (uint32_t *)&newValue; 263 | long oldValue = __atomic_exchange_n( (uint32_t *)value , *_newValue , __ATOMIC_SEQ_CST ); 264 | #endif // _WIN32 || _WIN64 265 | return *(Value*)&oldValue; 266 | } 267 | 268 | template< typename Value > 269 | Value SetAtomic64_( volatile Value * value , Value newValue ) 270 | { 271 | #if defined( _WIN32 ) || defined( _WIN64 ) 272 | __int64 *_newValue = (__int64 *)&newValue; 273 | __int64 oldValue = InterlockedExchange64( (__int64*)value , *_newValue ); 274 | #else // !_WIN32 && !_WIN64 275 | uint64_t *_newValue = (uint64_t *)&newValue; 276 | uint64_t oldValue = __atomic_exchange_n( (uint64_t *)value , *_newValue , __ATOMIC_SEQ_CST );; 277 | #endif // _WIN32 || _WIN64 278 | return *(Value*)&oldValue; 279 | } 280 | 281 | template< typename Value > 282 | bool SetAtomic8_( volatile Value *value , Value newValue , Value oldValue ) 283 | { 284 | #if defined( _WIN32 ) || defined( _WIN64 ) 285 | char *_oldValue = (char *)&oldValue; 286 | char *_newValue = (char *)&newValue; 287 | return _InterlockedCompareExchange8( (char*)value , *_newValue , *_oldValue )==*_oldValue; 288 | #else // !_WIN32 && !_WIN64 289 | uint8_t *_newValue = (uint8_t *)&newValue; 290 | return __atomic_compare_exchange_n( (uint8_t *)value , (uint8_t *)&oldValue , *_newValue , false , __ATOMIC_SEQ_CST , __ATOMIC_SEQ_CST ); 291 | #endif // _WIN32 || _WIN64 292 | } 293 | 294 | template< typename Value > 295 | bool SetAtomic32_( volatile Value *value , Value newValue , Value oldValue ) 296 | { 297 | #if defined( _WIN32 ) || defined( _WIN64 ) 298 | long *_oldValue = (long *)&oldValue; 299 | long *_newValue = (long *)&newValue; 300 | return InterlockedCompareExchange( (long*)value , *_newValue , *_oldValue )==*_oldValue; 301 | #else // !_WIN32 && !_WIN64 302 | uint32_t *_newValue = (uint32_t *)&newValue; 303 | return __atomic_compare_exchange_n( (uint32_t *)value , (uint32_t *)&oldValue , *_newValue , false , __ATOMIC_SEQ_CST , __ATOMIC_SEQ_CST ); 304 | #endif // _WIN32 || _WIN64 305 | } 306 | 307 | template< typename Value > 308 | bool SetAtomic64_( volatile Value * value , Value newValue , Value oldValue ) 309 | { 310 | #if defined( _WIN32 ) || defined( _WIN64 ) 311 | __int64 *_oldValue = (__int64 *)&oldValue; 312 | __int64 *_newValue = (__int64 *)&newValue; 313 | return InterlockedCompareExchange64( (__int64*)value , *_newValue , *_oldValue )==*_oldValue; 314 | #else // !_WIN32 && !_WIN64 315 | uint64_t *_newValue = (uint64_t *)&newValue; 316 | return __atomic_compare_exchange_n( (uint64_t *)value , (uint64_t *)&oldValue , *_newValue , false , __ATOMIC_SEQ_CST , __ATOMIC_SEQ_CST ); 317 | #endif // _WIN32 || _WIN64 318 | } 319 | 320 | template< typename Value > 321 | void AddAtomic8_( volatile Value *a , Value b ) 322 | { 323 | Value current = ReadAtomic8_( a ); 324 | Value sum = current+b; 325 | #if defined( _WIN32 ) || defined( _WIN64 ) 326 | char *_current = (char *)¤t; 327 | char *_sum = (char *)∑ 328 | while( InterlockedCompareExchange( (char*)a , *_sum , *_current )!=*_current ) 329 | { 330 | current = ReadAtomic8_( a ); 331 | sum = current + b; 332 | } 333 | #else // !_WIN32 && !_WIN64 334 | uint8_t *_current = (uint8_t *)¤t; 335 | uint8_t *_sum = (uint8_t *)∑ 336 | while( __sync_val_compare_and_swap( (uint8_t *)a , *_current , *_sum )!=*_current ) 337 | { 338 | current = ReadAtomic8_( a ); 339 | sum = current+b; 340 | } 341 | #endif // _WIN32 || _WIN64 342 | } 343 | 344 | template< typename Value > 345 | void AddAtomic32_( volatile Value *a , Value b ) 346 | { 347 | Value current = ReadAtomic32_( a ); 348 | Value sum = current+b; 349 | #if defined( _WIN32 ) || defined( _WIN64 ) 350 | long *_current = (long *)¤t; 351 | long *_sum = (long *)∑ 352 | while( InterlockedCompareExchange( (long*)a , *_sum , *_current )!=*_current ) 353 | { 354 | current = ReadAtomic32_( a ); 355 | sum = current + b; 356 | } 357 | #else // !_WIN32 && !_WIN64 358 | uint32_t *_current = (uint32_t *)¤t; 359 | uint32_t *_sum = (uint32_t *)∑ 360 | while( __sync_val_compare_and_swap( (uint32_t *)a , *_current , *_sum )!=*_current ) 361 | { 362 | current = ReadAtomic32_( a ); 363 | sum = current+b; 364 | } 365 | #endif // _WIN32 || _WIN64 366 | } 367 | 368 | template< typename Value > 369 | void AddAtomic64_( volatile Value * a , Value b ) 370 | { 371 | #if 1 372 | Value current = ReadAtomic64_( a ); 373 | Value sum = current+b; 374 | while( !SetAtomic64_( a , sum , current ) ) 375 | { 376 | current = ReadAtomic64_( a ); 377 | sum = current+b; 378 | } 379 | #else 380 | Value current = ReadAtomic64_( a ); 381 | Value sum = current+b; 382 | #if defined( _WIN32 ) || defined( _WIN64 ) 383 | __int64 *_current = (__int64 *)¤t; 384 | __int64 *_sum = (__int64 *)∑ 385 | while( InterlockedCompareExchange64( (__int64*)a , *_sum , *_current )!=*_current ) 386 | { 387 | current = ReadAtomic64_( a ); 388 | sum = current+b; 389 | } 390 | #else // !_WIN32 && !_WIN64 391 | uint64_t *_current = (uint64_t *)¤t; 392 | uint64_t *_sum = (uint64_t *)∑ 393 | while( __sync_val_compare_and_swap( (uint64_t *)a , *_current , *_sum )!=*_current ) 394 | { 395 | current = ReadAtomic64_( a); 396 | sum = current+b; 397 | } 398 | #endif // _WIN32 || _WIN64 399 | #endif 400 | } 401 | } 402 | #endif // MY_ATOMIC_INCLUDED 403 | -------------------------------------------------------------------------------- /Misha/CmdLineParser.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | #ifndef CMD_LINE_PARSER_INCLUDED 30 | #define CMD_LINE_PARSER_INCLUDED 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include "Exceptions.h" 43 | 44 | 45 | namespace MishaK 46 | { 47 | /** This class represents a named argument that can be read from the command line */ 48 | class CmdLineReadable 49 | { 50 | public: 51 | /** Has the argument been set */ 52 | bool set; 53 | 54 | /** The argument's name */ 55 | std::string name; 56 | 57 | /** Constructor with the name of the argument */ 58 | CmdLineReadable( const std::string &name ); 59 | 60 | /** Destructor */ 61 | virtual ~CmdLineReadable( void ); 62 | 63 | /** Try to set the argument from the list of command line arguments. 64 | *** Returns thenumber of arguments ingested.*/ 65 | virtual int read( char **argv , int argc ); 66 | 67 | /** Transforms a string into the prescribed type */ 68 | template< typename Type > 69 | static Type ToType( const std::string &str ); 70 | }; 71 | 72 | /** This templated class represents a named argument of the prescribed type */ 73 | template< class Type > 74 | class CmdLineParameter : public CmdLineReadable 75 | { 76 | public: 77 | /** The value the parameter has been set to */ 78 | Type value; 79 | 80 | /** Constructor with the name of the argument */ 81 | CmdLineParameter( const std::string &name ); 82 | 83 | /** Constructor with the name of the argument and the default value */ 84 | CmdLineParameter( const std::string &name , Type v ); 85 | 86 | /** Try to set the argument from the list of command line arguments. 87 | *** Returns thenumber of arguments ingested.*/ 88 | int read( char **argv , int argc ); 89 | }; 90 | 91 | /** This templated class represents a named argument taking a fixed number of values of the prescribed type */ 92 | template< class Type , int Dim > 93 | class CmdLineParameterArray : public CmdLineReadable 94 | { 95 | public: 96 | /** The values the parameter has been set to */ 97 | Type values[Dim]; 98 | 99 | /** Constructor with the name of the argument and the default values */ 100 | CmdLineParameterArray( const std::string &name, const Type* v=NULL ); 101 | 102 | /** Try to set the argument from the list of command line arguments. 103 | *** Returns thenumber of arguments ingested.*/ 104 | int read( char **argv , int argc ); 105 | }; 106 | 107 | /** This templated class represents a named argument taking a variable number of values of of the prescribed type */ 108 | template< class Type > 109 | class CmdLineParameters : public CmdLineReadable 110 | { 111 | public: 112 | /** The number of values the argument takes */ 113 | unsigned int count; 114 | 115 | /** The values the parameter has been set to */ 116 | Type *values; 117 | 118 | /** Constructor with the name of the argument */ 119 | CmdLineParameters( const std::string &name ); 120 | 121 | /** Destructor deallocating the array of values */ 122 | ~CmdLineParameters( void ); 123 | 124 | /** Try to set the argument from the list of command line arguments. 125 | *** Returns thenumber of arguments ingested.*/ 126 | int read( char **argv , int argc ); 127 | 128 | /** Method for resizing the contents */ 129 | void resize( unsigned int sz ); 130 | }; 131 | 132 | /** This function takes a list of arguments and tries to set the parameters. 133 | *** The last parameter must be a NULL pointer. */ 134 | void CmdLineParse( int argc , char **argv, CmdLineReadable **params ); 135 | 136 | /** This function takes a vectros of arguments and tries to set the parameters. */ 137 | void CmdLineParse( int argc , char **argv, const std::vector< CmdLineReadable * > ¶ms ); 138 | 139 | /** Converts a string to upper case*/ 140 | std::string ToUpper( const std::string &str ); 141 | 142 | /** Converts a string to lower case*/ 143 | std::string ToLower( const std::string &str ); 144 | 145 | /** Returns the file extension */ 146 | std::string GetFileExtension( const std::string &fileName ); 147 | 148 | /** Returns and array of individual lines read from a file */ 149 | std::vector< std::string > ReadLines( const std::string &fileName ); 150 | 151 | /** Returns and array of individual words pulled from a string */ 152 | std::vector< std::string > GetWords( const std::string &str ); 153 | 154 | /** Returns and array of individual words read from a file */ 155 | std::vector< std::string > ReadWords( const std::string &fileName ); 156 | 157 | #include "CmdLineParser.inl" 158 | } 159 | #endif // CMD_LINE_PARSER_INCLUDED 160 | -------------------------------------------------------------------------------- /Misha/CmdLineParser.inl: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | ///////////////////// 30 | // CmdLineReadable // 31 | ///////////////////// 32 | inline CmdLineReadable::CmdLineReadable( const std::string &n ) : name(n) , set(false) {} 33 | 34 | inline CmdLineReadable::~CmdLineReadable( void ){} 35 | 36 | inline int CmdLineReadable::read( char ** , int ){ set = true ; return 0; } 37 | 38 | template< typename Type > 39 | Type CmdLineReadable::ToType( const std::string &str ) 40 | { 41 | Type type; 42 | std::stringstream( str ) >> type; 43 | return type; 44 | } 45 | 46 | template<> 47 | std::string CmdLineReadable::ToType( const std::string &str ){ return str; } 48 | 49 | ////////////////////// 50 | // CmdLineParameter // 51 | ////////////////////// 52 | template< class Type > CmdLineParameter< Type >::CmdLineParameter( const std::string &name ) : CmdLineReadable(name) { value = Type(); } 53 | 54 | template< class Type > CmdLineParameter< Type >::CmdLineParameter( const std::string &name , Type v ) : CmdLineReadable(name) , value(v) {} 55 | 56 | template< class Type > 57 | int CmdLineParameter< Type >::read( char **argv , int argc ) 58 | { 59 | if( argc>0 ) 60 | { 61 | value = ToType< Type >( argv[0] ); 62 | set = true; 63 | return 1; 64 | } 65 | else return 0; 66 | } 67 | 68 | /////////////////////////// 69 | // CmdLineParameterArray // 70 | /////////////////////////// 71 | template< class Type , int Dim > 72 | CmdLineParameterArray< Type , Dim >::CmdLineParameterArray( const std::string &name , const Type* v ) : CmdLineReadable(name) 73 | { 74 | if( v ) for( int i=0 ; i 79 | int CmdLineParameterArray< Type , Dim >::read( char **argv , int argc ) 80 | { 81 | if( argc>=Dim ) 82 | { 83 | for( int i=0 ; i( argv[i] ); 84 | set = true; 85 | return Dim; 86 | } 87 | else return 0; 88 | } 89 | 90 | /////////////////////// 91 | // CmdLineParameters // 92 | /////////////////////// 93 | template< class Type > 94 | CmdLineParameters< Type >::CmdLineParameters( const std::string &name ) : CmdLineReadable(name) , values(NULL) , count(0) { } 95 | 96 | template< class Type > 97 | CmdLineParameters< Type >::~CmdLineParameters( void ) 98 | { 99 | if( values ) delete[] values; 100 | values = NULL; 101 | count = 0; 102 | } 103 | 104 | template< class Type > 105 | int CmdLineParameters< Type >::read( char **argv , int argc ) 106 | { 107 | if( values ) delete[] values; 108 | values = NULL; 109 | 110 | if( argc>0 ) 111 | { 112 | count = atoi(argv[0]); 113 | if( count<=0 || argc<=(int)count ) return 1; 114 | values = new Type[count]; 115 | if( !values ) return 0; 116 | for( unsigned int i=0 ; i( argv[i+1] ); 117 | set = true; 118 | return count+1; 119 | } 120 | else return 0; 121 | } 122 | 123 | template< class Type > 124 | void CmdLineParameters< Type >::resize( unsigned int sz ) 125 | { 126 | if( values ) delete[] values; 127 | values = NULL; 128 | count = sz; 129 | if( count ) values = new Type[count]; 130 | } 131 | 132 | ////////////////////// 133 | // Helper functions // 134 | ////////////////////// 135 | 136 | inline void CmdLineParse( int argc , char **argv , CmdLineReadable** params ) 137 | { 138 | while( argc>0 ) 139 | { 140 | if( argv[0][0]=='-' && argv[0][1]=='-' ) 141 | { 142 | CmdLineReadable* readable=NULL; 143 | for( int i=0 ; params[i]!=NULL && readable==NULL ; i++ ) if( params[i]->name==argv[0]+2 ) readable = params[i]; 144 | if( readable ) 145 | { 146 | int j = readable->read( argv+1 , argc-1 ); 147 | argv += j , argc -= j; 148 | } 149 | else 150 | { 151 | MK_WARN( "Invalid option: " , argv[0] ); 152 | for( int i=0 ; params[i]!=NULL ; i++ ) std::cerr << "\t--" << params[i]->name << std::endl; 153 | } 154 | } 155 | else MK_WARN( "Parameter name should be of the form --: " , argv[0] ); 156 | ++argv , --argc; 157 | } 158 | } 159 | 160 | inline void CmdLineParse( int argc , char **argv , const std::vector< CmdLineReadable * > ¶ms ) 161 | { 162 | while( argc>0 ) 163 | { 164 | if( argv[0][0]=='-' && argv[0][1]=='-' ) 165 | { 166 | CmdLineReadable* readable=NULL; 167 | for( int i=0 ; iname==argv[0]+2 ) readable = params[i]; 168 | if( readable ) 169 | { 170 | int j = readable->read( argv+1 , argc-1 ); 171 | argv += j , argc -= j; 172 | } 173 | else 174 | { 175 | MK_WARN( "Invalid option: " , argv[0] ); 176 | for( int i=0 ; iname << std::endl; 177 | } 178 | } 179 | else MK_WARN( "Parameter name should be of the form --: " , argv[0] ); 180 | ++argv , --argc; 181 | } 182 | } 183 | 184 | inline std::string ToUpper( const std::string &str ) 185 | { 186 | auto _ToUpper = []( char c ){ return c>='a' && c<='z' ? c+'A'-'a' : c; }; 187 | std::string upper; 188 | upper.resize( str.size() ); 189 | std::transform( str.begin() , str.end() , upper.begin() , _ToUpper ); 190 | return upper; 191 | } 192 | 193 | inline std::string ToLower( const std::string &str ) 194 | { 195 | auto _ToLower = []( char c ){ return c>='A' && c<='Z' ? c+'a'-'A' : c; }; 196 | std::string lower; 197 | lower.resize( str.size() ); 198 | std::transform( str.begin() , str.end() , lower.begin() , _ToLower ); 199 | return lower; 200 | } 201 | 202 | inline std::string GetFileExtension( const std::string &fileName ) 203 | { 204 | std::string ext; 205 | std::stringstream stream( fileName ); 206 | while( std::getline( stream , ext , '.' ) ) ; 207 | return ext; 208 | } 209 | 210 | inline std::vector< std::string > ReadWords( const std::string &fileName ) 211 | { 212 | std::ifstream istream; 213 | istream.open( fileName ); 214 | if( !istream ) MK_THROW( "Failed to open file for reading: " , fileName ); 215 | std::vector< std::string > words; 216 | std::string word; 217 | while( istream >> word ) words.push_back( word ); 218 | return words; 219 | } 220 | 221 | inline std::vector< std::string > GetWords( const std::string &str ) 222 | { 223 | std::stringstream sstream( str ); 224 | std::vector< std::string > words; 225 | std::string word; 226 | while( sstream >> word ) words.push_back( word ); 227 | return words; 228 | } 229 | 230 | inline std::vector< std::string > ReadLines( const std::string &fileName ) 231 | { 232 | std::ifstream istream; 233 | istream.open( fileName ); 234 | if( !istream ) MK_THROW( "Failed to open file for reading: " , fileName ); 235 | std::vector< std::string > lines; 236 | std::string line; 237 | while( std::getline( istream , line ) ) lines.push_back( line ); 238 | return lines; 239 | } 240 | -------------------------------------------------------------------------------- /Misha/Exceptions.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2019, Michael Kazhdan 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | #ifndef EXCEPTIONS_INCLUDED 30 | #define EXCEPTIONS_INCLUDED 31 | 32 | #define VERBOSE_MESSAGING 33 | //#define TIMED_MESSAGING 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #ifdef TIMED_MESSAGING 42 | #include "Timer.h" 43 | Timer waningTimer; 44 | #endif // TIMED_MESSAGING 45 | 46 | 47 | namespace MishaK 48 | { 49 | template< typename ... Arguments > void _AddToMessageStream( std::stringstream &stream , Arguments ... arguments ); 50 | inline void _AddToMessageStream( std::stringstream &stream ){ return; } 51 | template< typename Argument , typename ... Arguments > void _AddToMessageStream( std::stringstream &stream , Argument argument , Arguments ... arguments ) 52 | { 53 | stream << argument; 54 | _AddToMessageStream( stream , arguments ... ); 55 | } 56 | 57 | #ifdef VERBOSE_MESSAGING 58 | template< typename ... Arguments > 59 | std::string MakeMessageString( std::string header , std::string fileName , int line , std::string functionName , Arguments ... arguments ) 60 | { 61 | size_t headerSize = header.size(); 62 | std::stringstream stream; 63 | 64 | // The first line is the header, the file name , and the line number 65 | stream << header << " " << fileName << " (Line " << line << ")" << std::endl; 66 | 67 | // Inset the second line by the size of the header and write the function name 68 | for( size_t i=0 ; i<=headerSize ; i++ ) stream << " "; 69 | stream << functionName << std::endl; 70 | 71 | // Inset the third line by the size of the header and write the rest 72 | for( size_t i=0 ; i<=headerSize ; i++ ) stream << " "; 73 | _AddToMessageStream( stream , arguments ... ); 74 | 75 | return stream.str(); 76 | } 77 | struct Exception : public std::exception 78 | { 79 | const char *what( void ) const noexcept { return _message.c_str(); } 80 | template< typename ... Args > 81 | Exception( const char *fileName , int line , const char *functionName , const char *format , Args ... args ) 82 | { 83 | _message = MakeMessageString( "[EXCEPTION]" , fileName , line , functionName , format , args ... ); 84 | } 85 | private: 86 | std::string _message; 87 | }; 88 | 89 | template< typename ... Args > void Throw( const char *fileName , int line , const char *functionName , const char *format , Args ... args ){ throw Exception( fileName , line , functionName , format , args ... ); } 90 | template< typename ... Args > 91 | void Warn( const char *fileName , int line , const char *functionName , const char *format , Args ... args ) 92 | { 93 | static std::mutex warnMutex; 94 | std::lock_guard< std::mutex > lock( warnMutex ); 95 | #ifdef TIMED_MESSAGING 96 | std::cerr << MakeMessageString( "[WARNING]" , fileName , line , functionName , format , args ... , " (Time=" , waningTimer.elapsed() , ")" ) << std::endl; 97 | #else // !TIMED_MESSAGING 98 | std::cerr << MakeMessageString( "[WARNING]" , fileName , line , functionName , format , args ... ) << std::endl; 99 | #endif // TIMED_MESSAGING 100 | } 101 | template< typename ... Args > 102 | void ErrorOut( const char *fileName , int line , const char *functionName , const char *format , Args ... args ) 103 | { 104 | static std::mutex errorOutMutex; 105 | std::lock_guard< std::mutex > lock( errorOutMutex ); 106 | std::cerr << MakeMessageString( "[ERROR]" , fileName , line , functionName , format , args ... ) << std::endl; 107 | exit( 0 ); 108 | } 109 | #else // !VERBOSE_MESSAGING 110 | template< typename ... Arguments > 111 | std::string MakeMessageString( std::string header , std::string functionName , Arguments ... arguments ) 112 | { 113 | std::stringstream stream; 114 | 115 | // The first line is the header, the file name , and the line number 116 | stream << header << " " << functionName << ": "; 117 | 118 | _AddToMessageStream( stream , arguments ... ); 119 | 120 | return stream.str(); 121 | } 122 | 123 | struct Exception : public std::exception 124 | { 125 | const char *what( void ) const noexcept { return _message.c_str(); } 126 | template< typename ... Args > 127 | Exception( const char *functionName , const char *format , Args ... args ) 128 | { 129 | _message = MakeMessageString( "[EXCEPTION]" , functionName , format , args ... ); 130 | } 131 | private: 132 | std::string _message; 133 | }; 134 | template< typename ... Args > void Throw( const char *functionName , const char *format , Args ... args ){ throw Exception( functionName , format , args ... ); } 135 | template< typename ... Args > 136 | void Warn( const char *functionName , const char *format , Args ... args ) 137 | { 138 | static std::mutex warnMutex; 139 | std::lock_guard< std::mutex > lock( warnMutex ); 140 | std::cerr << MakeMessageString( "[WARNING]" , functionName , format , args ... ) << std::endl; 141 | } 142 | template< typename ... Args > 143 | void ErrorOut( const char *functionName , const char *format , Args ... args ) 144 | { 145 | static std::mutex errorOutMutex; 146 | std::lock_guard< std::mutex > lock( errorOutMutex ); 147 | std::cerr << MakeMessageString( "[WARNING]" , functionName , format , args ... ) << std::endl; 148 | exit( 0 ); 149 | } 150 | #endif // VERBOSE_MESSAGING 151 | } 152 | #ifdef VERBOSE_MESSAGING 153 | #ifndef MK_WARN 154 | #define MK_WARN( ... ) MishaK::Warn( __FILE__ , __LINE__ , __FUNCTION__ , __VA_ARGS__ ) 155 | #endif // MK_WARN 156 | #ifndef MK_WARN_ONCE 157 | #define MK_WARN_ONCE( ... ) { static bool firstTime = true ; if( firstTime ) MishaK::Warn( __FILE__ , __LINE__ , __FUNCTION__ , __VA_ARGS__ ) ; firstTime = false; } 158 | #endif // MK_WARN_ONCE 159 | #ifndef MK_THROW 160 | #define MK_THROW( ... ) MishaK::Throw( __FILE__ , __LINE__ , __FUNCTION__ , __VA_ARGS__ ) 161 | #endif // MK_THROW 162 | #ifndef MK_ERROR_OUT 163 | #define MK_ERROR_OUT( ... ) MishaK::ErrorOut( __FILE__ , __LINE__ , __FUNCTION__ , __VA_ARGS__ ) 164 | #endif // MK_ERROR_OUT 165 | #else // !VERBOSE_MESSAGING 166 | #ifndef MK_WARN 167 | #define MK_WARN( ... ) MishaK::Warn( __FUNCTION__ , __VA_ARGS__ ) 168 | #endif // MK_WARN 169 | #ifndef MK_WARN_ONCE 170 | #define MK_WARN_ONCE( ... ) { static bool firstTime = true ; if( firstTime ) MishaK::Warn( __FUNCTION__ , __VA_ARGS__ ) ; firstTime = false; } 171 | #endif // MK_WARN_ONCE 172 | #ifndef MK_THROW 173 | #define MK_THROW( ... ) MishaK::Throw( __FUNCTION__ , __VA_ARGS__ ) 174 | #endif // MK_THROW 175 | #ifndef MK_ERROR_OUT 176 | #define MK_ERROR_OUT( ... ) MishaK::ErrorOut( __FUNCTION__ , __VA_ARGS__ ) 177 | #endif // MK_ERROR_OUT 178 | #endif // VERBOSE_MESSAGING 179 | 180 | #endif // EXCEPTIONS_INCLUDED 181 | -------------------------------------------------------------------------------- /Misha/FEM.BasisInfo.inc: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2015, Michael Kazhdan and Fabian Prada 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | template<> inline const unsigned int BasisInfo< BASIS_0_WHITNEY >::CoefficientsPerElement = 1; 30 | template<> inline const unsigned int BasisInfo< BASIS_1_CONFORMING >::CoefficientsPerElement = 2; 31 | template<> inline const unsigned int BasisInfo< BASIS_1_WHITNEY >::CoefficientsPerElement = 1; 32 | template<> inline const unsigned int BasisInfo< BASIS_1_TRIANGLE_CONSTANT >::CoefficientsPerElement = 2; 33 | template<> inline const unsigned int BasisInfo< BASIS_2_WHITNEY >::CoefficientsPerElement = 1; 34 | template<> inline const unsigned int BasisInfo< BASIS_2_VERTEX_CONSTANT >::CoefficientsPerElement = 1; 35 | 36 | template<> inline const unsigned int BasisInfo< BASIS_0_WHITNEY >::Coefficients = 3; 37 | template<> inline const unsigned int BasisInfo< BASIS_1_CONFORMING >::Coefficients = 6; 38 | template<> inline const unsigned int BasisInfo< BASIS_1_WHITNEY >::Coefficients = 3; 39 | template<> inline const unsigned int BasisInfo< BASIS_1_TRIANGLE_CONSTANT >::Coefficients = 2; 40 | template<> inline const unsigned int BasisInfo< BASIS_2_WHITNEY >::Coefficients = 1; 41 | template<> inline const unsigned int BasisInfo< BASIS_2_VERTEX_CONSTANT >::Coefficients = 3; 42 | 43 | template<> inline const unsigned int BasisInfo< BASIS_0_WHITNEY >::Dimension = 0; 44 | template<> inline const unsigned int BasisInfo< BASIS_1_CONFORMING >::Dimension = 1; 45 | template<> inline const unsigned int BasisInfo< BASIS_1_WHITNEY >::Dimension = 1; 46 | template<> inline const unsigned int BasisInfo< BASIS_1_TRIANGLE_CONSTANT >::Dimension = 1; 47 | template<> inline const unsigned int BasisInfo< BASIS_2_WHITNEY >::Dimension = 2; 48 | template<> inline const unsigned int BasisInfo< BASIS_2_VERTEX_CONSTANT >::Dimension = 2; 49 | 50 | template<> inline const bool BasisInfo< BASIS_0_WHITNEY >::Lumpable = true; 51 | template<> inline const bool BasisInfo< BASIS_1_CONFORMING >::Lumpable = false; 52 | template<> inline const bool BasisInfo< BASIS_1_WHITNEY >::Lumpable = true; 53 | template<> inline const bool BasisInfo< BASIS_1_TRIANGLE_CONSTANT >::Lumpable = false; 54 | template<> inline const bool BasisInfo< BASIS_2_WHITNEY >::Lumpable = true; 55 | template<> inline const bool BasisInfo< BASIS_2_VERTEX_CONSTANT >::Lumpable = true; 56 | 57 | template<> inline const unsigned int BasisInfo< BASIS_0_WHITNEY >::ElementType = ELEMENT_VERTEX; 58 | template<> inline const unsigned int BasisInfo< BASIS_1_CONFORMING >::ElementType = ELEMENT_VERTEX; 59 | template<> inline const unsigned int BasisInfo< BASIS_1_WHITNEY >::ElementType = ELEMENT_EDGE; 60 | template<> inline const unsigned int BasisInfo< BASIS_1_TRIANGLE_CONSTANT >::ElementType = ELEMENT_TRIANGLE; 61 | template<> inline const unsigned int BasisInfo< BASIS_2_WHITNEY >::ElementType = ELEMENT_TRIANGLE; 62 | template<> inline const unsigned int BasisInfo< BASIS_2_VERTEX_CONSTANT >::ElementType = ELEMENT_VERTEX; 63 | 64 | template<> inline const bool BasisInfo< BASIS_0_WHITNEY >::Singular = false; 65 | template<> inline const bool BasisInfo< BASIS_1_CONFORMING >::Singular = true; 66 | template<> inline const bool BasisInfo< BASIS_1_WHITNEY >::Singular = false; 67 | template<> inline const bool BasisInfo< BASIS_1_TRIANGLE_CONSTANT >::Singular = false; 68 | template<> inline const bool BasisInfo< BASIS_2_WHITNEY >::Singular = false; 69 | template<> inline const bool BasisInfo< BASIS_2_VERTEX_CONSTANT >::Singular = false; 70 | -------------------------------------------------------------------------------- /Misha/MultiThreading.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2017, Michael Kazhdan 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | #ifndef MULTI_THREADING_INCLUDED 29 | #define MULTI_THREADING_INCLUDED 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #ifdef _OPENMP 37 | #include 38 | #endif // _OPENMP 39 | 40 | namespace MishaK 41 | { 42 | struct ThreadPool 43 | { 44 | enum ParallelType 45 | { 46 | #ifdef _OPENMP 47 | OPEN_MP , 48 | #endif // _OPENMP 49 | ASYNC , 50 | NONE 51 | }; 52 | static const std::vector< std::string > ParallelNames; 53 | 54 | enum ScheduleType 55 | { 56 | STATIC , 57 | DYNAMIC 58 | }; 59 | static const std::vector< std::string > ScheduleNames; 60 | 61 | static unsigned int NumThreads( void ){ return _NumThreads; } 62 | static ParallelType ParallelizationType; 63 | static size_t ChunkSize; 64 | static ScheduleType Schedule; 65 | 66 | template< typename Function , typename ... Functions > 67 | static void ParallelSections( const Function &function , const Functions & ... functions ) 68 | { 69 | std::vector< std::future< void > > futures; 70 | if constexpr( sizeof ... (Functions) ) 71 | { 72 | futures.reserve( sizeof...(Functions) ); 73 | _ParallelSections( futures , functions... ); 74 | } 75 | function(); 76 | for( unsigned int i=0 ; i 80 | static void ParallelSections( const Function &&function , const Functions && ... functions ) 81 | { 82 | std::vector< std::future< void > > futures; 83 | if constexpr( sizeof ... (Functions) ) 84 | { 85 | futures.reserve( sizeof...(Functions) ); 86 | _ParallelSections( futures , std::move(functions)... ); 87 | } 88 | function(); 89 | for( unsigned int i=0 ; i*/ > 93 | static void ParallelFor( size_t begin , size_t end , Kernel && kernel , unsigned int numThreads=_NumThreads , ParallelType pType=ParallelizationType , ScheduleType schedule=Schedule , size_t chunkSize=ChunkSize ) 94 | { 95 | static_assert( std::is_convertible_v< Kernel , std::function< void ( unsigned int , size_t ) > > || std::is_convertible_v< Kernel , std::function< void ( size_t ) > > , "[ERROR] Kernel poorly formed" ); 96 | static const bool NeedsThread = std::is_convertible_v< Kernel , std::function< void ( unsigned int , size_t ) > >; 97 | if( begin>=end ) return; 98 | size_t range = end - begin; 99 | size_t chunks = ( range + chunkSize - 1 ) / chunkSize; 100 | std::atomic< size_t > index; 101 | index.store( 0 ); 102 | 103 | // If the computation is serial, go ahead and run it 104 | if( pType==ParallelType::NONE || numThreads<=1 ) 105 | { 106 | for( size_t i=begin ; i _ChunkFunction = [ &kernel , begin , end , chunkSize ]( unsigned int thread , size_t chunk ) 120 | { 121 | const size_t _begin = begin + chunkSize*chunk; 122 | const size_t _end = std::min< size_t >( end , _begin+chunkSize ); 123 | for( size_t i=_begin ; i<_end ; i++ ) 124 | if constexpr( NeedsThread ) kernel( thread , i ); 125 | else kernel( i ); 126 | }; 127 | 128 | std::function< void (unsigned int ) > _StaticThreadFunction = [ &_ChunkFunction , chunks , numThreads ]( unsigned int thread ) 129 | { 130 | for( size_t chunk=thread ; chunk _DynamicThreadFunction = [ &_ChunkFunction , chunks , &index ]( unsigned int thread ) 134 | { 135 | size_t chunk; 136 | while( ( chunk=index.fetch_add(1) ) ThreadFunction; 140 | if ( schedule==ScheduleType::STATIC ) ThreadFunction = _StaticThreadFunction; 141 | else if( schedule==ScheduleType::DYNAMIC ) ThreadFunction = _DynamicThreadFunction; 142 | 143 | if( false ){} 144 | #ifdef _OPENMP 145 | else if( pType==ParallelType::OPEN_MP ) 146 | { 147 | if( schedule==ScheduleType::STATIC ) 148 | #pragma omp parallel for num_threads( numThreads ) schedule( static , 1 ) 149 | for( int c=0 ; c > futures; 159 | futures.resize( numThreads-1 ); 160 | for( unsigned int t=1 ; t 171 | static void _ParallelSections( std::vector< std::future< void > > &futures , const Function &function , const Functions & ... functions ) 172 | { 173 | futures.push_back( std::async( std::launch::async , function ) ); 174 | if constexpr( sizeof...(Functions) ) _ParallelSections( futures , functions... ); 175 | } 176 | 177 | template< typename Function , typename ... Functions > 178 | static void _ParallelSections( std::vector< std::future< void > > &futures , const Function &&function , const Functions && ... functions ) 179 | { 180 | futures.push_back( std::async( std::launch::async , function ) ); 181 | if constexpr( sizeof...(Functions) ) _ParallelSections( futures , std::move(functions)... ); 182 | } 183 | }; 184 | 185 | //inline ThreadPool::ParallelType ThreadPool::ParallelizationType = ThreadPool::ParallelType::NONE; // Default is threading disabled 186 | inline ThreadPool::ParallelType ThreadPool::ParallelizationType = (ThreadPool::ParallelType)0; // Default is threading enable 187 | inline unsigned int ThreadPool::_NumThreads = std::thread::hardware_concurrency(); 188 | inline ThreadPool::ScheduleType ThreadPool::Schedule = ThreadPool::DYNAMIC; 189 | inline size_t ThreadPool::ChunkSize = 128; 190 | 191 | const inline std::vector< std::string > ThreadPool::ParallelNames = 192 | { 193 | #ifdef _OPENMP 194 | "open mp" , 195 | #endif // _OPENMP 196 | "async" , 197 | "none" 198 | }; 199 | const inline std::vector< std::string > ThreadPool::ScheduleNames = { "static" , "dynamic" }; 200 | } 201 | #endif // MULTI_THREADING_INCLUDED 202 | -------------------------------------------------------------------------------- /Misha/Ply.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2019, Michael Kazhdan 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | 30 | #ifndef PLY_INCLUDED 31 | #define PLY_INCLUDED 32 | 33 | #define NEW_PLY 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include "PlyFile.h" 40 | #include "Geometry.h" 41 | #include "Exceptions.h" 42 | 43 | namespace MishaK 44 | { 45 | namespace PLY 46 | { 47 | // Converts from C-type to PLY type 48 | template< class Real > int Type( void ); 49 | 50 | // Converts from C-type to PLY name 51 | template< typename Integer > struct Traits{ static const std::string name; }; 52 | 53 | // A structure representing a face 54 | template< typename Index > 55 | struct Face 56 | { 57 | unsigned int nr_vertices; 58 | Index *vertices; 59 | 60 | static GregTurk::PlyProperty Properties[]; 61 | }; 62 | 63 | int DefaultFileType( void ); 64 | 65 | // PLY read functionality 66 | int ReadHeader( std::string fileName , const GregTurk::PlyProperty *properties , int propertyNum , bool *readFlags ); 67 | 68 | std::vector< GregTurk::PlyProperty > ReadVertexHeader( std::string fileName ); 69 | std::vector< GregTurk::PlyProperty > ReadVertexHeader( std::string fileName , int &file_type ); 70 | 71 | template< typename VertexFactory , typename Index > 72 | int Read( std::string fileName , const VertexFactory &vFactory , std::vector< typename VertexFactory::VertexType > &vertices , std::vector< std::pair< Index , Index > > *edges , std::vector< std::vector< Index > > *polygons , bool *vertexPropertiesFlag=nullptr , std::vector< std::string > *comments=nullptr ); 73 | 74 | template< typename VertexFactory > 75 | int ReadVertices( std::string fileName , const VertexFactory &vFactory , std::vector< typename VertexFactory::VertexType > &vertices , bool *vertexPropertiesFlag=nullptr , std::vector< std::string > *comments=nullptr ); 76 | 77 | template< typename VertexFactory , typename Index > 78 | int ReadTriangles( std::string fileName , const VertexFactory &vFactory , std::vector< typename VertexFactory::VertexType > &vertices , std::vector< SimplexIndex< 2 , Index > > &triangles , bool *vertexPropertiesFlag=nullptr , std::vector< std::string > *comments=nullptr ); 79 | 80 | template< typename VertexFactory , typename Real , unsigned int Dim , typename Index > 81 | int ReadTriangles( std::string fileName , const VertexFactory &vFactory , std::vector< typename VertexFactory::VertexType > &vertices , std::vector< SimplexIndex< 2 , Index > > &triangles , std::function< Point< Real , Dim > ( typename VertexFactory::VertexType ) > VertexToPointFunctor , bool *vertexPropertiesFlag=nullptr , std::vector< std::string > *comments=nullptr ); 82 | 83 | template< typename VertexFactory , typename Index > 84 | int ReadPolygons( std::string fileName , const VertexFactory &vFactory , std::vector< typename VertexFactory::VertexType > &vertices , std::vector< std::vector< Index > > &polygons , bool *readFlags=nullptr , std::vector< std::string > *comments=nullptr ); 85 | 86 | template< typename VertexFactory , typename Polygon > 87 | int ReadPolygons( std::string fileName , const VertexFactory &vFactory , std::vector< typename VertexFactory::VertexType >& vertices , std::vector< Polygon >& polygons , GregTurk::PlyProperty *polygonProperties , int polygonPropertyNum , bool *vertexPropertiesFlag=nullptr , bool *polygonPropertiesFlag=nullptr , std::vector< std::string > *comments=nullptr ); 88 | 89 | template< typename VertexFactory , typename Index > 90 | int ReadTetrahedra( std::string fileName , const VertexFactory &vFactory , std::vector< typename VertexFactory::VertexType > &vertices , std::vector< SimplexIndex< 3 , Index > > &tetrahedra , bool *vertexPropertiesFlag=nullptr , std::vector< std::string > *comments=nullptr ); 91 | 92 | template< typename VertexFactory , unsigned int Dim , typename Index > 93 | int ReadSimplices( std::string fileName , const VertexFactory &vFactory , std::vector< typename VertexFactory::VertexType > &vertices , std::vector< SimplexIndex< Dim , Index > > &simplices , bool *vertexPropertiesFlag=nullptr , std::vector< std::string > *comments=nullptr ); 94 | 95 | // PLY write functionality 96 | template< typename VertexFactory > 97 | void WriteVertices( std::string fileName , const VertexFactory &vFactory , const std::vector< typename VertexFactory::VertexType > &vertices , int file_type , const std::vector< std::string > *comments=NULL ); 98 | 99 | template< typename VertexFactory , typename Index > 100 | void Write( std::string fileName , const VertexFactory &vFactory , const std::vector< typename VertexFactory::VertexType > &vertices , const std::vector< std::pair< Index , Index > > *edges , const std::vector< std::vector< Index > > *polygons , int file_type , const std::vector< std::string > *comments=NULL ); 101 | 102 | template< typename VertexFactory , typename Index > 103 | void WriteTriangles( std::string fileName , const VertexFactory &vFactory , const std::vector< typename VertexFactory::VertexType > &vertices , const std::vector< SimplexIndex< 2 , Index > > &triangles , int file_type , const std::vector< std::string > *comments=NULL ); 104 | 105 | template< typename VertexFactory , typename Index > 106 | void WritePolygons( std::string fileName , const VertexFactory &vFactory , const std::vector< typename VertexFactory::VertexType > &vertices , const std::vector< std::vector< Index > > &polygons , int file_type , const std::vector< std::string > *comments=NULL ); 107 | 108 | template< class VertexFactory , typename Polygon > 109 | void WritePolygons( std::string fileName , const VertexFactory &vFactory , const std::vector< typename VertexFactory::VertexType > &vertices , const std::vector< Polygon > &polygons , GregTurk::PlyProperty* polygonProperties , int polygonPropertyNum , int file_type , const std::vector< std::string > *comments=NULL ); 110 | 111 | template< typename VertexFactory , typename Index > 112 | void WriteTetrahedra( std::string fileName , const VertexFactory &vFactory , const std::vector< typename VertexFactory::VertexType > &vertices , const std::vector< SimplexIndex< 3 , Index > > &tetrahedra , int file_type , const std::vector< std::string > *comments=NULL ); 113 | 114 | #include "Ply.inl" 115 | } 116 | } 117 | #endif // PLY_INCLUDED 118 | -------------------------------------------------------------------------------- /Misha/PlyFile.h: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Header for PLY polygon files. 4 | 5 | - Greg Turk, March 1994 6 | 7 | A PLY file contains a single polygonal _object_. 8 | 9 | An object is composed of lists of _elements_. Typical elements are 10 | vertices, faces, edges and materials. 11 | 12 | Each type of element for a given object has one or more _properties_ 13 | associated with the element type. For instance, a vertex element may 14 | have as properties three floating-point values x,y,z and three unsigned 15 | chars for red, green and blue. 16 | 17 | --------------------------------------------------------------- 18 | 19 | Copyright (c) 1994 The Board of Trustees of The Leland Stanford 20 | Junior University. All rights reserved. 21 | 22 | Permission to use, copy, modify and distribute this software and its 23 | documentation for any purpose is hereby granted without fee, provided 24 | that the above copyright notice and this permission notice appear in 25 | all copies of this software and that you do not sell the software. 26 | 27 | THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND, 28 | EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 29 | WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 30 | */ 31 | 32 | #ifndef PLY_FILE_INCLUDED 33 | #define PLY_FILE_INCLUDED 34 | 35 | #include 36 | #include 37 | 38 | #include 39 | #include 40 | #include 41 | #include 42 | #include 43 | #include "Exceptions.h" 44 | #include "PlyFile.h" 45 | 46 | namespace GregTurk 47 | { 48 | #define PLY_ASCII 1 /* ascii PLY file */ 49 | #define PLY_BINARY_BE 2 /* binary PLY file, big endian */ 50 | #define PLY_BINARY_LE 3 /* binary PLY file, little endian */ 51 | #define PLY_BINARY_NATIVE 4 /* binary PLY file, same endianness as current architecture */ 52 | 53 | #define PLY_OKAY 0 /* ply routine worked okay */ 54 | #define PLY_ERROR -1 /* error in ply routine */ 55 | 56 | /* scalar data types supported by PLY format */ 57 | 58 | #define PLY_START_TYPE 0 59 | #define PLY_CHAR 1 60 | #define PLY_SHORT 2 61 | #define PLY_INT 3 62 | #define PLY_LONGLONG 4 63 | #define PLY_UCHAR 5 64 | #define PLY_USHORT 6 65 | #define PLY_UINT 7 66 | #define PLY_ULONGLONG 8 67 | #define PLY_FLOAT 9 68 | #define PLY_DOUBLE 10 69 | #define PLY_INT_8 11 70 | #define PLY_UINT_8 12 71 | #define PLY_INT_16 13 72 | #define PLY_UINT_16 14 73 | #define PLY_INT_32 15 74 | #define PLY_UINT_32 16 75 | #define PLY_INT_64 17 76 | #define PLY_UINT_64 18 77 | #define PLY_FLOAT_32 19 78 | #define PLY_FLOAT_64 20 79 | 80 | #define PLY_END_TYPE 21 81 | 82 | #define PLY_SCALAR 0 83 | #define PLY_LIST 1 84 | 85 | #define PLY_STRIP_COMMENT_HEADER 0 86 | 87 | const std::string PlyTypes[] 88 | { 89 | "start type" , 90 | "char" , 91 | "short" , 92 | "int" , 93 | "long long " , 94 | "unsigned char" , 95 | "unsigned short" , 96 | "unsigned int" , 97 | "unsigned long long" , 98 | "float" , 99 | "double" , 100 | "int8" , 101 | "unsigned int8" , 102 | "int16" , 103 | "unsigned int16" , 104 | "int32" , 105 | "unsigned int32" , 106 | "int64" , 107 | "unsigned int64" , 108 | "float32" , 109 | "float64" 110 | }; 111 | 112 | /* description of a property */ 113 | struct PlyProperty 114 | { 115 | std::string name; /* property name */ 116 | int external_type; /* file's data type */ 117 | int internal_type; /* program's data type */ 118 | int offset; /* offset bytes of prop in a struct */ 119 | 120 | int is_list; /* 1 = list, 0 = scalar */ 121 | int count_external; /* file's count type */ 122 | int count_internal; /* program's count type */ 123 | int count_offset; /* offset byte for list count */ 124 | 125 | PlyProperty( const std::string &n , int et , int it , int o , int il=0 , int ce=0 , int ci=0 , int co=0 ) : name(n) , external_type(et) , internal_type(it) , offset(o) , is_list(il) , count_external(ce) , count_internal(ci) , count_offset(co){ } 126 | PlyProperty( const std::string &n ) : PlyProperty( n , 0 , 0 , 0 , 0 , 0 , 0 , 0 ){ } 127 | PlyProperty( void ) : external_type(0) , internal_type(0) , offset(0) , is_list(0) , count_external(0) , count_internal(0) , count_offset(0){ } 128 | }; 129 | 130 | std::ostream &operator << ( std::ostream &os , PlyProperty p ) 131 | { 132 | return os << "{ " << p.name << " , " << PlyTypes[ p.external_type ] << " , " << PlyTypes[ p.internal_type ] << " , " << p.offset << " }"; 133 | } 134 | 135 | 136 | struct PlyStoredProperty 137 | { 138 | PlyProperty prop ; char store; 139 | PlyStoredProperty( void ){ } 140 | PlyStoredProperty( const PlyProperty &p , char s ) : prop(p) , store(s){ } 141 | }; 142 | 143 | /* description of an element */ 144 | struct PlyElement 145 | { 146 | std::string name; /* element name */ 147 | size_t num; /* number of elements in this object */ 148 | int size; /* size of element (bytes) or -1 if variable */ 149 | std::vector< PlyStoredProperty > props; /* list of properties in the file */ 150 | int other_offset; /* offset to un-asked-for props, or -1 if none*/ 151 | int other_size; /* size of other_props structure */ 152 | inline PlyProperty *find_property( const std::string &prop_name , int &index ); 153 | }; 154 | 155 | /* describes other properties in an element */ 156 | struct PlyOtherProp 157 | { 158 | std::string name; /* element name */ 159 | int size; /* size of other_props */ 160 | std::vector< PlyProperty > props; /* list of properties in other_props */ 161 | }; 162 | 163 | /* storing other_props for an other element */ 164 | struct OtherData 165 | { 166 | void *other_props; 167 | OtherData( void ) : other_props(NULL){ } 168 | ~OtherData( void ){ if( other_props ) free( other_props ); } 169 | }; 170 | 171 | /* data for one "other" element */ 172 | struct OtherElem 173 | { 174 | std::string elem_name; /* names of other elements */ 175 | std::vector< OtherData > other_data; /* actual property data for the elements */ 176 | PlyOtherProp other_props; /* description of the property data */ 177 | }; 178 | 179 | /* "other" elements, not interpreted by user */ 180 | struct PlyOtherElems 181 | { 182 | std::vector< OtherElem > other_list; /* list of data for other elements */ 183 | }; 184 | 185 | /* description of PLY file */ 186 | struct PlyFile 187 | { 188 | FILE *fp; /* file pointer */ 189 | int file_type; /* ascii or binary */ 190 | float version; /* version number of file */ 191 | std::vector< PlyElement > elems; /* list of elements of object */ 192 | std::vector< std::string > comments; /* list of comments */ 193 | std::vector< std::string > obj_info; /* list of object info items */ 194 | PlyElement *which_elem; /* which element we're currently writing */ 195 | PlyOtherElems *other_elems; /* "other" elements from a PLY file */ 196 | 197 | static inline PlyFile *Write( const std::string & , const std::vector< std::string > & , int , float & ); 198 | static inline PlyFile *Read ( const std::string & , std::vector< std::string > & , int & , float & ); 199 | 200 | PlyFile( FILE *f ) : fp(f) , other_elems(NULL) , version(1.) { } 201 | ~PlyFile( void ){ if( fp ) fclose(fp) ; if(other_elems) delete other_elems; } 202 | 203 | inline void describe_element ( const std::string & , size_t , int , const PlyProperty * ); 204 | inline void describe_property( const std::string & , const PlyProperty * ); 205 | inline void describe_other_elements( PlyOtherElems * ); 206 | inline PlyElement *find_element( const std::string & ); 207 | inline void element_count( const std::string & , size_t ); 208 | inline void header_complete( void ); 209 | inline void put_element_setup( const std::string & ); 210 | inline void put_element ( void * ); 211 | inline void put_comment ( const std::string & ); 212 | inline void put_obj_info( const std::string & ); 213 | inline void put_other_elements( void ); 214 | inline void add_element ( const std::vector< std::string > & ); 215 | inline void add_property( const std::vector< std::string > & ); 216 | inline void add_comment ( const std::string & ); 217 | inline void add_obj_info( const std::string & ); 218 | 219 | inline std::vector< PlyProperty * > get_element_description( const std::string & , size_t & ); 220 | inline void get_element_setup( const std::string & , int , PlyProperty * ); 221 | inline int get_property( const std::string & , const PlyProperty * ); 222 | inline void describe_other_properties( const PlyOtherProp & , int ); 223 | inline bool set_other_properties( const std::string & , int , PlyOtherProp & ); 224 | inline void get_element( void * ); 225 | inline std::vector< std::string > &get_comments( void ); 226 | inline std::vector< std::string > &get_obj_info( void ); 227 | inline void get_info( float & , int & ); 228 | inline PlyOtherElems *get_other_element( std::string & , size_t ); 229 | protected: 230 | inline void _ascii_get_element ( void * ); 231 | inline void _binary_get_element( void * ); 232 | static inline PlyFile *_Write( FILE * , const std::vector< std::string > & , int ); 233 | static inline PlyFile *_Read ( FILE * , std::vector< std::string > & ); 234 | }; 235 | 236 | #include "PlyFile.inl" 237 | } 238 | #endif // PLY_FILE_INCLUDED 239 | -------------------------------------------------------------------------------- /Misha/Poly34.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkazhdan/ShapeGradientDomain/5cec06855b05bd25b0bfa8f88f205b719cf44a31/Misha/Poly34.h -------------------------------------------------------------------------------- /Misha/Poly34.inl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkazhdan/ShapeGradientDomain/5cec06855b05bd25b0bfa8f88f205b719cf44a31/Misha/Poly34.inl -------------------------------------------------------------------------------- /Misha/SparseMatrix.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | #ifndef __SPARSEMATRIX_HPP 30 | #define __SPARSEMATRIX_HPP 31 | #define MATRIX_MULTIPLY_INTERFACE 1 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | 39 | #include "Vector.h" 40 | #include "SparseMatrixInterface.h" 41 | #include "Array.h" 42 | #include "MultiThreading.h" 43 | #include "Atomic.h" 44 | 45 | namespace MishaK 46 | { 47 | template< class T , class IndexType > class SparseMatrix : public SparseMatrixInterface< T , ConstPointer( MatrixEntry< T , IndexType > ) > 48 | { 49 | template< class T2 , class IndexType2 > friend class SparseMatrix; 50 | Pointer( Pointer( MatrixEntry< T , IndexType > ) ) _entries; 51 | public: 52 | static void Swap( SparseMatrix& M1 , SparseMatrix& M2 ) 53 | { 54 | std::swap( M1.rows , M2.rows ); 55 | std::swap( M1.rowSizes , M2.rowSizes ); 56 | std::swap( M1._entries , M2._entries ); 57 | } 58 | typedef SparseMatrixInterface< T , ConstPointer( MatrixEntry< T , IndexType > ) > Interface; 59 | typedef ConstPointer( MatrixEntry< T , IndexType > ) RowIterator; 60 | 61 | size_t rows; 62 | Pointer( size_t ) rowSizes; 63 | 64 | void read( FILE* fp ); 65 | void write( FILE* fp ) const; 66 | 67 | SparseMatrix( void ); 68 | SparseMatrix( const SparseMatrix& M ); 69 | SparseMatrix( SparseMatrix&& M ); 70 | template< class T2 , class IndexType2 > 71 | SparseMatrix( const SparseMatrix< T2 , IndexType2 >& M ); 72 | ~SparseMatrix(); 73 | SparseMatrix& operator = ( SparseMatrix&& M ); 74 | SparseMatrix< T , IndexType >& operator = ( const SparseMatrix< T , IndexType >& M ); 75 | template< class T2 , class IndexType2 > 76 | SparseMatrix< T , IndexType >& operator = ( const SparseMatrix< T2 , IndexType2 >& M ); 77 | 78 | template< class T2 > void operator()( const T2* in , T2* out ) const; 79 | 80 | template< class T2 > Vector< T2 > operator * ( const Vector< T2 >& V ) const; 81 | 82 | template< class T2 , class IndexType2 > 83 | SparseMatrix< T , IndexType >& copy( const SparseMatrix< T2 , IndexType2 >& M ); 84 | 85 | inline ConstPointer( MatrixEntry< T , IndexType > ) begin( size_t row ) const { return _entries[row]; } 86 | inline ConstPointer( MatrixEntry< T , IndexType > ) end ( size_t row ) const { return _entries[row] + rowSizes[row]; } 87 | inline size_t Rows ( void ) const { return rows; } 88 | inline size_t RowSize ( size_t idx ) const { return rowSizes[idx]; } 89 | 90 | SparseMatrix( size_t rows ); 91 | void resize ( size_t rows ); 92 | void SetRowSize( size_t row , size_t count ); 93 | void ResetRowSize( size_t row , size_t count ); 94 | void CollapseRow( int row ); 95 | void CollapseRows( void ); 96 | inline Pointer( MatrixEntry< T , IndexType > ) operator[] ( size_t idx ) { return _entries[idx]; } 97 | inline ConstPointer( MatrixEntry< T , IndexType > ) operator[] ( size_t idx ) const { return _entries[idx]; } 98 | 99 | double SquareNorm( void ) const { return SquareNorm( []( T t ){ return t*t; } ); } 100 | template< typename SquareNormFunctor > double SquareNorm( SquareNormFunctor F=[]( T t ){ return t*t; } ) const; 101 | double ASymmetricSquareNorm( void ) const; 102 | double AHermitianSquareNorm( void ) const; 103 | 104 | /** Sets the column index of all allocated entries to -1 so that they are 105 | * treated as non-existent. This is needed because SetRowSize() uses 106 | * malloc instead of new and MatrixEntry's constructor is never called. */ 107 | void invalidateEntries(); 108 | 109 | /** Adds a scalar value to an element in the Matrix, using a new element if 110 | * necessary. If no pre-allocated space for a new element exists, false is 111 | * returned. 112 | * WARNING: no check is done to remove entries that become zero after 113 | * addition */ 114 | bool addScalarToEntry( T s , IndexType i , IndexType j ); 115 | 116 | // With copy move, these should be well-behaved from a memory perspective 117 | static SparseMatrix Identity( size_t dim ); 118 | SparseMatrix transpose( T (*TransposeFunction)( const T& )=NULL ) const; 119 | SparseMatrix transpose( size_t outRows , T (*TransposeFunction)( const T& )=NULL ) const; 120 | SparseMatrix operator * ( T s ) const; 121 | SparseMatrix operator / ( T s ) const; 122 | SparseMatrix operator * ( const SparseMatrix& M ) const; 123 | SparseMatrix operator + ( const SparseMatrix& M ) const; 124 | SparseMatrix operator - ( const SparseMatrix& M ) const; 125 | SparseMatrix& operator *= ( T s ); 126 | SparseMatrix& operator /= ( T s ); 127 | SparseMatrix& operator *= ( const SparseMatrix& M ); 128 | SparseMatrix& operator += ( const SparseMatrix& M ); 129 | SparseMatrix& operator -= ( const SparseMatrix& M ); 130 | 131 | // [WARNING] The pointer needs to be deallocated 132 | Pointer( T ) operator * ( const Pointer( T ) in ) const; 133 | }; 134 | template< class T1 , class T2 , class T3 , class IndexType > 135 | bool TransposeMultiply( const SparseMatrix< T1 , IndexType >& At , const SparseMatrix< T2 , IndexType >& B , SparseMatrix< T3 , IndexType >& out , T1 (*TransposeFunction)( const T1& )=NULL ); 136 | template< class T1 , class T2 , class T3 , class IndexType > 137 | bool TransposeMultiply( const SparseMatrix< T1 , IndexType >& At , const SparseMatrix< T2 , IndexType >& B , SparseMatrix< T3 , IndexType >& out , size_t outRows , T1 (*TransposeFunction)( const T1& )=NULL ); 138 | #if MATRIX_MULTIPLY_INTERFACE 139 | template< class A_T , class A_const_iterator , class B_T , class B_const_iterator , class Out_T , class Out_IndexType > 140 | bool Multiply( const SparseMatrixInterface< A_T , A_const_iterator >& A , const SparseMatrixInterface< B_T , B_const_iterator >& B , SparseMatrix< Out_T , Out_IndexType >& out , unsigned int threads = 1 ); 141 | template< class T , class In_const_iterator , class Out_IndexType > 142 | bool Transpose( const SparseMatrixInterface< T , In_const_iterator >& At , SparseMatrix< T , Out_IndexType >& A , T (*TransposeFunction)( const T& )=NULL ); 143 | template< class T , class In_const_iterator , class Out_IndexType > 144 | bool Transpose( const SparseMatrixInterface< T , In_const_iterator >& At , SparseMatrix< T , Out_IndexType >& A , size_t outRows , T (*TransposeFunction)( const T& )=NULL ); 145 | #else 146 | template< class T1 , class T2 , class T3 , class IndexType > 147 | bool Multiply(const SparseMatrix< T1, IndexType > &A, const SparseMatrix< T2, IndexType > &B, SparseMatrix< T3, IndexType > &out , unsigned int threads = 1); 148 | template< class T , class IndexType > 149 | bool Transpose( const SparseMatrix< T , IndexType >& At , SparseMatrix< T , IndexType >& A , T (*TransposeFunction)( const T& )=NULL ); 150 | template< class T , class IndexType > 151 | bool Transpose( const SparseMatrix< T , IndexType >& At , SparseMatrix< T , IndexType >& A , size_t outRows , T (*TransposeFunction)( const T& )=NULL ); 152 | #endif // MATRIX_MULTIPLY_INTERFACE 153 | 154 | template< class T , class IndexType > 155 | class SparseSymmetricMatrix : public SparseMatrix< T , IndexType > 156 | { 157 | public: 158 | template 159 | Vector operator * (const Vector& V) const; 160 | template 161 | void Multiply ( const Vector& In, Vector& Out ) const; 162 | }; 163 | 164 | template< class T , unsigned int Radius > class BandedMatrixIterator 165 | { 166 | size_t _rows , _row; 167 | int _offset; 168 | ConstPointer( T ) _values; 169 | MatrixEntry< size_t , T > _entry; 170 | public: 171 | bool operator !=( const BandedMatrixIterator& i ) const { return i._row!=_row || i._offset!=_offset; } 172 | const MatrixEntry< T , size_t >& operator -> ( void ) const { return _entry; } 173 | BandedMatrixIterator& operator ++ ( void ) 174 | { 175 | _offset++; 176 | if( _offset<=Radius ) _entry = MatrixEntry< T , size_t >( ( _rows + _row + _offset ) % _rows , _values[ Radius+_offset ] ); 177 | return *this; 178 | } 179 | BandedMatrixIterator( size_t rows , size_t row , ConstPointer( T ) values ){ _rows = rows , _row = row , _values = values, _offset = -(int)Radius; } 180 | BandedMatrixIterator( size_t row ){ _row = row , _offset = Radius+1; } 181 | }; 182 | template< class T , unsigned int Radius > class BandedMatrix : public SparseMatrixInterface< T , BandedMatrixIterator< T , Radius > > 183 | { 184 | template< class T2 , unsigned int Radius2 > friend class BandedMatrix; 185 | size_t _rows; 186 | Pointer( T ) _entries; 187 | public: 188 | BandedMatrix( void ); 189 | BandedMatrix( size_t rows ); 190 | BandedMatrix( size_t rows , const T& clearValue ); 191 | template< class T2 > BandedMatrix( const BandedMatrix< T2 , Radius >& M ); 192 | template< class T2 > BandedMatrix& operator = ( const BandedMatrix< T2 , Radius >& M ); 193 | ~BandedMatrix(); 194 | 195 | BandedMatrixIterator< T , Radius > begin( size_t row ) const { return BandedMatrixIterator< T , Radius >( _rows , row , _entries + row * (2*Radius+1) ); } 196 | BandedMatrixIterator< T , Radius > end( size_t row ) const { return BandedMatrixIterator< T , Radius >( row ); } 197 | size_t Rows( void ) const{ return _rows; } 198 | size_t RowSize( size_t idx ) const { return 2*Radius+1; } 199 | 200 | template< class T2 > void multiply ( ConstPointer( T2 ) in , Pointer( T2 ) out , unsigned int threads=1 ) const; 201 | template< class T2 > void multiply2( ConstPointer( T2 ) in , Pointer( T2 ) out , unsigned int threads=1 ) const; 202 | 203 | inline size_t rows( void ) const { return _rows; } 204 | inline size_t entries( void ) const { return _rows * ( 2 * Radius + 1 ); } 205 | 206 | void resize( size_t rows ); 207 | void resize( size_t rows , const T& clearValue ); 208 | inline Pointer( T ) operator[] ( size_t idx ) { return _entries + idx * ( 2 * Radius + 1 ); } 209 | inline ConstPointer( T ) operator[] ( size_t idx ) const { return _entries + idx * ( 2 * Radius + 1 ); } 210 | double squareNorm( void ) const; 211 | }; 212 | 213 | template 214 | static unsigned int SolveConjugateGradient( const Matrix& SPD , const Vector& b , const int& iters , Vector& solution , const double eps=1e-8 ); 215 | template 216 | static unsigned int SolveConjugateGradient( const Matrix& SPD , const Vector& b , const int& iters , Vector& solution , const double eps=1e-8 ); 217 | template 218 | static unsigned int SolveConjugateGradient2( const Matrix& SPD , const Vector& b , const int& iters , Vector& solution , const double eps=1e-8 ); 219 | 220 | template< class RealIn , class RealOut> 221 | void CompressSparseMatrix( const SparseMatrix< RealIn , int > & M, SparseMatrix< RealOut, int > & _M ); 222 | 223 | #include "SparseMatrix.inl" 224 | } 225 | #endif /* __SPARSEMATRIX_HPP */ 226 | -------------------------------------------------------------------------------- /Misha/SparseMatrixInterface.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023, Michael Kazhdan 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | #ifndef SPARSE_MATRIX_INTERFACE_INCLUDED 29 | #define SPARSE_MATRIX_INTERFACE_INCLUDED 30 | 31 | #define FORCE_TWO_BYTE_ALIGNMENT 1 32 | #include "Array.h" 33 | #include "MultiThreading.h" 34 | #include 35 | 36 | namespace MishaK 37 | { 38 | 39 | #if FORCE_TWO_BYTE_ALIGNMENT 40 | #pragma pack(push) 41 | #pragma pack(2) 42 | #endif // FORCE_TWO_BYTE_ALIGNMENT 43 | template< class T , class IndexType > 44 | struct MatrixEntry 45 | { 46 | MatrixEntry( void ) { N =-1 , Value = 0; } 47 | MatrixEntry( IndexType i ) { N = i , Value = 0; } 48 | MatrixEntry( IndexType n , T v ){ N = n , Value = v; } 49 | IndexType N; 50 | T Value; 51 | }; 52 | 53 | #if FORCE_TWO_BYTE_ALIGNMENT 54 | #pragma pack(pop) 55 | #endif // FORCE_TWO_BYTE_ALIGNMENT 56 | 57 | 58 | enum 59 | { 60 | MULTIPLY_ADD = 1 , 61 | MULTIPLY_NEGATE = 2 62 | }; 63 | 64 | template< class T , class const_iterator > class SparseMatrixInterface 65 | { 66 | public: 67 | virtual const_iterator begin( size_t row ) const = 0; 68 | virtual const_iterator end ( size_t row ) const = 0; 69 | virtual size_t Rows ( void ) const = 0; 70 | virtual size_t RowSize( size_t idx ) const = 0; 71 | 72 | size_t Entries( void ) const; 73 | 74 | double SquareNorm( void ) const; 75 | double SquareASymmetricNorm( void ) const; 76 | double SquareASymmetricNorm( int& idx1 , int& idx2 ) const; 77 | 78 | template< class T2 , class T2Real=T > void Multiply ( ConstPointer( T2 ) In , Pointer( T2 ) Out , int multiplyFlag=0 ) const; 79 | template< class T2 , class T2Real=T > void MultiplyScaled( T scale , ConstPointer( T2 ) In , Pointer( T2 ) Out , int multiplyFlag=0 ) const; 80 | template< class T2 , class T2Real=T > void Multiply ( Pointer( T2 ) In , Pointer( T2 ) Out , int multiplyFlag=0 ) const { Multiply < T2 , T2Real >( ( ConstPointer(T2) )( In ) , Out , multiplyFlag ); } 81 | template< class T2 , class T2Real=T > void MultiplyScaled( T scale , Pointer( T2 ) In , Pointer( T2 ) Out , int multiplyFlag=0 ) const { MultiplyScaled< T2 , T2Real >( scale , ( ConstPointer(T2) )( In ) , Out , multiplyFlag ); } 82 | 83 | template< class T2 > void SetDiagonal( Pointer( T2 ) diagonal ) const; 84 | template< class T2 > void JacobiIteration( ConstPointer( T2 ) diagonal , ConstPointer( T2 ) b , Pointer( T2 ) x , Pointer( T2 ) Mx , T2 sor ) const; 85 | template< class T2 > void JacobiIteration( ConstPointer( T2 ) diagonal , ConstPointer( T2 ) b , Pointer( T2 ) x , T2 sor ) const { Pointer( T2 ) Mx = AllocPointer< T2 >( Rows() ) ; JacobiIteration( diagonal , b , x , Mx , sor ) ; FreePointer( Mx ); } 86 | #if 1 87 | template< class T2 , bool StripDiagonal=false > void GSIteration( ConstPointer( T2 ) diagonal , ConstPointer( T2 ) b , Pointer( T2 ) x , bool forward ) const; 88 | template< class T2 , bool StripDiagonal=false > void GSIteration( std::vector< std::vector< int > >& multiColorIndices , ConstPointer( T2 ) diagonal , ConstPointer( T2 ) b , Pointer( T2 ) x , bool forward ) const; 89 | #else 90 | template< class T2 > void GSIteration( ConstPointer( T2 ) diagonal , ConstPointer( T2 ) b , Pointer( T2 ) x , bool forward ) const; 91 | template< class T2 > void GSIteration( std::vector< std::vector< int > >& multiColorIndices , ConstPointer( T2 ) diagonal , ConstPointer( T2 ) b , Pointer( T2 ) x , bool forward ) const; 92 | 93 | #endif 94 | }; 95 | // Assuming that the SPDOperator class defines: 96 | // int SPDOperator::Rows( void ) const 97 | // auto SPDOperator::Multiply( ConstPointer( T ) , Pointer( T ) ) const 98 | template< class SPDOperator , class T > int SolveCG( const SPDOperator& M , ConstPointer( T ) b , int iters , Pointer( T ) x , T eps=1e-8 , bool solveNormal=false ); 99 | 100 | #include "SparseMatrixInterface.inl" 101 | } 102 | #endif // SPARSE_MATRIX_INTERFACE_INCLUDED 103 | -------------------------------------------------------------------------------- /Misha/SparseMatrixInterface.inl: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2023, Michael Kazhdan 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | template< class T , class const_iterator > size_t SparseMatrixInterface< T , const_iterator >::Entries( void ) const 30 | { 31 | size_t entries = 0; 32 | for( size_t i=0 ; i double SparseMatrixInterface< T , const_iterator >::SquareNorm( void ) const 36 | { 37 | double n=0; 38 | for( size_t i=0 ; iValue * iter->Value; 42 | } 43 | return n; 44 | 45 | } 46 | template< class T , class const_iterator > double SparseMatrixInterface< T , const_iterator >::SquareASymmetricNorm( void ) const 47 | { 48 | double n=0; 49 | for( size_t i=0 ; iN; 55 | const_iterator e = end( j ); 56 | double value = 0; 57 | for( const_iterator iter2 = begin( j ) ; iter2!=e ; iter2++ ) 58 | { 59 | int k = iter2->N; 60 | if( k==i ) value += iter2->Value; 61 | } 62 | n += (iter1->Value-value) * (iter1->Value-value); 63 | } 64 | } 65 | return n; 66 | } 67 | template< class T , class const_iterator > double SparseMatrixInterface< T , const_iterator >::SquareASymmetricNorm( int& idx1 , int& idx2 ) const 68 | { 69 | double n=0; 70 | double max=0; 71 | for( size_t i=0 ; iN; 77 | const_iterator e = end( j ); 78 | double value = 0; 79 | for( const_iterator iter2 = begin( j ) ; iter2!=e ; iter2++ ) 80 | { 81 | int k = iter2->N; 82 | if( k==i ) value += iter2->Value; 83 | } 84 | double temp = (iter->Value-value) * (iter->Value-value); 85 | n += temp; 86 | if( temp>=max ) idx1 = i , idx2 = j , max=temp; 87 | } 88 | } 89 | return n; 90 | } 91 | template< class T , class const_iterator > 92 | template< class T2 , class T2Real > 93 | void SparseMatrixInterface< T , const_iterator >::Multiply( ConstPointer( T2 ) In , Pointer( T2 ) Out , int multiplyFlag ) const 94 | { 95 | ConstPointer( T2 ) in = In; 96 | ThreadPool::ParallelFor 97 | ( 98 | 0 , Rows() , 99 | [&]( unsigned int , size_t i ) 100 | { 101 | T2 temp; 102 | memset( &temp , 0 , sizeof(T2) ); 103 | ConstPointer( T2 ) _in = in; 104 | const_iterator e = end( i ); 105 | #if 1 106 | for( const_iterator iter = begin( i ) ; iter!=e ; iter++ ) temp += _in[ iter->N ] * static_cast< T2Real >( iter->Value ); 107 | #else 108 | for( const_iterator iter = begin( i ) ; iter!=e ; iter++ ) temp += (T2)( _in[ iter->N ] * iter->Value ); 109 | #endif 110 | if( multiplyFlag & MULTIPLY_NEGATE ) temp = -temp; 111 | if( multiplyFlag & MULTIPLY_ADD ) Out[i] += temp; 112 | else Out[i] = temp; 113 | } 114 | ); 115 | } 116 | template< class T , class const_iterator > 117 | template< class T2 , class T2Real > 118 | void SparseMatrixInterface< T , const_iterator >::MultiplyScaled( T scale , ConstPointer( T2 ) In , Pointer( T2 ) Out , int multiplyFlag ) const 119 | { 120 | ConstPointer( T2 ) in = In; 121 | ThreadPool::ParallelFor 122 | ( 123 | 0 , Rows() , 124 | [&]( unsigned int , size_t i ) 125 | { 126 | T2 temp; 127 | memset( &temp , 0 , sizeof(T2) ); 128 | ConstPointer( T2 ) _in = in; 129 | const_iterator e = end( i ); 130 | for( const_iterator iter = begin( i ) ; iter!=e ; iter++ ) temp += _in[ iter->N ] * static_cast< T2Real >( iter->Value ); 131 | temp *= scale; 132 | if( multiplyFlag & MULTIPLY_NEGATE ) temp = -temp; 133 | if( multiplyFlag & MULTIPLY_ADD ) Out[i] += temp; 134 | else Out[i] = temp; 135 | } 136 | ); 137 | } 138 | 139 | template< class T , class const_iterator > 140 | template< class T2 > 141 | void SparseMatrixInterface< T , const_iterator >::SetDiagonal( Pointer( T2 ) diagonal ) const 142 | { 143 | ThreadPool::ParallelFor 144 | ( 145 | 0 , Rows() , 146 | [&]( unsigned int , size_t i ) 147 | { 148 | diagonal[i] = (T2)0; 149 | const_iterator e = end( i ); 150 | for( const_iterator iter = begin( i ) ; iter!=e ; iter++ ) if( iter->N==i ) diagonal[i] += iter->Value; 151 | } 152 | ); 153 | } 154 | template< class T , class const_iterator > 155 | template< class T2 > 156 | void SparseMatrixInterface< T , const_iterator >::JacobiIteration( ConstPointer( T2 ) diagonal , ConstPointer( T2 ) b , Pointer( T2 ) x , Pointer( T2 ) Mx , T2 sor ) const 157 | { 158 | Multiply( x , Mx ); 159 | ThreadPool::ParallelFor( 0 , Rows() , [&]( unsigned int , size_t i ){ x[i] += ( b[i] - Mx[i] ) * sor / diagonal[i]; } ); 160 | } 161 | #if 1 162 | template< class T , class const_iterator > 163 | template< class T2 , bool StripDiagonal > 164 | void SparseMatrixInterface< T , const_iterator >::GSIteration( ConstPointer( T2 ) diagonal , ConstPointer( T2 ) b , Pointer( T2 ) x , bool forward ) const 165 | { 166 | if( StripDiagonal ) 167 | { 168 | #define ITERATE( j ) \ 169 | { \ 170 | T2 _b = b[j]; \ 171 | const_iterator e = end( j ); \ 172 | for( const_iterator iter = begin( j ) ; iter!=e ; iter++ ) _b -= x[iter->N] * iter->Value; \ 173 | x[j] = _b / diagonal[j]; \ 174 | } 175 | 176 | if( forward ) for( int j=0 ; j=0 ; j-- ){ ITERATE( j ); } 178 | #undef ITERATE 179 | } 180 | else 181 | { 182 | #define ITERATE( j ) \ 183 | { \ 184 | T2 _b = b[j]; \ 185 | const_iterator e = end( j ); \ 186 | for( const_iterator iter = begin( j ) ; iter!=e ; iter++ ) _b -= x[iter->N] * iter->Value; \ 187 | x[j] += _b / diagonal[j]; \ 188 | } 189 | 190 | if( forward ) for( int j=0 ; j=0 ; j-- ){ ITERATE( j ); } 192 | #undef ITERATE 193 | } 194 | } 195 | template< class T , class const_iterator > 196 | template< class T2 , bool StripDiagonal > 197 | void SparseMatrixInterface< T , const_iterator >::GSIteration( std::vector< std::vector< int > >& multiColorIndices , ConstPointer( T2 ) diagonal , ConstPointer( T2 ) b , Pointer( T2 ) x , bool forward ) const 198 | { 199 | #ifdef _WIN32 200 | #define SetOMPParallel __pragma( omp parallel for ) 201 | #else // !_WIN32 202 | #define SetOMPParallel _Pragma( "omp parallel for" ) 203 | #endif // _WIN32 204 | 205 | if( StripDiagonal ) 206 | { 207 | #define ITERATE( indices ) \ 208 | { \ 209 | SetOMPParallel \ 210 | for( int k=0 ; kN] * iter->Value; \ 216 | x[jj] = _b / diagonal[jj]; \ 217 | } \ 218 | } 219 | if( forward ) for( int j=0 ; j=0 ; j-- ){ ITERATE( multiColorIndices[j] ); } 221 | #undef ITERATE 222 | } 223 | else 224 | { 225 | #define ITERATE( indices ) \ 226 | { \ 227 | SetOMPParallel \ 228 | for( int k=0 ; kN] * iter->Value; \ 234 | x[jj] += _b / diagonal[jj]; \ 235 | } \ 236 | } 237 | if( forward ) for( int j=0 ; j=0 ; j-- ){ ITERATE( multiColorIndices[j] ); } 239 | #undef ITERATE 240 | } 241 | #undef SetOMPParallel 242 | } 243 | #else 244 | template< class T , class const_iterator > 245 | template< class T2 > 246 | void SparseMatrixInterface< T , const_iterator >::GSIteration( ConstPointer( T2 ) diagonal , ConstPointer( T2 ) b , Pointer( T2 ) x , bool forward ) const 247 | { 248 | #define ITERATE( j ) \ 249 | { \ 250 | T2 _b = b[j]; \ 251 | const_iterator e = end( j ); \ 252 | for( const_iterator iter = begin( j ) ; iter!=e ; iter++ ) _b -= x[iter->N] * iter->Value; \ 253 | x[j] += _b / diagonal[j]; \ 254 | } 255 | 256 | if( forward ) for( int j=0 ; j=0 ; j-- ){ ITERATE( j ); } 258 | #undef ITERATE 259 | } 260 | template< class T , class const_iterator > 261 | template< class T2 > 262 | void SparseMatrixInterface< T , const_iterator >::GSIteration( std::vector< std::vector< int > >& multiColorIndices , ConstPointer( T2 ) diagonal , ConstPointer( T2 ) b , Pointer( T2 ) x , bool forward ) const 263 | { 264 | #ifdef _WIN32 265 | #define SetOMPParallel __pragma( omp parallel for ) 266 | #else // !_WIN32 267 | #define SetOMPParallel _Pragma( "omp parallel for" ) 268 | #endif // _WIN32 269 | #define ITERATE( indices ) \ 270 | { \ 271 | SetOMPParallel \ 272 | for( int k=0 ; kN] * iter->Value; \ 278 | x[jj] += _b / diagonal[jj]; \ 279 | } \ 280 | } 281 | if( forward ) for( int j=0 ; j=0 ; j-- ){ ITERATE( multiColorIndices[j] ); } 283 | #undef ITERATE 284 | #undef SetOMPParallel 285 | } 286 | #endif 287 | template< class SPDOperator , class T > int SolveCG( const SPDOperator& M , ConstPointer( T ) b , int iters , Pointer( T ) x , T eps , bool solveNormal ) 288 | { 289 | eps *= eps; 290 | int dim = M.Rows(); 291 | Pointer( T ) r = AllocPointer< T >( dim ); 292 | Pointer( T ) d = AllocPointer< T >( dim ); 293 | Pointer( T ) q = AllocPointer< T >( dim ); 294 | Pointer( T ) temp = NullPointer< T >( ); 295 | memset( x , 0 , sizeof(T)* dim ); 296 | if( solveNormal ) temp = AllocPointer< T >( dim ); 297 | 298 | double delta_new = 0 , delta_0; 299 | if( solveNormal ) 300 | { 301 | M.Multiply( ( ConstPointer( T ) )x , temp ) , M.Multiply( ( ConstPointer( T ) )temp , r ) , M.Multiply( ( ConstPointer( T ) )b , temp ); 302 | std::vector< double > _delta_news( ThreadPool::NumThreads() , 0 ); 303 | ThreadPool::ParallelFor( 0 , dim , [&]( unsigned int t , size_t i ){ d[i] = r[i] = temp[i] - r[i] ; _delta_news[t] += r[i] * r[i]; } ); 304 | for( unsigned int t=0 ; t<_delta_news.size() ; t++ ) delta_new += _delta_news[t]; 305 | } 306 | else 307 | { 308 | M.Multiply( ( ConstPointer( T ) )x , r ); 309 | std::vector< double > _delta_news( ThreadPool::NumThreads() , 0 ); 310 | ThreadPool::ParallelFor( 0 , dim , [&]( unsigned int t , size_t i ){ d[i] = r[i] = b[i] - r[i] ; _delta_news[t] += r[i] * r[i]; } ); 311 | for( unsigned int t=0 ; t<_delta_news.size() ; t++ ) delta_new += _delta_news[t]; 312 | } 313 | delta_0 = delta_new; 314 | if( delta_neweps*delta_0 ; ii++ ) 324 | { 325 | if( solveNormal ) M.Multiply( ( ConstPointer( T ) )d , temp ) , M.Multiply( ( ConstPointer( T ) )temp , q ); 326 | else M.Multiply( ( ConstPointer( T ) )d , q ); 327 | double dDotQ = 0; 328 | std::vector< double > _dDotQs( ThreadPool::NumThreads() , 0 ); 329 | ThreadPool::ParallelFor( 0 , dim , [&]( unsigned int t , size_t i ){ _dDotQs[t] += _dDotQs[t];} ); 330 | for( unsigned int t=0 ; t<_dDotQs.size() ; t++ ) dDotQ += _dDotQs[t]; 331 | T alpha = T( delta_new / dDotQ ); 332 | double delta_old = delta_new; 333 | delta_new = 0; 334 | if( (ii%50)==(50-1) ) 335 | { 336 | ThreadPool::ParallelFor( 0 , dim , [&]( unsigned int , size_t i ){ x[i] += d[i] * alpha; } ); 337 | if( solveNormal ) M.Multiply( ( ConstPointer( T ) )x , temp ) , M.Multiply( ( ConstPointer( T ) )temp , r ); 338 | else M.Multiply( ( ConstPointer( T ) )x , r ); 339 | std::vector< double > _delta_news( ThreadPool::NumThreads() , 0 ); 340 | ThreadPool::ParallelFor( 0 , dim , [&]( unsigned int t , size_t i ){ r[i] = b[i] - r[i] ; _delta_news[t] += r[i] * r[i] ; x[i] += d[i] * alpha; } ); 341 | for( unsigned int t=0 ; t<_delta_news.size() ; t++ ) delta_new += _delta_news[t]; 342 | } 343 | else 344 | { 345 | std::vector< double > _delta_news( ThreadPool::NumThreads() , 0 ); 346 | ThreadPool::ParallelFor( 0 , dim , [&]( unsigned int t , size_t i ){ r[i] -= q[i] * alpha ; _delta_news[t] += r[i] * r[i] ; x[i] += d[i] * alpha; } ); 347 | for( unsigned int t=0 ; t<_delta_news.size() ; t++ ) delta_new += _delta_news[t]; 348 | } 349 | 350 | T beta = T( delta_new / delta_old ); 351 | ThreadPool::ParallelFor( 0 , dim , [&]( unsigned int , size_t i ){ d[i] = r[i] + d[i] * beta; } ); 352 | } 353 | FreePointer( r ); 354 | FreePointer( d ); 355 | FreePointer( q ); 356 | FreePointer( temp ); 357 | return ii; 358 | } 359 | -------------------------------------------------------------------------------- /Misha/Vector.h: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | #ifndef __VECTOR_HPP 30 | #define __VECTOR_HPP 31 | 32 | #include 33 | #include "Array.h" 34 | 35 | namespace MishaK 36 | { 37 | template 38 | class Vector 39 | { 40 | public: 41 | // For better compatibility with std::vector 42 | typedef T value_type; 43 | 44 | Vector(); 45 | Vector( const Vector& V ); 46 | Vector( size_t N ); 47 | Vector( size_t N, T* pV ); 48 | ~Vector(); 49 | 50 | // const T& operator () (size_t i) const; 51 | // T& operator () (size_t i); 52 | #if defined WIN32 || defined WIN64 // JP: none of this works on gcc: "ambiguous overloads" 53 | #if 1 // This is a real pain, because depending on whether 54 | // one compiles with 32-bit or 64-bit, size-t is unsigned int or unsigned long long 55 | const T& operator[]( unsigned int i ) const { return m_pV[i]; } 56 | T& operator[]( unsigned int i ) { return m_pV[i]; } 57 | const T& operator[]( int i ) const { return m_pV[i]; } 58 | T& operator[]( int i ) { return m_pV[i]; } 59 | #ifdef _WIN64 60 | const T& operator[]( unsigned long long i ) const { return m_pV[i]; } 61 | T& operator[]( unsigned long long i ) { return m_pV[i]; } 62 | const T& operator[]( long long i ) const { return m_pV[i]; } 63 | T& operator[]( long long i ) { return m_pV[i]; } 64 | #endif // _WIN64 65 | #else 66 | const T& operator[]( size_t i ) const { return m_pV[i]; } 67 | T& operator[]( size_t i ) { return m_pV[i]; } 68 | const T& operator[]( int i ) const { return m_pV[i]; } 69 | T& operator[]( int i ) { return m_pV[i]; } 70 | #endif 71 | #else // Mac 72 | const T& operator[] (size_t i) const { return m_pV[i]; } 73 | T& operator[] (size_t i) { return m_pV[i]; } 74 | #endif // Windows 75 | 76 | 77 | void SetZero(); 78 | 79 | size_t size() const; 80 | void resize( size_t N ); 81 | 82 | Vector operator * (const T& A) const; 83 | Vector operator / (const T& A) const; 84 | Vector operator - (const Vector& V) const; 85 | Vector operator + (const Vector& V) const; 86 | 87 | operator Pointer( T )( ); 88 | operator ConstPointer( T )( ) const; 89 | 90 | Pointer( T ) operator + ( int idx ); 91 | Pointer( T ) operator - ( int idx ); 92 | ConstPointer( T ) operator + ( int idx ) const; 93 | ConstPointer( T ) operator - ( int idx ) const; 94 | 95 | Vector& operator *= (const T& A); 96 | Vector& operator /= (const T& A); 97 | Vector& operator += (const Vector& V); 98 | Vector& operator -= (const Vector& V); 99 | 100 | template 101 | Vector& AddScaled(const Vector& V,const Real& scale); 102 | template 103 | Vector& SubtractScaled(const Vector& V,const Real& scale); 104 | template 105 | static void Add(const Vector& V1,const Real& scale1,const Vector& V2,const Real& scale2,Vector& Out); 106 | template 107 | static void Add(const Vector& V1,const Real& scale1,const Vector& V2,Vector& Out); 108 | 109 | Vector operator - () const; 110 | 111 | Vector& operator = (const Vector& V); 112 | T Dot( const Vector& V ) const; 113 | template 114 | Real IPSDot( const Vector& V ) const; 115 | T Length() const; 116 | 117 | /* 118 | T Norm( size_t Ln ) const; 119 | void Normalize(); 120 | */ 121 | // T* m_pV; 122 | Pointer( T ) m_pV; 123 | protected: 124 | size_t m_N; 125 | 126 | }; 127 | 128 | template 129 | class NVector 130 | { 131 | public: 132 | NVector(); 133 | NVector( const NVector& V ); 134 | NVector( size_t N ); 135 | NVector( size_t N, T* pV ); 136 | ~NVector(); 137 | 138 | const T* operator () (size_t i) const; 139 | T* operator () (size_t i); 140 | const T* operator [] (size_t i) const; 141 | T* operator [] (size_t i); 142 | 143 | void SetZero(); 144 | 145 | size_t size() const; 146 | void resize( size_t N ); 147 | 148 | NVector operator * (const T& A) const; 149 | NVector operator / (const T& A) const; 150 | NVector operator - (const NVector& V) const; 151 | NVector operator + (const NVector& V) const; 152 | 153 | NVector& operator *= (const T& A); 154 | NVector& operator /= (const T& A); 155 | NVector& operator += (const NVector& V); 156 | NVector& operator -= (const NVector& V); 157 | 158 | NVector& AddScaled(const NVector& V,const T& scale); 159 | NVector& SubtractScaled(const NVector& V,const T& scale); 160 | static void Add(const NVector& V1,const T& scale1,const NVector& V2,const T& scale2,NVector& Out); 161 | static void Add(const NVector& V1,const T& scale1,const NVector& V2, NVector& Out); 162 | 163 | NVector operator - () const; 164 | 165 | NVector& operator = (const NVector& V); 166 | 167 | T Dot( const NVector& V ) const; 168 | 169 | T Length() const; 170 | 171 | T Norm( size_t Ln ) const; 172 | void Normalize(); 173 | 174 | T* m_pV; 175 | protected: 176 | size_t m_N; 177 | 178 | }; 179 | #include "Vector.inl" 180 | } 181 | #endif 182 | -------------------------------------------------------------------------------- /Misha/Vector.inl: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | #ifndef __VECTORIMPL_HPP 30 | #define __VECTORIMPL_HPP 31 | 32 | #define Assert assert 33 | 34 | //////////// 35 | // Vector // 36 | //////////// 37 | template< class T > inline Vector< T >::operator Pointer( T ) ( ) { return m_pV; } 38 | template< class T > inline Vector< T >::operator ConstPointer( T ) ( ) const { return ( ConstPointer( T ) )m_pV; } 39 | template< class T > inline Pointer( T ) Vector< T >::operator + ( int idx ) { return m_pV + idx; } 40 | template< class T > inline Pointer( T ) Vector< T >::operator - ( int idx ) { return m_pV - idx; } 41 | template< class T > inline ConstPointer( T ) Vector< T >::operator + ( int idx ) const { return ( ConstPointer( T ) )m_pV + idx; } 42 | template< class T > inline ConstPointer( T ) Vector< T >::operator - ( int idx ) const { return ( ConstPointer( T ) )m_pV - idx; } 43 | template 44 | Vector::Vector() 45 | { 46 | m_N = 0; 47 | // m_pV = 0; 48 | m_pV = NullPointer< T >( ); 49 | } 50 | template 51 | Vector::Vector( const Vector& V ) 52 | { 53 | m_N = 0; 54 | // m_pV = 0; 55 | m_pV = NullPointer< T >( ); 56 | resize(V.m_N); 57 | memcpy( m_pV, V.m_pV, m_N*sizeof(T) ); 58 | } 59 | template 60 | Vector::Vector( size_t N ) 61 | { 62 | m_N=0; 63 | // m_pV=0; 64 | m_pV = NullPointer< T >( ); 65 | resize(N); 66 | } 67 | template 68 | void Vector::resize( size_t N ) 69 | { 70 | if( m_N!=N ) 71 | { 72 | if( m_N ) FreePointer( m_pV ); 73 | m_pV = NullPointer< T >( ); 74 | m_N = N; 75 | if( N ) m_pV = AllocPointer< T >( N ); 76 | } 77 | if( N ) memset( m_pV, 0, N*sizeof(T) ); 78 | } 79 | template 80 | Vector::Vector( size_t N, T* pV ) 81 | { 82 | resize(N); 83 | memcpy( m_pV, pV, N*sizeof(T) ); 84 | } 85 | template 86 | Vector::~Vector(){resize(0);} 87 | template 88 | Vector& Vector::operator = (const Vector& V) 89 | { 90 | resize(V.m_N); 91 | memcpy( m_pV, V.m_pV, m_N*sizeof(T) ); 92 | return *this; 93 | } 94 | template 95 | size_t Vector::size() const{return m_N;} 96 | template 97 | void Vector::SetZero(void){memset(m_pV,0,sizeof(T)*m_N);} 98 | #if 0 99 | template 100 | const T& Vector::operator () (size_t i) const 101 | { 102 | Assert( i < m_N ); 103 | return m_pV[i]; 104 | } 105 | template 106 | T& Vector::operator () (size_t i) 107 | { 108 | return m_pV[i]; 109 | } 110 | #endif 111 | template 112 | Vector Vector::operator * (const T& A) const 113 | { 114 | Vector V(*this); 115 | for (size_t i=0; i 120 | Vector& Vector::operator *= (const T& A) 121 | { 122 | for (size_t i=0; i 127 | Vector Vector::operator / (const T& A) const 128 | { 129 | Vector V(*this); 130 | for (size_t i=0; i 135 | Vector& Vector::operator /= (const T& A) 136 | { 137 | for (size_t i=0; i 142 | Vector Vector::operator + (const Vector& V0) const 143 | { 144 | Vector V(m_N); 145 | for (size_t i=0; i 151 | template 152 | Vector& Vector::AddScaled(const Vector& V,const Real& scale) 153 | { 154 | for (size_t i=0; i 160 | template 161 | Vector& Vector::SubtractScaled(const Vector& V,const Real& scale) 162 | { 163 | for (size_t i=0; i 169 | template 170 | void Vector::Add(const Vector& V1,const Real& scale1,const Vector& V2,const Real& scale2,Vector& Out){ 171 | for (size_t i=0; i 175 | template 176 | void Vector::Add(const Vector& V1,const Real& scale1,const Vector& V2,Vector& Out){ 177 | for (size_t i=0; i 181 | Vector& Vector::operator += (const Vector& V) 182 | { 183 | for (size_t i=0; i 189 | Vector Vector::operator - (const Vector& V0) const 190 | { 191 | Vector V(m_N); 192 | for (size_t i=0; i 198 | Vector Vector::operator - (void) const 199 | { 200 | Vector V(m_N); 201 | 202 | for (size_t i=0; i 208 | Vector& Vector::operator -= (const Vector& V) 209 | { 210 | for (size_t i=0; i 217 | T Vector::Norm( size_t Ln ) const 218 | { 219 | T N = T(); 220 | for (size_t i = 0; i 225 | void Vector::Normalize() 226 | { 227 | T N = 1.0f/Norm(2); 228 | for (size_t i = 0; i 233 | T Vector::Length() const 234 | { 235 | T N = T(); 236 | for (size_t i = 0; i 242 | T Vector::Dot( const Vector& V ) const 243 | { 244 | T V0 = T(); 245 | for (size_t i=0; i 252 | template 253 | Real Vector::IPSDot( const Vector& V ) const 254 | { 255 | Real dot = 0; 256 | for (size_t i=0; i 265 | NVector::NVector() 266 | { 267 | m_N = 0; 268 | m_pV = 0; 269 | } 270 | template 271 | NVector::NVector( const NVector& V ) 272 | { 273 | m_N = 0; 274 | m_pV = 0; 275 | resize(V.m_N); 276 | memcpy( m_pV, V.m_pV, m_N*sizeof(T)*Dim ); 277 | } 278 | template 279 | NVector::NVector( size_t N ) 280 | { 281 | m_N=0; 282 | m_pV=0; 283 | resize(N); 284 | } 285 | template 286 | void NVector::resize( size_t N ) 287 | { 288 | if(m_N!=N){ 289 | if(m_N){delete[] m_pV;} 290 | m_pV=NULL; 291 | m_N = N; 292 | if(N){m_pV = new T[Dim*N];} 293 | } 294 | memset( m_pV, 0, N*sizeof(T)*Dim ); 295 | } 296 | template 297 | NVector::NVector( size_t N, T* pV ) 298 | { 299 | resize(N); 300 | memcpy( m_pV, pV, N*sizeof(T)*Dim ); 301 | } 302 | template 303 | NVector::~NVector(){resize(0);} 304 | template 305 | NVector& NVector::operator = (const NVector& V) 306 | { 307 | resize(V.m_N); 308 | memcpy( m_pV, V.m_pV, m_N*sizeof(T)*Dim ); 309 | return *this; 310 | } 311 | template 312 | size_t NVector::size() const{return m_N;} 313 | template 314 | void NVector::SetZero(void){for (size_t i=0; i 316 | const T* NVector::operator () (size_t i) const 317 | { 318 | Assert( i < m_N ); 319 | return &m_pV[i*Dim]; 320 | } 321 | template 322 | T* NVector::operator () (size_t i) 323 | { 324 | return &m_pV[i*Dim]; 325 | } 326 | template 327 | const T* NVector::operator [] (size_t i) const 328 | { 329 | return &m_pV[i*Dim]; 330 | } 331 | template 332 | T* NVector::operator [] (size_t i) 333 | { 334 | return &m_pV[i*Dim]; 335 | } 336 | template 337 | NVector NVector::operator * (const T& A) const 338 | { 339 | NVector V(*this); 340 | for (size_t i=0; i 345 | NVector& NVector::operator *= (const T& A) 346 | { 347 | for (size_t i=0; i 352 | NVector NVector::operator / (const T& A) const 353 | { 354 | NVector V(*this); 355 | for (size_t i=0; i 360 | NVector& NVector::operator /= (const T& A) 361 | { 362 | for (size_t i=0; i 367 | NVector NVector::operator + (const NVector& V0) const 368 | { 369 | NVector V(m_N); 370 | for (size_t i=0; i 376 | NVector& NVector::AddScaled(const NVector& V,const T& scale) 377 | { 378 | for (size_t i=0; i 384 | NVector& NVector::SubtractScaled(const NVector& V,const T& scale) 385 | { 386 | for (size_t i=0; i 392 | void NVector::Add(const NVector& V1,const T& scale1,const NVector& V2,const T& scale2,NVector& Out){ 393 | for (size_t i=0; i 397 | void NVector::Add(const NVector& V1,const T& scale1,const NVector& V2,NVector& Out){ 398 | for (size_t i=0; i 402 | NVector& NVector::operator += (const NVector& V) 403 | { 404 | for (size_t i=0; i 410 | NVector NVector::operator - (const NVector& V0) const 411 | { 412 | NVector V(m_N); 413 | for (size_t i=0; i 419 | NVector NVector::operator - (void) const 420 | { 421 | NVector V(m_N); 422 | 423 | for (size_t i=0; i 429 | NVector& NVector::operator -= (const NVector& V) 430 | { 431 | for (size_t i=0; i 437 | T NVector::Norm( size_t Ln ) const 438 | { 439 | T N = T(); 440 | for (size_t i = 0; i 445 | void NVector::Normalize() 446 | { 447 | T N = 1.0f/Norm(2); 448 | for (size_t i = 0; i 452 | T NVector::Length() const 453 | { 454 | T N = T(); 455 | for (size_t i = 0; i 460 | T NVector::Dot( const NVector& V ) const 461 | { 462 | T V0 = T(); 463 | for (size_t i=0; i 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #ifdef EIGEN_USE_MKL_ALL 38 | #include 39 | #endif // EIGEN_USE_MKL_ALL 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | #include 50 | #include 51 | 52 | using namespace MishaK; 53 | 54 | CmdLineParameter< std::string > 55 | In( "in" ) , 56 | Out( "out" ); 57 | 58 | CmdLineParameter< float > 59 | NormalSmoothingWeight( "nWeight" , 1e-4f ); 60 | 61 | CmdLineReadable 62 | Verbose( "verbose" ); 63 | 64 | CmdLineReadable* params[] = 65 | { 66 | &In , 67 | &Out , 68 | &NormalSmoothingWeight , 69 | &Verbose , 70 | NULL 71 | }; 72 | 73 | void ShowUsage( const char* ex ) 74 | { 75 | printf( "Usage %s:\n" , ex ); 76 | printf( "\t --%s \n" , In.name.c_str() ); 77 | printf( "\t[--%s ]\n" , Out.name.c_str() ); 78 | printf( "\t[--%s =%g]\n" , NormalSmoothingWeight.name.c_str() , NormalSmoothingWeight.value ); 79 | printf( "\t[--%s]\n" , Verbose.name.c_str() ); 80 | } 81 | 82 | #ifdef EIGEN_USE_MKL_ALL 83 | using Solver = Eigen::PardisoLLT< Eigen::SparseMatrix< double , Eigen::ColMajor , __int64 > >; 84 | #else // !EIGEN_USE_MKL_ALL 85 | using Solver = Eigen::SimplicialLLT< Eigen::SparseMatrix< double > >; 86 | #endif // EIGEN_USE_MKL_ALL 87 | 88 | enum{ VERTEX_POSITION , VERTEX_NORMAL , VERTEX_COLOR }; 89 | 90 | int main( int argc , char* argv[] ) 91 | { 92 | CmdLineParse( argc-1 , argv+1 , params ); 93 | if( !In.set ) 94 | { 95 | ShowUsage( argv[0] ); 96 | return EXIT_FAILURE; 97 | } 98 | 99 | static const unsigned int K = 2; 100 | static const unsigned int Dim = K+1; 101 | using Real = double; 102 | using Factory = VertexFactory::Factory< float , VertexFactory::PositionFactory< float , Dim > , VertexFactory::NormalFactory< float , Dim > , VertexFactory::RGBColorFactory< float > >; 103 | using Vertex = typename Factory::VertexType; 104 | 105 | Miscellany::Timer timer; 106 | { 107 | std::vector< SimplexIndex< K , int > > simplices; 108 | std::vector< Vertex > vertices; 109 | 110 | int file_type; 111 | 112 | Miscellany::PerformanceMeter pMeter( '.' ); 113 | 114 | ////////////////////// 115 | // Read in the data // 116 | pMeter.reset(); 117 | { 118 | Factory factory; 119 | bool *readFlags = new bool[ factory.plyReadNum() ]; 120 | file_type = PLY::ReadSimplices( In.value , factory , vertices , simplices , readFlags ); 121 | 122 | bool hasNormals = factory.template plyValidReadProperties< VERTEX_NORMAL >( readFlags ); 123 | 124 | // Create normals if they are not already there 125 | if( !hasNormals ) 126 | { 127 | for( int i=0 ; i() = Point< float , Dim >(); 128 | for( int i=0 ; i s; 131 | for( unsigned int k=0 ; k<=K ; k++ ) s[k] = vertices[ simplices[i][k] ].template get< VERTEX_POSITION >(); 132 | Point< float , Dim > n = s.normal(); 133 | for( int k=0 ; k<=K ; k++ ) vertices[ simplices[i][k] ].template get< VERTEX_NORMAL >() += n; 134 | } 135 | for( int i=0 ; i() /= Point< float , Dim >::Length( vertices[i].template get< VERTEX_NORMAL >() ); 136 | } 137 | delete[] readFlags; 138 | 139 | if( Verbose.set ) std::cout << "Source Vertices / Simplices: " << vertices.size() << " / " << simplices.size() << std::endl; 140 | } 141 | if( Verbose.set ) std::cout << pMeter( "Read mesh" ) << std::endl; 142 | // Read in the data // 143 | ////////////////////// 144 | 145 | ////////////////////////// 146 | // Set the Riemannian mesh 147 | pMeter.reset(); 148 | Real originalArea = 0; 149 | FEM::RiemannianMesh< Real > mesh( GetPointer( simplices ) , simplices.size() ); 150 | { 151 | // Create the embedded metric and normalize to have unit area 152 | mesh.template setMetricFromEmbedding< Dim >( [&]( unsigned int i ){ return vertices[i].template get< VERTEX_POSITION >(); } ); 153 | originalArea = mesh.area(); 154 | mesh.makeUnitArea(); 155 | } 156 | if( Verbose.set ) std::cout << pMeter( "Set Riemannian mesh" ) << std::endl; 157 | // Set the Riemannian mesh 158 | ////////////////////////// 159 | 160 | ///////////////////// 161 | // Smooth the normals 162 | if( NormalSmoothingWeight.value>0 ) 163 | { 164 | Solver solver; 165 | 166 | /////////////////////////////////////// 167 | // System matrix symbolic factorization 168 | { 169 | pMeter.reset(); 170 | solver.analyzePattern( mesh.template massMatrix< FEM::BASIS_0_WHITNEY , true >() ); 171 | if( Verbose.set ) std::cout << pMeter( "Symbolic factorization" ) << std::endl; 172 | } 173 | // System matrix symbolic factorization 174 | /////////////////////////////////////// 175 | 176 | std::vector< Point< Real , Dim > > normals( vertices.size() ); 177 | for( unsigned int i=0 ; i(); 178 | 179 | Miscellany::PerformanceMeter pMeter( '.' ); 180 | normals = GradientDomain::ProcessVertexVertex< Solver , Point< Real , Dim > , Real >( solver , mesh , (Real)1. , NormalSmoothingWeight.value , [&]( unsigned int v ){ return normals[v]; } , []( unsigned int ){ return Point< Real , Dim >(); } ); 181 | ThreadPool::ParallelFor 182 | ( 183 | 0 , normals.size() , 184 | [&]( unsigned int , size_t i ){ normals[i] /= Point< Real , Dim >::Length( normals[i] ); } 185 | ); 186 | for( unsigned int i=0 ; i() = normals[i]; 187 | if( Verbose.set ) std::cout << pMeter( "Normal smoothing" ) << std::endl; 188 | } 189 | // Smooth the normals 190 | ///////////////////// 191 | 192 | ///////////////////////// 193 | // Compute the curvatures 194 | { 195 | Miscellany::PerformanceMeter pMeter( '.' ); 196 | 197 | Real scl = (Real)(1./sqrt(originalArea) ); 198 | std::vector< ProjectiveData< Real , Real > > _simplcexCurvatures( simplices.size() ); 199 | ThreadPool::ParallelFor 200 | ( 201 | 0 , simplices.size() , 202 | [&]( unsigned int , size_t i ) 203 | { 204 | Simplex< Real , Dim , K > s; 205 | Point< Real , Dim > n[K+1]; 206 | Real curvatures[K]; 207 | for( unsigned int k=0 ; k<=K ; k++ ) s[k] = Point< Real , Dim >( vertices[ simplices[i][k] ].template get< VERTEX_POSITION >() ) * scl , n[k] = Point< Real , Dim > ( vertices[ simplices[i][k] ].template get< VERTEX_NORMAL >() ); 208 | CurvatureMetric::PrincipalCurvatures< Real , K >( s , n , curvatures ); 209 | 210 | Real area = s.measure() , kappa = 0; 211 | for( unsigned int k=0 ; k( kappa * area , area ); 214 | } 215 | ); 216 | 217 | if( Verbose.set ) std::cout << pMeter( "Computed curvatures" ) << std::endl; 218 | 219 | std::vector< ProjectiveData< Real , Real > > _vertexCurvatures( vertices.size() ); 220 | for( unsigned int i=0 ; i::infinity() , max = -std::numeric_limits< Real >::infinity(); 223 | { 224 | ProjectiveData< Real , Real > _variance; 225 | 226 | for( unsigned int i=0 ; i<_vertexCurvatures.size() ; i++ ) 227 | { 228 | Real k = _vertexCurvatures[i].value(); 229 | _variance += ProjectiveData< Real , Real >( k * k * _vertexCurvatures[i].weight , _vertexCurvatures[i].weight ); 230 | min = std::min< Real >( min , k ); 231 | max = std::max< Real >( max , k ); 232 | } 233 | sigma = (Real)sqrt( _variance.value() ); 234 | } 235 | if( Verbose.set ) std::cout << "Standard deviation: " << sigma << " : [ " << min << " , " << max << " ]" << std::endl; 236 | 237 | auto CurvatureToColor = [&]( Real kappa ) 238 | { 239 | Point< Real , 3 > clr; 240 | 241 | Real v = kappa / ( 2 * sigma ); 242 | v = std::min< Real >( (Real)1 , std::max< Real >( (Real)-1 , v ) ); 243 | 244 | clr = Point< Real , 3 >( (Real)1 , (Real)1 , (Real)1 ) * (1-v); 245 | return clr * 255; 246 | }; 247 | 248 | for( unsigned int i=0 ; i() = CurvatureToColor( _vertexCurvatures[i].value() ); 249 | } 250 | // Adjust the metric to take into account the curvature 251 | /////////////////////////////////////////////////////// 252 | 253 | //////////////////// 254 | // Output the result 255 | if( Out.set ) PLY::WriteSimplices( Out.value , Factory() , vertices , simplices , file_type ); 256 | // Output the result 257 | //////////////////// 258 | } 259 | if( Verbose.set ) std::cout << "Processed: " << timer() << std::endl; 260 | 261 | return EXIT_SUCCESS; 262 | } 263 | -------------------------------------------------------------------------------- /ShapeCurvature/ShapeCurvature.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Debug 10 | x64 11 | 12 | 13 | Release 14 | Win32 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8} 23 | Win32Proj 24 | ShapeCurvature 25 | 10.0 26 | 27 | 28 | 29 | Application 30 | true 31 | v143 32 | Unicode 33 | 34 | 35 | Application 36 | true 37 | v143 38 | Unicode 39 | 40 | 41 | Application 42 | false 43 | v143 44 | true 45 | Unicode 46 | 47 | 48 | Application 49 | false 50 | v143 51 | true 52 | Unicode 53 | No 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | true 73 | 74 | 75 | true 76 | 77 | 78 | false 79 | 80 | 81 | false 82 | $(SolutionDir)Bin\$(Platform)\ 83 | $(Platform)\$(Configuration)\$(ProjectName)\ 84 | 85 | 86 | 87 | 88 | 89 | Level3 90 | Disabled 91 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 92 | 93 | 94 | Console 95 | true 96 | 97 | 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 105 | 106 | 107 | Console 108 | true 109 | 110 | 111 | 112 | 113 | Level3 114 | 115 | 116 | MaxSpeed 117 | true 118 | true 119 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 120 | ..;C:\Research\Libraries\include; 121 | true 122 | 123 | 124 | Console 125 | true 126 | true 127 | true 128 | 129 | 130 | 131 | 132 | Level3 133 | 134 | 135 | MaxSpeed 136 | true 137 | true 138 | _CRT_SECURE_NO_WARNINGS;WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions) 139 | ..;%(AdditionalIncludeDirectories) 140 | true 141 | stdcpp20 142 | 143 | 144 | Console 145 | true 146 | true 147 | true 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | -------------------------------------------------------------------------------- /ShapeGradientDomain.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.11.35312.102 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShapeGradientDomain", "ShapeGradientDomain\ShapeGradientDomain.vcxproj", "{BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Include", "Include", "{0A8A5C24-2566-43F1-A6FF-4DF7E4C68A34}" 9 | ProjectSection(SolutionItems) = preProject 10 | Include\CurvatureMetric.h = Include\CurvatureMetric.h 11 | Include\GradientDomain.h = Include\GradientDomain.h 12 | Include\PreProcessor.h = Include\PreProcessor.h 13 | EndProjectSection 14 | EndProject 15 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Misha", "Misha", "{C7B71F77-27A2-4416-B807-9512F8A99829}" 16 | ProjectSection(SolutionItems) = preProject 17 | Misha\Algebra.h = Misha\Algebra.h 18 | Misha\Array.h = Misha\Array.h 19 | Misha\Array.inl = Misha\Array.inl 20 | Misha\Atomic.h = Misha\Atomic.h 21 | Misha\CmdLineParser.h = Misha\CmdLineParser.h 22 | Misha\CmdLineParser.inl = Misha\CmdLineParser.inl 23 | Misha\Exceptions.h = Misha\Exceptions.h 24 | Misha\FEM.h = Misha\FEM.h 25 | Misha\FEM.BasisInfo.inc = Misha\FEM.BasisInfo.inc 26 | Misha\FEM.inl = Misha\FEM.inl 27 | Misha\Geometry.h = Misha\Geometry.h 28 | Misha\Geometry.inl = Misha\Geometry.inl 29 | Misha\Miscellany.h = Misha\Miscellany.h 30 | Misha\MultiThreading.h = Misha\MultiThreading.h 31 | Misha\Ply.h = Misha\Ply.h 32 | Misha\Ply.inl = Misha\Ply.inl 33 | Misha\PlyFile.h = Misha\PlyFile.h 34 | Misha\PlyFile.inl = Misha\PlyFile.inl 35 | Misha\PlyVertexData.h = Misha\PlyVertexData.h 36 | Misha\PlyVertexData.inl = Misha\PlyVertexData.inl 37 | Misha\Poly34.h = Misha\Poly34.h 38 | Misha\Poly34.inl = Misha\Poly34.inl 39 | Misha\Polynomial.h = Misha\Polynomial.h 40 | Misha\Polynomial.inl = Misha\Polynomial.inl 41 | Misha\SparseMatrix.h = Misha\SparseMatrix.h 42 | Misha\SparseMatrix.inl = Misha\SparseMatrix.inl 43 | Misha\SparseMatrixInterface.h = Misha\SparseMatrixInterface.h 44 | Misha\SparseMatrixInterface.inl = Misha\SparseMatrixInterface.inl 45 | Misha\Vector.h = Misha\Vector.h 46 | Misha\Vector.inl = Misha\Vector.inl 47 | EndProjectSection 48 | EndProject 49 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ShapeCurvature", "ShapeCurvature\ShapeCurvature.vcxproj", "{92543D37-6A33-4F5F-8BC1-19F73B7077B8}" 50 | EndProject 51 | Global 52 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 53 | Debug|Mixed Platforms = Debug|Mixed Platforms 54 | Debug|Win32 = Debug|Win32 55 | Debug|x64 = Debug|x64 56 | Release|Mixed Platforms = Release|Mixed Platforms 57 | Release|Win32 = Release|Win32 58 | Release|x64 = Release|x64 59 | EndGlobalSection 60 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 61 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 62 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Debug|Mixed Platforms.Build.0 = Debug|Win32 63 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Debug|Win32.ActiveCfg = Debug|Win32 64 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Debug|Win32.Build.0 = Debug|Win32 65 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Debug|x64.ActiveCfg = Debug|x64 66 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Debug|x64.Build.0 = Debug|x64 67 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Release|Mixed Platforms.ActiveCfg = Release|Win32 68 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Release|Mixed Platforms.Build.0 = Release|Win32 69 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Release|Win32.ActiveCfg = Release|Win32 70 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Release|Win32.Build.0 = Release|Win32 71 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Release|x64.ActiveCfg = Release|x64 72 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B}.Release|x64.Build.0 = Release|x64 73 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Debug|Mixed Platforms.ActiveCfg = Debug|x64 74 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Debug|Mixed Platforms.Build.0 = Debug|x64 75 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Debug|Win32.ActiveCfg = Debug|Win32 76 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Debug|Win32.Build.0 = Debug|Win32 77 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Debug|x64.ActiveCfg = Debug|x64 78 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Debug|x64.Build.0 = Debug|x64 79 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Release|Mixed Platforms.ActiveCfg = Release|x64 80 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Release|Mixed Platforms.Build.0 = Release|x64 81 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Release|Win32.ActiveCfg = Release|Win32 82 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Release|Win32.Build.0 = Release|Win32 83 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Release|x64.ActiveCfg = Release|x64 84 | {92543D37-6A33-4F5F-8BC1-19F73B7077B8}.Release|x64.Build.0 = Release|x64 85 | EndGlobalSection 86 | GlobalSection(SolutionProperties) = preSolution 87 | HideSolutionNode = FALSE 88 | EndGlobalSection 89 | GlobalSection(ExtensibilityGlobals) = postSolution 90 | SolutionGuid = {7C75CE27-BE90-41AA-8708-6E1AD19B5D53} 91 | EndGlobalSection 92 | EndGlobal 93 | -------------------------------------------------------------------------------- /ShapeGradientDomain/ShapeGradientDomain.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2016, Michael Kazhdan 3 | All rights reserved. 4 | 5 | Redistribution and use in source and binary forms, with or without modification, 6 | are permitted provided that the following conditions are met: 7 | 8 | Redistributions of source code must retain the above copyright notice, this list of 9 | conditions and the following disclaimer. Redistributions in binary form must reproduce 10 | the above copyright notice, this list of conditions and the following disclaimer 11 | in the documentation and/or other materials provided with the distribution. 12 | 13 | Neither the name of the Johns Hopkins University nor the names of its contributors 14 | may be used to endorse or promote products derived from this software without specific 15 | prior written permission. 16 | 17 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 18 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES 19 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 20 | SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 21 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 22 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 23 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 | ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH 26 | DAMAGE. 27 | */ 28 | 29 | #include 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include 37 | #ifdef EIGEN_USE_MKL_ALL 38 | #include 39 | #endif // EIGEN_USE_MKL_ALL 40 | 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | 49 | #include 50 | #include 51 | 52 | using namespace MishaK; 53 | 54 | enum struct SignalType 55 | { 56 | POSITION , 57 | NORMAL , 58 | COLOR , 59 | NORMAL_TO_POSITION , 60 | COUNT 61 | }; 62 | const std::string SignalNames[] = { std::string( "position" ) , std::string( "normal" ) , std::string( "color" ) , std::string( "normal to position" ) }; 63 | 64 | CmdLineParameter< std::string > 65 | In( "in" ) , 66 | Out( "out" ); 67 | 68 | CmdLineParameter< float > 69 | CurvatureWeight( "kWeight" , 0.f ) , 70 | NormalSmoothingWeight( "nWeight" , 1e-4f ) , 71 | GradientWeight( "gWeight" , 1e-4f ) , 72 | GradientScale( "gScale" , 1.f ) , 73 | NormalProjectionWeight( "npWeight" , 1e2f ); 74 | 75 | CmdLineParameter< int > 76 | Signal( "signal" , static_cast< int >( SignalType::POSITION ) ); 77 | 78 | CmdLineReadable 79 | Anisotropic( "anisotropic" ) , 80 | Verbose( "verbose" ); 81 | 82 | CmdLineReadable* params[] = 83 | { 84 | &In , 85 | &Out , 86 | &GradientWeight , 87 | &GradientScale , 88 | &NormalProjectionWeight , 89 | &Anisotropic , 90 | &Signal , 91 | &CurvatureWeight , 92 | &NormalSmoothingWeight , 93 | &Verbose , 94 | NULL 95 | }; 96 | 97 | void ShowUsage( const char* ex ) 98 | { 99 | printf( "Usage %s:\n" , ex ); 100 | printf( "\t --%s \n" , In.name.c_str() ); 101 | printf( "\t[--%s ]\n" , Out.name.c_str() ); 102 | printf( "\t[--%s =%g]\n" , NormalSmoothingWeight.name.c_str() , NormalSmoothingWeight.value ); 103 | printf( "\t[--%s =%g]\n" , GradientWeight.name.c_str() , GradientWeight.value ); 104 | printf( "\t[--%s =%g]\n" , GradientScale.name.c_str() , GradientScale.value ); 105 | printf( "\t[--%s =%f]\n" , CurvatureWeight.name.c_str() , CurvatureWeight.value ); 106 | printf( "\t[--%s =%g]\n" , NormalProjectionWeight.name.c_str() , NormalProjectionWeight.value ); 107 | printf( "\t[--%s =%d]\n" , Signal.name.c_str() , Signal.value ); 108 | for( int i=0 ; i( SignalType::COUNT ) ; i++ ) printf( "\t\t%d] %s\n" , i , SignalNames[i].c_str() ); 109 | printf( "\t[--%s]\n" , Anisotropic.name.c_str() ); 110 | printf( "\t[--%s]\n" , Verbose.name.c_str() ); 111 | } 112 | 113 | #ifdef EIGEN_USE_MKL_ALL 114 | using Solver = Eigen::PardisoLLT< Eigen::SparseMatrix< double , Eigen::ColMajor , __int64 > >; 115 | #else // !EIGEN_USE_MKL_ALL 116 | using Solver = Eigen::SimplicialLLT< Eigen::SparseMatrix< double > >; 117 | #endif // EIGEN_USE_MKL_ALL 118 | 119 | enum{ VERTEX_POSITION , VERTEX_NORMAL , VERTEX_COLOR }; 120 | 121 | using Factory = VertexFactory::Factory< float , VertexFactory::PositionFactory< float , 3 > , VertexFactory::NormalFactory< float , 3 > , VertexFactory::RGBColorFactory< float > >; 122 | using Vertex = typename Factory::VertexType; 123 | 124 | 125 | template< bool HasNormals , bool HasColors > struct OutPLY; 126 | 127 | template<> 128 | struct OutPLY< true , true > 129 | { 130 | static const unsigned int NormalIndex = 1 , ColorIndex = 1; 131 | using Factory = VertexFactory::Factory< float , VertexFactory::PositionFactory< float , 3 > , VertexFactory::NormalFactory< float , 3 > , VertexFactory::RGBColorFactory< float > >; 132 | }; 133 | 134 | template<> 135 | struct OutPLY< true , false > 136 | { 137 | static const unsigned int NormalIndex = 1 , ColorIndex = -1; 138 | using Factory = VertexFactory::Factory< float , VertexFactory::PositionFactory< float , 3 > , VertexFactory::NormalFactory< float , 3 > >; 139 | }; 140 | 141 | template<> 142 | struct OutPLY< false , true > 143 | { 144 | static const unsigned int NormalIndex = -1 , ColorIndex = 1; 145 | using Factory = VertexFactory::Factory< float , VertexFactory::PositionFactory< float , 3 > , VertexFactory::RGBColorFactory< float > >; 146 | }; 147 | 148 | template<> 149 | struct OutPLY< false , false > 150 | { 151 | static const unsigned int NormalIndex = -1 , ColorIndex = -1; 152 | using Factory = VertexFactory::Factory< float , VertexFactory::PositionFactory< float , 3 > >; 153 | }; 154 | 155 | template< bool HasNormals , bool HasColors > 156 | void WriteMesh( std::string fileName , const std::vector< Vertex > &vertices , const std::vector< TriangleIndex > &triangles , int file_type ) 157 | { 158 | using OutFactory = typename OutPLY< HasNormals , HasColors >::Factory; 159 | using OutVertex = typename OutFactory::VertexType; 160 | static const unsigned int NormalIndex = OutPLY< HasNormals , HasColors >::NormalIndex; 161 | static const unsigned int ColorIndex = OutPLY< HasNormals , HasColors >::ColorIndex; 162 | 163 | std::vector< OutVertex > outVertices( vertices.size() ); 164 | for( unsigned int i=0 ; i() = vertices[i].template get< VERTEX_POSITION >(); 167 | if constexpr( HasNormals ) outVertices[i].template get< NormalIndex >() = vertices[i].template get< VERTEX_NORMAL >(); 168 | if constexpr( HasColors ) outVertices[i].template get< ColorIndex >() = vertices[i].template get< VERTEX_COLOR >(); 169 | } 170 | PLY::WriteTriangles( fileName , OutFactory() , outVertices , triangles , file_type ); 171 | } 172 | 173 | template< class Real > 174 | int _main( void ) 175 | { 176 | std::vector< TriangleIndex > triangles; 177 | std::vector< Vertex > vertices; 178 | 179 | int file_type; 180 | bool hasNormals , hasColors; 181 | 182 | Solver solver; 183 | 184 | Miscellany::PerformanceMeter pMeter( '.' ); 185 | 186 | ////////////////////// 187 | // Read in the data // 188 | pMeter.reset(); 189 | { 190 | Factory factory; 191 | bool *readFlags = new bool[ factory.plyReadNum() ]; 192 | file_type = PLY::ReadTriangles( In.value , factory , vertices , triangles , readFlags ); 193 | 194 | hasNormals = factory.template plyValidReadProperties< VERTEX_NORMAL >( readFlags ); 195 | hasColors = factory.template plyValidReadProperties< VERTEX_COLOR >( readFlags ); 196 | 197 | // Create normals if they are not already there 198 | if( !hasNormals ) 199 | { 200 | for( int i=0 ; i() = Point3D< float >(); 201 | for( int i=0 ; i n = Point3D< float >::CrossProduct( vertices[ triangles[i][1] ].template get< VERTEX_POSITION >() - vertices[ triangles[i][0] ].template get< VERTEX_POSITION >() , vertices[ triangles[i][2] ].template get< VERTEX_POSITION >() - vertices[ triangles[i][0] ].template get< VERTEX_POSITION >() ); 204 | for( int j=0 ; j<3 ; j++ ) vertices[ triangles[i][j] ].template get< VERTEX_NORMAL >() += n; 205 | } 206 | for( int i=0 ; i() /= Point< float , 3 >::Length( vertices[i].template get<1>() ); 207 | } 208 | 209 | if( SignalType( Signal.value )==SignalType::NORMAL ) hasNormals = true; 210 | if( SignalType( Signal.value )==SignalType::COLOR && !hasColors ) MK_ERROR_OUT( "No color channel specified" ); 211 | delete[] readFlags; 212 | if( Verbose.set ) std::cout << "Source Vertices / Triangles: " << vertices.size() << " / " << triangles.size() << std::endl; 213 | } 214 | if( Verbose.set ) std::cout << pMeter( "Read mesh" ) << std::endl; 215 | // Read in the data // 216 | ////////////////////// 217 | 218 | ////////////////////////// 219 | // Set the Riemannian mesh 220 | pMeter.reset(); 221 | Real originalArea = 0; 222 | FEM::RiemannianMesh< Real > mesh( GetPointer( triangles ) , triangles.size() ); 223 | { 224 | // Create the embedded metric and normalize to have unit are 225 | mesh.template setMetricFromEmbedding< 3 >( [&]( unsigned int i ){ return vertices[i].template get<0>(); } ); 226 | originalArea = mesh.area(); 227 | mesh.makeUnitArea(); 228 | } 229 | if( Verbose.set ) std::cout << pMeter( "Set Riemannian mesh" ) << std::endl; 230 | // Set the Riemannian mesh 231 | ////////////////////////// 232 | 233 | /////////////////////////////////////// 234 | // System matrix symbolic factorization 235 | pMeter.reset(); 236 | solver.analyzePattern( mesh.template stiffnessMatrix< FEM::BASIS_0_WHITNEY , true >() ); 237 | if( Verbose.set ) std::cout << pMeter( "Symbolic factorization" ) << std::endl; 238 | // System matrix symbolic factorization 239 | /////////////////////////////////////// 240 | 241 | /////////////////////////////////////////////////////// 242 | // Adjust the metric to take into account the curvature 243 | if( CurvatureWeight.value>0 ) 244 | { 245 | pMeter.reset(); 246 | std::vector< Point< Real , 3 > > curvatureNormals( vertices.size() ); 247 | for( unsigned int i=0 ; i(); 248 | 249 | /////////////////// 250 | // Normal smoothing 251 | if( NormalSmoothingWeight.value>0 ) 252 | { 253 | Miscellany::PerformanceMeter pMeter( '.' ); 254 | curvatureNormals = GradientDomain::ProcessVertexVertex< Solver , Point3D< Real > , Real >( solver , mesh , (Real)1. , NormalSmoothingWeight.value , [&]( unsigned int v ){ return curvatureNormals[v]; } , []( unsigned int ){ return Point< Real , 3 >(); } ); 255 | ThreadPool::ParallelFor 256 | ( 257 | 0 , curvatureNormals.size() , 258 | [&]( unsigned int , size_t i ){ curvatureNormals[i] /= Point< Real , 3 >::Length( curvatureNormals[i] ); } 259 | ); 260 | if( Verbose.set ) std::cout << pMeter( "Normal smoothing" ) << std::endl; 261 | } 262 | // Normal smoothing 263 | /////////////////// 264 | 265 | { 266 | Miscellany::PerformanceMeter pMeter( '.' ); 267 | 268 | // Input: Principal curvature values 269 | // Output: Positive entries of the diagonal matrix describing the scaling along the principal curvature directions 270 | // Outputting the identity matrix reproduces the embedding metric 271 | auto PrincipalCurvatureFunctor = [&]( unsigned int , Point< Real , 2 > pCurvatures ) 272 | { 273 | pCurvatures[0] *= pCurvatures[0]; 274 | pCurvatures[1] *= pCurvatures[1]; 275 | if( !Anisotropic.set ) pCurvatures[0] = pCurvatures[1] = ( pCurvatures[0] + pCurvatures[1] ) / (Real)2.; 276 | return Point< Real , 2 >( (Real)1. , (Real)1. ) + pCurvatures * static_cast< Real >( CurvatureWeight.value ); 277 | }; 278 | 279 | Real scl = static_cast< Real >( 1./sqrt(originalArea) ); 280 | CurvatureMetric::SetCurvatureMetric 281 | ( 282 | mesh , 283 | [&vertices,scl]( unsigned int idx ){ return Point< Real , 3 >( vertices[idx].template get< VERTEX_POSITION >() ) * scl; } , 284 | // [&]( unsigned int idx ){ return Point< Real , 3 >( vertices[idx].template get< VERTEX_POSITION >() ) * scl; } , 285 | [&]( unsigned int idx ){ return Point< Real , 3 >( curvatureNormals[idx] ); } , 286 | PrincipalCurvatureFunctor 287 | ); 288 | if( Verbose.set ) std::cout << pMeter( "Metric update" ) << std::endl; 289 | } 290 | if( Verbose.set ) std::cout << pMeter( "Adjusted metric" ) << std::endl; 291 | } 292 | // Adjust the metric to take into account the curvature 293 | /////////////////////////////////////////////////////// 294 | 295 | 296 | /////////////// 297 | // Set the data 298 | std::vector< Point3D< Real > > signal( vertices.size() ); 299 | switch( SignalType( Signal.value ) ) 300 | { 301 | case SignalType::POSITION: for( int i=0 ; i( vertices[i].template get< VERTEX_POSITION >() ) ; break; 302 | case SignalType::NORMAL_TO_POSITION: 303 | case SignalType::NORMAL : for( int i=0 ; i( vertices[i].template get< VERTEX_NORMAL >() ) ; break; 304 | case SignalType::COLOR : for( int i=0 ; i( vertices[i].template get< VERTEX_COLOR >() ) ; break; 305 | default: MK_ERROR_OUT( "Unrecognized signal type: " , Signal.value ); 306 | } 307 | // Set the data 308 | /////////////// 309 | 310 | //////////////////// 311 | // Smooth the signal 312 | if( GradientWeight.value>0 && GradientScale.value!=1 ) 313 | { 314 | pMeter.reset(); 315 | { 316 | // Low frequencies described in terms of values at vertices 317 | auto LowFrequencyVertexValues = [&]( unsigned int v ){ return signal[v]; }; 318 | 319 | // High frequencies described in terms of scaled values at vertices 320 | auto HighFrequencyVertexValues = [&]( unsigned int v ){ return signal[v]*(Real)GradientScale.value; }; 321 | 322 | signal = GradientDomain::ProcessVertexVertex< Solver , Point3D< Real > , Real >( solver , mesh , (Real)1. , (Real)GradientWeight.value , LowFrequencyVertexValues , HighFrequencyVertexValues ); 323 | } 324 | if( Verbose.set ) std::cout << pMeter( "Processed" ) << std::endl; 325 | } 326 | // Smooth the signal 327 | //////////////////// 328 | 329 | ////////////////////////////////// 330 | // Fit the geometry to the normals 331 | if( SignalType( Signal.value )==SignalType::NORMAL_TO_POSITION ) 332 | { 333 | pMeter.reset(); 334 | signal = GradientDomain::FitToNormals< Solver >( solver , mesh , (Real)1. , (Real)NormalProjectionWeight.value , [&]( unsigned int v ){ return vertices[v].template get< VERTEX_POSITION >(); } , [&]( unsigned int v ){ return signal[v]; } ); 335 | if( Verbose.set ) std::cout << pMeter( "Fit geometry" ) << std::endl; 336 | } 337 | // Fit the geometry to the normals 338 | ////////////////////////////////// 339 | 340 | //////////////////////////////////////////// 341 | // Copy the processed signal into the vertices 342 | switch( SignalType( Signal.value ) ) 343 | { 344 | case SignalType::NORMAL_TO_POSITION: 345 | case SignalType::POSITION: for( int i=0 ; i() = Point3D< float >( signal[i] ) ; break; 346 | case SignalType::NORMAL : for( int i=0 ; i() = Point3D< float >( signal[i] ) ; break; 347 | case SignalType::COLOR : for( int i=0 ; i() = Point3D< float >( signal[i] ) ; break; 348 | default: MK_ERROR_OUT( "Unrecognized singal type: " , Signal.value ); 349 | } 350 | // Copy the processed signal to the vertices 351 | //////////////////////////////////////////// 352 | 353 | //////////////////// 354 | // Output the result 355 | if( Out.set ) 356 | { 357 | if( hasColors && hasNormals ) WriteMesh< true , true >( Out.value , vertices , triangles , file_type ); 358 | else if( hasColors ) WriteMesh< false , true >( Out.value , vertices , triangles , file_type ); 359 | else if( hasNormals ) WriteMesh< true , false >( Out.value , vertices , triangles , file_type ); 360 | else WriteMesh< false , false >( Out.value , vertices , triangles , file_type ); 361 | } 362 | // Output the result 363 | //////////////////// 364 | return EXIT_SUCCESS; 365 | } 366 | 367 | int main( int argc , char* argv[] ) 368 | { 369 | CmdLineParse( argc-1 , argv+1 , params ); 370 | if( !In.set ) 371 | { 372 | ShowUsage( argv[0] ); 373 | return EXIT_FAILURE; 374 | } 375 | 376 | Miscellany::Timer timer; 377 | _main< double >(); 378 | if( Verbose.set ) std::cout << "Processed: " << timer() << std::endl; 379 | 380 | return EXIT_SUCCESS; 381 | } 382 | -------------------------------------------------------------------------------- /ShapeGradientDomain/ShapeGradientDomain.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 23 | 24 | 25 | {BC0EC73C-2206-4CC4-AA9C-6E3A0BF2A37B} 26 | Win32Proj 27 | ShapeGradientDomainEigen 28 | 10.0 29 | ShapeGradientDomain 30 | 31 | 32 | 33 | Application 34 | true 35 | v143 36 | Unicode 37 | 38 | 39 | Application 40 | false 41 | v143 42 | true 43 | Unicode 44 | 45 | 46 | Application 47 | true 48 | v143 49 | Unicode 50 | 51 | 52 | Application 53 | false 54 | v143 55 | true 56 | Unicode 57 | No 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | true 79 | 80 | 81 | true 82 | 83 | 84 | false 85 | 86 | 87 | false 88 | $(Platform)\$(Configuration)\$(ProjectName)\ 89 | $(SolutionDir)Bin\$(Platform)\ 90 | 91 | 92 | 93 | 94 | 95 | Level3 96 | Disabled 97 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 98 | 99 | 100 | Console 101 | true 102 | 103 | 104 | 105 | 106 | 107 | 108 | Level3 109 | Disabled 110 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 111 | 112 | 113 | Console 114 | true 115 | 116 | 117 | 118 | 119 | Level3 120 | 121 | 122 | MaxSpeed 123 | true 124 | true 125 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 126 | 127 | 128 | Console 129 | true 130 | true 131 | true 132 | 133 | 134 | 135 | 136 | Level3 137 | 138 | 139 | MaxSpeed 140 | true 141 | true 142 | USE_EIGEN;_CRT_SECURE_NO_WARNINGS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 143 | ..;%(AdditionalIncludeDirectories) 144 | true 145 | /FS %(AdditionalOptions) 146 | stdcpp17 147 | 148 | 149 | Console 150 | true 151 | true 152 | true 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | -------------------------------------------------------------------------------- /armadillo.curvature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkazhdan/ShapeGradientDomain/5cec06855b05bd25b0bfa8f88f205b719cf44a31/armadillo.curvature.png -------------------------------------------------------------------------------- /armadillo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mkazhdan/ShapeGradientDomain/5cec06855b05bd25b0bfa8f88f205b719cf44a31/armadillo.png --------------------------------------------------------------------------------