diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 426c079b..00000000 --- a/.gitmodules +++ /dev/null @@ -1,12 +0,0 @@ -[submodule "src/Externals/dualmc"] - path = src/Externals/dualmc - url = ./../dualmc.git -[submodule "src/Externals/yaml-cpp"] - path = src/Externals/yaml-cpp - url = https://github.com/jbeder/yaml-cpp.git -[submodule "src/Externals/googletest"] - path = src/Externals/googletest - url = https://github.com/google/googletest.git -[submodule "src/Externals/spdlog"] - path = src/Externals/spdlog - url = https://github.com/gabime/spdlog.git \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 829a4114..f10c3db2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,11 @@ else() include_directories(${EIGEN3_INCLUDE_DIR}) endif() +include(cmake/downloadGoogletest.cmake) +include(cmake/downloadSpdlog.cmake) +include(cmake/downloadYamlCpp.cmake) + + # putting all executables in cmake-build-*/bin set(EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin) diff --git a/README.md b/README.md index f018b28b..b34744dd 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,8 @@ It analyzes maxima data generated by the open-source quantum Monte Carlo softwar ## Installation ### Installing required packages -To install inPsights, Git, CMake, the GNU Compiler Collection (gcc) and the Eigen3 library must be installed. This is most easily achieved by employing a packet manager. +To install inPsights, Git, CMake, the GNU Compiler Collection (gcc) must be installed. +This is most easily achieved by employing a packet manager. #### MacOS Make sure that the Xcode Command Line Tools are installed already with: @@ -16,10 +17,6 @@ xcode-select --install To install the required packages on MacOS, the [homebrew package manager](https://brew.sh) can be used. -It can be downloaded and installed from the command line as follows: -```bash -/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)" -``` To download the packages with `homebrew` execute the following command in the terminal: ```bash brew update @@ -27,8 +24,9 @@ brew upgrade brew install git cmake gcc@9 lapack eigen boost qt ``` -Alternatively, the Qt5 online installer can be used, which is found on the [Qt webpage](https://www.qt.io/download). -During the installation, make sure to install Qt for the `x86_64` architecture and select `sources`, `Qt3D`, and additionally `QtCharts` (which will be required in future versions as well). +Alternatively, the [Qt5 online installer](https://www.qt.io/download-open-source) can be used. +During the installation, make sure to install Qt for the `x86_64` architecture +and select `sources`, `Qt3D`, and additionally `QtCharts` (which will be required in future versions as well). #### Ubuntu @@ -57,19 +55,6 @@ sudo apt-get -y install qtbase5-dev qt3d5-dev ``` This might cause problems during the build of the inPsights GUI. -#### Submodules in inPsights -After cloning the repository, make sure to initialize and update the submodules -```bash -git submodule update --init --recursive -``` -to initialize all the submodules. - -The next time you checkout a branch e.g. the submodules do not need to be initialized again afterwards. Thus -```bash -git submodule update --recursive -``` -should be sufficient. - ### Setting environment variables #### Compilers @@ -103,7 +88,7 @@ If Qt5 was download from the webpage and installed via the installer, the follow export Qt5_DIR=/home//Qt/5.XX.X/gcc_64 ``` -If Qt5 was installed via `apt-get`, CMake should automatically find the library (not tested). +If Qt5 was installed via `apt-get`, CMake should find the library automatically. ## Building ProcessMaxima and inPsights @@ -117,7 +102,7 @@ and configure CMake for an out-of-source release build: ```bash cmake .. ``` -CMake options can be specified to build the GUI or to use a precompiled version of the Eigen library +CMake options can be specified to build the GUI or to use a pre-compiled version of the Eigen library ```bash cmake .. -DBUILD_GUI=ON -DBUILD_EIGEN=OFF ``` diff --git a/cmake/downloadGoogletest.cmake b/cmake/downloadGoogletest.cmake new file mode 100644 index 00000000..42f833e2 --- /dev/null +++ b/cmake/downloadGoogletest.cmake @@ -0,0 +1,18 @@ +# Download and unpack Googletest Library at configure time + +message("Configuring googletest...") + +configure_file(cmake/downloadGoogletest.in + googletest-download/CMakeLists.txt) +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download ) +execute_process(COMMAND ${CMAKE_COMMAND} --build . + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-download ) + +# Add Googletest library directly to our build. This adds +# the following targets: gtest, gmock + +add_subdirectory( + ${CMAKE_BINARY_DIR}/googletest-src + ${CMAKE_BINARY_DIR}/googletest-build + ) diff --git a/cmake/downloadGoogletest.in b/cmake/downloadGoogletest.in new file mode 100755 index 00000000..ff064770 --- /dev/null +++ b/cmake/downloadGoogletest.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8.2) + +project(googletest-download NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + GIT_REPOSITORY "https://github.com/google/googletest.git" + GIT_TAG "release-1.10.0" + SOURCE_DIR "${CMAKE_BINARY_DIR}/googletest-src" + BINARY_DIR "${CMAKE_BINARY_DIR}/googletest-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/cmake/downloadSpdlog.cmake b/cmake/downloadSpdlog.cmake new file mode 100644 index 00000000..ce73e5e4 --- /dev/null +++ b/cmake/downloadSpdlog.cmake @@ -0,0 +1,18 @@ +# Download and unpack Spdlog Library at configure time + +message("Configuring spdlog...") + +configure_file(cmake/downloadSpdlog.in + spdlog-download/CMakeLists.txt) +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/spdlog-download ) +execute_process(COMMAND ${CMAKE_COMMAND} --build . + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/spdlog-download ) + +# Add Spdlog library directly to our build. This adds +# the following targets: spdlog + +add_subdirectory( + ${CMAKE_BINARY_DIR}/spdlog-src + ${CMAKE_BINARY_DIR}/spdlog-build + ) diff --git a/cmake/downloadSpdlog.in b/cmake/downloadSpdlog.in new file mode 100755 index 00000000..4a1355e1 --- /dev/null +++ b/cmake/downloadSpdlog.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8.2) + +project(spdlog-download NONE) + +include(ExternalProject) +ExternalProject_Add(spdlog + GIT_REPOSITORY "https://github.com/gabime/spdlog.git" + GIT_TAG "v1.8.2" + SOURCE_DIR "${CMAKE_BINARY_DIR}/spdlog-src" + BINARY_DIR "${CMAKE_BINARY_DIR}/spdlog-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/cmake/downloadYamlCpp.cmake b/cmake/downloadYamlCpp.cmake new file mode 100644 index 00000000..e5ed983a --- /dev/null +++ b/cmake/downloadYamlCpp.cmake @@ -0,0 +1,21 @@ +# Download and unpack yaml-cpp Library at configure time + +message("Configuring yaml-cpp...") + +set(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "Don't build the YAML tests.") +set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "Don't build YAML contributions.") + +configure_file(cmake/downloadYamlCpp.in + yaml-cpp-download/CMakeLists.txt) +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/yaml-cpp-download ) +execute_process(COMMAND ${CMAKE_COMMAND} --build . + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/yaml-cpp-download ) + +# Add yaml-cpp library directly to our build. This adds +# the following targets: yaml-cpp + +add_subdirectory( + ${CMAKE_BINARY_DIR}/yaml-cpp-src + ${CMAKE_BINARY_DIR}/yaml-cpp-build + ) \ No newline at end of file diff --git a/cmake/downloadYamlCpp.in b/cmake/downloadYamlCpp.in new file mode 100755 index 00000000..da96a1d4 --- /dev/null +++ b/cmake/downloadYamlCpp.in @@ -0,0 +1,15 @@ +cmake_minimum_required(VERSION 2.8.2) + +project(yaml-cpp-download NONE) + +include(ExternalProject) +ExternalProject_Add(yaml-cpp + GIT_REPOSITORY "https://github.com/jbeder/yaml-cpp.git" + GIT_TAG "yaml-cpp-0.6.3" + SOURCE_DIR "${CMAKE_BINARY_DIR}/yaml-cpp-src" + BINARY_DIR "${CMAKE_BINARY_DIR}/yaml-cpp-build" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/src/BaseLib/tests/AYamlTest.cpp b/src/BaseLib/tests/AYamlTest.cpp index 8b17f04d..dde11f05 100644 --- a/src/BaseLib/tests/AYamlTest.cpp +++ b/src/BaseLib/tests/AYamlTest.cpp @@ -22,6 +22,6 @@ TEST(AYamlTest, JsonCompatibility){ out << YAML::EndMap; std::string outstring = out.c_str(); - std::string expected ="{\"Molecule\": {\"Atoms\": {\"Types\": [\"He\", \"H\"],\n \"Positions\": [\n [0, 0, 0.37],\n [0, 0, -0.37],\n ]},\n\"Electrons\": {\"Types\": [\"a\", \"a\", \"b\"],\n \"Positions\": [\n [0, 0, 0.37],\n [0, 0, 0.37],\n [0, 0, -0.37],\n ]}}}"; + std::string expected ="{\"Molecule\": {\"Atoms\": {\"Types\": [\"He\", \"H\"],\n \"Positions\": [\n [0, 0, 0.37],\n [0, 0, -0.37],\n ]}\n\"Electrons\": {\"Types\": [\"a\", \"a\", \"b\"],\n \"Positions\": [\n [0, 0, 0.37],\n [0, 0, 0.37],\n [0, 0, -0.37],\n ]}}}"; ASSERT_EQ(outstring,expected); } \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b709bddb..e140dc7c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,5 +1,4 @@ add_subdirectory(BaseLib) -add_subdirectory(Externals) add_subdirectory(Methods) if (${BUILD_GUI}) diff --git a/src/Externals/CMakeLists.txt b/src/Externals/CMakeLists.txt deleted file mode 100644 index 74c08a62..00000000 --- a/src/Externals/CMakeLists.txt +++ /dev/null @@ -1,8 +0,0 @@ -cmake_minimum_required(VERSION 3.11) - -add_subdirectory(googletest) -add_subdirectory(dualmc) -set(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "Don't build the YAML tests.") -set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "Don't build YAML contributions.") -add_subdirectory(yaml-cpp) -add_subdirectory(spdlog) \ No newline at end of file diff --git a/src/Externals/dualmc b/src/Externals/dualmc deleted file mode 160000 index 991a54fc..00000000 --- a/src/Externals/dualmc +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 991a54fcb48dd035b5845be3d6e7d199f34c2e62 diff --git a/src/Externals/googletest b/src/Externals/googletest deleted file mode 160000 index 3af06fe1..00000000 --- a/src/Externals/googletest +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3af06fe1664d30f98de1e78c53a7087e842a2547 diff --git a/src/Externals/spdlog b/src/Externals/spdlog deleted file mode 160000 index 616caa5d..00000000 --- a/src/Externals/spdlog +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 616caa5d30172b65cc3a06800894c575d70cb8e6 diff --git a/src/Externals/yaml-cpp b/src/Externals/yaml-cpp deleted file mode 160000 index 98acc5a8..00000000 --- a/src/Externals/yaml-cpp +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 98acc5a8874faab28b82c28936f4b400b389f5d6 diff --git a/src/GUI/source/InPsightsWidget.cpp b/src/GUI/source/InPsightsWidget.cpp index c1a3ce88..a0ae7728 100644 --- a/src/GUI/source/InPsightsWidget.cpp +++ b/src/GUI/source/InPsightsWidget.cpp @@ -273,7 +273,7 @@ void InPsightsWidget::showSplashScreen() { splashScreen->setPixmap(pixmap); splashScreen->show(); - std::string message = "Version " + inPsights::version() + " (pre-release)\n "\ + std::string message = "Version " + inPsights::version() + " (alpha)\n "\ "Copyright © 2016-2020 Michael A. Heuer."; splashScreen->showMessage(message.c_str(), Qt::AlignBottom, Qt::gray); diff --git a/src/Methods/SurfaceGeneration/CMakeLists.txt b/src/Methods/SurfaceGeneration/CMakeLists.txt index e940700a..f9bb2000 100644 --- a/src/Methods/SurfaceGeneration/CMakeLists.txt +++ b/src/Methods/SurfaceGeneration/CMakeLists.txt @@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.11) project(SurfaceGeneration CXX) +add_subdirectory(dualmc) + set ( PROJECT_FOLDER_NAME ${PROJECT_NAME} ) set ( PROJECT_PATH ${PROJECT_NAME}) set ( OUTPUT_NAME "${PROJECT_FOLDER_NAME}" ) diff --git a/src/Methods/SurfaceGeneration/dualmc/CMakeLists.txt b/src/Methods/SurfaceGeneration/dualmc/CMakeLists.txt new file mode 100644 index 00000000..72a0b1e8 --- /dev/null +++ b/src/Methods/SurfaceGeneration/dualmc/CMakeLists.txt @@ -0,0 +1,23 @@ +cmake_minimum_required(VERSION 3.9) +project (dualmc CXX) + +set ( PROJECT_FOLDER_NAME ${PROJECT_NAME}) +set ( PROJECT_PATH ${PROJECT_NAME}) +set ( OUTPUT_NAME "${PROJECT_FOLDER_NAME}" ) +message ( "-- ++ CREATING PROJECT OR MAKEFILE ---> ${OUTPUT_NAME}" ) + +set(HEADER_FILES + include/DualMC.h + include/Tables.h + include/HelperFunctions.h + ) + +set(SOURCE_FILES + source/DualMC.cpp + ) + +add_library(${PROJECT_NAME} STATIC ${SOURCE_FILES} ${HEADER_FILES}) +target_include_directories(${PROJECT_NAME} + PUBLIC include + PRIVATE source + ) diff --git a/src/Methods/SurfaceGeneration/dualmc/include/DualMC.h b/src/Methods/SurfaceGeneration/dualmc/include/DualMC.h new file mode 100644 index 00000000..15c9306c --- /dev/null +++ b/src/Methods/SurfaceGeneration/dualmc/include/DualMC.h @@ -0,0 +1,198 @@ +// Copyright (C) 2009, 2017 Dominik Wodniok. +// SPDX-License-Identifier: BSD-3-Clause + +#ifndef DUALMC_H_INCLUDED +#define DUALMC_H_INCLUDED + +// stl includes +#include +#include +#include + +namespace dualmc { + + using VertexComponentsType = float; + using QuadIndexType = std::int32_t; + + /// vertex structure for dual points + struct Vertex { + Vertex() = default; + + Vertex(Vertex const &v) = default; + + Vertex(VertexComponentsType x, VertexComponentsType y, VertexComponentsType z); + + VertexComponentsType x, y, z; + }; + + /// quad indices structure + struct Quad { + Quad() = default; + + Quad(QuadIndexType i0, QuadIndexType i1, QuadIndexType i2, QuadIndexType i3); + + QuadIndexType i0, i1, i2, i3; + }; + +/// \class DualMC +/// \author Dominik Wodniok +/// \date 2009 +/// Class which implements the dual marching cubes algorithm from Gregory M. Nielson. +/// Faces and vertices of the standard marching cubes algorithm correspond to +/// vertices and faces in the dual algorithm. As a vertex in standard marching cubes +/// usually is shared by 4 faces, the dual mesh is entirely made from quadrangles. +/// Unfortunately, under rare circumstances the original algorithm can create +/// non-manifold meshes. See the remarks of the original paper on this. +/// The class optionally can guarantee manifold meshes by taking the Manifold +/// Dual Marching Cubes approach from Rephael Wenger as described in +/// chapter 3.3.5 of his book "Isosurfaces: Geometry, Topology, and Algorithms". + template + class DualMC { + public: + // typedefs + typedef T VolumeDataType; + + /// Extracts the iso surface for a given volume and iso value. + /// Output is a list of vertices and a list of indices, which connect + /// vertices to quads. + /// The quad mesh either uses shared vertex indices or is a quad soup if + /// desired. + void build( + VolumeDataType const *data, + int32_t const dimX, int32_t const dimY, int32_t const dimZ, + VolumeDataType const iso, + bool const generateManifold, + bool const generateSoup, + std::vector &vertices, + std::vector &quads + ); + + private: + + /// Extract quad mesh with shared vertex indices. + void buildSharedVerticesQuads( + VolumeDataType const iso, + std::vector &vertices, + std::vector &quads + ); + + /// Extract quad soup. + void buildQuadSoup( + VolumeDataType const iso, + std::vector &vertices, + std::vector &quads + ); + + + private: + + /// enum with edge codes for a 12-bit voxel edge mask to indicate + /// grid edges which intersect the ISO surface of classic marching cubes + enum DMCEdgeCode { + EDGE0 = 1, + EDGE1 = 1 << 1, + EDGE2 = 1 << 2, + EDGE3 = 1 << 3, + EDGE4 = 1 << 4, + EDGE5 = 1 << 5, + EDGE6 = 1 << 6, + EDGE7 = 1 << 7, + EDGE8 = 1 << 8, + EDGE9 = 1 << 9, + EDGE10 = 1 << 10, + EDGE11 = 1 << 11, + FORCE_32BIT = 0xffffffff + }; + + /// get the 8-bit in-out mask for the voxel corners of the cell cube at (cx,cy,cz) + /// and the given iso value + int getCellCode(int32_t const cx, int32_t const cy, int32_t const cz, VolumeDataType const iso) const; + + /// Get the 12-bit dual point code mask, which encodes the traditional + /// marching cube vertices of the traditional marching cubes face which + /// corresponds to the dual point. + /// This is also where the manifold dual marching cubes algorithm is + /// implemented. + int getDualPointCode(int32_t const cx, int32_t const cy, int32_t const cz, + VolumeDataType const iso, DMCEdgeCode const edge) const; + + /// Given a dual point code and iso value, compute the dual point. + void calculateDualPoint(int32_t const cx, int32_t const cy, int32_t const cz, + VolumeDataType const iso, int const pointCode, Vertex &v) const; + + /// Get the shared index of a dual point which is uniquly identified by its + /// cell cube index and a cube edge. The dual point is computed, + /// if it has not been computed before. + QuadIndexType getSharedDualPointIndex(int32_t const cx, int32_t const cy, int32_t const cz, + VolumeDataType const iso, DMCEdgeCode const edge, + std::vector &vertices); + + /// Compute a linearized cell cube index. + int32_t gA(int32_t const x, int32_t const y, int32_t const z) const; + + private: + // static lookup tables needed for (manifold) dual marching cubes + + /// Dual Marching Cubes table + /// Encodes the edge vertices for the 256 marching cubes cases. + /// A marching cube case produces up to four faces and ,thus, up to four + /// dual points. + static int32_t const dualPointsList[256][4]; + + /// Table which encodes the ambiguous face of cube configurations, which + /// can cause non-manifold meshes. + /// Needed for manifold dual marching cubes. + static uint8_t const problematicConfigs[256]; + + private: + + /// convenience volume extent array for x-,y-, and z-dimension + int32_t dims[3]; + + /// convenience volume data point + VolumeDataType const *data; + + /// store whether the manifold dual marching cubes algorithm should be + /// applied. + bool generateManifold; + + /// Dual point key structure for hashing of shared vertices + struct DualPointKey { + // a dual point can be uniquely identified by ite linearized volume cell + // id and point code + int32_t linearizedCellID; + int pointCode; + + /// Equal operator for unordered map + bool operator==(DualPointKey const &other) const; + }; + + /// Functor for dual point key hash generation + struct DualPointKeyHash { + size_t operator()(DualPointKey const &k) const { + return size_t(k.linearizedCellID) | (size_t(k.pointCode) << 32u); + } + }; + + /// Hash map for shared vertex index computations + std::unordered_map pointToIndex; + }; + + template + inline + int32_t DualMC::gA(int32_t const x, int32_t const y, int32_t const z) const { + return x + dims[0] * (y + dims[1] * z); + } + +//------------------------------------------------------------------------------ + template + inline + bool DualMC::DualPointKey::operator==(typename DualMC::DualPointKey const &other) const { + return linearizedCellID == other.linearizedCellID && pointCode == other.pointCode; + } + +#include "HelperFunctions.h" +#include "Tables.h" + +} // END: namespace dualmc +#endif // DUALMC_H_INCLUDED diff --git a/src/Methods/SurfaceGeneration/dualmc/include/HelperFunctions.h b/src/Methods/SurfaceGeneration/dualmc/include/HelperFunctions.h new file mode 100644 index 00000000..16c6b9d9 --- /dev/null +++ b/src/Methods/SurfaceGeneration/dualmc/include/HelperFunctions.h @@ -0,0 +1,479 @@ +// Copyright (C) 2009, 2017 Dominik Wodniok. +// SPDX-License-Identifier: BSD-3-Clause + +//------------------------------------------------------------------------------ + +#include + +template +inline +int DualMC::getCellCode(int32_t const cx, int32_t const cy, int32_t const cz, VolumeDataType const iso) const { + // determine for each cube corner if it is outside or inside + int code = 0; + if (data[gA(cx, cy, cz)] >= iso) + code |= 1; + if (data[gA(cx + 1, cy, cz)] >= iso) + code |= 2; + if (data[gA(cx, cy + 1, cz)] >= iso) + code |= 4; + if (data[gA(cx + 1, cy + 1, cz)] >= iso) + code |= 8; + if (data[gA(cx, cy, cz + 1)] >= iso) + code |= 16; + if (data[gA(cx + 1, cy, cz + 1)] >= iso) + code |= 32; + if (data[gA(cx, cy + 1, cz + 1)] >= iso) + code |= 64; + if (data[gA(cx + 1, cy + 1, cz + 1)] >= iso) + code |= 128; + return code; +} + +//------------------------------------------------------------------------------ + +template +inline +int DualMC::getDualPointCode(int32_t const cx, int32_t const cy, int32_t const cz, VolumeDataType const iso, + DMCEdgeCode const edge) const { + int cubeCode = getCellCode(cx, cy, cz, iso); + + // is manifold dual marching cubes desired? + if (generateManifold) { + // The Manifold Dual Marching Cubes approach from Rephael Wenger as described in + // chapter 3.3.5 of his book "Isosurfaces: Geometry, Topology, and Algorithms" + // is implemente here. + // If a problematic C16 or C19 configuration shares the ambiguous face + // with another C16 or C19 configuration we simply invert the cube code + // before looking up dual points. Doing this for these pairs ensures + // manifold meshes. + // But this removes the dualism to marching cubes. + + // check if we have a potentially problematic configuration + uint8_t const direction = problematicConfigs[uint8_t(cubeCode)]; + // If the direction code is in {0,...,5} we have a C16 or C19 configuration. + if (direction != 255) { + // We have to check the neighboring cube, which shares the ambiguous + // face. For this we decode the direction. This could also be done + // with another lookup table. + // copy current cube coordinates into an array. + int32_t neighborCoords[] = {cx, cy, cz}; + // get the dimension of the non-zero coordinate axis + unsigned int const component = direction >> 1; + // get the sign of the direction + int32_t delta = (direction & 1) == 1 ? 1 : -1; + // modify the correspong cube coordinate + neighborCoords[component] += delta; + // have we left the volume in this direction? + if (neighborCoords[component] >= 0 && neighborCoords[component] < (dims[component] - 1)) { + // get the cube configuration of the relevant neighbor + int neighborCubeCode = getCellCode(neighborCoords[0], neighborCoords[1], neighborCoords[2], iso); + // Look up the neighbor configuration ambiguous face direction. + // If the direction is valid we have a C16 or C19 neighbor. + // As C16 and C19 have exactly one ambiguous face this face is + // guaranteed to be shared for the pair. + if (problematicConfigs[uint8_t(neighborCubeCode)] != 255) { + // replace the cube configuration with its inverse. + cubeCode ^= 0xff; + } + } + } + } + for (int i = 0; i < 4; ++i) + if (dualPointsList[cubeCode][i] & edge) { + return dualPointsList[cubeCode][i]; + } + return 0; +} + +//------------------------------------------------------------------------------ + +template +inline +void DualMC::calculateDualPoint(int32_t const cx, int32_t const cy, int32_t const cz, VolumeDataType const iso, + int const pointCode, Vertex &v) const { + // initialize the point with lower voxel coordinates + v.x = cx; + v.y = cy; + v.z = cz; + + // compute the dual point as the mean of the face vertices belonging to the + // original marching cubes face + Vertex p; + p.x = 0; + p.y = 0; + p.z = 0; + int points = 0; + + // sum edge intersection vertices using the point code + if (pointCode & EDGE0) { + p.x += ((float) iso - (float) data[gA(cx, cy, cz)]) / + ((float) data[gA(cx + 1, cy, cz)] - (float) data[gA(cx, cy, cz)]); + points++; + } + + if (pointCode & EDGE1) { + p.x += 1.0f; + p.z += ((float) iso - (float) data[gA(cx + 1, cy, cz)]) / + ((float) data[gA(cx + 1, cy, cz + 1)] - (float) data[gA(cx + 1, cy, cz)]); + points++; + } + + if (pointCode & EDGE2) { + p.x += ((float) iso - (float) data[gA(cx, cy, cz + 1)]) / + ((float) data[gA(cx + 1, cy, cz + 1)] - (float) data[gA(cx, cy, cz + 1)]); + p.z += 1.0f; + points++; + } + + if (pointCode & EDGE3) { + p.z += ((float) iso - (float) data[gA(cx, cy, cz)]) / + ((float) data[gA(cx, cy, cz + 1)] - (float) data[gA(cx, cy, cz)]); + points++; + } + + if (pointCode & EDGE4) { + p.x += ((float) iso - (float) data[gA(cx, cy + 1, cz)]) / + ((float) data[gA(cx + 1, cy + 1, cz)] - (float) data[gA(cx, cy + 1, cz)]); + p.y += 1.0f; + points++; + } + + if (pointCode & EDGE5) { + p.x += 1.0f; + p.z += ((float) iso - (float) data[gA(cx + 1, cy + 1, cz)]) / + ((float) data[gA(cx + 1, cy + 1, cz + 1)] - (float) data[gA(cx + 1, cy + 1, cz)]); + p.y += 1.0f; + points++; + } + + if (pointCode & EDGE6) { + p.x += ((float) iso - (float) data[gA(cx, cy + 1, cz + 1)]) / + ((float) data[gA(cx + 1, cy + 1, cz + 1)] - (float) data[gA(cx, cy + 1, cz + 1)]); + p.z += 1.0f; + p.y += 1.0f; + points++; + } + + if (pointCode & EDGE7) { + p.z += ((float) iso - (float) data[gA(cx, cy + 1, cz)]) / + ((float) data[gA(cx, cy + 1, cz + 1)] - (float) data[gA(cx, cy + 1, cz)]); + p.y += 1.0f; + points++; + } + + if (pointCode & EDGE8) { + p.y += ((float) iso - (float) data[gA(cx, cy, cz)]) / + ((float) data[gA(cx, cy + 1, cz)] - (float) data[gA(cx, cy, cz)]); + points++; + } + + if (pointCode & EDGE9) { + p.x += 1.0f; + p.y += ((float) iso - (float) data[gA(cx + 1, cy, cz)]) / + ((float) data[gA(cx + 1, cy + 1, cz)] - (float) data[gA(cx + 1, cy, cz)]); + points++; + } + + if (pointCode & EDGE10) { + p.x += 1.0f; + p.y += ((float) iso - (float) data[gA(cx + 1, cy, cz + 1)]) / + ((float) data[gA(cx + 1, cy + 1, cz + 1)] - (float) data[gA(cx + 1, cy, cz + 1)]); + p.z += 1.0f; + points++; + } + + if (pointCode & EDGE11) { + p.z += 1.0f; + p.y += ((float) iso - (float) data[gA(cx, cy, cz + 1)]) / + ((float) data[gA(cx, cy + 1, cz + 1)] - (float) data[gA(cx, cy, cz + 1)]); + points++; + } + + // divide by number of accumulated points + float invPoints = 1.0f / (float) points; + p.x *= invPoints; + p.y *= invPoints; + p.z *= invPoints; + + // offset point by voxel coordinates + v.x += p.x; + v.y += p.y; + v.z += p.z; +} + +//------------------------------------------------------------------------------ + +template +inline +QuadIndexType DualMC::getSharedDualPointIndex( + int32_t const cx, int32_t const cy, int32_t const cz, + VolumeDataType const iso, DMCEdgeCode const edge, + std::vector &vertices +) { + // create a key for the dual point from its linearized cell ID and point code + DualPointKey key; + key.linearizedCellID = gA(cx, cy, cz); + key.pointCode = getDualPointCode(cx, cy, cz, iso, edge); + + // have we already computed the dual point? + auto iterator = pointToIndex.find(key); + if (iterator != pointToIndex.end()) { + // just return the dual point index + return iterator->second; + } else { + // create new vertex and vertex id + QuadIndexType newVertexId = vertices.size(); + vertices.emplace_back(); + calculateDualPoint(cx, cy, cz, iso, key.pointCode, vertices.back()); + // insert vertex ID into map and also return it + pointToIndex[key] = newVertexId; + return newVertexId; + } +} + +//------------------------------------------------------------------------------ + +template +inline +void DualMC::build( + VolumeDataType const *data, + int32_t const dimX, int32_t const dimY, int32_t const dimZ, + VolumeDataType const iso, + bool const generateManifold, + bool const generateSoup, + std::vector &vertices, + std::vector &quads +) { + + // set members + this->dims[0] = dimX; + this->dims[1] = dimY; + this->dims[2] = dimZ; + this->data = data; + this->generateManifold = generateManifold; + + // clear vertices and quad indices + vertices.clear(); + quads.clear(); + + // generate quad soup or shared vertices quad list + if (generateSoup) { + buildQuadSoup(iso, vertices, quads); + } else { + buildSharedVerticesQuads(iso, vertices, quads); + } +} + +//------------------------------------------------------------------------------ + +template +inline +void DualMC::buildQuadSoup( + VolumeDataType const iso, + std::vector &vertices, + std::vector &quads +) { + + int32_t const reducedX = dims[0] - 2; + int32_t const reducedY = dims[1] - 2; + int32_t const reducedZ = dims[2] - 2; + + Vertex vertex0; + Vertex vertex1; + Vertex vertex2; + Vertex vertex3; + int pointCode; + + // iterate voxels + for (int32_t z = 0; z < reducedZ; ++z) + for (int32_t y = 0; y < reducedY; ++y) + for (int32_t x = 0; x < reducedX; ++x) { + // construct quad for x edge + if (z > 0 && y > 0) { + // is edge intersected? + bool const entering = data[gA(x, y, z)] < iso && data[gA(x + 1, y, z)] >= iso; + bool const exiting = data[gA(x, y, z)] >= iso && data[gA(x + 1, y, z)] < iso; + if (entering || exiting) { + // generate quad + pointCode = getDualPointCode(x, y, z, iso, EDGE0); + calculateDualPoint(x, y, z, iso, pointCode, vertex0); + + pointCode = getDualPointCode(x, y, z - 1, iso, EDGE2); + calculateDualPoint(x, y, z - 1, iso, pointCode, vertex1); + + pointCode = getDualPointCode(x, y - 1, z - 1, iso, EDGE6); + calculateDualPoint(x, y - 1, z - 1, iso, pointCode, vertex2); + + pointCode = getDualPointCode(x, y - 1, z, iso, EDGE4); + calculateDualPoint(x, y - 1, z, iso, pointCode, vertex3); + + if (entering) { + vertices.emplace_back(vertex0); + vertices.emplace_back(vertex1); + vertices.emplace_back(vertex2); + vertices.emplace_back(vertex3); + } else { + vertices.emplace_back(vertex0); + vertices.emplace_back(vertex3); + vertices.emplace_back(vertex2); + vertices.emplace_back(vertex1); + } + } + } + + // construct quad for y edge + if (z > 0 && x > 0) { + // is edge intersected? + bool const entering = data[gA(x, y, z)] < iso && data[gA(x, y + 1, z)] >= iso; + bool const exiting = data[gA(x, y, z)] >= iso && data[gA(x, y + 1, z)] < iso; + if (entering || exiting) { + // generate quad + pointCode = getDualPointCode(x, y, z, iso, EDGE8); + calculateDualPoint(x, y, z, iso, pointCode, vertex0); + + pointCode = getDualPointCode(x, y, z - 1, iso, EDGE11); + calculateDualPoint(x, y, z - 1, iso, pointCode, vertex1); + + pointCode = getDualPointCode(x - 1, y, z - 1, iso, EDGE10); + calculateDualPoint(x - 1, y, z - 1, iso, pointCode, vertex2); + + pointCode = getDualPointCode(x - 1, y, z, iso, EDGE9); + calculateDualPoint(x - 1, y, z, iso, pointCode, vertex3); + + if (exiting) { + vertices.emplace_back(vertex0); + vertices.emplace_back(vertex1); + vertices.emplace_back(vertex2); + vertices.emplace_back(vertex3); + } else { + vertices.emplace_back(vertex0); + vertices.emplace_back(vertex3); + vertices.emplace_back(vertex2); + vertices.emplace_back(vertex1); + } + } + } + + // construct quad for z edge + if (x > 0 && y > 0) { + // is edge intersected? + bool const entering = data[gA(x, y, z)] < iso && data[gA(x, y, z + 1)] >= iso; + bool const exiting = data[gA(x, y, z)] >= iso && data[gA(x, y, z + 1)] < iso; + if (entering || exiting) { + // generate quad + pointCode = getDualPointCode(x, y, z, iso, EDGE3); + calculateDualPoint(x, y, z, iso, pointCode, vertex0); + + pointCode = getDualPointCode(x - 1, y, z, iso, EDGE1); + calculateDualPoint(x - 1, y, z, iso, pointCode, vertex1); + + pointCode = getDualPointCode(x - 1, y - 1, z, iso, EDGE5); + calculateDualPoint(x - 1, y - 1, z, iso, pointCode, vertex2); + + pointCode = getDualPointCode(x, y - 1, z, iso, EDGE7); + calculateDualPoint(x, y - 1, z, iso, pointCode, vertex3); + + if (exiting) { + vertices.emplace_back(vertex0); + vertices.emplace_back(vertex1); + vertices.emplace_back(vertex2); + vertices.emplace_back(vertex3); + } else { + vertices.emplace_back(vertex0); + vertices.emplace_back(vertex3); + vertices.emplace_back(vertex2); + vertices.emplace_back(vertex1); + } + } + } + } + + // generate triangle soup quads + size_t const numQuads = vertices.size() / 4; + quads.reserve(numQuads); + for (size_t i = 0; i < numQuads; ++i) { + quads.emplace_back(i * 4, i * 4 + 1, i * 4 + 2, i * 4 + 3); + } +} + +//------------------------------------------------------------------------------ + +template +inline +void DualMC::buildSharedVerticesQuads( + VolumeDataType const iso, + std::vector &vertices, + std::vector &quads +) { + + + int32_t const reducedX = dims[0] - 2; + int32_t const reducedY = dims[1] - 2; + int32_t const reducedZ = dims[2] - 2; + + QuadIndexType i0, i1, i2, i3; + + pointToIndex.clear(); + + // iterate voxels + for (int32_t z = 0; z < reducedZ; ++z) + for (int32_t y = 0; y < reducedY; ++y) + for (int32_t x = 0; x < reducedX; ++x) { + // construct quads for x edge + if (z > 0 && y > 0) { + bool const entering = data[gA(x, y, z)] < iso && data[gA(x + 1, y, z)] >= iso; + bool const exiting = data[gA(x, y, z)] >= iso && data[gA(x + 1, y, z)] < iso; + if (entering || exiting) { + // generate quad + i0 = getSharedDualPointIndex(x, y, z, iso, EDGE0, vertices); + i1 = getSharedDualPointIndex(x, y, z - 1, iso, EDGE2, vertices); + i2 = getSharedDualPointIndex(x, y - 1, z - 1, iso, EDGE6, vertices); + i3 = getSharedDualPointIndex(x, y - 1, z, iso, EDGE4, vertices); + + if (entering) { + quads.emplace_back(i0, i1, i2, i3); + } else { + quads.emplace_back(i0, i3, i2, i1); + } + } + } + + // construct quads for y edge + if (z > 0 && x > 0) { + bool const entering = data[gA(x, y, z)] < iso && data[gA(x, y + 1, z)] >= iso; + bool const exiting = data[gA(x, y, z)] >= iso && data[gA(x, y + 1, z)] < iso; + if (entering || exiting) { + // generate quad + i0 = getSharedDualPointIndex(x, y, z, iso, EDGE8, vertices); + i1 = getSharedDualPointIndex(x, y, z - 1, iso, EDGE11, vertices); + i2 = getSharedDualPointIndex(x - 1, y, z - 1, iso, EDGE10, vertices); + i3 = getSharedDualPointIndex(x - 1, y, z, iso, EDGE9, vertices); + + if (exiting) { + quads.emplace_back(i0, i1, i2, i3); + } else { + quads.emplace_back(i0, i3, i2, i1); + } + } + } + + // construct quads for z edge + if (x > 0 && y > 0) { + bool const entering = data[gA(x, y, z)] < iso && data[gA(x, y, z + 1)] >= iso; + bool const exiting = data[gA(x, y, z)] >= iso && data[gA(x, y, z + 1)] < iso; + if (entering || exiting) { + // generate quad + i0 = getSharedDualPointIndex(x, y, z, iso, EDGE3, vertices); + i1 = getSharedDualPointIndex(x - 1, y, z, iso, EDGE1, vertices); + i2 = getSharedDualPointIndex(x - 1, y - 1, z, iso, EDGE5, vertices); + i3 = getSharedDualPointIndex(x, y - 1, z, iso, EDGE7, vertices); + + if (exiting) { + quads.emplace_back(i0, i1, i2, i3); + } else { + quads.emplace_back(i0, i3, i2, i1); + } + } + } + } +} diff --git a/src/Methods/SurfaceGeneration/dualmc/include/Tables.h b/src/Methods/SurfaceGeneration/dualmc/include/Tables.h new file mode 100644 index 00000000..f63f4f83 --- /dev/null +++ b/src/Methods/SurfaceGeneration/dualmc/include/Tables.h @@ -0,0 +1,344 @@ +// Copyright (C) 2009, 2018 Dominik Wodniok. +// SPDX-License-Identifier: BSD-3-Clause + +#include + +// Coordinate system +// +// y +// | +// | +// | +// 0-----x +// / +// / +// z +// + +// Cell Corners +// (Corners are voxels. Number correspond to Morton codes of corner coordinates) +// +// 2-------------------3 +// /| /| +// / | / | +// / | / | +// 6-------------------7 | +// | | | | +// | | | | +// | | | | +// | | | | +// | 0---------------|---1 +// | / | / +// | / | / +// |/ |/ +// 4-------------------5 +// + + +// Cell Edges +// +// o--------4----------o +// /| /| +// 7 | 5 | +// / | / | +// o--------6----------o | +// | 8 | 9 +// | | | | +// | | | | +// 11 | 10 | +// | o--------0------|---o +// | / | / +// | 3 | 1 +// |/ |/ +// o--------2----------o +// + +// Encodes the edge vertices for the 256 marching cubes cases. +// A marching cube case produces up to four faces and ,thus, up to four +// dual points. + + +template +int32_t const DualMC::dualPointsList[256][4] = { +{0, 0, 0, 0}, // 0 +{EDGE0|EDGE3|EDGE8, 0, 0, 0}, // 1 +{EDGE0|EDGE1|EDGE9, 0, 0, 0}, // 2 +{EDGE1|EDGE3|EDGE8|EDGE9, 0, 0, 0}, // 3 +{EDGE4|EDGE7|EDGE8, 0, 0, 0}, // 4 +{EDGE0|EDGE3|EDGE4|EDGE7, 0, 0, 0}, // 5 +{EDGE0|EDGE1|EDGE9, EDGE4|EDGE7|EDGE8, 0, 0}, // 6 +{EDGE1|EDGE3|EDGE4|EDGE7|EDGE9, 0, 0, 0}, // 7 +{EDGE4|EDGE5|EDGE9, 0, 0, 0}, // 8 +{EDGE0|EDGE3|EDGE8, EDGE4|EDGE5|EDGE9, 0, 0}, // 9 +{EDGE0|EDGE1|EDGE4|EDGE5, 0, 0, 0}, // 10 +{EDGE1|EDGE3|EDGE4|EDGE5|EDGE8, 0, 0, 0}, // 11 +{EDGE5|EDGE7|EDGE8|EDGE9, 0, 0, 0}, // 12 +{EDGE0|EDGE3|EDGE5|EDGE7|EDGE9, 0, 0, 0}, // 13 +{EDGE0|EDGE1|EDGE5|EDGE7|EDGE8, 0, 0, 0}, // 14 +{EDGE1|EDGE3|EDGE5|EDGE7, 0, 0, 0}, // 15 +{EDGE2|EDGE3|EDGE11, 0, 0, 0}, // 16 +{EDGE0|EDGE2|EDGE8|EDGE11, 0, 0, 0}, // 17 +{EDGE0|EDGE1|EDGE9, EDGE2|EDGE3|EDGE11, 0, 0}, // 18 +{EDGE1|EDGE2|EDGE8|EDGE9|EDGE11, 0, 0, 0}, // 19 +{EDGE4|EDGE7|EDGE8, EDGE2|EDGE3|EDGE11, 0, 0}, // 20 +{EDGE0|EDGE2|EDGE4|EDGE7|EDGE11, 0, 0, 0}, // 21 +{EDGE0|EDGE1|EDGE9, EDGE4|EDGE7|EDGE8, EDGE2|EDGE3|EDGE11, 0}, // 22 +{EDGE1|EDGE2|EDGE4|EDGE7|EDGE9|EDGE11, 0, 0, 0}, // 23 +{EDGE4|EDGE5|EDGE9, EDGE2|EDGE3|EDGE11, 0, 0}, // 24 +{EDGE0|EDGE2|EDGE8|EDGE11, EDGE4|EDGE5|EDGE9, 0, 0}, // 25 +{EDGE0|EDGE1|EDGE4|EDGE5, EDGE2|EDGE3|EDGE11, 0, 0}, // 26 +{EDGE1|EDGE2|EDGE4|EDGE5|EDGE8|EDGE11, 0, 0, 0}, // 27 +{EDGE5|EDGE7|EDGE8|EDGE9, EDGE2|EDGE3|EDGE11, 0, 0}, // 28 +{EDGE0|EDGE2|EDGE5|EDGE7|EDGE9|EDGE11, 0, 0, 0}, // 29 +{EDGE0|EDGE1|EDGE5|EDGE7|EDGE8, EDGE2|EDGE3|EDGE11, 0, 0}, // 30 +{EDGE1|EDGE2|EDGE5|EDGE7|EDGE11, 0, 0, 0}, // 31 +{EDGE1|EDGE2|EDGE10, 0, 0, 0}, // 32 +{EDGE0|EDGE3|EDGE8, EDGE1|EDGE2|EDGE10, 0, 0}, // 33 +{EDGE0|EDGE2|EDGE9|EDGE10, 0, 0, 0}, // 34 +{EDGE2|EDGE3|EDGE8|EDGE9|EDGE10, 0, 0, 0}, // 35 +{EDGE4|EDGE7|EDGE8, EDGE1|EDGE2|EDGE10, 0, 0}, // 36 +{EDGE0|EDGE3|EDGE4|EDGE7, EDGE1|EDGE2|EDGE10, 0, 0}, // 37 +{EDGE0|EDGE2|EDGE9|EDGE10, EDGE4|EDGE7|EDGE8, 0, 0}, // 38 +{EDGE2|EDGE3|EDGE4|EDGE7|EDGE9|EDGE10, 0, 0, 0}, // 39 +{EDGE4|EDGE5|EDGE9, EDGE1|EDGE2|EDGE10, 0, 0}, // 40 +{EDGE0|EDGE3|EDGE8, EDGE4|EDGE5|EDGE9, EDGE1|EDGE2|EDGE10, 0}, // 41 +{EDGE0|EDGE2|EDGE4|EDGE5|EDGE10, 0, 0, 0}, // 42 +{EDGE2|EDGE3|EDGE4|EDGE5|EDGE8|EDGE10, 0, 0, 0}, // 43 +{EDGE5|EDGE7|EDGE8|EDGE9, EDGE1|EDGE2|EDGE10, 0, 0}, // 44 +{EDGE0|EDGE3|EDGE5|EDGE7|EDGE9, EDGE1|EDGE2|EDGE10, 0, 0}, // 45 +{EDGE0|EDGE2|EDGE5|EDGE7|EDGE8|EDGE10, 0, 0, 0}, // 46 +{EDGE2|EDGE3|EDGE5|EDGE7|EDGE10, 0, 0, 0}, // 47 +{EDGE1|EDGE3|EDGE10|EDGE11, 0, 0, 0}, // 48 +{EDGE0|EDGE1|EDGE8|EDGE10|EDGE11, 0, 0, 0}, // 49 +{EDGE0|EDGE3|EDGE9|EDGE10|EDGE11, 0, 0, 0}, // 50 +{EDGE8|EDGE9|EDGE10|EDGE11, 0, 0, 0}, // 51 +{EDGE4|EDGE7|EDGE8, EDGE1|EDGE3|EDGE10|EDGE11, 0, 0}, // 52 +{EDGE0|EDGE1|EDGE4|EDGE7|EDGE10|EDGE11, 0, 0, 0}, // 53 +{EDGE0|EDGE3|EDGE9|EDGE10|EDGE11, EDGE4|EDGE7|EDGE8, 0, 0}, // 54 +{EDGE4|EDGE7|EDGE9|EDGE10|EDGE11, 0, 0, 0}, // 55 +{EDGE4|EDGE5|EDGE9, EDGE1|EDGE3|EDGE10|EDGE11, 0, 0}, // 56 +{EDGE0|EDGE1|EDGE8|EDGE10|EDGE11, EDGE4|EDGE5|EDGE9, 0, 0}, // 57 +{EDGE0|EDGE3|EDGE4|EDGE5|EDGE10|EDGE11, 0, 0, 0}, // 58 +{EDGE4|EDGE5|EDGE8|EDGE10|EDGE11, 0, 0, 0}, // 59 +{EDGE5|EDGE7|EDGE8|EDGE9, EDGE1|EDGE3|EDGE10|EDGE11, 0, 0}, // 60 +{EDGE0|EDGE1|EDGE5|EDGE7|EDGE9|EDGE10|EDGE11, 0, 0, 0}, // 61 +{EDGE0|EDGE3|EDGE5|EDGE7|EDGE8|EDGE10|EDGE11, 0, 0, 0}, // 62 +{EDGE5|EDGE7|EDGE10|EDGE11, 0, 0, 0}, // 63 +{EDGE6|EDGE7|EDGE11, 0, 0, 0}, // 64 +{EDGE0|EDGE3|EDGE8, EDGE6|EDGE7|EDGE11, 0, 0}, // 65 +{EDGE0|EDGE1|EDGE9, EDGE6|EDGE7|EDGE11, 0, 0}, // 66 +{EDGE1|EDGE3|EDGE8|EDGE9, EDGE6|EDGE7|EDGE11, 0, 0}, // 67 +{EDGE4|EDGE6|EDGE8|EDGE11, 0, 0, 0}, // 68 +{EDGE0|EDGE3|EDGE4|EDGE6|EDGE11, 0, 0, 0}, // 69 +{EDGE0|EDGE1|EDGE9, EDGE4|EDGE6|EDGE8|EDGE11, 0, 0}, // 70 +{EDGE1|EDGE3|EDGE4|EDGE6|EDGE9|EDGE11, 0, 0, 0}, // 71 +{EDGE4|EDGE5|EDGE9, EDGE6|EDGE7|EDGE11, 0, 0}, // 72 +{EDGE0|EDGE3|EDGE8, EDGE4|EDGE5|EDGE9, EDGE6|EDGE7|EDGE11, 0}, // 73 +{EDGE0|EDGE1|EDGE4|EDGE5, EDGE6|EDGE7|EDGE11, 0, 0}, // 74 +{EDGE1|EDGE3|EDGE4|EDGE5|EDGE8, EDGE6|EDGE7|EDGE11, 0, 0}, // 75 +{EDGE5|EDGE6|EDGE8|EDGE9|EDGE11, 0, 0, 0}, // 76 +{EDGE0|EDGE3|EDGE5|EDGE6|EDGE9|EDGE11, 0, 0, 0}, // 77 +{EDGE0|EDGE1|EDGE5|EDGE6|EDGE8|EDGE11, 0, 0, 0}, // 78 +{EDGE1|EDGE3|EDGE5|EDGE6|EDGE11, 0, 0, 0}, // 79 +{EDGE2|EDGE3|EDGE6|EDGE7, 0, 0, 0}, // 80 +{EDGE0|EDGE2|EDGE6|EDGE7|EDGE8, 0, 0, 0}, // 81 +{EDGE0|EDGE1|EDGE9, EDGE2|EDGE3|EDGE6|EDGE7, 0, 0}, // 82 +{EDGE1|EDGE2|EDGE6|EDGE7|EDGE8|EDGE9, 0, 0, 0}, // 83 +{EDGE2|EDGE3|EDGE4|EDGE6|EDGE8, 0, 0, 0}, // 84 +{EDGE0|EDGE2|EDGE4|EDGE6, 0, 0, 0}, // 85 +{EDGE0|EDGE1|EDGE9, EDGE2|EDGE3|EDGE4|EDGE6|EDGE8, 0, 0}, // 86 +{EDGE1|EDGE2|EDGE4|EDGE6|EDGE9, 0, 0, 0}, // 87 +{EDGE4|EDGE5|EDGE9, EDGE2|EDGE3|EDGE6|EDGE7, 0, 0}, // 88 +{EDGE0|EDGE2|EDGE6|EDGE7|EDGE8, EDGE4|EDGE5|EDGE9, 0, 0}, // 89 +{EDGE0|EDGE1|EDGE4|EDGE5, EDGE2|EDGE3|EDGE6|EDGE7, 0, 0}, // 90 +{EDGE1|EDGE2|EDGE4|EDGE5|EDGE6|EDGE7|EDGE8, 0, 0, 0}, // 91 +{EDGE2|EDGE3|EDGE5|EDGE6|EDGE8|EDGE9, 0, 0, 0}, // 92 +{EDGE0|EDGE2|EDGE5|EDGE6|EDGE9, 0, 0, 0}, // 93 +{EDGE0|EDGE1|EDGE2|EDGE3|EDGE5|EDGE6|EDGE8, 0, 0, 0}, // 94 +{EDGE1|EDGE2|EDGE5|EDGE6, 0, 0, 0}, // 95 +{EDGE1|EDGE2|EDGE10, EDGE6|EDGE7|EDGE11, 0, 0}, // 96 +{EDGE0|EDGE3|EDGE8, EDGE1|EDGE2|EDGE10, EDGE6|EDGE7|EDGE11, 0}, // 97 +{EDGE0|EDGE2|EDGE9|EDGE10, EDGE6|EDGE7|EDGE11, 0, 0}, // 98 +{EDGE2|EDGE3|EDGE8|EDGE9|EDGE10, EDGE6|EDGE7|EDGE11, 0, 0}, // 99 +{EDGE4|EDGE6|EDGE8|EDGE11, EDGE1|EDGE2|EDGE10, 0, 0}, // 100 +{EDGE0|EDGE3|EDGE4|EDGE6|EDGE11, EDGE1|EDGE2|EDGE10, 0, 0}, // 101 +{EDGE0|EDGE2|EDGE9|EDGE10, EDGE4|EDGE6|EDGE8|EDGE11, 0, 0}, // 102 +{EDGE2|EDGE3|EDGE4|EDGE6|EDGE9|EDGE10|EDGE11, 0, 0, 0}, // 103 +{EDGE4|EDGE5|EDGE9, EDGE1|EDGE2|EDGE10, EDGE6|EDGE7|EDGE11, 0}, // 104 +{EDGE0|EDGE3|EDGE8, EDGE4|EDGE5|EDGE9, EDGE1|EDGE2|EDGE10, EDGE6|EDGE7|EDGE11}, // 105 +{EDGE0|EDGE2|EDGE4|EDGE5|EDGE10, EDGE6|EDGE7|EDGE11, 0, 0}, // 106 +{EDGE2|EDGE3|EDGE4|EDGE5|EDGE8|EDGE10, EDGE6|EDGE7|EDGE11, 0, 0}, // 107 +{EDGE5|EDGE6|EDGE8|EDGE9|EDGE11, EDGE1|EDGE2|EDGE10, 0, 0}, // 108 +{EDGE0|EDGE3|EDGE5|EDGE6|EDGE9|EDGE11, EDGE1|EDGE2|EDGE10, 0, 0}, // 109 +{EDGE0|EDGE2|EDGE5|EDGE6|EDGE8|EDGE10|EDGE11, 0, 0, 0}, // 110 +{EDGE2|EDGE3|EDGE5|EDGE6|EDGE10|EDGE11, 0, 0, 0}, // 111 +{EDGE1|EDGE3|EDGE6|EDGE7|EDGE10, 0, 0, 0}, // 112 +{EDGE0|EDGE1|EDGE6|EDGE7|EDGE8|EDGE10, 0, 0, 0}, // 113 +{EDGE0|EDGE3|EDGE6|EDGE7|EDGE9|EDGE10, 0, 0, 0}, // 114 +{EDGE6|EDGE7|EDGE8|EDGE9|EDGE10, 0, 0, 0}, // 115 +{EDGE1|EDGE3|EDGE4|EDGE6|EDGE8|EDGE10, 0, 0, 0}, // 116 +{EDGE0|EDGE1|EDGE4|EDGE6|EDGE10, 0, 0, 0}, // 117 +{EDGE0|EDGE3|EDGE4|EDGE6|EDGE8|EDGE9|EDGE10, 0, 0, 0}, // 118 +{EDGE4|EDGE6|EDGE9|EDGE10, 0, 0, 0}, // 119 +{EDGE4|EDGE5|EDGE9, EDGE1|EDGE3|EDGE6|EDGE7|EDGE10, 0, 0}, // 120 +{EDGE0|EDGE1|EDGE6|EDGE7|EDGE8|EDGE10, EDGE4|EDGE5|EDGE9, 0, 0}, // 121 +{EDGE0|EDGE3|EDGE4|EDGE5|EDGE6|EDGE7|EDGE10, 0, 0, 0}, // 122 +{EDGE4|EDGE5|EDGE6|EDGE7|EDGE8|EDGE10, 0, 0, 0}, // 123 +{EDGE1|EDGE3|EDGE5|EDGE6|EDGE8|EDGE9|EDGE10, 0, 0, 0}, // 124 +{EDGE0|EDGE1|EDGE5|EDGE6|EDGE9|EDGE10, 0, 0, 0}, // 125 +{EDGE0|EDGE3|EDGE8, EDGE5|EDGE6|EDGE10, 0, 0}, // 126 +{EDGE5|EDGE6|EDGE10, 0, 0, 0}, // 127 +{EDGE5|EDGE6|EDGE10, 0, 0, 0}, // 128 +{EDGE0|EDGE3|EDGE8, EDGE5|EDGE6|EDGE10, 0, 0}, // 129 +{EDGE0|EDGE1|EDGE9, EDGE5|EDGE6|EDGE10, 0, 0}, // 130 +{EDGE1|EDGE3|EDGE8|EDGE9, EDGE5|EDGE6|EDGE10, 0, 0}, // 131 +{EDGE4|EDGE7|EDGE8, EDGE5|EDGE6|EDGE10, 0, 0}, // 132 +{EDGE0|EDGE3|EDGE4|EDGE7, EDGE5|EDGE6|EDGE10, 0, 0}, // 133 +{EDGE0|EDGE1|EDGE9, EDGE4|EDGE7|EDGE8, EDGE5|EDGE6|EDGE10, 0}, // 134 +{EDGE1|EDGE3|EDGE4|EDGE7|EDGE9, EDGE5|EDGE6|EDGE10, 0, 0}, // 135 +{EDGE4|EDGE6|EDGE9|EDGE10, 0, 0, 0}, // 136 +{EDGE0|EDGE3|EDGE8, EDGE4|EDGE6|EDGE9|EDGE10, 0, 0}, // 137 +{EDGE0|EDGE1|EDGE4|EDGE6|EDGE10, 0, 0, 0}, // 138 +{EDGE1|EDGE3|EDGE4|EDGE6|EDGE8|EDGE10, 0, 0, 0}, // 139 +{EDGE6|EDGE7|EDGE8|EDGE9|EDGE10, 0, 0, 0}, // 140 +{EDGE0|EDGE3|EDGE6|EDGE7|EDGE9|EDGE10, 0, 0, 0}, // 141 +{EDGE0|EDGE1|EDGE6|EDGE7|EDGE8|EDGE10, 0, 0, 0}, // 142 +{EDGE1|EDGE3|EDGE6|EDGE7|EDGE10, 0, 0, 0}, // 143 +{EDGE2|EDGE3|EDGE11, EDGE5|EDGE6|EDGE10, 0, 0}, // 144 +{EDGE0|EDGE2|EDGE8|EDGE11, EDGE5|EDGE6|EDGE10, 0, 0}, // 145 +{EDGE0|EDGE1|EDGE9, EDGE2|EDGE3|EDGE11, EDGE5|EDGE6|EDGE10, 0}, // 146 +{EDGE1|EDGE2|EDGE8|EDGE9|EDGE11, EDGE5|EDGE6|EDGE10, 0, 0}, // 147 +{EDGE4|EDGE7|EDGE8, EDGE2|EDGE3|EDGE11, EDGE5|EDGE6|EDGE10, 0}, // 148 +{EDGE0|EDGE2|EDGE4|EDGE7|EDGE11, EDGE5|EDGE6|EDGE10, 0, 0}, // 149 +{EDGE0|EDGE1|EDGE9, EDGE4|EDGE7|EDGE8, EDGE2|EDGE3|EDGE11, EDGE5|EDGE6|EDGE10}, // 150 +{EDGE1|EDGE2|EDGE4|EDGE7|EDGE9|EDGE11, EDGE5|EDGE6|EDGE10, 0, 0}, // 151 +{EDGE4|EDGE6|EDGE9|EDGE10, EDGE2|EDGE3|EDGE11, 0, 0}, // 152 +{EDGE0|EDGE2|EDGE8|EDGE11, EDGE4|EDGE6|EDGE9|EDGE10, 0, 0}, // 153 +{EDGE0|EDGE1|EDGE4|EDGE6|EDGE10, EDGE2|EDGE3|EDGE11, 0, 0}, // 154 +{EDGE1|EDGE2|EDGE4|EDGE6|EDGE8|EDGE10|EDGE11, 0, 0, 0}, // 155 +{EDGE6|EDGE7|EDGE8|EDGE9|EDGE10, EDGE2|EDGE3|EDGE11, 0, 0}, // 156 +{EDGE0|EDGE2|EDGE6|EDGE7|EDGE9|EDGE10|EDGE11, 0, 0, 0}, // 157 +{EDGE0|EDGE1|EDGE6|EDGE7|EDGE8|EDGE10, EDGE2|EDGE3|EDGE11, 0, 0}, // 158 +{EDGE1|EDGE2|EDGE6|EDGE7|EDGE10|EDGE11, 0, 0, 0}, // 159 +{EDGE1|EDGE2|EDGE5|EDGE6, 0, 0, 0}, // 160 +{EDGE0|EDGE3|EDGE8, EDGE1|EDGE2|EDGE5|EDGE6, 0, 0}, // 161 +{EDGE0|EDGE2|EDGE5|EDGE6|EDGE9, 0, 0, 0}, // 162 +{EDGE2|EDGE3|EDGE5|EDGE6|EDGE8|EDGE9, 0, 0, 0}, // 163 +{EDGE4|EDGE7|EDGE8, EDGE1|EDGE2|EDGE5|EDGE6, 0, 0}, // 164 +{EDGE0|EDGE3|EDGE4|EDGE7, EDGE1|EDGE2|EDGE5|EDGE6, 0, 0}, // 165 +{EDGE0|EDGE2|EDGE5|EDGE6|EDGE9, EDGE4|EDGE7|EDGE8, 0, 0}, // 166 +{EDGE2|EDGE3|EDGE4|EDGE5|EDGE6|EDGE7|EDGE9, 0, 0, 0}, // 167 +{EDGE1|EDGE2|EDGE4|EDGE6|EDGE9, 0, 0, 0}, // 168 +{EDGE0|EDGE3|EDGE8, EDGE1|EDGE2|EDGE4|EDGE6|EDGE9, 0, 0}, // 169 +{EDGE0|EDGE2|EDGE4|EDGE6, 0, 0, 0}, // 170 +{EDGE2|EDGE3|EDGE4|EDGE6|EDGE8, 0, 0, 0}, // 171 +{EDGE1|EDGE2|EDGE6|EDGE7|EDGE8|EDGE9, 0, 0, 0}, // 172 +{EDGE0|EDGE1|EDGE2|EDGE3|EDGE6|EDGE7|EDGE9, 0, 0, 0}, // 173 +{EDGE0|EDGE2|EDGE6|EDGE7|EDGE8, 0, 0, 0}, // 174 +{EDGE2|EDGE3|EDGE6|EDGE7, 0, 0, 0}, // 175 +{EDGE1|EDGE3|EDGE5|EDGE6|EDGE11, 0, 0, 0}, // 176 +{EDGE0|EDGE1|EDGE5|EDGE6|EDGE8|EDGE11, 0, 0, 0}, // 177 +{EDGE0|EDGE3|EDGE5|EDGE6|EDGE9|EDGE11, 0, 0, 0}, // 178 +{EDGE5|EDGE6|EDGE8|EDGE9|EDGE11, 0, 0, 0}, // 179 +{EDGE4|EDGE7|EDGE8, EDGE1|EDGE3|EDGE5|EDGE6|EDGE11, 0, 0}, // 180 +{EDGE0|EDGE1|EDGE4|EDGE5|EDGE6|EDGE7|EDGE11, 0, 0, 0}, // 181 +{EDGE0|EDGE3|EDGE5|EDGE6|EDGE9|EDGE11, EDGE4|EDGE7|EDGE8, 0, 0}, // 182 +{EDGE4|EDGE5|EDGE6|EDGE7|EDGE9|EDGE11, 0, 0, 0}, // 183 +{EDGE1|EDGE3|EDGE4|EDGE6|EDGE9|EDGE11, 0, 0, 0}, // 184 +{EDGE0|EDGE1|EDGE4|EDGE6|EDGE8|EDGE9|EDGE11, 0, 0, 0}, // 185 +{EDGE0|EDGE3|EDGE4|EDGE6|EDGE11, 0, 0, 0}, // 186 +{EDGE4|EDGE6|EDGE8|EDGE11, 0, 0, 0}, // 187 +{EDGE1|EDGE3|EDGE6|EDGE7|EDGE8|EDGE9|EDGE11, 0, 0, 0}, // 188 +{EDGE0|EDGE1|EDGE9, EDGE6|EDGE7|EDGE11, 0, 0}, // 189 +{EDGE0|EDGE3|EDGE6|EDGE7|EDGE8|EDGE11, 0, 0, 0}, // 190 +{EDGE6|EDGE7|EDGE11, 0, 0, 0}, // 191 +{EDGE5|EDGE7|EDGE10|EDGE11, 0, 0, 0}, // 192 +{EDGE0|EDGE3|EDGE8, EDGE5|EDGE7|EDGE10|EDGE11, 0, 0}, // 193 +{EDGE0|EDGE1|EDGE9, EDGE5|EDGE7|EDGE10|EDGE11, 0, 0}, // 194 +{EDGE1|EDGE3|EDGE8|EDGE9, EDGE5|EDGE7|EDGE10|EDGE11, 0, 0}, // 195 +{EDGE4|EDGE5|EDGE8|EDGE10|EDGE11, 0, 0, 0}, // 196 +{EDGE0|EDGE3|EDGE4|EDGE5|EDGE10|EDGE11, 0, 0, 0}, // 197 +{EDGE0|EDGE1|EDGE9, EDGE4|EDGE5|EDGE8|EDGE10|EDGE11, 0, 0}, // 198 +{EDGE1|EDGE3|EDGE4|EDGE5|EDGE9|EDGE10|EDGE11, 0, 0, 0}, // 199 +{EDGE4|EDGE7|EDGE9|EDGE10|EDGE11, 0, 0, 0}, // 200 +{EDGE0|EDGE3|EDGE8, EDGE4|EDGE7|EDGE9|EDGE10|EDGE11, 0, 0}, // 201 +{EDGE0|EDGE1|EDGE4|EDGE7|EDGE10|EDGE11, 0, 0, 0}, // 202 +{EDGE1|EDGE3|EDGE4|EDGE7|EDGE8|EDGE10|EDGE11, 0, 0, 0}, // 203 +{EDGE8|EDGE9|EDGE10|EDGE11, 0, 0, 0}, // 204 +{EDGE0|EDGE3|EDGE9|EDGE10|EDGE11, 0, 0, 0}, // 205 +{EDGE0|EDGE1|EDGE8|EDGE10|EDGE11, 0, 0, 0}, // 206 +{EDGE1|EDGE3|EDGE10|EDGE11, 0, 0, 0}, // 207 +{EDGE2|EDGE3|EDGE5|EDGE7|EDGE10, 0, 0, 0}, // 208 +{EDGE0|EDGE2|EDGE5|EDGE7|EDGE8|EDGE10, 0, 0, 0}, // 209 +{EDGE0|EDGE1|EDGE9, EDGE2|EDGE3|EDGE5|EDGE7|EDGE10, 0, 0}, // 210 +{EDGE1|EDGE2|EDGE5|EDGE7|EDGE8|EDGE9|EDGE10, 0, 0, 0}, // 211 +{EDGE2|EDGE3|EDGE4|EDGE5|EDGE8|EDGE10, 0, 0, 0}, // 212 +{EDGE0|EDGE2|EDGE4|EDGE5|EDGE10, 0, 0, 0}, // 213 +{EDGE0|EDGE1|EDGE9, EDGE2|EDGE3|EDGE4|EDGE5|EDGE8|EDGE10, 0, 0}, // 214 +{EDGE1|EDGE2|EDGE4|EDGE5|EDGE9|EDGE10, 0, 0, 0}, // 215 +{EDGE2|EDGE3|EDGE4|EDGE7|EDGE9|EDGE10, 0, 0, 0}, // 216 +{EDGE0|EDGE2|EDGE4|EDGE7|EDGE8|EDGE9|EDGE10, 0, 0, 0}, // 217 +{EDGE0|EDGE1|EDGE2|EDGE3|EDGE4|EDGE7|EDGE10, 0, 0, 0}, // 218 +{EDGE4|EDGE7|EDGE8, EDGE1|EDGE2|EDGE10, 0, 0}, // 219 +{EDGE2|EDGE3|EDGE8|EDGE9|EDGE10, 0, 0, 0}, // 220 +{EDGE0|EDGE2|EDGE9|EDGE10, 0, 0, 0}, // 221 +{EDGE0|EDGE1|EDGE2|EDGE3|EDGE8|EDGE10, 0, 0, 0}, // 222 +{EDGE1|EDGE2|EDGE10, 0, 0, 0}, // 223 +{EDGE1|EDGE2|EDGE5|EDGE7|EDGE11, 0, 0, 0}, // 224 +{EDGE0|EDGE3|EDGE8, EDGE1|EDGE2|EDGE5|EDGE7|EDGE11, 0, 0}, // 225 +{EDGE0|EDGE2|EDGE5|EDGE7|EDGE9|EDGE11, 0, 0, 0}, // 226 +{EDGE2|EDGE3|EDGE5|EDGE7|EDGE8|EDGE9|EDGE11, 0, 0, 0}, // 227 +{EDGE1|EDGE2|EDGE4|EDGE5|EDGE8|EDGE11, 0, 0, 0}, // 228 +{EDGE0|EDGE1|EDGE2|EDGE3|EDGE4|EDGE5|EDGE11, 0, 0, 0}, // 229 +{EDGE0|EDGE2|EDGE4|EDGE5|EDGE8|EDGE9|EDGE11, 0, 0, 0}, // 230 +{EDGE4|EDGE5|EDGE9, EDGE2|EDGE3|EDGE11, 0, 0}, // 231 +{EDGE1|EDGE2|EDGE4|EDGE7|EDGE9|EDGE11, 0, 0, 0}, // 232 +{EDGE0|EDGE3|EDGE8, EDGE1|EDGE2|EDGE4|EDGE7|EDGE9|EDGE11, 0, 0}, // 233 +{EDGE0|EDGE2|EDGE4|EDGE7|EDGE11, 0, 0, 0}, // 234 +{EDGE2|EDGE3|EDGE4|EDGE7|EDGE8|EDGE11, 0, 0, 0}, // 235 +{EDGE1|EDGE2|EDGE8|EDGE9|EDGE11, 0, 0, 0}, // 236 +{EDGE0|EDGE1|EDGE2|EDGE3|EDGE9|EDGE11, 0, 0, 0}, // 237 +{EDGE0|EDGE2|EDGE8|EDGE11, 0, 0, 0}, // 238 +{EDGE2|EDGE3|EDGE11, 0, 0, 0}, // 239 +{EDGE1|EDGE3|EDGE5|EDGE7, 0, 0, 0}, // 240 +{EDGE0|EDGE1|EDGE5|EDGE7|EDGE8, 0, 0, 0}, // 241 +{EDGE0|EDGE3|EDGE5|EDGE7|EDGE9, 0, 0, 0}, // 242 +{EDGE5|EDGE7|EDGE8|EDGE9, 0, 0, 0}, // 243 +{EDGE1|EDGE3|EDGE4|EDGE5|EDGE8, 0, 0, 0}, // 244 +{EDGE0|EDGE1|EDGE4|EDGE5, 0, 0, 0}, // 245 +{EDGE0|EDGE3|EDGE4|EDGE5|EDGE8|EDGE9, 0, 0, 0}, // 246 +{EDGE4|EDGE5|EDGE9, 0, 0, 0}, // 247 +{EDGE1|EDGE3|EDGE4|EDGE7|EDGE9, 0, 0, 0}, // 248 +{EDGE0|EDGE1|EDGE4|EDGE7|EDGE8|EDGE9, 0, 0, 0}, // 249 +{EDGE0|EDGE3|EDGE4|EDGE7, 0, 0, 0}, // 250 +{EDGE4|EDGE7|EDGE8, 0, 0, 0}, // 251 +{EDGE1|EDGE3|EDGE8|EDGE9, 0, 0, 0}, // 252 +{EDGE0|EDGE1|EDGE9, 0, 0, 0}, // 253 +{EDGE0|EDGE3|EDGE8, 0, 0, 0}, // 254 +{0, 0, 0, 0} // 255 +}; + +/// Encodes the ambiguous face of cube configurations, which +/// can cause non-manifold meshes. +/// Non-problematic configurations have a value of 255. +/// The first bit of each value actually encodes a positive or negative +/// direction while the second and third bit enumerate the axis. +template +uint8_t const DualMC::problematicConfigs[256] = { +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,1,0,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,3,255,255,2,255, +255,255,255,255,255,255,255,5,255,255,255,255,255,255,5,5, +255,255,255,255,255,255,4,255,255,255,3,3,1,1,255,255, +255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, +255,255,255,255,255,255,255,255,255,255,255,5,255,5,255,5, +255,255,255,255,255,255,255,3,255,255,255,255,255,2,255,255, +255,255,255,255,255,3,255,3,255,4,255,255,0,255,0,255, +255,255,255,255,255,255,255,1,255,255,255,0,255,255,255,255, +255,255,255,1,255,255,255,1,255,4,2,255,255,255,2,255, +255,255,255,0,255,2,4,255,255,255,255,0,255,2,255,255, +255,255,255,255,255,255,4,255,255,4,255,255,255,255,255,255 +}; diff --git a/src/Methods/SurfaceGeneration/dualmc/source/DualMC.cpp b/src/Methods/SurfaceGeneration/dualmc/source/DualMC.cpp new file mode 100644 index 00000000..54d7f19d --- /dev/null +++ b/src/Methods/SurfaceGeneration/dualmc/source/DualMC.cpp @@ -0,0 +1,22 @@ +// Copyright (C) 2019 Michael Heuer. +// SPDX-License-Identifier: GPL-3.0-or-later + +// obtained from https://github.com/dominikwodniok/dualmc + +#include + +namespace dualmc { + Vertex::Vertex( + VertexComponentsType x, + VertexComponentsType y, + VertexComponentsType z + ) : x(x), y(y), z(z) {} + + + Quad::Quad( + QuadIndexType i0, + QuadIndexType i1, + QuadIndexType i2, + QuadIndexType i3 + ) : i0(i0), i1(i1), i2(i2), i3(i3) {} +} diff --git a/src/Methods/SurfaceGeneration/include/ConvexHull.h b/src/Methods/SurfaceGeneration/include/ConvexHull.h index e579644a..38003da7 100755 --- a/src/Methods/SurfaceGeneration/include/ConvexHull.h +++ b/src/Methods/SurfaceGeneration/include/ConvexHull.h @@ -1,5 +1,8 @@ -#ifndef CONVEXHULL_HPP_ -#define CONVEXHULL_HPP_ +// SPDX-License-Identifier: CC0-1.0 +// from https://github.com/akuukka/quickhull + +#ifndef CONVEXHULL_H +#define CONVEXHULL_H #include #include "Mesh.h" @@ -207,4 +210,4 @@ namespace quickhull { } -#endif /* CONVEXHULL_HPP_ */ +#endif //CONVEXHULL_H diff --git a/src/Methods/SurfaceGeneration/include/HalfEdgeMesh.h b/src/Methods/SurfaceGeneration/include/HalfEdgeMesh.h index de760162..b43fa33a 100755 --- a/src/Methods/SurfaceGeneration/include/HalfEdgeMesh.h +++ b/src/Methods/SurfaceGeneration/include/HalfEdgeMesh.h @@ -1,7 +1,10 @@ +// SPDX-License-Identifier: CC0-1.0 +// from https://github.com/akuukka/quickhull + #include "Mesh.h" -#ifndef HalfEdgeMesh_h -#define HalfEdgeMesh_h +#ifndef HALFEDGEMESH_H +#define HALFEDGEMESH_H namespace quickhull { @@ -76,5 +79,4 @@ namespace quickhull { }; } - -#endif /* HalfEdgeMesh_h */ +#endif //HALFEDGEMESH_H diff --git a/src/Methods/SurfaceGeneration/include/MathUtils.h b/src/Methods/SurfaceGeneration/include/MathUtils.h index 12a4c215..6f02b435 100755 --- a/src/Methods/SurfaceGeneration/include/MathUtils.h +++ b/src/Methods/SurfaceGeneration/include/MathUtils.h @@ -1,6 +1,8 @@ +// SPDX-License-Identifier: CC0-1.0 +// from https://github.com/akuukka/quickhull -#ifndef QuickHull_MathUtils_hpp -#define QuickHull_MathUtils_hpp +#ifndef MATHUTILS_H +#define MATHUTILS_H #include #include @@ -34,5 +36,4 @@ namespace quickhull { } - -#endif +#endif //MATHUTILS_H diff --git a/src/Methods/SurfaceGeneration/include/Mesh.h b/src/Methods/SurfaceGeneration/include/Mesh.h index dfe1fc29..fb396ab6 100755 --- a/src/Methods/SurfaceGeneration/include/Mesh.h +++ b/src/Methods/SurfaceGeneration/include/Mesh.h @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: CC0-1.0 +// from https://github.com/akuukka/quickhull + #ifndef MESH_HPP_ #define MESH_HPP_ diff --git a/src/Methods/SurfaceGeneration/include/Plane.h b/src/Methods/SurfaceGeneration/include/Plane.h index c35b6457..b9cc2670 100755 --- a/src/Methods/SurfaceGeneration/include/Plane.h +++ b/src/Methods/SurfaceGeneration/include/Plane.h @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: CC0-1.0 +// from https://github.com/akuukka/quickhull + #ifndef QHPLANE_HPP_ #define QHPLANE_HPP_ diff --git a/src/Methods/SurfaceGeneration/include/Pool.h b/src/Methods/SurfaceGeneration/include/Pool.h index 9f27f045..0b688c35 100755 --- a/src/Methods/SurfaceGeneration/include/Pool.h +++ b/src/Methods/SurfaceGeneration/include/Pool.h @@ -1,5 +1,8 @@ -#ifndef Pool_h -#define Pool_h +// SPDX-License-Identifier: CC0-1.0 +// from https://github.com/akuukka/quickhull + +#ifndef POOL_H +#define POOL_H #include #include @@ -31,4 +34,4 @@ namespace quickhull { }; } -#endif /* Pool_h */ +#endif //POOL_H diff --git a/src/Methods/SurfaceGeneration/include/QuickHull.h b/src/Methods/SurfaceGeneration/include/QuickHull.h index 6e1644f1..f9fdcd4a 100755 --- a/src/Methods/SurfaceGeneration/include/QuickHull.h +++ b/src/Methods/SurfaceGeneration/include/QuickHull.h @@ -1,3 +1,6 @@ +// SPDX-License-Identifier: CC0-1.0 +// from https://github.com/akuukka/quickhull + #ifndef QUICKHULL_HPP_ #define QUICKHULL_HPP_ @@ -11,7 +14,8 @@ #include "HalfEdgeMesh.h" #include "MathUtils.h" -/* +/* https://github.com/akuukka/quickhull + * * Implementation of the 3D QuickHull algorithm by Antti Kuukka * * No copyrights. What follows is 100% Public Domain. diff --git a/src/Methods/SurfaceGeneration/include/Ray.h b/src/Methods/SurfaceGeneration/include/Ray.h index 7b8270a8..7bfe085c 100755 --- a/src/Methods/SurfaceGeneration/include/Ray.h +++ b/src/Methods/SurfaceGeneration/include/Ray.h @@ -1,5 +1,8 @@ -#ifndef QuickHull_Ray_hpp -#define QuickHull_Ray_hpp +// SPDX-License-Identifier: CC0-1.0 +// from https://github.com/akuukka/quickhull + +#ifndef RAY_H +#define RAY_H #include @@ -18,4 +21,4 @@ namespace quickhull { } -#endif +#endif //RAY_H diff --git a/src/Methods/SurfaceGeneration/include/SurfaceData.h b/src/Methods/SurfaceGeneration/include/SurfaceData.h index ef6bae23..db6b3530 100644 --- a/src/Methods/SurfaceGeneration/include/SurfaceData.h +++ b/src/Methods/SurfaceGeneration/include/SurfaceData.h @@ -29,5 +29,4 @@ namespace YAML { Emitter &operator<<(Emitter &out, const SurfaceData &rhs) ; } - #endif //INPSIGHTS_SURFACEDATA_H diff --git a/src/Methods/SurfaceGeneration/include/Types.h b/src/Methods/SurfaceGeneration/include/Types.h index ba110084..39ec9621 100755 --- a/src/Methods/SurfaceGeneration/include/Types.h +++ b/src/Methods/SurfaceGeneration/include/Types.h @@ -1,5 +1,8 @@ -#ifndef QuickHull_Types_hpp -#define QuickHull_Types_hpp +// SPDX-License-Identifier: CC0-1.0 +// from https://github.com/akuukka/quickhull + +#ifndef TYPES_H +#define TYPES_H #include @@ -8,4 +11,4 @@ namespace quickhull { typedef size_t IndexType; } -#endif +#endif //TYPES_H diff --git a/src/Methods/SurfaceGeneration/include/VertexDataSource.h b/src/Methods/SurfaceGeneration/include/VertexDataSource.h index 717b3228..2927191b 100755 --- a/src/Methods/SurfaceGeneration/include/VertexDataSource.h +++ b/src/Methods/SurfaceGeneration/include/VertexDataSource.h @@ -1,5 +1,8 @@ -#ifndef VertexDataSource_h -#define VertexDataSource_h +// SPDX-License-Identifier: CC0-1.0 +// from https://github.com/akuukka/quickhull + +#ifndef VERTEXDATASOURCE_H +#define VERTEXDATASOURCE_H #include @@ -46,5 +49,4 @@ namespace quickhull { } - -#endif /* VertexDataSource_h */ +#endif //VERTEXDATASOURCE_H diff --git a/src/Methods/SurfaceGeneration/source/QuickHull.cpp b/src/Methods/SurfaceGeneration/source/QuickHull.cpp index 09d46891..010383ab 100755 --- a/src/Methods/SurfaceGeneration/source/QuickHull.cpp +++ b/src/Methods/SurfaceGeneration/source/QuickHull.cpp @@ -1,7 +1,9 @@ +// SPDX-License-Identifier: CC0-1.0 +// from https://github.com/akuukka/quickhull + #include "QuickHull.h" #include "MathUtils.h" #include "Types.h" -#include #include #include #include diff --git a/src/Methods/SurfaceGeneration/tests/AQuickHullTest.cpp b/src/Methods/SurfaceGeneration/tests/AQuickHullTest.cpp index 786b7f56..17c8f666 100755 --- a/src/Methods/SurfaceGeneration/tests/AQuickHullTest.cpp +++ b/src/Methods/SurfaceGeneration/tests/AQuickHullTest.cpp @@ -6,7 +6,6 @@ #include #include -#include "MolecularGeometry.h" #include "TestMolecules.h" using namespace testing;