diff --git a/.gitignore b/.gitignore index b8bd026..fbe53f3 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ *.exe *.out *.app + +bin/* diff --git a/.travis.yml b/.travis.yml index ff130bd..210700f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,12 @@ -sudo: false language: cpp + notifications: - email: false + slack: sciinstitute:lZnpQQXNd4Io5iGDPQDpJmI1 + compiler: - gcc - clang -#before_cache: + cache: directories: - $HOME/deps @@ -14,13 +15,10 @@ before_install: - if [ ! -d $HOME/deps ]; then mkdir $HOME/deps; fi - if [ ! -f $HOME/deps/tetgen1.4.3.tar.gz ]; then wget --quiet --directory-prefix=$HOME/deps http://tetgen.org/files/tetgen1.4.3.tar.gz; fi - if [ ! -f $HOME/deps/tetgen_cmake.tgz ]; then wget --quiet --directory-prefix=$HOME/deps http://www.sci.utah.edu/devbuilds/seg3d/tetgen_cmake.tgz; fi - - if [ ! -f $HOME/deps/release-1.7.0.tar.gz ]; then wget --quiet --directory-prefix=$HOME/deps https://github.com/google/googletest/archive/release-1.7.0.tar.gz; fi + - if [ ! -f $HOME/deps/release-1.10.0.tar.gz ]; then wget --quiet --directory-prefix=$HOME/deps https://github.com/google/googletest/archive/release-1.10.0.tar.gz; fi - if [ ! -f $HOME/deps/3.2.10.tar.gz ]; then wget --quiet --directory-prefix=$HOME/deps http://bitbucket.org/eigen/eigen/get/3.2.10.tar.gz; fi - pip install --user cpp-coveralls - ls $HOME/deps -install: - # C++11 support required - - if [ "$CXX" = "g++" ]; then export CXX="g++-4.8" CC="gcc-4.8"; fi addons: apt: sources: @@ -29,10 +27,6 @@ addons: packages: - cmake - cmake-data - - gcc-4.8 - - g++-4.8 - - clang -#before_script: script: # build Tetgen dependency - mkdir build @@ -43,26 +37,25 @@ script: - tar xzf $HOME/deps/tetgen_cmake.tgz - popd # build Googletest dependency - - tar xzf $HOME/deps/release-1.7.0.tar.gz - - pushd googletest-release-1.7.0 + - tar xzf $HOME/deps/release-1.10.0.tar.gz + - pushd googletest-release-1.10.0 - mkdir build - cd build - cmake .. - - make -j4 + - make -j4 CXXFLAGS:=$(CXXFLAGS) -lpthread -lm - popd # untar Eigen dependency (no build needed) - tar xzf $HOME/deps/3.2.10.tar.gz # build ImplicitFunction library - cmake -DBUILD_TESTING:BOOL=ON -DENABLE_COVERAGE:BOOL=ON -DTravisCI_BUILD:BOOL=ON - -DGTEST_INCLUDE_DIR:PATH=`pwd`/googletest-release-1.7.0/include - -DGTEST_LIBRARY:FILEPATH=`pwd`/googletest-release-1.7.0/build/libgtest.a - -DGTEST_MAIN_LIBRARY:FILEPATH=`pwd`/googletest-release-1.7.0/build/libgtest_main.a + -DGTEST_INCLUDE_DIR:PATH=`pwd`/googletest-release-1.10.0/googletest/include + -DGTEST_LIBRARY:FILEPATH=`pwd`/googletest-release-1.10.0/build/lib/libgtest.a + -DGTEST_MAIN_LIBRARY:FILEPATH=`pwd`/googletest-release-1.10.0/build/lib/libgtest_main.a -DTetgen_DIR:PATH=`pwd`/tetgen1.4.3 -DEIGEN3_INSTALL_DIR:PATH=`pwd`/eigen-eigen-b9cd8366d4e8 .. - - make -j4 + - make -j4 CXXFLAGS:=$(CXXFLAGS) -lpthread -lm - ./ImplicitFunction_Tests -#after_failure: + after_success: - cd $TRAVIS_BUILD_DIR - coveralls --exclude build --exclude Tests --gcov-options '\-lp' -#after_script: diff --git a/CMakeLists.txt b/CMakeLists.txt index 23417a1..39a6a59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE # USE OR OTHER DEALINGS IN THE SOFTWARE. -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.5) project(ImplicitFunction) diff --git a/ETSP.cpp b/ETSP.cpp index a1fa645..3320065 100644 --- a/ETSP.cpp +++ b/ETSP.cpp @@ -102,7 +102,7 @@ void ETSP::MST() graph[toAdd].push_back(i+j-toAdd); graph[i+j-toAdd].push_back(toAdd); - + } } @@ -119,14 +119,14 @@ vector ETSP::match() bestMatch.push_back(i); } } - + //for(int i=0; i0) { double best=1e10; - do + do { double curr = 0; for(int i=0; i visited; visited.resize(data.size(),false); - int curr=0; inverse_mapped_order.resize(data.size()); traverse(0, visited); /*for(int i=0; i( this->data_->fnc_.size() ); #ifndef NDEBUG @@ -329,27 +328,27 @@ void RBF::fmmBuildTree(vector &myPoints, BHNode *myNode) //printf("[%lf %lf %lf] [%lf %lf %lf] %d\n", myNode->box_.min_[0], myNode->box_.min_[1], myNode->box_.min_[2], myNode->box_.max_[0], myNode->box_.max_[1], myNode->box_.max_[2], myPoints.size()); vector children[8]; const int N = myPoints.size(); - + myNode->index_ = fmm_->numOfNodes; fmm_->numOfNodes += 1; fmm_->nodePointer.push_back(myNode); - + myNode->mass_ = N; myNode->leaf_ = (N <= 1) ? true : false; myNode->center_ = vec3::zero; - + myNode->coeff_ = 1; //REPLACE //add all the coefficients - + for (int i = 0; i < N; i++) myNode->pts_.push_back( myPoints[i] ); - + for (int i = 0; i < N; i++) { vec3 location(this->data_->surfacePoints_[0][myPoints[i]], this->data_->surfacePoints_[1][myPoints[i]], this->data_->surfacePoints_[2][myPoints[i]]); myNode->center_ = myNode->center_ + (location/N); } - + if (N == 1) { for (int i = 0; i < 8; i++) @@ -377,9 +376,9 @@ void RBF::fmmBuildTree(vector &myPoints, BHNode *myNode) octant += 2; if (this->data_->surfacePoints_[2][myPoints[i]] > mid[2]) octant += 4; - + //printf("%d %d %d %lf %lf %lf\n", i,octant, myPoints[i], this->data_->surfacePoints_[0][myPoints[i]],this->data_->surfacePoints_[1][myPoints[i]], this->data_->surfacePoints_[2][myPoints[i]]); - + children[octant].push_back(myPoints[i]); } @@ -453,6 +452,6 @@ double RBF::fmmComputeValueRecurse(const vec3& x, BHNode *myNode) double RBF::fmmComputeKernel(const vec3& b, BHNode *myNode) { double r = length(myNode->center_ - b); - + return computeRadialFunction(r); -} \ No newline at end of file +} diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt index ee9ed94..4b5faf8 100644 --- a/Tests/CMakeLists.txt +++ b/Tests/CMakeLists.txt @@ -23,10 +23,11 @@ set(ImplicitFunction_Tests_SRCS ConvexHull2DTests.cpp ConvexHull3DTests.cpp -# RBFTests.cpp + RBFTests.cpp RBFInterfaceTests.cpp ScatteredDataTests.cpp Vec3Tests.cpp + Seg3DIntegrationTest.cpp ) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ImplicitFunction_BINARY_DIR}) @@ -47,3 +48,9 @@ target_link_libraries(ImplicitFunction_Tests ${GTEST_LIBRARY} ${GTEST_MAIN_LIBRARY} ) + +IF(UNIX) + TARGET_LINK_LIBRARIES(ImplicitFunction_Tests -lpthread -lm) +ENDIF() + +ADD_TEST("ImplicitFunction_Tests" ${ImplicitFunction_BINARY_DIR}/ImplicitFunction_Tests) diff --git a/Tests/RBFInterfaceTests.cpp b/Tests/RBFInterfaceTests.cpp index a94581c..d12ff81 100644 --- a/Tests/RBFInterfaceTests.cpp +++ b/Tests/RBFInterfaceTests.cpp @@ -91,7 +91,7 @@ TEST_F(RBFInterfaceTest, BasicInterfaceTestThinPlate) std::string line; std::getline(in, line); //std::cerr << line << " vs " << rasterData[i][j][k] << std::endl; - double d = std::stod(line); + //double d = std::stod(line); } } } @@ -124,7 +124,7 @@ TEST_F(RBFInterfaceTest, BasicInterfaceTestGaussian) std::string line; std::getline(in, line); //std::cerr << line << " vs " << rasterData[i][j][k] << std::endl; - double d = std::stod(line); + //double d = std::stod(line); } } } @@ -157,9 +157,9 @@ TEST_F(RBFInterfaceTest, BasicInterfaceTestMultiQuad) std::string line; std::getline(in, line); //std::cerr << line << " vs " << rasterData[i][j][k] << std::endl; - double d = std::stod(line); + //double d = std::stod(line); } } } in.close(); -} \ No newline at end of file +} diff --git a/Tests/RBFTests.cpp b/Tests/RBFTests.cpp index 2d949fa..d470ebf 100644 --- a/Tests/RBFTests.cpp +++ b/Tests/RBFTests.cpp @@ -44,19 +44,14 @@ class RBFTest : public ::testing::Test func10.insert(func10.begin(), 10, 0); axisInfo10.insert(axisInfo10.begin(), 10, axis_t::Z); - data = new ScatteredData( xCoords10, yCoords10, zCoords10, func10, axisInfo10 ); + data.reset(new ScatteredData( xCoords10, yCoords10, zCoords10, func10, axisInfo10 )); } - virtual void TearDown() - { - delete data; - } - - ScatteredData *data; + std::unique_ptr data; }; TEST_F(RBFTest, BasicSetup) { // TODO: need to expose getters to test RBF state - RBF rbf(data, ThinPlate); -} \ No newline at end of file + RBF rbf(data.get(), ThinPlate); +} diff --git a/Tests/Seg3DIntegrationTest.cpp b/Tests/Seg3DIntegrationTest.cpp new file mode 100644 index 0000000..4e95d0f --- /dev/null +++ b/Tests/Seg3DIntegrationTest.cpp @@ -0,0 +1,133 @@ +//------------------------------------------------------------------- +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files ( the "Software" ), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall +// be included in all copies or substantial portions of the +// Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +// KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE +// USE OR OTHER DEALINGS IN THE SOFTWARE. +//------------------------------------------------------------------- +//------------------------------------------------------------------- + +#include + +#include +#include +#include + +#include "RBFInterface.h" +#include "vec3.h" + +typedef std::vector< std::string > ViewModeList; + +class Seg3DIntegrationTest : public ::testing::Test +{ +protected: + virtual void SetUp() + { + view_modes_.assign(modelPointData.size(), "axial"); + + for ( const auto& mode : view_modes_ ) + { + if ( mode == "sagittal" ) // X + { + axisData_.push_back(axis_t::X); + } + else if (mode == "coronal" ) // Y + { + axisData_.push_back(axis_t::Y); + } + else if ( mode == "axial" ) // Z + { + axisData_.push_back(axis_t::Z); + } + else + { + throw "Invalid viewer mode"; + } + } + } + + //TODO: loop this [0,20] + double normalOffset_ {2.0}; + //TODO: loop over these bools + bool compute2DConvexHull_ {false}, invertSeedOrder_ {false}; + //TODO: loop over kernels + //enum Kernel { Gaussian, ThinPlate, MultiQuadratic }; + Kernel kernel_ {ThinPlate}; + + std::vector modelPointData = { + {329.27408562074709, -3.1975149796730840, 477.29595999999998 } + , {312.11090641613799, -17.909120331180826, 477.29595999999998 } + , {311.62052986743487, -40.630377485176155, 477.29595999999998 } + , {324.86069668241902, -53.707360019849709, 477.29595999999998 } + , {326.65874402766383, -46.515019625779246, 477.29595999999998 } + , {324.69723783285133, -25.918772133668394, 477.29595999999998 } + , {311.78398871700256, -39.486141513392205, 478.19439699999998 } + , {313.09165951354419, -19.380280866331621, 478.19439699999998 } + , {330.58175641728877, -4.6686755148238497, 478.19439699999998 } + , {325.35107323112214, -25.264923006934715, 478.19439699999998 } + , {326.65874402766383, -44.880396808945051, 478.19439699999998 } + , {323.71648473544508, -53.543897738166287, 478.19439699999998 } + , {329.92792101901790, -5.8129114866077956, 479.09283399999998 } + , {313.90895376138275, -21.341828246532643, 479.09283399999998 } + , {313.58203606224731, -36.707282724774082, 479.09283399999998 } + , {323.71648473544508, -49.784265259447636, 479.09283399999998 } + , {326.82220287723152, -43.409236273794278, 479.09283399999998 } + , {324.86069668241902, -25.918772133668394, 479.09283399999998 } + }; + + ViewModeList view_modes_; + std::vector axisData_; + + vec3 modelOrigin_ {229.25999999999999, -126.41900000000000, 405.42099999999999 }; + vec3 modelGridSize_ {160.00000000000000, 232.00000000000000, 160.00000000000000 }; + vec3 modelGridSpacing_ {1.0000000000000000, 0.89843700000000004, 0.89843700000000004 }; +}; + +TEST_F(Seg3DIntegrationTest, ImplicitModel) +{ + RBFInterface modelAlgo( modelPointData, + modelOrigin_, modelGridSize_, modelGridSpacing_, + normalOffset_, axisData_, + compute2DConvexHull_, invertSeedOrder_, kernel_ ); + + auto thresholdValue = modelAlgo.getThresholdValue(); + + EXPECT_EQ(0.0, thresholdValue); + + const auto rasterData = modelAlgo.getRasterData(); + + EXPECT_EQ(rasterData.size(), 160); + EXPECT_EQ(rasterData[0].size(), 232); + EXPECT_EQ(rasterData[0][0].size(), 160); + + //TODO: convert to move semantics for seg3d datablock usage + #if 0 + for (size_t i = 0; i < dstDataBlock->get_nx(); ++i) + { + for (size_t j = 0; j < dstDataBlock->get_ny(); ++j) + { + for (size_t k = 0; k < dstDataBlock->get_nz(); ++k) + { + dstDataBlock->set_data_at( i, j, k, rasterData[i][j][k] ); + } + } + } + #endif +}