├── README.md ├── MeshFrame ├── MeshFrame │ ├── TetMesh │ │ ├── TetMeshTypeDefs.h │ │ ├── TProps.h │ │ ├── TMeshStaticLibHeaders.h │ │ ├── SurfaceMesh │ │ │ ├── SurfaceMeshHeaders.h │ │ │ ├── SurfaceFaceStatic.h │ │ │ ├── SurfaceVertexStatic.h │ │ │ └── SurfaceMeshStatic.h │ │ ├── VertexStatic.h │ │ ├── face.h │ │ ├── edge.h │ │ ├── tet.h │ │ ├── tvertex.h │ │ ├── vertex.h │ │ ├── tedge.h │ │ ├── halfface.h │ │ ├── halfedge.h │ │ └── TMeshStatic.h │ ├── TriMesh │ │ ├── MeshCoreHeaders.h │ │ ├── Color.h │ │ ├── MeshStatic.h │ │ ├── VertexStatic.h │ │ ├── Face.h │ │ ├── Edge.h │ │ ├── HalfEdge.h │ │ ├── Props.h │ │ ├── Vertex.h │ │ ├── MeshDynamic.h │ │ ├── Iterators.h │ │ └── Iterators2.h │ ├── Types │ │ └── TypeDefs.h │ ├── Utility │ │ ├── Time.h │ │ ├── CommandParser.h │ │ ├── IO.h │ │ ├── Str.h │ │ ├── IO.cpp │ │ └── Parser.h │ ├── Parser │ │ ├── IOFuncDef.h │ │ ├── parser.h │ │ ├── StrUtil_fast.h │ │ ├── strutil.h │ │ └── traits_io.h │ └── Memory │ │ ├── MPIterator.h │ │ ├── MemoryPoolThreadSafe.h │ │ ├── MemoryPool2.h │ │ ├── MemoryPool.h │ │ └── Array.h └── cmake │ └── MeshFrame2Config.cmake └── LICENSE /README.md: -------------------------------------------------------------------------------- 1 | # MeshFrame2 2 | An open source, header only, blazing fast mesh processing library; supporting both triangular mesh and tetrahedral mesh. 3 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/TetMeshTypeDefs.h: -------------------------------------------------------------------------------- 1 | #include "Eigen/core" 2 | #include "../Types/TypeDefs.h" 3 | 4 | 5 | namespace MF 6 | { 7 | namespace TetMesh { 8 | typedef Eigen::Matrix TTetIdsMat; 9 | using Vec4BlockI = Eigen::Block; 10 | 11 | } 12 | 13 | } -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/MeshCoreHeaders.h: -------------------------------------------------------------------------------- 1 | #ifndef _MESH_CORE_HEADERS_H_ 2 | #define _MESH_CORE_HEADERS_H_ 3 | 4 | #include "Vertex.h" 5 | #include "HalfEdge.h" 6 | #include "Edge.h" 7 | #include "Face.h" 8 | #include "BaseMesh.h" 9 | #include "MeshStatic.h" 10 | 11 | #include "Iterators2.h" 12 | #endif // !_MESH_CORE_HEADERS_H_ 13 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/TProps.h: -------------------------------------------------------------------------------- 1 | #ifndef _TPROPS_H_ 2 | #define _TPROPS_H_ 3 | #include "../TriMesh/Props.h" 4 | 5 | namespace MF 6 | { 7 | namespace TetMesh 8 | { 9 | MAKE_PROPHANDLE(V); 10 | MAKE_PROPHANDLE(E); 11 | MAKE_PROPHANDLE(F); 12 | MAKE_PROPHANDLE(HE); 13 | MAKE_PROPHANDLE(HF); 14 | MAKE_PROPHANDLE(T); 15 | 16 | } 17 | } 18 | 19 | #endif // !_PROPS_H_ 20 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/Color.h: -------------------------------------------------------------------------------- 1 | #include 2 | #ifndef _COLOR_H_ 3 | #define _COLOR_H_ 4 | 5 | union ColorUnion 6 | { 7 | struct 8 | { 9 | float r; 10 | float g; 11 | float b; 12 | }; 13 | 14 | float & operator [] (int i){ 15 | assert(i >= 0 && i < 3); 16 | return color[i]; 17 | }; 18 | 19 | private: 20 | float color[3] = { 0,0,0 }; 21 | }; 22 | 23 | 24 | #endif // _COLOR_H_ 25 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Types/TypeDefs.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #define POINT_VEC_DIMS 3 6 | 7 | 8 | namespace MF 9 | { 10 | template 11 | using TVerticesMat = Eigen::Matrix; 12 | 13 | template 14 | using TVec3 = Eigen::Matrix; 15 | template 16 | using TVec2 = Eigen::Matrix; 17 | 18 | template 19 | using TVec3Block = Eigen::Block, POINT_VEC_DIMS, 1>; 20 | 21 | typedef int32_t IdType; 22 | } -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Utility/Time.h: -------------------------------------------------------------------------------- 1 | #ifndef __MESHFRAME_TIME_H__ 2 | #define __MESHFRAME_TIME_H__ 3 | 4 | #include 5 | #include 6 | 7 | namespace MF { 8 | struct Time 9 | { 10 | static std::string getCurTimeString() { 11 | std::time_t curtime = std::chrono::system_clock::to_time_t(std::chrono::system_clock::now()); 12 | std::string timeStr = std::ctime(&curtime); 13 | // remove the '\n' at end 14 | timeStr.pop_back(); 15 | 16 | timeStr = STR::replace(timeStr, " ", "_"); 17 | timeStr = STR::replace(timeStr, ":", "-"); 18 | 19 | return timeStr; 20 | } 21 | }; 22 | } 23 | 24 | #endif // !__MESHFRAME_TIME_H__ 25 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/MeshStatic.h: -------------------------------------------------------------------------------- 1 | #ifndef _MESHFRAME_MESHSTATIC_H_ 2 | #define _MESHFRAME_MESHSTATIC_H_ 3 | 4 | #include "BaseMesh.h" 5 | #include "VertexStatic.h" 6 | #include "Face.h" 7 | #include "Edge.h" 8 | #include "HalfEdge.h" 9 | 10 | #include "Iterators2.h" 11 | 12 | namespace MF { 13 | namespace TriMesh { 14 | template 15 | using CTriMeshStaticDType = CMeshBase, CEdge, CFace, CHalfEdge>; 16 | typedef CTriMeshStaticDType TriMeshStaticF; 17 | typedef CTriMeshStaticDType TriMeshStaticD; 18 | 19 | typedef CIterators TriMeshStaticIteratorF; 20 | typedef CIterators TriMeshStaticIteratorD; 21 | } 22 | } 23 | 24 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/TMeshStaticLibHeaders.h: -------------------------------------------------------------------------------- 1 | #ifndef _TMESHLIB_HEADERS_H_ 2 | #define _TMESHLIB_HEADERS_H_ 3 | 4 | #include "TMeshStatic.h" 5 | #include "VertexStatic.h" 6 | #include "Tvertex.h" 7 | #include "Edge.h" 8 | #include "TEdge.h" 9 | #include "Face.h" 10 | #include "Halfface.h" 11 | #include "Halfedge.h" 12 | #include "Tet.h" 13 | 14 | #include "TIterators.h" 15 | 16 | namespace MF 17 | { 18 | namespace TetMesh 19 | { 20 | template 21 | using CTMeshStaticDType = CTMeshStatic, CHalfEdge, CTEdge, CEdge, CHalfFace, CFace, CTet>; 22 | typedef CTMeshStaticDType TMeshStaticF; 23 | typedef CTMeshStaticDType TMeshStaticD; 24 | } 25 | } 26 | 27 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/VertexStatic.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file Vertex.h 3 | * \brief Base class of vertex 4 | * \Version 2.0 5 | * \Update 11/03/2022 6 | */ 7 | 8 | #ifndef _MESHFRAME_VERTEX_STATIC_H_ 9 | #define _MESHFRAME_VERTEX_STATIC_H_ 10 | 11 | #include "Vertex.h" 12 | #include "../Types/TypeDefs.h" 13 | 14 | #include "MeshStatic.h" 15 | 16 | namespace MF { 17 | namespace TriMesh { 18 | template 19 | class CVertexStatic : public TriMesh::CVertexBase 20 | { 21 | public: 22 | void setPVertPos(TVerticesMat* pVertPos) { 23 | mPVertPos = pVertPos; 24 | } 25 | 26 | TVec3 position() { 27 | return pos; 28 | } 29 | 30 | 31 | protected: 32 | TVec3 pos; 33 | }; 34 | 35 | } 36 | 37 | }//name space MF 38 | 39 | #endif //_MESHFRAME_VERTEX_STATIC_H_ -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/SurfaceMesh/SurfaceMeshHeaders.h: -------------------------------------------------------------------------------- 1 | #ifndef _TMESHLIB_SURFACE_MESH_HEADERS_H_ 2 | #define _TMESHLIB_SURFACE_MESH_HEADERS_H_ 3 | 4 | #include "../TMeshStaticLibHeaders.h" 5 | #include "../../TriMesh/MeshCoreHeaders.h" 6 | 7 | #include "SurfaceVertexStatic.h" 8 | #include "SurfaceFaceStatic.h" 9 | #include "SurfaceMeshStatic.h" 10 | 11 | 12 | namespace MF { 13 | namespace TetMesh { 14 | //template 15 | //class CSurfaceMeshStatic : TriMesh::CMeshBase 16 | 17 | template 18 | using CSurfaceMeshStaticDType = CSurfaceMeshStatic, TriMesh::CEdge, CSurfaceFace, TriMesh::CHalfEdge>; 19 | 20 | typedef CSurfaceMeshStaticDType CSurfaceMeshStaticF; 21 | typedef CSurfaceMeshStaticDType CSurfaceMeshStaticD; 22 | } 23 | } 24 | 25 | #endif -------------------------------------------------------------------------------- /MeshFrame/cmake/MeshFrame2Config.cmake: -------------------------------------------------------------------------------- 1 | message( "Adding MeshFrame." ) 2 | 3 | # please use x64 arch 4 | SET (MESHFRAME_INCLUDE_DIR ${CMAKE_CURRENT_LIST_DIR}/..) 5 | 6 | 7 | file(GLOB MESHFRAME_SOURCE_CPP_UTILITY 8 | ${MESHFRAME_INCLUDE_DIR}/MeshFrame/Utility/*.cpp 9 | ) 10 | 11 | SET (MESHFRAME_SOURCE_CPP 12 | ${MESHFRAME_SOURCE_CPP_UTILITY} 13 | ) 14 | 15 | # SET (MESHFRAME_SOURCE_CPP_CUDA 16 | # ${MESHFRAME_SOURCE_CPP}/MeshFrame/common/logger.cpp 17 | # ${MESHFRAME_SOURCE_CPP}/MeshFrame/common/windows/getopt.c 18 | # ${MESHFRAME_SOURCE_CPP}/MeshFrame/NetWrapper/NetWrapper.cpp 19 | # ${MESHFRAME_SOURCE_CPP}/MeshFrame/MarkerLabeler/MarkerLabeler.cpp 20 | # ${MESHFRAME_SOURCE_CPP}/MeshFrame/Image/Image.cpp 21 | # 22 | # ) 23 | 24 | find_package(Eigen3 REQUIRED) 25 | 26 | message( "Found Eigen3 at:" ${EIGEN3_INCLUDE_DIRS}) 27 | 28 | SET (MESHFRAME_INCLUDE_DIR 29 | ${MESHFRAME_INCLUDE_DIR} 30 | ${EIGEN3_INCLUDE_DIRS} 31 | ) 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/SurfaceMesh/SurfaceFaceStatic.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file Vertex.h 3 | * \brief Base class of vertex 4 | * \Version 2.0 5 | * \Update 11/25/2022 6 | */ 7 | 8 | #ifndef _MESHFRAME_TETMESH_SURFACE_FACE_H_ 9 | #define _MESHFRAME_TETMESH_SURFACE_FACE_H_ 10 | 11 | #include "../../TriMesh/Face.h" 12 | #include "../halfface.h" 13 | 14 | namespace MF { 15 | namespace TetMesh { 16 | class CSurfaceFace : public TriMesh::CFace 17 | { 18 | public: 19 | CSurfaceFace() { }; 20 | ~CSurfaceFace() { } 21 | 22 | void setTetMeshHalfFacePtr(TetMesh::CHalfFace* in_PTetMeshVertex) { 23 | pTetMeshHalfFace = in_PTetMeshVertex; 24 | in_PTetMeshVertex->setSurfaceMeshFacePtr((void*)this); 25 | } 26 | TetMesh::CHalfFace* getTetMeshHalfFacePtr() { 27 | return pTetMeshHalfFace; 28 | } 29 | 30 | 31 | protected: 32 | TetMesh::CHalfFace * pTetMeshHalfFace = nullptr; 33 | 34 | }; 35 | } 36 | } 37 | 38 | #endif //_MESHLIB_VERTEX_H_defined -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/VertexStatic.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file vertex.h 3 | * \brief Base vertex Class for all types of Tetrahedron Mesh Classes 4 | * 5 | * This is the fundamental class for vertex 6 | * \date 10/10/2022 7 | * 8 | */ 9 | 10 | #ifndef _TMESHLIB_VERTEX_STATIC_H_ 11 | #define _TMESHLIB_VERTEX_STATIC_H_ 12 | 13 | #include 14 | #include 15 | #include "../Memory/Array.h" 16 | #include "vertex.h" 17 | #include "../Types/TypeDefs.h" 18 | 19 | namespace MF 20 | { 21 | namespace TetMesh 22 | { 23 | template 24 | class CVertexStatic: public CVertexBase 25 | { 26 | public: 27 | CVertexStatic() { }; 28 | ~CVertexStatic(){ } 29 | 30 | void setPVertPos(TVerticesMat* pVertPos) { 31 | mPVertPos = pVertPos; 32 | } 33 | 34 | TVec3Block position() { 35 | return mPVertPos->block<3, 1>(0, m_id); 36 | } 37 | 38 | 39 | protected: 40 | 41 | TVerticesMat* mPVertPos = nullptr; 42 | }; 43 | }; 44 | }; 45 | 46 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Parser/IOFuncDef.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifdef _MSC_VER 3 | #ifndef _CRT_SECURE_NO_WARNINGS 4 | #define _CRT_SECURE_NO_WARNINGS 5 | #endif 6 | #endif 7 | #include 8 | #include 9 | 10 | #define MAX_LINE_SIZE 1024 11 | #define MAX_TRAIT_STRING_SIZE MAX_LINE_SIZE 12 | #define MAX_TOKEN_STRING_SIZE MAX_LINE_SIZE 13 | #define MAX_DATA_STRING_SIZE MAX_LINE_SIZE 14 | 15 | #ifdef _WIN32 16 | #define SAFE_SPRINT sprintf_s 17 | #define SAFE_STRCAT(dst, src) strcat_s(dst, MAX_LINE_SIZE, src) 18 | #define SAFE_FOPEN fopen_s 19 | #define SAFE_STRCPY(dst, src) strcpy_s(dst, MAX_LINE_SIZE, src) 20 | #define SAFE_SSCANF sscanf_s 21 | 22 | #elif __ANDROID__ 23 | #define SAFE_SPRINT snprintf 24 | #define SAFE_STRCAT strncat 25 | #define SAFE_FOPEN fopen 26 | #define SAFE_STRCPY strncpy 27 | 28 | #elif __linux__ 29 | #define SAFE_SPRINT snprintf 30 | #define SAFE_STRCAT strncat 31 | #define SAFE_FOPEN fopen 32 | #define SAFE_STRCPY strncpy 33 | #elif __unix__ 34 | #define SAFE_SPRINT snprintf 35 | #define SAFE_STRCAT strncat 36 | #define SAFE_FOPEN fopen 37 | #define SAFE_STRCPY strncpy 38 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/SurfaceMesh/SurfaceVertexStatic.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file Vertex.h 3 | * \brief Base class of vertex 4 | * \Version 2.0 5 | * \Update 11/25/2022 6 | */ 7 | 8 | #ifndef _MESHFRAME_TETMESH_SURFACE_VERTEX_H_ 9 | #define _MESHFRAME_TETMESH_SURFACE_VERTEX_H_ 10 | 11 | #include "../../TriMesh/vertex.h" 12 | #include "../VertexStatic.h" 13 | 14 | namespace MF { 15 | namespace TetMesh { 16 | template 17 | class CSurfaceVertexStatic : public TriMesh::CVertexBase 18 | { 19 | public: 20 | CSurfaceVertexStatic() { }; 21 | ~CSurfaceVertexStatic() { } 22 | 23 | void setTetMeshVertPtr(TetMesh::CVertexStatic* in_PTetMeshVertex) { 24 | pTetMeshVertex = in_PTetMeshVertex; 25 | in_PTetMeshVertex->setSurfaceMeshVertexPtr((void*)this); 26 | } 27 | TetMesh::CVertexStatic* getTetMeshVertPtr() { 28 | return pTetMeshVertex; 29 | } 30 | 31 | IdType getTetMeshVertId() { 32 | return pTetMeshVertex->id(); 33 | } 34 | 35 | 36 | TVec3Block position() { 37 | return pTetMeshVertex->position(); 38 | } 39 | 40 | protected: 41 | TetMesh::CVertexStatic* pTetMeshVertex = nullptr; 42 | 43 | }; 44 | } 45 | } 46 | 47 | #endif //_MESHLIB_VERTEX_H_defined -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Utility/CommandParser.h: -------------------------------------------------------------------------------- 1 | #ifndef __COMMAND_PARSER__ 2 | #define __COMMAND_PARSER__ 3 | #include "cxxopts.hpp" 4 | 5 | #define REQUIRE_NUM_INPUTS(n)\ 6 | if (argc < n+1) {\ 7 | std::cout << "[Error] Need at least " << n << " input parameters!" << std::endl; \ 8 | return -1;\ 9 | } 10 | 11 | struct BaseCmdArgsParser { 12 | //bool checkFileNamesMatch = true; 13 | //int maxNumFilesToProcess = -1; 14 | 15 | BaseCmdArgsParser() : 16 | options("CalibConfig", "Configs for calibration application.") 17 | { 18 | options.add_options() 19 | //("c,checkFileNamesMatch", "Sort each lists of files and only keep file with name exists in all path lists.", cxxopts::value(checkFileNamesMatch)) 20 | //("m, maxNumFilesToProcess", "Maximum number of files to process by the calibrator.", cxxopts::value(maxNumFilesToProcess)) 21 | ; 22 | } 23 | 24 | void parse(int argc, char** argv) { 25 | try 26 | { 27 | auto result = options.parse(argc, argv); 28 | } 29 | catch (const cxxopts::OptionException& e) 30 | { 31 | std::cout << "Error parsing options: " << e.what() << std::endl; 32 | std::cout << options.help(); 33 | exit(1); 34 | } 35 | } 36 | 37 | cxxopts::Options options; 38 | 39 | 40 | }; 41 | 42 | #endif // !__COMMAND_PARSER__ 43 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/face.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file face.h 3 | * \brief Base Face Class for all types of Tetrahedron Mesh Classes 4 | * 5 | * This is the fundamental class for Face 6 | * \author David Gu 7 | * \date 10/01/2011 8 | * 9 | */ 10 | 11 | #ifndef _TMESHLIB_FACE_H_ 12 | #define _TMESHLIB_FACE_H_ 13 | 14 | #include 15 | 16 | namespace MF 17 | { 18 | namespace TetMesh 19 | { 20 | 21 | class CVertexBase; 22 | class CTVertex; 23 | class CHalfEdge; 24 | class CEdge; 25 | class CHalfFace; 26 | class CFace; 27 | class CTet; 28 | 29 | /*! 30 | * \brief CFace, base class for Face 31 | */ 32 | class CFace 33 | { 34 | public: 35 | CFace() 36 | { 37 | m_pLeft = NULL; 38 | m_pRight = NULL; 39 | m_bIsBoundary = false; 40 | }; 41 | 42 | ~CFace(){}; 43 | 44 | CHalfFace * left() { return m_pLeft; }; 45 | CHalfFace * right(){ return m_pRight; }; 46 | 47 | void SetLeft(CHalfFace * pHf) { m_pLeft = pHf; }; 48 | void SetRight(CHalfFace * pHf) { m_pRight = pHf; }; 49 | bool & boundary(){ return m_bIsBoundary; }; 50 | 51 | size_t& index() { return m_index; }; 52 | 53 | protected: 54 | 55 | CHalfFace * m_pLeft; 56 | CHalfFace * m_pRight; 57 | bool m_bIsBoundary; 58 | size_t m_index; 59 | }; 60 | }; 61 | }; 62 | 63 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/edge.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file edge.h 3 | * \brief Base edge Class for all types of Tetrahedron Mesh Classes 4 | * 5 | * This is the fundamental class for edge 6 | * \author David Gu 7 | * \date 10/01/2011 8 | * 9 | */ 10 | 11 | #ifndef _TMESHLIB_EDGE_H_ 12 | #define _TMESHLIB_EDGE_H_ 13 | 14 | #include 15 | #include 16 | 17 | 18 | namespace MF 19 | { 20 | namespace TetMesh 21 | { 22 | class CVertexBase; 23 | class CTVertex; 24 | class CHalfEdge; 25 | class CEdge; 26 | class CHalfFace; 27 | class CFace; 28 | class CTet; 29 | 30 | /*! 31 | * \brief CEdge, base class for edge 32 | */ 33 | class CEdge //Edge among tets 34 | { 35 | public: 36 | 37 | CEdge() { m_vertices[0] = NULL; m_vertices[1] = NULL; m_bIsBoundary = false; }; 38 | 39 | ~CEdge() { m_lTEdges.clear(); }; 40 | 41 | std::vector * edges() { return &m_lTEdges; }; 42 | 43 | bool & boundary() { return m_bIsBoundary; }; 44 | 45 | CVertexBase* vertex1() { return m_vertices[0]; }; 46 | CVertexBase* vertex2() { return m_vertices[1]; }; 47 | 48 | void SetVertex1(CVertexBase* v) { m_vertices[0] = v; }; 49 | void SetVertex2(CVertexBase* v) { m_vertices[1] = v; }; 50 | 51 | public: 52 | size_t& index() { return m_index; }; 53 | private: 54 | size_t m_index; 55 | protected: 56 | std::vector m_lTEdges; 57 | CVertexBase* m_vertices[2]; 58 | bool m_bIsBoundary; 59 | 60 | }; 61 | 62 | }; 63 | }; 64 | 65 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/tet.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file tet.h 3 | * \brief Base tet Class for all types of Tetrahedron Mesh Classes 4 | * 5 | * This is the fundamental class for tet 6 | * \author David Gu 7 | * \date 10/01/2011 8 | * 9 | */ 10 | 11 | #ifndef _TMESHLIB_TET_H_ 12 | #define _TMESHLIB_TET_H_ 13 | 14 | #include 15 | namespace MF 16 | { 17 | namespace TetMesh 18 | { 19 | class CVertexBase; 20 | class CTVertex; 21 | class CHalfEdge; 22 | class CEdge; 23 | class CHalfFace; 24 | class CFace; 25 | class CTet; 26 | 27 | /*! 28 | * \brief CTet, base class for Tet 29 | */ 30 | class CTet 31 | { 32 | public: 33 | 34 | CTet() { m_iID = 0; }; 35 | ~CTet(){}; 36 | 37 | CHalfFace * half_face(int j) { return m_pHalfFace[j]; }; 38 | CTVertex * tvertex(int j) { return m_pTVertex[j]; }; 39 | CVertexBase* vertex(int j) { return m_pTVertex[j]->vert(); }; 40 | const CVertexBase* vertex(int j) const { return m_pTVertex[j]->vert(); }; 41 | void setTVertex(CTVertex * pTV, int j) { m_pTVertex[j] = pTV; }; 42 | void setHalfFace(CHalfFace * pHF, int j) { m_pHalfFace[j] = pHF; }; 43 | 44 | int & id() { return m_iID; }; 45 | 46 | virtual void _from_string() { }; 47 | virtual void _to_string() { }; 48 | 49 | public: 50 | size_t& index() { return m_index; }; 51 | private: 52 | size_t m_index; 53 | protected: 54 | 55 | CHalfFace * m_pHalfFace[4]; 56 | CTVertex * m_pTVertex[4]; 57 | int m_iID; 58 | }; 59 | }; 60 | }; 61 | 62 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/tvertex.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file tvertex.h 3 | * \brief Base tvertex Class for all types of Tetrahedron Mesh Classes 4 | * 5 | * This is the fundamental class for tvertex 6 | * \author David Gu 7 | * \date 10/01/2011 8 | * 9 | */ 10 | 11 | #ifndef _TMESHLIB_TVERTEX_H_ 12 | #define _TMESHLIB_TVERTEX_H_ 13 | 14 | #include 15 | 16 | namespace MF 17 | { 18 | namespace TetMesh 19 | { 20 | 21 | class CVertexBase; 22 | class CHalfEdge; 23 | class CEdge; 24 | class CHalfFace; 25 | class CFace; 26 | class CTet; 27 | 28 | 29 | /*! 30 | * \brief CTVertex, base class for Tetrahedron vertex 31 | */ 32 | class CTVertex 33 | { 34 | public: 35 | CTVertex() { m_pVertex = NULL; m_pTet = NULL; m_pHalfedge = NULL; }; 36 | ~CTVertex() {}; 37 | 38 | int & id() { return m_iID; }; 39 | 40 | CVertexBase* vert() { return m_pVertex; }; 41 | CTet * tet() { return m_pTet; }; 42 | CHalfEdge * halfedge() { return m_pHalfedge; }; 43 | 44 | void set_vert(CVertexBase * pV) { m_pVertex = pV; }; 45 | void set_tet(CTet * pT) { m_pTet = pT; }; 46 | void set_halfedge(CHalfEdge * pH) { m_pHalfedge = pH; }; 47 | 48 | public: 49 | size_t& index() { return m_index; }; 50 | private: 51 | size_t m_index; 52 | protected: 53 | //vertex ID 54 | int m_iID; 55 | CVertexBase* m_pVertex; 56 | CTet * m_pTet; 57 | //outgoing, halfedge start from this TVertex 58 | CHalfEdge * m_pHalfedge; 59 | }; 60 | 61 | }; 62 | }; 63 | 64 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Utility/IO.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | //#ifdef _WIN32 8 | //#include 9 | //#endif 10 | 11 | namespace MF { 12 | struct IO 13 | { 14 | struct FileParts 15 | { 16 | FileParts() {} 17 | FileParts(std::string filename) { 18 | std::replace(filename.begin(), filename.end(), '\\', '/'); // replace all '\' to '/', 19 | 20 | int idx0 = filename.rfind("/"); 21 | 22 | int idx1 = filename.rfind("."); 23 | 24 | path = filename.substr(0, idx0 + 1); 25 | name = filename.substr(idx0 + 1, idx1 - idx0 - 1); 26 | if (idx1 != -1) { 27 | ext = filename.substr(idx1); 28 | } 29 | else 30 | { 31 | ext = ""; 32 | } 33 | } 34 | std::string path; 35 | std::string name; 36 | std::string ext; 37 | }; 38 | 39 | static FileParts fileparts(std::string filename) 40 | { 41 | std::replace(filename.begin(), filename.end(), '\\', '/'); // replace all '\' to '/', 42 | 43 | int idx0 = filename.rfind("/"); 44 | 45 | int idx1 = filename.rfind("."); 46 | 47 | FileParts fp; 48 | fp.path = filename.substr(0, idx0 + 1); 49 | fp.name = filename.substr(idx0 + 1, idx1 - idx0 - 1); 50 | if (idx1 != -1) { 51 | fp.ext = filename.substr(idx1); 52 | } 53 | else 54 | { 55 | fp.ext = ""; 56 | } 57 | 58 | return fp; 59 | } 60 | 61 | // Returns false on success, true on error 62 | static bool createFolder(std::string folderName); 63 | static bool folderExists(const char* folderName); 64 | 65 | static bool copyFile(std::string src, std::string dst); 66 | 67 | }; 68 | } -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Utility/Str.h: -------------------------------------------------------------------------------- 1 | #ifndef _MESHFRAME_STR_H_ 2 | #define _MESHFRAME_STR_H_ 3 | #include 4 | #include 5 | 6 | namespace MF { 7 | struct STR 8 | { 9 | static void split(std::vector& result, const char* str, char c = ' ') 10 | { 11 | do 12 | { 13 | const char* begin = str; 14 | 15 | while (*str != c && *str) 16 | str++; 17 | 18 | result.push_back(std::string(begin, str)); 19 | } while (0 != *str++); 20 | 21 | return; 22 | } 23 | 24 | static std::string padToNew(const std::string& str, const size_t num, const char paddingChar = ' ') 25 | { 26 | std::string newStr = str; 27 | if (num > newStr.size()) 28 | newStr.insert(0, num - newStr.size(), paddingChar); 29 | 30 | return newStr; 31 | } 32 | 33 | static void padTo(std::string& str, const size_t num, const char paddingChar = ' ') 34 | { 35 | if (num > str.size()) 36 | str.insert(0, num - str.size(), paddingChar); 37 | } 38 | 39 | static std::string replace(std::string& inStr, const std::string subStrToReplace, const std::string replacement, bool replaceAll = true) { 40 | if (!inStr.size()) 41 | { 42 | return inStr; 43 | } 44 | std::string outStr; 45 | size_t index = 0; 46 | outStr = inStr; 47 | do { 48 | /* Locate the substring to replace. */ 49 | index = outStr.find(subStrToReplace, index); 50 | if (index == std::string::npos) break; 51 | 52 | /* Make the replacement. */ 53 | outStr.replace(index, subStrToReplace.size(), replacement); 54 | 55 | /* Advance index forward so the next iteration doesn't pick it up as well. */ 56 | index += 3; 57 | } while (replaceAll); 58 | 59 | return outStr; 60 | }; 61 | }; 62 | } 63 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/vertex.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file vertex.h 3 | * \brief Base vertex Class for all types of Tetrahedron Mesh Classes 4 | * 5 | * This is the fundamental class for vertex 6 | * \date 10/10/2022 7 | * 8 | */ 9 | 10 | #ifndef _TMESHLIB_VERTEX_H_ 11 | #define _TMESHLIB_VERTEX_H_ 12 | 13 | #include 14 | #include 15 | #include "../Memory/Array.h" 16 | 17 | namespace MF 18 | { 19 | namespace TetMesh 20 | { 21 | class CTVertex; 22 | class CHalfEdge; 23 | class CEdge; 24 | class CTEdge; 25 | class CHalfFace; 26 | class CFace; 27 | class CTet; 28 | 29 | typedef std::vector CEArray; 30 | typedef std::vector CTVArray; 31 | 32 | class CVertexBase 33 | { 34 | public: 35 | CVertexBase() { m_index = 0; m_bIsBoundary = false; }; 36 | ~CVertexBase(){ } 37 | 38 | virtual int& id() { return m_id; }; 39 | size_t & index() { return m_index; }; 40 | bool & boundary() { return m_bIsBoundary; }; 41 | 42 | CEArray * edges() { return &m_pEdges; }; 43 | CTVArray * tvertices() { return &m_pTVertices; }; 44 | std::list * HalfFaces(){ return &m_pHFaces; }; 45 | 46 | void setSurfaceMeshVertexPtr(void* in_PSurfaceMeshVertex) { 47 | pSurfaceMeshVertex = in_PSurfaceMeshVertex; 48 | } 49 | 50 | void* getSurfaceMeshVertexPtr() { 51 | return pSurfaceMeshVertex; 52 | } 53 | 54 | protected: 55 | int m_id; 56 | size_t m_index; 57 | bool m_bIsBoundary; 58 | 59 | std::list m_pHFaces; //temporary HalfFace list, will be empty after loading the whole mesh 60 | 61 | CTVArray m_pTVertices; //adjacent TVertecies 62 | CEArray m_pEdges; //adjacent Edges; 63 | 64 | //std::string m_string; 65 | void* pSurfaceMeshVertex = nullptr; 66 | 67 | }; 68 | }; 69 | }; 70 | 71 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/Face.h: -------------------------------------------------------------------------------- 1 | #ifndef _MESHFRAME_FACE_H_ 2 | #define _MESHFRAME_FACE_H_ 3 | /*! 4 | * \file Face.h 5 | * \brief Base class of face 6 | * 7 | * \Version 1.0 8 | * \Update 11/03/2022 9 | */ 10 | #include 11 | 12 | #define STRINGSIZE 256 13 | 14 | namespace MF{ 15 | namespace TriMesh { 16 | 17 | 18 | class CHalfEdge; 19 | 20 | /*! 21 | \brief CFace base class of all kinds of face classes 22 | */ 23 | class CFace 24 | { 25 | public: 26 | /*! 27 | CFace constructor 28 | */ 29 | CFace() { m_halfedge = NULL; }; 30 | /*! 31 | CFace destructor 32 | */ 33 | ~CFace() {}; 34 | /*! 35 | One of the halfedges attaching to the current face. 36 | */ 37 | CHalfEdge*& halfedge() { return m_halfedge; }; 38 | /*! 39 | index of the current face 40 | */ 41 | size_t& index() { return m_index; }; 42 | /*! 43 | The reference to the current face id 44 | */ 45 | int& id() { return m_id; }; 46 | /*! 47 | The value of the current face id. 48 | */ 49 | const int id() const { return m_id; }; 50 | 51 | //virtual bool hasNormal() { 52 | // return false; 53 | //} 54 | //virtual CPoint & normal() { 55 | // static CPoint _normal; 56 | // printf("Face does not have normal!\n"); 57 | // assert(false); 58 | // system("pause"); 59 | // return _normal; 60 | //} 61 | 62 | //virtual bool hasColor() { 63 | // return false; 64 | //} 65 | //virtual ColorUnion & color() { 66 | // printf("Face does not have color!\n"); 67 | // static ColorUnion _color; 68 | // assert(false); 69 | // system("pause"); 70 | // return _color; 71 | //} 72 | protected: 73 | /*! 74 | index of the current face 75 | */ 76 | size_t m_index; 77 | /*! 78 | id of the current face 79 | */ 80 | int m_id; 81 | /*! 82 | One halfedge attaching to the current face. 83 | */ 84 | CHalfEdge* m_halfedge; 85 | }; 86 | 87 | }//name space TriMesh 88 | }//name space MF 89 | 90 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/tedge.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file tedge.h 3 | * \brief Base tedge Class for all types of Tetrahedron Mesh Classes 4 | * 5 | * This is the fundamental class for tedge 6 | * \author David Gu 7 | * \date 10/01/2011 8 | * 9 | */ 10 | 11 | #ifndef _TMESHLIB_TEDGE_H_ 12 | #define _TMESHLIB_TEDGE_H_ 13 | 14 | #include 15 | #include "halfedge.h" 16 | namespace MF 17 | { 18 | namespace TetMesh 19 | { 20 | 21 | class CVertexBase; 22 | class CTVertex; 23 | class CHalfEdge; 24 | class CEdge; 25 | class CHalfFace; 26 | class CFace; 27 | class CTet; 28 | 29 | /*! 30 | * \brief CTEdge, base class for tedge 31 | */ 32 | class CTEdge //Edge inside a tetrahedron 33 | { 34 | public: 35 | 36 | CTEdge(){ m_pLeft = NULL; m_pRight = NULL; }; 37 | ~CTEdge(){}; 38 | 39 | CHalfEdge * left() { return m_pLeft; }; 40 | CHalfEdge * right(){ return m_pRight; }; 41 | CEdge * edge() { return m_pEdge; }; 42 | CTet * tet() { return m_pTet; }; 43 | CTEdge * dual() { return m_pLeft->prev()->dual()->next()->tedge(); } //tedge in the same tet, against the current one 44 | 45 | 46 | void SetLeft(CHalfEdge * pHe) { m_pLeft = pHe; }; 47 | void SetRight(CHalfEdge* pHe) { m_pRight = pHe; }; 48 | void SetEdge(CEdge * pE) { m_pEdge = pE; }; 49 | void SetTet(CTet * pT) { m_pTet = pT; }; 50 | 51 | bool operator==(const CTEdge & e) 52 | { 53 | //for (int i = 0; i < 2; i++) 54 | //{ 55 | // if (m_key[i] != e.m_key[i]) return false; 56 | //} 57 | //return true; 58 | 59 | return m_key[0] == e.m_key[0] && m_key[1] == e.m_key[1]; 60 | } 61 | 62 | int & key(int k) { return m_key[k]; }; 63 | 64 | public: 65 | size_t& index() { return m_index; }; 66 | private: 67 | size_t m_index; 68 | protected: 69 | 70 | CHalfEdge * m_pLeft; 71 | CHalfEdge * m_pRight; 72 | CEdge * m_pEdge; 73 | CTet * m_pTet; 74 | int m_key[2]; // The ids of the two vertices on the tdge, sorted thus m_key[0] < m_key[1] 75 | 76 | }; 77 | }; 78 | }; 79 | 80 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/halfface.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file halfface.h 3 | * \brief Base HalfFace Class for all types of Tetrahedron Mesh Classes 4 | * 5 | * This is the fundamental class for HalfFace 6 | * \author David Gu 7 | * \date 10/01/2011 8 | * 9 | */ 10 | 11 | #ifndef _TMESHLIB_HALFFACE_H_ 12 | #define _TMESHLIB_HALFFACE_H_ 13 | 14 | #include 15 | 16 | namespace MF 17 | { 18 | namespace TetMesh 19 | { 20 | 21 | class CVertexBase; 22 | class CTVertex; 23 | class CHalfEdge; 24 | class CEdge; 25 | class CHalfFace; 26 | class CFace; 27 | class CTet; 28 | 29 | /*! 30 | * \brief CHalfFace, base class for HalfFace 31 | */ 32 | class CHalfFace 33 | { 34 | public: 35 | CHalfFace() 36 | { 37 | m_pHalfEdge = nullptr; 38 | m_pFace = nullptr; 39 | m_pTet = nullptr; 40 | m_pDual = nullptr; 41 | }; 42 | 43 | ~CHalfFace(){}; 44 | 45 | CHalfEdge * half_edge() { return m_pHalfEdge; }; 46 | CFace * face() { return m_pFace; }; 47 | CTet * tet() { return m_pTet; }; 48 | CHalfFace * dual() { return m_pDual; }; 49 | int & key(int k) { return m_key[k]; }; 50 | 51 | void SetHalfEdge(CHalfEdge * pHe) { m_pHalfEdge = pHe; }; 52 | void SetFace(CFace * pF) { m_pFace = pF; }; 53 | void SetTet(CTet * pT) { m_pTet = pT; }; 54 | void SetDual(CHalfFace *pF) { m_pDual = pF; }; 55 | bool operator==(const CHalfFace & f) 56 | { 57 | for (int i = 0; i < 3; i++) 58 | if (m_key[i] != f.m_key[i]) return false; 59 | return true; 60 | }; 61 | 62 | void setSurfaceMeshFacePtr(void * in_pSurfaceMeshFace) { 63 | m_surfaceFace = in_pSurfaceMeshFace; 64 | } 65 | 66 | void* getSurfaceFacePtr() { 67 | return m_surfaceFace; 68 | } 69 | 70 | public: 71 | size_t& index() { return m_index; }; 72 | private: 73 | size_t m_index; 74 | 75 | 76 | protected: 77 | 78 | CHalfEdge * m_pHalfEdge; 79 | CFace * m_pFace; 80 | CTet * m_pTet; 81 | CHalfFace * m_pDual; 82 | int m_key[3]; 83 | void * m_surfaceFace = nullptr; 84 | }; 85 | }; 86 | }; 87 | 88 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Utility/IO.cpp: -------------------------------------------------------------------------------- 1 | #include "IO.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #ifdef _WIN32 10 | #include 11 | #include 12 | #include 13 | #include 14 | #endif 15 | 16 | using namespace MF; 17 | 18 | bool IO::folderExists(const char* folderName) 19 | { 20 | if (_access(folderName, 0) == -1) { 21 | //File not found 22 | return false; 23 | } 24 | 25 | DWORD attr = GetFileAttributes((LPCSTR)folderName); 26 | if (!(attr & FILE_ATTRIBUTE_DIRECTORY)) { 27 | // File is not a directory 28 | return false; 29 | } 30 | 31 | return true; 32 | } 33 | 34 | bool IO::copyFile(std::string src, std::string dst) 35 | { 36 | std::ifstream is(src, std::ios::in | std::ios::binary); 37 | std::ofstream os(dst, std::ios::out | std::ios::binary); 38 | 39 | if (is.is_open() && os.is_open()) { 40 | 41 | std::copy(std::istreambuf_iterator(is), std::istreambuf_iterator(), 42 | std::ostreambuf_iterator(os)); 43 | os.close(); 44 | is.close(); 45 | return true; 46 | } 47 | else 48 | { 49 | return false; 50 | } 51 | } 52 | 53 | bool IO::createFolder(std::string folderName) 54 | { 55 | std::list folderLevels; 56 | char* c_str = (char*)folderName.c_str(); 57 | 58 | // Point to end of the string 59 | char* strPtr = &c_str[strlen(c_str) - 1]; 60 | 61 | // Create a list of the folders which do not currently exist 62 | do { 63 | if (folderExists(c_str)) { 64 | break; 65 | } 66 | // Break off the last folder name, store in folderLevels list 67 | do { 68 | strPtr--; 69 | } while ((*strPtr != '\\') && (*strPtr != '/') && (strPtr >= c_str)); 70 | folderLevels.push_front(std::string(strPtr + 1)); 71 | strPtr[1] = 0; 72 | } while (strPtr >= c_str); 73 | 74 | if (_chdir(c_str)) { 75 | return true; 76 | } 77 | 78 | // Create the folders iteratively 79 | for (std::list::iterator it = folderLevels.begin(); it != folderLevels.end(); it++) { 80 | if (CreateDirectory(it->c_str(), NULL) == 0) { 81 | return true; 82 | } 83 | _chdir(it->c_str()); 84 | } 85 | 86 | return false; 87 | } -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/halfedge.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file halfedge.h 3 | * \brief Base tvertex Class for all types of Tetrahedron Mesh Classes 4 | * 5 | * This is the fundamental class for tvertex 6 | * \author David Gu 7 | * \date 10/01/2011 8 | * 9 | */ 10 | 11 | #ifndef _TMESHLIB_HALFEDGE_H_ 12 | #define _TMESHLIB_HALFEDGE_H_ 13 | 14 | #include 15 | 16 | namespace MF 17 | { 18 | namespace TetMesh 19 | { 20 | class CVertexBase; 21 | class CTVertex; 22 | class CHalfEdge; 23 | class CEdge; 24 | class CHalfFace; 25 | class CFace; 26 | class CTet; 27 | 28 | /*! 29 | * \brief CHalfEdge, base class for Half edge 30 | */ 31 | class CHalfEdge 32 | { 33 | public: 34 | CHalfEdge() 35 | { 36 | //m_pSource = NULL; 37 | m_pTarget = NULL; 38 | m_pDual = NULL; 39 | m_pNext = NULL; 40 | m_pPrev = NULL; 41 | m_pTEdge = NULL; 42 | m_pHalfFace = NULL; 43 | }; 44 | 45 | ~CHalfEdge(){}; 46 | 47 | CVertexBase* source() { return m_pPrev->target(); }; 48 | CVertexBase* target() { return m_pTarget->vert(); }; 49 | 50 | CTVertex * tSource() { return m_pPrev->tTarget(); }; 51 | CTVertex * tTarget() { return m_pTarget; }; 52 | 53 | CHalfEdge* dual() { return m_pDual; }; 54 | CHalfEdge* next() { return m_pNext; }; 55 | CHalfEdge* prev() { return m_pPrev; }; 56 | CTEdge * tedge(){ return m_pTEdge; }; 57 | CHalfFace* half_face() { return m_pHalfFace; }; 58 | 59 | //void SetSource(CTVertex* pVert){ m_pSource = pVert; }; 60 | void SetTarget(CTVertex* pVert){ m_pTarget = pVert; }; 61 | void SetDual(CHalfEdge* pHe){ m_pDual = pHe; }; 62 | void SetNext(CHalfEdge* pHe){ m_pNext = pHe; }; 63 | void SetPrev(CHalfEdge* pHe){ m_pPrev = pHe; }; 64 | void SetTEdge(CTEdge* pTe){ m_pTEdge = pTe; }; 65 | void SetHalfFace(CHalfFace *pF){ m_pHalfFace = pF; }; 66 | 67 | public: 68 | size_t& index() { return m_index; }; 69 | private: 70 | size_t m_index; 71 | 72 | protected: 73 | 74 | //CTVertex *m_pSource; 75 | CTVertex *m_pTarget; 76 | CHalfEdge *m_pDual; 77 | CHalfEdge *m_pNext; 78 | CHalfEdge *m_pPrev; 79 | CTEdge *m_pTEdge; 80 | CHalfFace *m_pHalfFace; 81 | 82 | }; 83 | }; 84 | }; 85 | 86 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/Edge.h: -------------------------------------------------------------------------------- 1 | #ifndef _MESHFRAME_EDGE_H_ 2 | #define _MESHFRAME_EDGE_H_ 3 | /*! 4 | * \file Edge.h 5 | * \brief Base class of edge 6 | * 7 | * \Version 2.0 8 | * \Update 11/03/2022 9 | */ 10 | 11 | #include 12 | #include 13 | #include 14 | #include "HalfEdge.h" 15 | 16 | #define STRINGSIZE 256 17 | 18 | namespace MF { 19 | namespace TriMesh { 20 | 21 | class CHalfEdge; 22 | class CVertexBase; 23 | 24 | /*! 25 | \brief CEdge class, which is the base class of all kinds of edge classes 26 | */ 27 | class CEdge 28 | { 29 | public: 30 | /*! 31 | CEdge constructor, set both halfedge pointers to be NULL. 32 | */ 33 | CEdge() {}; 34 | /*! 35 | CEdge destructor. 36 | */ 37 | ~CEdge() {}; 38 | /*! 39 | Edge index. 40 | */ 41 | size_t& index() { return m_index; }; 42 | /*! 43 | Edge ID 44 | */ 45 | virtual int& id() { return m_id; }; 46 | 47 | /*! 48 | The halfedge attached to the current edge 49 | \param id either 0 or 1 50 | \return the halfedge[id] 51 | */ 52 | CHalfEdge* halfedge(int id) { 53 | switch (id) 54 | { 55 | case 0: 56 | return m_halfedge; 57 | break; 58 | case 1: 59 | if (m_halfedge != NULL) 60 | { 61 | return m_halfedge->he_sym(); 62 | } 63 | else { 64 | return NULL; 65 | } 66 | break; 67 | default: 68 | break; 69 | } 70 | }; 71 | CHalfEdge*& halfedge() { return m_halfedge; }; 72 | /*! 73 | whether the edge is on the boundary. 74 | */ 75 | bool boundary() { return (m_halfedge->he_sym() == NULL); }; 76 | /*! 77 | The dual halfedge to the input halfedge 78 | \param he halfedge attached to the current edge 79 | \return the other halfedge attached to the current edge 80 | */ 81 | CHalfEdge*& other(CHalfEdge* he) { return he->he_sym(); }; 82 | /*! 83 | The string of the current edge. 84 | */ 85 | //char * string() { return m_string; }; 86 | /*! 87 | Read the traits from the string. 88 | */ 89 | //virtual void _from_string(const char* str) {}; 90 | ///*! 91 | // Save the traits to the string, whose Maximum length is MAX_TRAIT_LINE in BaseMesh.h. 92 | //*/ 93 | //virtual void _to_string(char* str) {}; 94 | 95 | //virtual bool hasColor() { 96 | // return false; 97 | //} 98 | //virtual ColorUnion& color() { 99 | // static ColorUnion _color; 100 | // printf("Face does not have normal!\n"); 101 | // assert(false); 102 | // system("pause"); 103 | // return _color; 104 | //} 105 | protected: 106 | 107 | /*! 108 | Pointer to the two halfedges attached to the current edge. 109 | */ 110 | CHalfEdge* m_halfedge = NULL; 111 | 112 | /*! 113 | Edge index. 114 | */ 115 | size_t m_index; 116 | 117 | int m_id; 118 | 119 | }; 120 | 121 | }//namespace TriMesh 122 | 123 | }//namespace MF 124 | 125 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Memory/MPIterator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | /*! 4 | * \file MPIterator.h 5 | * \brief Iterators for accessing MemoryPool 6 | * \date 01/06/2018 7 | */ 8 | 9 | template 10 | class MemoryPool; 11 | 12 | template 13 | class MPIterator : public std::iterator{ 14 | public: 15 | typedef typename std::vector::iterator MemberIter; 16 | public: 17 | /*Construct*/ 18 | MPIterator(MemberIter viter, size_t index, size_t blocksize, size_t size, std::vector& _deleteMask, size_t _memberTSize) 19 | :mCurrentViter(viter), mIndex(index), mBlockSize(blocksize), mSize(size), deleteMask(_deleteMask), memberTSize(_memberTSize) 20 | { 21 | bool ifFindBegin = false; 22 | mBlockOffset = mIndex % mBlockSize; 23 | while (mIndex < mSize) 24 | { 25 | mCurrentBlock = (*mCurrentViter); 26 | while (mBlockOffset < mBlockSize && mIndex < mSize) 27 | { 28 | if (!deleteMask[mIndex]) 29 | { 30 | ifFindBegin = true; 31 | break; 32 | } 33 | mBlockOffset++; 34 | mIndex++; 35 | } 36 | if (ifFindBegin == true) break; 37 | mBlockOffset = 0; 38 | mCurrentViter++; 39 | } 40 | }; 41 | /*! 42 | The pointer, gained from MemoryPool->getPointer(index) 43 | */ 44 | T * value() { return (T*)(mCurrentBlock + mBlockOffset * memberTSize ); } 45 | /*! 46 | The pointer, gained from MemoryPool->getPointer(index) 47 | */ 48 | T * operator*() { return (T*)(mCurrentBlock + mBlockOffset * memberTSize); } 49 | /*! 50 | MPIterator prefix operator ++, goes to the next pointer 51 | */ 52 | MPIterator & operator++() 53 | { 54 | mIndex++; 55 | // if already meets the last element, it will not proceed; 56 | if (mIndex >= mSize) return *this; 57 | mBlockOffset++; 58 | if (mBlockOffset >= mBlockSize) 59 | { 60 | mBlockOffset = 0; 61 | mCurrentViter++; 62 | mCurrentBlock = (*mCurrentViter); 63 | } 64 | while (deleteMask[mIndex]) 65 | { 66 | mIndex++; 67 | if (mIndex >= mSize) break; 68 | mBlockOffset++; 69 | if (mBlockOffset >= mBlockSize) 70 | { 71 | mBlockOffset = 0; 72 | mCurrentViter++; 73 | mCurrentBlock = (*mCurrentViter); 74 | } 75 | } 76 | return *this; 77 | } 78 | /*! 79 | MPIterator postfix operator ++, goes to the next pointer 80 | */ 81 | MPIterator & operator++(int) 82 | { 83 | if (mIndex >= mSize) return *this; 84 | mIndex++; 85 | mBlockOffset++; 86 | if (mBlockOffset >= mBlockSize) 87 | { 88 | mBlockOffset = 0; 89 | mCurrentViter++; 90 | mCurrentBlock = (*mCurrentViter); 91 | } 92 | if (mIndex >= mSize) return *this; 93 | while (deleteMask[mIndex]) 94 | { 95 | mIndex++; 96 | mBlockOffset++; 97 | if (mBlockOffset >= mBlockSize) 98 | { 99 | mBlockOffset = 0; 100 | mCurrentViter++; 101 | mCurrentBlock = (*mCurrentViter); 102 | } 103 | if (mIndex >= mSize) return *this; 104 | } 105 | return *this; 106 | } 107 | /*! 108 | MPIterator operator ==, judge if two iterators are equal 109 | */ 110 | bool operator==(const MPIterator & otherIter) { return mIndex == otherIter.mIndex; } 111 | /*! 112 | MPIterator operator !=, judge if two iterators are not equal 113 | */ 114 | bool operator!=(const MPIterator & otherIter) { return mIndex != otherIter.mIndex; } 115 | 116 | public: 117 | /*Current vector iterator*/ 118 | MemberIter mCurrentViter; 119 | /*Current Index*/ 120 | size_t mIndex; 121 | /*Block's size*/ 122 | size_t mBlockSize; 123 | /*Max size*/ 124 | size_t mSize; 125 | /*Size of a member in MemoryPool*/ 126 | size_t mMemberSize; 127 | /*Current block's offset*/ 128 | size_t mBlockOffset; 129 | /*Current Block*/ 130 | char* mCurrentBlock; 131 | /*Deleted mask of wether a member has been deleted*/ 132 | std::vector & deleteMask; 133 | /*Size of true member*/ 134 | const size_t memberTSize; 135 | }; 136 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/SurfaceMesh/SurfaceMeshStatic.h: -------------------------------------------------------------------------------- 1 | #ifndef _TMESHLIB_SURFACE_MESH_H_ 2 | #define _TMESHLIB_SURFACE_MESH_H_ 3 | 4 | //#include "../TIterators.h" 5 | 6 | namespace MF 7 | { 8 | namespace TetMesh 9 | { 10 | // VertexType must be a child class of SurfaceVertexStatic (defined in SurfaceVertex.h) 11 | // FaceType must be a child class of CSurfaceFace 12 | template 13 | class CSurfaceMeshStatic : public TriMesh::CMeshBase { 14 | public: 15 | template 16 | void initialize(CTetMeshStatic* pTetMesh) { 17 | typedef MF::TetMesh::TIterators TItParent; 18 | 19 | std::vector _surfaceVerts; 20 | std::vector _surfaceFaces; 21 | 22 | pTetMesh->tetMeshSurfaceMesh(_surfaceVerts, _surfaceFaces); 23 | 24 | for (int iV = 0; iV < _surfaceVerts.size(); iV++) 25 | { 26 | VertexType* currentVertex = createVertexWithId(_surfaceVerts[iV]->id()); 27 | currentVertex->setTetMeshVertPtr(_surfaceVerts[iV]); 28 | } 29 | 30 | for (int iF = 0; iF < _surfaceFaces.size(); iF++) 31 | { 32 | VertexType* currentVs[3]; 33 | /*Assume each face is a triangle*/ 34 | //int fV = 0; 35 | //for (typename CTetMeshStatic::VPtr pFV : TItParent::HF_VIterator(_surfaceFaces[iF])) { 36 | // int vId = pFV->id(); 37 | // currentVs[fV] = mVMap[vId]; 38 | // fV++; 39 | //} 40 | 41 | typename CTetMeshStatic::HEPtr pHE = (CTetMeshStatic::HEPtr)_surfaceFaces[iF]->half_edge(); 42 | for (int fV = 0; fV < 3; ++fV) { 43 | int vId = pHE->source()->id(); 44 | currentVs[fV] = mVMap[vId]; 45 | 46 | pHE = (CTetMeshStatic::HEPtr)pHE->next(); 47 | } 48 | 49 | FaceType* currentFace = createFace(currentVs, iF); 50 | currentFace->setTetMeshHalfFacePtr(_surfaceFaces[iF]); 51 | 52 | mFIdMap.insert(FIdMapPair(iF, currentFace)); 53 | } 54 | 55 | /*Label boundary edges*/ 56 | for (int i = 0; i < mEContainer.getCurrentIndex(); ++i) 57 | { 58 | EdgeType* currentE = mEContainer.getPointer(i); 59 | HalfEdgeType* currentHE0 = edgeHalfedge(currentE, 0); 60 | HalfEdgeType* currentHE1 = edgeHalfedge(currentE, 1); 61 | if (currentHE1 == NULL) 62 | { 63 | currentHE0->source()->boundary() = true; 64 | currentHE0->target()->boundary() = true; 65 | } 66 | } 67 | /*Remove isolated vertex*/ 68 | int numIsolatedVertices = 0; 69 | 70 | std::vector isolatedVertexs; 71 | //#pragma omp parallel for 72 | for (int i = 0; i < mVContainer.getCurrentIndex(); ++i) 73 | { 74 | VertexType* currentV = mVContainer.getPointer(i); 75 | if (mVContainer.hasBeenDeleted(currentV->index()) == false) 76 | { 77 | if (currentV->halfedge() != NULL) continue; 78 | isolatedVertexs.push_back(currentV); 79 | } 80 | } 81 | 82 | assert(isolatedVertexs.size()== 0); 83 | 84 | /* 85 | * Arrange the boundary half_edge of boundary vertices, to make its halfedge 86 | * to be the most ccw in half_edge 87 | */ 88 | for (int i = 0; i < mVContainer.getCurrentIndex(); ++i) 89 | { 90 | VertexType* currentV = mVContainer.getPointer(i); 91 | if (mVContainer.hasBeenDeleted(currentV->index()) == false) 92 | { 93 | if (!currentV->boundary()) continue; 94 | HalfEdgeType* currentHE = vertexMostCcwInHalfEdge(currentV); 95 | currentV->halfedge() = currentHE; 96 | } 97 | } 98 | mVMap.clear(); 99 | } 100 | 101 | private: 102 | void readVFList(const std::vector>* verts, 103 | const std::vector>* faces, const std::vector* vIds = nullptr, bool removeIsolatedVerts = true) = delete; 104 | 105 | void read_obj(const char* filename, bool removeIsolatedVertices = true) = delete; 106 | 107 | void read_ply(const char* input) = delete; 108 | void read_off(const char* input) = delete; 109 | 110 | void copy() = delete; 111 | 112 | void* pTetMesh = nullptr; 113 | 114 | }; 115 | } 116 | } 117 | 118 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/HalfEdge.h: -------------------------------------------------------------------------------- 1 | #ifndef _MESHFRAME_HALFEDGE_H_ 2 | #define _MESHFRAME_HALFEDGE_H_ 3 | /*! 4 | * \file HalfEdge.h 5 | * \brief Base class of HalfEdge 6 | * \Version 1.0 7 | * \Update 11/03/2022 8 | */ 9 | 10 | #include 11 | #include 12 | 13 | namespace MF { 14 | namespace TriMesh { 15 | class CVertexBase; 16 | class CEdge; 17 | class CFace; 18 | 19 | /*! 20 | * \brief CHalfEdge Base class of all kinds of halfedges. 21 | */ 22 | class CHalfEdge 23 | { 24 | public: 25 | 26 | /*! Constructor, initialize all pointers to be NULL. 27 | */ 28 | CHalfEdge() {}; 29 | /*! Destructure. 30 | */ 31 | ~CHalfEdge() {}; 32 | 33 | /*! Index, current halfedge's index*/ 34 | size_t& index() { return m_index; }; 35 | /*! Pointer to the edge attaching to the current halfedge. */ 36 | CEdge*& edge() { return m_edge; }; 37 | /*! Target vertex of the current halfedge. */ 38 | CVertexBase*& vertex() { return m_vertex; }; 39 | /*! Target vertex of the current halfedge. */ 40 | CVertexBase*& target() { return m_vertex; }; 41 | /*! Source vertex of the current halfedge. */ 42 | CVertexBase*& source() { return m_prev->vertex(); }; 43 | /*! Previous halfedge of the current halfedge. */ 44 | CHalfEdge*& he_prev() { return m_prev; }; 45 | /*! Next halfedge of the current halfedge. */ 46 | CHalfEdge*& he_next() { return m_next; }; 47 | /*! The dual halfedge of the current halfedge. */ 48 | CHalfEdge*& he_sym() { return m_sym; }; 49 | /*! The face, to which the current halfedge attach. */ 50 | CFace*& face() { return m_face; }; 51 | /*! Rotate the halfedge about the target vertex ccwly. 52 | \return if the current halfedge is the most ccw in halfedge of its target vertex, which is on boundary, return NULL. 53 | */ 54 | CHalfEdge* ccw_rotate_about_target(); 55 | /*! Rotate the halfedge about the target vertex clwly. 56 | \return if the current halfedge is the most clw in halfedge of its target vertex, which is on boundary, return NULL. 57 | */ 58 | CHalfEdge* clw_rotate_about_target(); 59 | /*! Rotate the halfedge about the source vertex ccwly. 60 | \return if the current halfedge is the most ccw out halfedge of its source vertex, which is on boundary, return NULL. 61 | */ 62 | CHalfEdge* ccw_rotate_about_source(); 63 | /*! Rotate the halfedge about the source vertex ccwly. 64 | \return if the current halfedge is the most clw out halfedge of its source vertex, which is on boundary, return NULL. 65 | */ 66 | CHalfEdge* clw_rotate_about_source(); 67 | /*! String of the current halfedge. */ 68 | //char * string() { return m_string; }; 69 | /*! Convert the traits to string, whose Maximum length is MAX_TRAIT_LINE in BaseMesh.h. */ 70 | void _to_string(char* str) {}; 71 | /*! Read traits from string. */ 72 | void _from_string(char* str) {}; 73 | 74 | protected: 75 | /*! Index, current halfedge's index*/ 76 | size_t m_index = 0; 77 | /*! Edge, current halfedge attached to. */ 78 | CEdge* m_edge = NULL; 79 | /*! Face, current halfedge attached to. */ 80 | CFace* m_face = NULL; 81 | /*! Target vertex of the current halfedge. */ 82 | CVertexBase* m_vertex = NULL; //target vertex 83 | /*! Previous halfedge of the current halfedge, in the same face. */ 84 | CHalfEdge* m_prev = NULL; 85 | /*! Next halfedge of the current halfedge, in the same face. */ 86 | CHalfEdge* m_next = NULL; 87 | /*! sym halfedge of the current halfedge, in the different face. */ 88 | CHalfEdge* m_sym = NULL; 89 | /*! The string of the current halfedge. */ 90 | //char m_string[STRINGSIZE]; 91 | }; 92 | 93 | //roate the halfedge about its target vertex CCWly 94 | 95 | inline CHalfEdge* CHalfEdge::ccw_rotate_about_target() 96 | { 97 | CHalfEdge* he_dual = he_sym(); 98 | if (he_dual == NULL) return NULL; 99 | 100 | return he_dual->he_prev(); 101 | }; 102 | 103 | //roate the halfedge about its target vertex CLWly 104 | 105 | inline CHalfEdge* CHalfEdge::clw_rotate_about_target() 106 | { 107 | CHalfEdge* he = he_next()->he_sym(); 108 | return he; 109 | }; 110 | 111 | //roate the halfedge about its source vertex CCWly 112 | 113 | 114 | inline CHalfEdge* CHalfEdge::ccw_rotate_about_source() 115 | { 116 | 117 | CHalfEdge* he = he_prev()->he_sym(); 118 | return he; 119 | }; 120 | 121 | //roate the halfedge about its source vertex CLWly 122 | 123 | inline CHalfEdge* CHalfEdge::clw_rotate_about_source() 124 | { 125 | CHalfEdge* he = he_sym(); 126 | if (he == NULL) return NULL; 127 | return he->he_next(); 128 | }; 129 | } //namespace TriMesh 130 | 131 | }//namespace MF 132 | 133 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Parser/parser.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file parser.h 3 | * \brief Parse the trait strings of vertex, edge, halfedge , face etc. 4 | * 5 | */ 6 | 7 | #ifndef _MESHLIB_PARSER_H_ 8 | #define _MESHLIB_PARSER_H_ 9 | 10 | #include "IOFuncDef.h" 11 | 12 | namespace Parser { 13 | //Return type 14 | enum ReturnType { StringOver = 1, TokenOut = 2, Success = 3, Failure = 4 }; 15 | 16 | /*! 17 | * \brief CToken class, key=(value), e.g. uv=(x y) 18 | */ 19 | 20 | class CToken 21 | { 22 | public: 23 | /*! key of the token */ 24 | char mKey[MAX_TOKEN_STRING_SIZE]; 25 | /*! value of the token */ 26 | char mValue[MAX_TOKEN_STRING_SIZE]; 27 | }; 28 | 29 | /*! 30 | * \brief CParser class 31 | */ 32 | 33 | class CParser 34 | { 35 | public: 36 | /*! 37 | * \brief CParser constructor 38 | * \param str input string 39 | */ 40 | CParser(const char * str) 41 | { 42 | size_t len = strlen(str); 43 | if (len >= MAX_LINE_SIZE) { 44 | printf("Error: Current string's length is over MAX LINE SIZE!\n"); 45 | return; 46 | } 47 | /*Copy string*/ 48 | unsigned int i; 49 | for (i = 0; i < len; i++) 50 | { 51 | mLine[i] = str[i]; 52 | } 53 | mLine[i] = 0; 54 | currrentPtr = mLine; 55 | int returnValue = nextToken(); 56 | switch (returnValue) 57 | { 58 | case Parser::StringOver: 59 | printf("Error: Can't find Value! In line : %s", mLine); 60 | break; 61 | case Parser::Failure: 62 | printf("Error: Can't find Value! In line : %s", mLine); 63 | break; 64 | case Parser::TokenOut: 65 | printf("Error: Token's length is over! In line : %s", mLine); 66 | break; 67 | default: 68 | break; 69 | } 70 | }; 71 | 72 | /*! 73 | * CParser Destructor 74 | */ 75 | ~CParser() {}; 76 | 77 | /*! 78 | * List of tokens extracted from the string 79 | */ 80 | CToken * tokens() { return &mToken; }; 81 | 82 | /*Jump to next token*/ 83 | int nextToken() { 84 | /*Skip the blank*/ 85 | SkipBlank(); 86 | /*If string over, return false*/ 87 | if (End()) return StringOver; 88 | /*Get the key from current line*/ 89 | char * pKey = mKey; 90 | char currentChar = NextChar(); 91 | while (currentChar != ' ' && currentChar != '=' && !End()) 92 | { 93 | *pKey++ = currentChar; 94 | currentChar = NextChar(); 95 | } 96 | if (currentChar != '=' && currentChar != ' ') 97 | { 98 | *pKey++ = currentChar; 99 | } 100 | *pKey = 0; 101 | while (currentChar == ' ' && !End()) 102 | { 103 | currentChar = NextChar(); 104 | } 105 | if (currentChar != '=') 106 | { 107 | size_t keySize = strlen(mKey); 108 | if (keySize >= MAX_TOKEN_STRING_SIZE) { 109 | return TokenOut; 110 | } 111 | SAFE_STRCPY(mToken.mKey, mKey); 112 | mToken.mKey[keySize] = '\0'; 113 | return Failure; 114 | } 115 | /*If string over, return false*/ 116 | if (End()) return StringOver; 117 | 118 | currentChar = NextChar(); 119 | 120 | while (currentChar != '(' && !End()) currentChar = NextChar(); 121 | 122 | char * pvalue = mValue; 123 | 124 | while (currentChar != ')' && !End()) 125 | { 126 | *pvalue++ = currentChar; 127 | currentChar = NextChar(); 128 | } 129 | *pvalue++ = currentChar; 130 | *pvalue = 0; 131 | 132 | size_t keySize = strlen(mKey); 133 | if (keySize >= MAX_TOKEN_STRING_SIZE) { 134 | return TokenOut; 135 | } 136 | SAFE_STRCPY(mToken.mKey, mKey); 137 | mToken.mKey[keySize] = '\0'; 138 | 139 | size_t valueSize = strlen(mValue); 140 | if (valueSize >= MAX_TOKEN_STRING_SIZE) { 141 | return TokenOut; 142 | } 143 | SAFE_STRCPY(mToken.mValue, mValue); 144 | mToken.mValue[valueSize] = '\0'; 145 | 146 | return Success; 147 | } 148 | 149 | private: 150 | 151 | /*! 152 | * get the next char in the current string 153 | */ 154 | char NextChar() 155 | { 156 | char currentChar = *currrentPtr; 157 | currrentPtr++; 158 | return currentChar; 159 | }; 160 | /*! 161 | * skip blank spaces 162 | */ 163 | void SkipBlank() 164 | { 165 | while (*currrentPtr == ' ') 166 | { 167 | currrentPtr++; 168 | } 169 | }; 170 | /*! 171 | * verify if we 172 | */ 173 | bool End() 174 | { 175 | return ((*currrentPtr) == 0); 176 | }; 177 | /*! 178 | * token 179 | */ 180 | CToken mToken; 181 | /*! 182 | * The buffer to contain the string 183 | */ 184 | char mLine[MAX_LINE_SIZE]; 185 | /*! 186 | * current key 187 | */ 188 | char mKey[MAX_TOKEN_STRING_SIZE]; 189 | /*! 190 | * current value 191 | */ 192 | char mValue[MAX_TOKEN_STRING_SIZE]; 193 | /*! 194 | * current pointer to the char buffer 195 | */ 196 | char * currrentPtr; 197 | }; 198 | } 199 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Utility/Parser.h: -------------------------------------------------------------------------------- 1 | #ifndef __PARSER__ 2 | #define __PARSER__ 3 | 4 | #define PUT_TO_JSON(j, arg) j[#arg] = arg 5 | #define EXTRACT_FROM_JSON(j, arg) MF::parseJsonParameters(j, #arg, arg) 6 | 7 | #include 8 | #include 9 | #include "../Json/json.hpp" 10 | #define REQUIRE_NUM_INPUTS(n)\ 11 | if (argc < n+1) {\ 12 | std::cout << "[Error] Need at least " << n << " input parameters!" << std::endl; \ 13 | return -1;\ 14 | } 15 | 16 | #define PARSE_VEC3_INDEXED_BY_ROUND_BRACKET(jsonParam, vec3)\ 17 | std::array vec3##Arr;\ 18 | if (MF::parseJsonParameters(jsonParam, #vec3, vec3##Arr))\ 19 | {\ 20 | vec3(0) = vec3##Arr[0];\ 21 | vec3(1) = vec3##Arr[1];\ 22 | vec3(2) = vec3##Arr[2];\ 23 | } 24 | 25 | #define PARSE_VEC3_INDEXED_BY_SQUARE_BRACKET(jsonParam, vec3)\ 26 | std::array vec3##Arr;\ 27 | if (MF::parseJsonParameters(jsonParam, #vec3, vec3##Arr))\ 28 | {\ 29 | vec3[0] = vec3##Arr[0];\ 30 | vec3[1] = vec3##Arr[1];\ 31 | vec3[2] = vec3##Arr[2];\ 32 | }\ 33 | 34 | #define PUT_TO_JSON_VEC3_INDEXED_BY_ROUND_BRACKET(jsonParam, vec3)\ 35 | std::array vec3##yArr;\ 36 | vec3##yArr[0] = vec3(0);\ 37 | vec3##yArr[1] = vec3(1);\ 38 | vec3##yArr[2] = vec3(2);\ 39 | jsonParam[#vec3] = vec3##yArr; 40 | 41 | #define PUT_TO_JSON_VEC3_INDEXED_BY_SQUARE_BRACKET(jsonParam, vec3)\ 42 | std::array vec3##yArr;\ 43 | vec3##yArr[0] = vec3[0];\ 44 | vec3##yArr[1] = vec3[1];\ 45 | vec3##yArr[2] = vec3[2];\ 46 | jsonParam[#vec3] = vec3##yArr; 47 | 48 | namespace MF { 49 | inline bool loadJson(std::string filePath, nlohmann::json& j) { 50 | std::ifstream ifs(filePath); 51 | if (ifs.is_open()) 52 | { 53 | try 54 | { 55 | ifs >> j; 56 | return true; 57 | } 58 | catch (nlohmann::json::exception& e) 59 | { 60 | std::cout << e.what() << '\n'; 61 | return false; 62 | } 63 | } 64 | else 65 | { 66 | std::cout << "Fail to open: " << filePath << '\n'; 67 | return false; 68 | } 69 | 70 | } 71 | 72 | inline bool saveJson(std::string filePath, nlohmann::json& j, int indent = -1) { 73 | std::ofstream ofs(filePath); 74 | if (ofs.is_open()) 75 | { 76 | try 77 | { 78 | ofs << j.dump(indent) << std::endl; 79 | return true; 80 | } 81 | catch (nlohmann::json::exception& e) 82 | { 83 | std::cout << e.what() << '\n'; 84 | return false; 85 | } 86 | } 87 | else 88 | { 89 | std::cout << "Fail to open: " << filePath << '\n'; 90 | return false; 91 | } 92 | } 93 | 94 | inline nlohmann::json tryGetJson(nlohmann::json j, std::string name) { 95 | nlohmann::json param; 96 | try 97 | { 98 | param = j.at(name); 99 | } 100 | catch (nlohmann::json::exception& e) 101 | { 102 | std::cout << e.what() << '\n'; 103 | std::cout << name << " does not exist in json and will be set to default value." << std::endl; 104 | return false; 105 | } 106 | return param; 107 | } 108 | 109 | template 110 | bool parseJsonParameters(nlohmann::json j, const std::string& name, T& param) { 111 | try 112 | { 113 | nlohmann::json paramJson = j.at(name); 114 | param = paramJson.get(); 115 | } 116 | catch (nlohmann::json::exception& e) 117 | { 118 | std::cout << "When loading: " << name << "\n" 119 | << e.what() << "\n" 120 | << name << " does not exist in json and will be set to default value." << std::endl; 121 | return false; 122 | } 123 | return true; 124 | } 125 | 126 | template 127 | bool convertJsonParameters(nlohmann::json j, T& param) { 128 | try 129 | { 130 | param = j.get(); 131 | } 132 | catch (nlohmann::json::exception& e) 133 | { 134 | std::cout<< e.what() << "\n"; 135 | return false; 136 | } 137 | return true; 138 | } 139 | 140 | struct BaseJsonConfig { 141 | 142 | virtual bool fromJson(nlohmann::json& j) = 0; 143 | virtual bool toJson(nlohmann::json& j) = 0; 144 | 145 | bool loadFromJsonFile(const std::string& inJsonParamFile, void * userData_in =nullptr) { 146 | nlohmann::json j; 147 | 148 | if (userData_in != nullptr) 149 | { 150 | userData = userData_in; 151 | } 152 | 153 | if (loadJson(inJsonParamFile, j)) 154 | { 155 | if (fromJson(j)) 156 | { 157 | 158 | return true; 159 | } 160 | else 161 | { 162 | return false; 163 | } 164 | } 165 | else 166 | { 167 | return false; 168 | } 169 | } 170 | 171 | bool writeToJsonFile(std::string filePath, int indent = -1, void* userData_in = nullptr) { 172 | std::ofstream ofs(filePath); 173 | 174 | if (userData_in != nullptr) 175 | { 176 | userData = userData_in; 177 | } 178 | 179 | if (ofs.is_open()) 180 | { 181 | nlohmann::json j; 182 | toJson(j); 183 | 184 | ofs << j.dump(indent); 185 | return true; 186 | } 187 | else 188 | { 189 | return false; 190 | } 191 | } 192 | void* userData = nullptr; 193 | }; 194 | 195 | } 196 | 197 | #endif // !__COMMAND_PARSER__ 198 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/Props.h: -------------------------------------------------------------------------------- 1 | #ifndef _PROPS_H_ 2 | #define _PROPS_H_ 3 | #include 4 | #define PROP_POOL_DEFAULT_BLOCK_SIZE 2048 5 | 6 | #define MAKE_PROPHANDLE(TARGET) \ 7 | template \ 8 | class TARGET##PropHandle : public BasicPropHandle { \ 9 | public:\ 10 | TARGET##PropHandle() {};\ 11 | TARGET##PropHandle(const T & initialVal) : typeInitialVal(initialVal) { toInitialize = true;};\ 12 | void setTypeInitialVal(const T & initialVal){\ 13 | typeInitialVal = initialVal; \ 14 | toInitialize = true;\ 15 | }\ 16 | void initializePropMember(void * pP) {\ 17 | *((T*)pP) = typeInitialVal;\ 18 | }; \ 19 | void initializePropMember(size_t index) {\ 20 | (*((PropPool *)pPropPool))[index] = typeInitialVal;\ 21 | }; \ 22 | void destructProp(){\ 23 | PropPool * pTPropPool = (PropPool *)pPropPool;\ 24 | delete pTPropPool;\ 25 | }\ 26 | private:\ 27 | T typeInitialVal; \ 28 | }; 29 | 30 | #define MAKE_PROP_OF(TARGET) \ 31 | Props m##TARGET##Props; \ 32 | public:\ 33 | template \ 34 | void add##TARGET##Prop(TARGET##PropHandle & prop){ \ 35 | if (prop.pPropPool != NULL){\ 36 | printf("Error! This prop handle has already been added to mesh!\n");\ 37 | throw -1;\ 38 | }\ 39 | PropPool * pPool = new PropPool(m##TARGET##Container.capacity(), m##TARGET##Container.getBlockSize());\ 40 | prop.pPropPool = (void*)pPool;\ 41 | if(prop.needInitialize()){\ 42 | for (int i = 0; i < m##TARGET##Container.getCurrentIndex(); ++i){\ 43 | if (m##TARGET##Container.hasBeenDeleted(i)) continue;\ 44 | prop.initializePropMember(i);\ 45 | }\ 46 | }\ 47 | prop.propIdx = m##TARGET##Props.size(); \ 48 | m##TARGET##Props.push_back(&prop);\ 49 | };\ 50 | template \ 51 | void add##TARGET##Prop(TARGET##PropHandle & prop, const T & initialVal){ \ 52 | if (prop.pPropPool != NULL){\ 53 | printf("Error! This prop handle has already been added to mesh!\n");\ 54 | throw -1;\ 55 | }\ 56 | prop.setTypeInitialVal(initialVal);\ 57 | PropPool * pPool = new PropPool(m##TARGET##Container.capacity(), m##TARGET##Container.getBlockSize());\ 58 | prop.pPropPool = (void*)pPool;\ 59 | for (int i = 0; i < m##TARGET##Container.getCurrentIndex(); ++i){\ 60 | if (m##TARGET##Container.hasBeenDeleted(i)) continue;\ 61 | prop.initializePropMember(i);\ 62 | }\ 63 | prop.propIdx = m##TARGET##Props.size(); \ 64 | m##TARGET##Props.push_back(&prop);\ 65 | };\ 66 | template \ 67 | T& get##TARGET##Prop(const TARGET##PropHandle & prop, TARGET##Ptr ptr){\ 68 | assert(prop.pPropPool != NULL);\ 69 | PropPool * pPropPool = (PropPool*)prop.pPropPool; \ 70 | return (*pPropPool)[ptr->index()];\ 71 | };\ 72 | template \ 73 | T& g##TARGET##P(const TARGET##PropHandle & prop, TARGET##Ptr ptr){\ 74 | assert(prop.pPropPool != NULL);\ 75 | PropPool * pPropPool = (PropPool*)prop.pPropPool; \ 76 | return (*pPropPool)[ptr->index()];\ 77 | };\ 78 | template \ 79 | void remove##TARGET##Prop(TARGET##PropHandle & prop){\ 80 | assert(prop.propIdx != -1);\ 81 | PropPool *pPropPool = (PropPool*)prop.pPropPool;\ 82 | delete pPropPool;\ 83 | prop.pPropPool = NULL;\ 84 | m##TARGET##Props.erase(m##TARGET##Props.begin() + prop.propIdx);\ 85 | for (int i = prop.propIdx; i < m##TARGET##Props.size(); ++i){\ 86 | m##TARGET##Props[i]->propIdx -= 1;\ 87 | }\ 88 | }; 89 | 90 | 91 | namespace MF { 92 | template 93 | class PropPool { 94 | public: 95 | PropPool(size_t preAllocate = PROP_POOL_DEFAULT_BLOCK_SIZE, size_t newBlockSize = PROP_POOL_DEFAULT_BLOCK_SIZE) : blockSize(newBlockSize){ 96 | size_t numBlocks = preAllocate / blockSize + 1; 97 | 98 | for (size_t i = 0; i < numBlocks; ++i) { 99 | T * pBlock = new T[blockSize]; 100 | memoryBlockPtrVec.push_back(pBlock); 101 | } 102 | }; 103 | 104 | ~PropPool() { 105 | for (int i = 0; i < memoryBlockPtrVec.size(); ++i) { 106 | delete[] memoryBlockPtrVec[i]; 107 | } 108 | } 109 | 110 | void reserve(size_t reserveSize) { 111 | if (blockSize * memoryBlockPtrVec.size() > reserveSize) { 112 | return; 113 | } 114 | 115 | size_t numBlocks = (reserveSize - blockSize * memoryBlockPtrVec.size()) / blockSize + 1; 116 | 117 | for (size_t i = 0; i < numBlocks; ++i) { 118 | T * pBlock = new T[blockSize]; 119 | if (pBlock == NULL) return; 120 | memoryBlockPtrVec.push_back(pBlock); 121 | } 122 | 123 | return; 124 | } 125 | 126 | T & operator[] (size_t index) { 127 | if (index >= blockSize * memoryBlockPtrVec.size()) { 128 | reserve(index + 1); 129 | } 130 | size_t blockIndex = index / blockSize; 131 | size_t offSet = index % blockSize; 132 | T * pStartMember = memoryBlockPtrVec[blockIndex]; 133 | return *(pStartMember + offSet); 134 | } 135 | 136 | T* getPointer(size_t index) { 137 | if (index >= blockSize * memoryBlockPtrVec.size()) { 138 | reserve(index + 1); 139 | } 140 | int blockIndex = index / blockSize; 141 | int offSet = index % blockSize; 142 | T * pStartMember = memoryBlockPtrVec[blockIndex]; 143 | return pStartMember + offSet; 144 | }; 145 | 146 | // non-copyable 147 | PropPool(const PropPool&) = delete; 148 | private: 149 | const size_t blockSize; 150 | std::vector memoryBlockPtrVec; 151 | }; 152 | 153 | class BasicPropHandle 154 | { 155 | public: 156 | BasicPropHandle() {}; 157 | size_t propIdx = 0; 158 | void * pPropPool = NULL; 159 | bool needInitialize() { return toInitialize; }; 160 | virtual void initializePropMember(void * pP) {}; 161 | virtual void initializePropMember(size_t index) {}; 162 | virtual void destructProp() {}; 163 | private: 164 | // Handle is not copyable 165 | //BasicPropHandle(const BasicPropHandle &); 166 | //BasicPropHandle &operator=(const BasicPropHandle &); 167 | protected: 168 | bool toInitialize = false; 169 | }; 170 | 171 | MAKE_PROPHANDLE(V); 172 | MAKE_PROPHANDLE(E); 173 | MAKE_PROPHANDLE(F); 174 | MAKE_PROPHANDLE(HE); 175 | 176 | typedef std::vector Props; 177 | 178 | 179 | 180 | } 181 | #endif // !_PROPS_H_ 182 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/Vertex.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file Vertex.h 3 | * \brief Base class of vertex 4 | * \Version 2.0 5 | * \Update 11/03/2022 6 | */ 7 | 8 | #ifndef _MESHFRAME_VERTEX_H_ 9 | #define _MESHFRAME_VERTEX_H_ 10 | 11 | #include 12 | #include "../Memory/Array.h" 13 | #include "HalfEdge.h" 14 | 15 | namespace MF { 16 | namespace TriMesh { 17 | 18 | class CHalfEdge; 19 | 20 | /*! 21 | \brief CVertex class, which is the base class of all kinds of vertex classes 22 | */ 23 | 24 | class CVertexBase 25 | { 26 | public: 27 | typedef CPArray CHEArray; 28 | 29 | /*! 30 | CVertexBase constructor 31 | */ 32 | CVertexBase() { m_halfedge = NULL; m_boundary = false; }; 33 | /*! 34 | CVertexBase destructor 35 | */ 36 | ~CVertexBase() {}; 37 | 38 | /*! The most counter clockwise outgoing halfedge of the vertex . 39 | */ 40 | CHalfEdge* most_ccw_out_halfedge(); 41 | /*! The most clockwise outgoing halfedge of the vertex . 42 | */ 43 | CHalfEdge* most_clw_out_halfedge(); 44 | /*! The most counter clockwise incoming halfedge of the vertex. 45 | */ 46 | CHalfEdge* most_ccw_in_halfedge(); 47 | /*! The most clockwise incoming halfedge of the vertex. 48 | */ 49 | CHalfEdge* most_clw_in_halfedge(); 50 | 51 | /*! One incoming halfedge of the vertex . 52 | */ 53 | CHalfEdge*& halfedge() { return m_halfedge; }; 54 | /*! Vertex index. 55 | */ 56 | size_t& index() { return m_index; }; 57 | /*! Vertex id. 58 | */ 59 | int& id() { return m_id; }; 60 | /*! Whether the vertex is on the boundary. 61 | */ 62 | bool& boundary() { return m_boundary; }; 63 | 64 | /*! Read traits from the string, this function is called by Basemesh.h 65 | * And should NEVER be varified by user, because some defualt reading process should be done before 66 | * the user doing his own reading procedure. 67 | * If you want to have your own reading procedure, change _from_string(); 68 | */ 69 | void _from_string_default(const char* str) {}; 70 | /*! Convert vertex traits to string, whose Maximum length is MAX_TRAIT_STRING_SIZE. 71 | * this function is called by Basemesh.h. And should NEVER be varified by user, 72 | * because some defualt writting process should be done before the user doing his own writting procedure. 73 | * If you want to have your own reading procedure, change _to_string(); 74 | */ 75 | void _to_string_default(char* str) {}; 76 | /*! Adjacent edges, temporarily used for loading the mesh 77 | */ 78 | 79 | /*! Convert vertex traits to string, whose Maximum length is MAX_TRAIT_STRING_SIZE defined in IOFuncDef.h. 80 | */ 81 | void _to_string(char* str) {}; 82 | /*! Read traits from the string, should be overrided if extra loading behavior is needed. 83 | */ 84 | void _from_string(const char* str) {}; 85 | /*! Vertex index. 86 | */ 87 | 88 | CHEArray& outHEs() { return m_outHEs; }; 89 | 90 | 91 | protected: 92 | 93 | size_t m_index; 94 | /*! Vertex ID. 95 | */ 96 | int m_id; 97 | /*! Vertex position point. 98 | */ 99 | CHalfEdge* m_halfedge; 100 | /*! Indicating if the vertex is on the boundary. 101 | */ 102 | bool m_boundary = false; 103 | /*! The string of the vertex, which stores the traits information. 104 | */ 105 | //char m_string[MAX_TRAIT_STRING_SIZE]; 106 | /*! List of adjacent edges, such that current vertex is the end vertex of the edge with smaller id 107 | */ 108 | CHEArray m_outHEs; 109 | 110 | }; //class CVertex 111 | 112 | 113 | /*! \brief The most counter clockwise incoming halfedge of the vertex 114 | * \return the most CCW in halfedge 115 | */ 116 | inline CHalfEdge* CVertexBase::most_ccw_in_halfedge() 117 | { 118 | //for interior vertex 119 | if (!m_boundary) 120 | { 121 | return m_halfedge; //current half edge is the most ccw in halfedge 122 | } 123 | 124 | //for boundary vertex 125 | CHalfEdge* he = m_halfedge->ccw_rotate_about_target(); 126 | CHalfEdge* pStartHE = he; 127 | //rotate to the most ccw in halfedge 128 | size_t numHEs = m_outHEs.size(); 129 | int numHEIterated = 0; 130 | while (he != NULL) 131 | { 132 | if (numHEIterated >= numHEs) { 133 | break; 134 | } 135 | 136 | m_halfedge = he; 137 | he = m_halfedge->ccw_rotate_about_target(); 138 | 139 | ++numHEIterated; 140 | } 141 | // the halfedge of the vertex becomes the most ccw in halfedge 142 | return m_halfedge; 143 | }; 144 | 145 | //most clockwise in halfedge 146 | 147 | inline CHalfEdge* CVertexBase::most_clw_in_halfedge() 148 | { 149 | //for interior vertex 150 | if (!m_boundary) 151 | { 152 | return most_ccw_in_halfedge()->ccw_rotate_about_target(); //the most ccw in halfedge rotate ccwly once to get the most clw in halfedge 153 | } 154 | //for boundary vertex 155 | CHalfEdge* he = m_halfedge->clw_rotate_about_target(); 156 | CHalfEdge* pStartHE = he; 157 | //rotate to the most clw in halfedge 158 | while (he != NULL) 159 | { 160 | m_halfedge = he; 161 | he = m_halfedge->clw_rotate_about_target(); 162 | if (he == pStartHE) { 163 | break; 164 | } 165 | } 166 | 167 | return m_halfedge; 168 | }; 169 | 170 | //most counter clockwise out halfedge 171 | 172 | inline CHalfEdge* CVertexBase::most_ccw_out_halfedge() 173 | { 174 | //for interior vertex 175 | if (!m_boundary) 176 | { 177 | return most_ccw_in_halfedge()->he_sym(); //most ccw out halfedge is the dual of the most ccw in halfedge 178 | } 179 | 180 | //for boundary vertex 181 | CHalfEdge* he = m_halfedge->he_next(); 182 | //get the out halfedge which is the next halfedge of the most ccw in halfedge 183 | CHalfEdge* ne = he->ccw_rotate_about_source(); 184 | //rotate ccwly around the source vertex 185 | while (ne != NULL) 186 | { 187 | he = ne; 188 | ne = he->ccw_rotate_about_source(); 189 | } 190 | 191 | return he; 192 | }; 193 | 194 | //most clockwise out halfedge 195 | 196 | inline CHalfEdge* CVertexBase::most_clw_out_halfedge() 197 | { 198 | //for interior vertex 199 | if (!m_boundary) 200 | { 201 | return most_ccw_out_halfedge()->ccw_rotate_about_source(); //most ccw out halfedge rotate ccwly once about the source 202 | } 203 | //get one out halfedge 204 | CHalfEdge* he = m_halfedge->he_next(); 205 | //rotate the out halfedge clwly about the source 206 | CHalfEdge* ne = he->clw_rotate_about_source(); 207 | 208 | while (ne != NULL) 209 | { 210 | he = ne; 211 | ne = he->clw_rotate_about_source(); 212 | } 213 | 214 | return he; 215 | }; 216 | 217 | } 218 | 219 | }//name space MeshLib 220 | 221 | #endif //_MESHLIB_VERTEX_H_defined -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Parser/StrUtil_fast.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file strutil.h 3 | * \brief std::string utilities 4 | * \date Documented on 10/08/2010 5 | * 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | 16 | // declaration 17 | namespace strutilTetMesh { 18 | 19 | //std::ostringstream oss; 20 | //std::istringstream iss; 21 | 22 | inline std::string trimLeft(const std::string& str) 23 | { 24 | std::string t = str; 25 | t.erase(0, t.find_first_not_of(" \t\n\r")); 26 | return t; 27 | }; 28 | 29 | inline std::string trimRight(const std::string& str) 30 | { 31 | std::string t = str; 32 | t.erase(t.find_last_not_of(" \t\n\r") + 1); 33 | return t; 34 | }; 35 | 36 | inline std::string trim(const std::string& str) 37 | { 38 | std::string t = str; 39 | t.erase(0, t.find_first_not_of(" \t\n\r")); 40 | t.erase(t.find_last_not_of(" \t\n\r") + 1); 41 | return t; 42 | }; 43 | 44 | inline std::string trim(const std::string& str, const std::string & delimitor) 45 | { 46 | std::string t = str; 47 | t.erase(0, t.find_first_not_of(delimitor)); 48 | t.erase(t.find_last_not_of(delimitor) + 1); 49 | return t; 50 | }; 51 | 52 | inline std::string toLower(const std::string& str) 53 | { 54 | std::string t = str; 55 | transform(t.begin(), t.end(), t.begin(), tolower); 56 | return t; 57 | }; 58 | 59 | inline std::string toUpper(const std::string& str) 60 | { 61 | std::string t = str; 62 | transform(t.begin(), t.end(), t.begin(), toupper); 63 | return t; 64 | }; 65 | 66 | inline bool startsWith(const std::string& str, const std::string& substr) 67 | { 68 | return str.find(substr) == 0; 69 | }; 70 | 71 | inline bool endsWith(const std::string& str, const std::string& substr) 72 | { 73 | return (str.rfind(substr) == (str.length() - substr.length()) && str.rfind(substr) >= 0); 74 | }; 75 | 76 | inline bool equalsIgnoreCase(const std::string& str1, const std::string& str2) 77 | { 78 | return toLower(str1) == toLower(str2); 79 | }; 80 | 81 | 82 | inline std::string toString(const bool& value, std::ostringstream& oss) 83 | { 84 | oss.clear(); 85 | oss.str(""); 86 | oss << std::boolalpha << value; 87 | return oss.str(); 88 | }; 89 | 90 | template bool parseString(const std::string& str, std::istringstream& iss) 91 | { 92 | bool value; 93 | iss.clear(); 94 | iss.str(str); 95 | iss >> std::boolalpha >> value; 96 | return value; 97 | }; 98 | 99 | 100 | template T parseString(const std::string& str, std::istringstream& iss) { 101 | T value; 102 | iss.clear(); 103 | iss.str(str); 104 | iss >> value; 105 | return value; 106 | }; 107 | 108 | template T parseHexString(const std::string& str, std::istringstream& iss) { 109 | T value; 110 | iss.str(str); 111 | iss >>std::hex >> value; 112 | return value; 113 | }; 114 | 115 | template std::string toString(const T& value, std::ostringstream& oss) { 116 | oss.clear(); 117 | oss.str(""); 118 | oss << value; 119 | return oss.str(); 120 | }; 121 | 122 | template std::string toHexString(const T& value, int width, std::ostringstream& oss) { 123 | oss.clear(); 124 | oss.str(""); 125 | oss << std::hex; 126 | if (width > 0) { 127 | oss << std::setw(width) << std::setfill('0'); 128 | } 129 | oss << value; 130 | return oss.str(); 131 | }; 132 | 133 | // Tokenizer class 134 | 135 | 136 | /*! 137 | * \brief String Tokenizer 138 | * 139 | * String tokenizer, which separate the whole string to tokens. 140 | */ 141 | class Tokenizer 142 | { 143 | public: 144 | Tokenizer(const std::string& str) 145 | : m_String(str), m_Offset(0), m_Delimiters(" ") {}; 146 | 147 | Tokenizer(const std::string& str, const std::string& delimiters) 148 | : m_String(str), m_Offset(0), m_Delimiters(delimiters) {}; 149 | 150 | bool nextToken() { return nextToken(m_Delimiters); }; 151 | 152 | 153 | bool nextToken(const std::string& delimiters) 154 | { 155 | // find the start charater of the next token. 156 | size_t i = m_String.find_first_not_of(delimiters, m_Offset); 157 | if (i == std::string::npos) { 158 | m_Offset = m_String.length(); 159 | return false; 160 | } 161 | 162 | // find the end of the token. 163 | size_t j = m_String.find_first_of(delimiters, i); 164 | if (j == std::string::npos) { 165 | m_Token = m_String.substr(i); 166 | m_Offset = m_String.length(); 167 | return true; 168 | } 169 | 170 | // to intercept the token and save current position 171 | m_Token = m_String.substr(i, j - i); 172 | m_Offset = j; 173 | return true; 174 | }; 175 | 176 | 177 | const std::string getToken() const { return m_Token; }; 178 | 179 | /** 180 | * to reset the tokenizer. After reset it, the tokenizer can get 181 | * the tokens from the first token. 182 | */ 183 | void reset() { m_Offset = 0; }; 184 | 185 | protected: 186 | size_t m_Offset; 187 | const std::string m_String; 188 | std::string m_Token; 189 | std::string m_Delimiters; 190 | }; 191 | 192 | inline std::vector split(const std::string& str, const std::string& delimiters) 193 | { 194 | std::vector ss; 195 | 196 | Tokenizer tokenizer(str, delimiters); 197 | while (tokenizer.nextToken()) 198 | { 199 | ss.push_back(tokenizer.getToken()); 200 | } 201 | 202 | return ss; 203 | }; 204 | 205 | }; 206 | 207 | /* 208 | struct string_token_iterator 209 | : public std::iterator 210 | { 211 | public: 212 | string_token_iterator() : str(0), start(0), end(0) {} 213 | string_token_iterator(const std::string & str_, const char * separator_ = " ") : 214 | separator(separator_), 215 | str(&str_), 216 | end(0) 217 | { 218 | find_next(); 219 | } 220 | string_token_iterator(const string_token_iterator & rhs) : 221 | separator(rhs.separator), 222 | str(rhs.str), 223 | start(rhs.start), 224 | end(rhs.end) 225 | { 226 | } 227 | 228 | string_token_iterator & operator++() 229 | { 230 | find_next(); 231 | return *this; 232 | } 233 | 234 | string_token_iterator operator++(int) 235 | { 236 | string_token_iterator temp(*this); 237 | ++(*this); 238 | return temp; 239 | } 240 | 241 | std::string operator*() const 242 | { 243 | return std::string(*str, start, end - start); 244 | } 245 | 246 | bool operator==(const string_token_iterator & rhs) const 247 | { 248 | return (rhs.str == str && rhs.start == start && rhs.end == end); 249 | } 250 | 251 | bool operator!=(const string_token_iterator & rhs) const 252 | { 253 | return !(rhs == *this); 254 | } 255 | 256 | private: 257 | 258 | void find_next(void) 259 | { 260 | start = str->find_first_not_of(separator, end); 261 | if(start == std::string::npos) 262 | { 263 | start = end = 0; 264 | str = 0; 265 | return; 266 | } 267 | 268 | end = str->find_first_of(separator, start); 269 | } 270 | 271 | const char * separator; 272 | const std::string * str; 273 | std::string::size_type start; 274 | std::string::size_type end; 275 | }; 276 | */ 277 | 278 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Memory/MemoryPoolThreadSafe.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /*! 3 | * \file MemoryPool.h 4 | * \brief A simple implation of memory pool, relying on std::vector and its index; 5 | * 6 | * The access and the delete of members of memory pool rely the index, which is a size_t variation. 7 | * 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "./MPIterator.h" 14 | #include 15 | 16 | #define DEFAULT_BLOCK_SIZE 2048 17 | 18 | template 19 | class MemoryPool { 20 | public: 21 | struct _memberType { 22 | bool deleted = false; 23 | }; 24 | class CMemberT : public T, public _memberType {}; 25 | public: 26 | /*Default construct*/ 27 | MemoryPool(); 28 | ~MemoryPool(); 29 | 30 | /*Construct*/ 31 | MemoryPool(size_t preAllocate, rsize_t newBlockSize = DEFAULT_BLOCK_SIZE); 32 | /*Class CMemberT*/ 33 | /*Reserve memory*/ 34 | bool reserve(size_t preAllocate); 35 | /*Generate a new member of type T and return its pointer*/ 36 | T * newMember(size_t & index); 37 | /*Transform from members index to its pointer*/ 38 | T * getPointer(size_t index); 39 | /*Deleted the memberof corresponding id, return false if it has already been deleted*/ 40 | bool deleteMember(size_t index); 41 | /*Judge if current pointer has been deleted*/ 42 | bool hasBeenDeleted(size_t index); 43 | /*Return the MemoryPool's maximal capacity*/ 44 | size_t capacity(); 45 | /*Return the MemoryPool's size*/ 46 | size_t size(); 47 | public: 48 | /*Return the MemoryPool's cuurent index*/ 49 | size_t getCurrentIndex(); 50 | MPIterator begin() 51 | { 52 | return MPIterator(memoryBlockPtrVec.begin(), 0, blockSize, currentIndex); 53 | } 54 | MPIterator end() 55 | { 56 | return MPIterator(memoryBlockPtrVec.end(), currentIndex, blockSize, currentIndex); 57 | } 58 | private: 59 | std::vector memoryBlockPtrVec; 60 | std::list deletedMembersList; 61 | /*Block's size*/ 62 | size_t blockSize = 1000; 63 | /*Max current member's number*/ 64 | size_t currentIndex; 65 | void * getMemberPointer(size_t index); 66 | 67 | 68 | std::mutex newMemberLock; 69 | std::mutex deleteMemberLock; 70 | }; 71 | 72 | template 73 | inline MemoryPool::MemoryPool() { 74 | blockSize = DEFAULT_BLOCK_SIZE; 75 | reserve(DEFAULT_BLOCK_SIZE); 76 | currentIndex = 0; 77 | } 78 | 79 | template 80 | inline MemoryPool::~MemoryPool() 81 | { 82 | for (int i = 0; i < memoryBlockPtrVec.size(); ++i) { 83 | delete[] memoryBlockPtrVec[i]; 84 | } 85 | } 86 | 87 | template 88 | inline MemoryPool::MemoryPool(size_t preAllocate, rsize_t newBlockSize) 89 | { 90 | blockSize = newBlockSize; 91 | size_t numBlocks = preAllocate / blockSize + 1; 92 | currentIndex = 0; 93 | 94 | for (size_t i = 0; i < numBlocks; ++i) { 95 | CMemberT * pBlock = new CMemberT[blockSize]; 96 | memoryBlockPtrVec.push_back(pBlock); 97 | } 98 | } 99 | 100 | template 101 | inline bool MemoryPool::reserve(size_t preAllocate) 102 | { 103 | std::lock_guard newMemberLockGuard(newMemberLock); 104 | std::lock_guard deleteMemberLockGuard(deleteMemberLock); 105 | 106 | if (currentIndex - deletedMembersList.size() > preAllocate) { 107 | return false; 108 | } 109 | 110 | if (blockSize * memoryBlockPtrVec.size() > preAllocate) { 111 | return true; 112 | } 113 | 114 | //blockSize = newBlockSize; 115 | size_t numBlocks = (preAllocate - blockSize * memoryBlockPtrVec.size())/ blockSize + 1; 116 | //currentIndex = 0; 117 | 118 | for (size_t i = 0; i < numBlocks; ++i) { 119 | CMemberT * pBlock = new CMemberT[blockSize]; 120 | if (pBlock == NULL) return false; 121 | memoryBlockPtrVec.push_back(pBlock); 122 | } 123 | 124 | return true; 125 | } 126 | 127 | template 128 | inline T * MemoryPool::newMember(size_t & index) 129 | { 130 | //std::lock_guard newMemberLockGuard(newMemberLock); 131 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 132 | 133 | if (deletedMembersList.empty()) { 134 | if (currentIndex >= memoryBlockPtrVec.size() * blockSize) { 135 | CMemberT * pBlock = new CMemberT[blockSize]; 136 | if (pBlock == NULL) { 137 | return NULL; 138 | } 139 | memoryBlockPtrVec.push_back(pBlock); 140 | } 141 | 142 | CMemberT * pNewMember = (CMemberT *)getMemberPointer(currentIndex); 143 | pNewMember->deleted = false; 144 | index = currentIndex; 145 | ++currentIndex; 146 | return (T*)pNewMember; 147 | } 148 | else 149 | { 150 | index = deletedMembersList.front(); 151 | deletedMembersList.pop_front(); 152 | CMemberT * pNewMember = (CMemberT *)getMemberPointer(index); 153 | pNewMember->deleted = false; 154 | T * pT = (T *)pNewMember; 155 | pT->~T(); 156 | *pT = T(); 157 | return pT; 158 | } 159 | } 160 | 161 | template 162 | inline void * MemoryPool::getMemberPointer(size_t index) 163 | { 164 | //assert(index < capacity()); 165 | int blockIndex = index / blockSize; 166 | int offSet = index % blockSize; 167 | CMemberT * pStartMember = memoryBlockPtrVec[blockIndex]; 168 | return (pStartMember + offSet); 169 | } 170 | 171 | template 172 | inline T * MemoryPool::getPointer(size_t index) 173 | { 174 | assert(index < blockSize * memoryBlockPtrVec.size()); 175 | int blockIndex = index / blockSize; 176 | int offSet = index % blockSize; 177 | CMemberT * pStartMember = memoryBlockPtrVec[blockIndex]; 178 | T * pT = (T *)(pStartMember + offSet); 179 | return pT; 180 | } 181 | 182 | template 183 | inline bool MemoryPool::deleteMember(size_t index) 184 | { 185 | assert(index < blockSize * memoryBlockPtrVec.size()); 186 | std::lock_guard newMemberLockGuard(newMemberLock); 187 | std::lock_guard deleteMemberLockGuard(deleteMemberLock); 188 | 189 | CMemberT * pMemberToDelete = (CMemberT *)getMemberPointer(index); 190 | if (pMemberToDelete->deleted == true) { 191 | return false; 192 | } 193 | else { 194 | pMemberToDelete->deleted = true; 195 | deletedMembersList.push_back(index); 196 | //T * pT = (T*)pMemberToDelete; 197 | //pT->~T(); 198 | return true; 199 | } 200 | } 201 | 202 | template 203 | inline bool MemoryPool::hasBeenDeleted(size_t index) 204 | { 205 | assert(index < blockSize * memoryBlockPtrVec.size()); 206 | std::lock_guard newMemberLockGuard(deleteMemberLock); 207 | 208 | CMemberT * pMemberToDelete = (CMemberT *)getMemberPointer(index); 209 | return pMemberToDelete->deleted; 210 | } 211 | 212 | template 213 | inline size_t MemoryPool::capacity() 214 | { 215 | std::lock_guard newMemberLockGuard(newMemberLock); 216 | std::lock_guard deleteMemberLockGuard(deleteMemberLock); 217 | 218 | return blockSize * memoryBlockPtrVec.size(); 219 | } 220 | 221 | template 222 | inline size_t MemoryPool::size() 223 | { 224 | std::lock_guard newMemberLockGuard(newMemberLock); 225 | std::lock_guard deleteMemberLockGuard(deleteMemberLock); 226 | 227 | return currentIndex - deletedMembersList.size(); 228 | } 229 | 230 | template 231 | inline size_t MemoryPool::getCurrentIndex() 232 | { 233 | std::lock_guard newMemberLockGuard(newMemberLock); 234 | std::lock_guard deleteMemberLockGuard(deleteMemberLock); 235 | 236 | return currentIndex; 237 | } -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Memory/MemoryPool2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /*! 3 | * \file MemoryPool.h 4 | * \brief A simple implation of memory pool, relying on std::vector and its index; 5 | * 6 | * The access and the delete of members of memory pool rely the index, which is a size_t variation. 7 | * 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "./MPIterator.h" 14 | #include 15 | 16 | #define DEFAULT_BLOCK_SIZE 2048 17 | 18 | template 19 | class MemoryPool { 20 | public: 21 | struct _memberType { 22 | bool deleted = false; 23 | }; 24 | class CMemberT : public T, public _memberType {}; 25 | public: 26 | /*Default construct*/ 27 | MemoryPool(); 28 | ~MemoryPool(); 29 | 30 | /*Construct*/ 31 | MemoryPool(size_t preAllocate, rsize_t newBlockSize = DEFAULT_BLOCK_SIZE); 32 | /*Class CMemberT*/ 33 | /*Reserve memory*/ 34 | bool reserve(size_t preAllocate); 35 | /*Generate a new member of type T and return its pointer*/ 36 | T * newMember(size_t & index); 37 | /*Transform from members index to its pointer*/ 38 | T * getPointer(size_t index); 39 | /*Deleted the memberof corresponding id, return false if it has already been deleted*/ 40 | bool deleteMember(size_t index); 41 | /*Judge if current pointer has been deleted*/ 42 | bool hasBeenDeleted(size_t index); 43 | /*Return the MemoryPool's maximal capacity*/ 44 | size_t capacity(); 45 | /*Return the MemoryPool's size*/ 46 | size_t size(); 47 | public: 48 | /*Return the MemoryPool's cuurent index*/ 49 | size_t getCurrentIndex(); 50 | MPIterator begin() 51 | { 52 | return MPIterator(memoryBlockPtrVec.begin(), 0, blockSize, currentIndex); 53 | } 54 | MPIterator end() 55 | { 56 | return MPIterator(memoryBlockPtrVec.end(), currentIndex, blockSize, currentIndex); 57 | } 58 | private: 59 | std::vector memoryBlockPtrVec; 60 | std::list deletedMembersList; 61 | /*Block's size*/ 62 | size_t blockSize = 1000; 63 | /*Max current member's number*/ 64 | size_t currentIndex; 65 | void * getMemberPointer(size_t index); 66 | 67 | //std::mutex newMemberLock; 68 | //std::mutex deleteMemberLock; 69 | }; 70 | 71 | template 72 | inline MemoryPool::MemoryPool() { 73 | blockSize = DEFAULT_BLOCK_SIZE; 74 | reserve(DEFAULT_BLOCK_SIZE); 75 | currentIndex = 0; 76 | } 77 | 78 | template 79 | inline MemoryPool::~MemoryPool() 80 | { 81 | for (int i = 0; i < memoryBlockPtrVec.size(); ++i) { 82 | delete[] memoryBlockPtrVec[i]; 83 | } 84 | } 85 | 86 | template 87 | inline MemoryPool::MemoryPool(size_t preAllocate, rsize_t newBlockSize) 88 | { 89 | blockSize = newBlockSize; 90 | size_t numBlocks = preAllocate / blockSize + 1; 91 | currentIndex = 0; 92 | 93 | for (size_t i = 0; i < numBlocks; ++i) { 94 | CMemberT * pBlock = new CMemberT[blockSize]; 95 | memoryBlockPtrVec.push_back(pBlock); 96 | } 97 | } 98 | 99 | template 100 | inline bool MemoryPool::reserve(size_t preAllocate) 101 | { 102 | //std::lock_guard newMemberLockGuard(newMemberLock); 103 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 104 | 105 | if (currentIndex - deletedMembersList.size() > preAllocate) { 106 | return false; 107 | } 108 | 109 | if (blockSize * memoryBlockPtrVec.size() > preAllocate) { 110 | return true; 111 | } 112 | 113 | //blockSize = newBlockSize; 114 | size_t numBlocks = (preAllocate - blockSize * memoryBlockPtrVec.size())/ blockSize + 1; 115 | //currentIndex = 0; 116 | 117 | for (size_t i = 0; i < numBlocks; ++i) { 118 | CMemberT * pBlock = new CMemberT[blockSize]; 119 | if (pBlock == NULL) return false; 120 | memoryBlockPtrVec.push_back(pBlock); 121 | } 122 | 123 | return true; 124 | } 125 | 126 | template 127 | inline T * MemoryPool::newMember(size_t & index) 128 | { 129 | //std::lock_guard newMemberLockGuard(newMemberLock); 130 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 131 | 132 | if (deletedMembersList.empty()) { 133 | if (currentIndex >= memoryBlockPtrVec.size() * blockSize) { 134 | CMemberT * pBlock = new CMemberT[blockSize]; 135 | if (pBlock == NULL) { 136 | return NULL; 137 | } 138 | memoryBlockPtrVec.push_back(pBlock); 139 | } 140 | 141 | CMemberT * pNewMember = (CMemberT *)getMemberPointer(currentIndex); 142 | pNewMember->deleted = false; 143 | index = currentIndex; 144 | ++currentIndex; 145 | return (T*)pNewMember; 146 | } 147 | else 148 | { 149 | index = deletedMembersList.front(); 150 | deletedMembersList.pop_front(); 151 | CMemberT * pNewMember = (CMemberT *)getMemberPointer(index); 152 | pNewMember->deleted = false; 153 | T * pT = (T *)pNewMember; 154 | pT->~T(); 155 | *pT = T(); 156 | return pT; 157 | } 158 | } 159 | 160 | template 161 | inline void * MemoryPool::getMemberPointer(size_t index) 162 | { 163 | //assert(index < capacity()); 164 | int blockIndex = index / blockSize; 165 | int offSet = index % blockSize; 166 | CMemberT * pStartMember = memoryBlockPtrVec[blockIndex]; 167 | return (pStartMember + offSet); 168 | } 169 | 170 | template 171 | inline T * MemoryPool::getPointer(size_t index) 172 | { 173 | assert(index < blockSize * memoryBlockPtrVec.size()); 174 | int blockIndex = index / blockSize; 175 | int offSet = index % blockSize; 176 | CMemberT * pStartMember = memoryBlockPtrVec[blockIndex]; 177 | T * pT = (T *)(pStartMember + offSet); 178 | return pT; 179 | } 180 | 181 | template 182 | inline bool MemoryPool::deleteMember(size_t index) 183 | { 184 | assert(index < blockSize * memoryBlockPtrVec.size()); 185 | //std::lock_guard newMemberLockGuard(newMemberLock); 186 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 187 | 188 | CMemberT * pMemberToDelete = (CMemberT *)getMemberPointer(index); 189 | if (pMemberToDelete->deleted == true) { 190 | return false; 191 | } 192 | else { 193 | pMemberToDelete->deleted = true; 194 | deletedMembersList.push_back(index); 195 | //T * pT = (T*)pMemberToDelete; 196 | //pT->~T(); 197 | return true; 198 | } 199 | } 200 | 201 | template 202 | inline bool MemoryPool::hasBeenDeleted(size_t index) 203 | { 204 | assert(index < blockSize * memoryBlockPtrVec.size()); 205 | //std::lock_guard newMemberLockGuard(deleteMemberLock); 206 | 207 | CMemberT * pMemberToDelete = (CMemberT *)getMemberPointer(index); 208 | return pMemberToDelete->deleted; 209 | } 210 | 211 | template 212 | inline size_t MemoryPool::capacity() 213 | { 214 | //std::lock_guard newMemberLockGuard(newMemberLock); 215 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 216 | 217 | return blockSize * memoryBlockPtrVec.size(); 218 | } 219 | 220 | template 221 | inline size_t MemoryPool::size() 222 | { 223 | //std::lock_guard newMemberLockGuard(newMemberLock); 224 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 225 | 226 | return currentIndex - deletedMembersList.size(); 227 | } 228 | 229 | template 230 | inline size_t MemoryPool::getCurrentIndex() 231 | { 232 | //std::lock_guard newMemberLockGuard(newMemberLock); 233 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 234 | 235 | return currentIndex; 236 | } -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TetMesh/TMeshStatic.h: -------------------------------------------------------------------------------- 1 | 2 | 3 | #ifndef _MESHFRAME_STATIC_TET_MESH_H_ 4 | #define _MESHFRAME_STATIC_TET_MESH_H_ 5 | 6 | #include "BaseTMesh.h" 7 | #include "TetMeshTypeDefs.h" 8 | #include "../Types/TypeDefs.h" 9 | 10 | namespace MF 11 | { 12 | namespace TetMesh 13 | { 14 | 15 | template 16 | class CTMeshStatic : public CTMeshBase 17 | { 18 | public: 19 | typedef CTMeshStatic* Ptr; 20 | typedef std::shared_ptr> SharedPtr; 21 | 22 | /*! 23 | return all the vertex position as a 3xN matrix 24 | */ 25 | TVerticesMat& vertPos() { return mVertPos; }; 26 | TTetIdsMat& tetVIds() { return mTetVIds; }; 27 | 28 | TVec3Block vert(size_t vId) { return mVertPos.block<3, 1>(0, vId); } 29 | Vec4BlockI tet(size_t tId) { return mTetVIds.block<4, 1>(0, tId); } 30 | 31 | /*! access the vertex with ID */ 32 | virtual VertexType* idVertex(int id) { return &mVContainer[id]; }; 33 | 34 | /*! access the tet with ID */ 35 | virtual TetType* idTet(int id) { return &mTContainer[id]; }; 36 | 37 | /*! 38 | Load tet mesh from a ".t" file 39 | */ 40 | void load_t(const char* input, bool checkOrientation = false); 41 | 42 | 43 | 44 | protected: 45 | TVerticesMat mVertPos; 46 | TTetIdsMat mTetVIds; 47 | 48 | }; 49 | 50 | template 51 | void CTMeshStatic::load_t(const char* input, bool checkOrientation) 52 | { 53 | std::ostringstream oss; 54 | std::istringstream iss; 55 | 56 | addVProp(mVHFArrayHandle); 57 | addVProp(mVTEArrayHandle); 58 | 59 | m_maxVertexId = 0; 60 | 61 | std::fstream is(input, std::fstream::in); 62 | 63 | if (is.fail()) 64 | { 65 | fprintf(stderr, "Error in opening file %s\n", input); 66 | return; 67 | } 68 | 69 | char buffer[MAX_LINE]; 70 | 71 | m_nVertices = 0; 72 | m_nTets = 0; 73 | m_nEdges = 0; 74 | 75 | while (!is.eof()) 76 | { 77 | is.getline(buffer, MAX_LINE); 78 | std::string line(buffer); 79 | line = strutilTetMesh::trim(line); 80 | strutilTetMesh::Tokenizer stokenizer(line, " \r\n"); 81 | 82 | stokenizer.nextToken(); 83 | std::string token = stokenizer.getToken(); 84 | 85 | if (token == "Vertex") m_nVertices++; 86 | if (token == "Tet") m_nTets++; 87 | if (token == "Edge") m_nEdges++; 88 | } 89 | 90 | is.clear(); // forget we hit the end of file 91 | is.seekg(0, std::ios::beg); // move to the start of the file 92 | 93 | mVertPos.resize(3, m_nVertices); 94 | mTetVIds.resize(4, m_nTets); 95 | 96 | //read in the vertices 97 | int vId = 0; 98 | std::map tFileIdToVId; 99 | for (int i = 0; i < m_nVertices && is.getline(buffer, MAX_LINE); i++) 100 | { 101 | std::string line(buffer); 102 | line = strutilTetMesh::trim(line); 103 | strutilTetMesh::Tokenizer stokenizer(line, " \r\n"); 104 | 105 | stokenizer.nextToken(); 106 | std::string token = stokenizer.getToken(); 107 | 108 | if (token != "Vertex") 109 | { 110 | fprintf(stderr, "File Format Error\r\n"); 111 | return; 112 | } 113 | 114 | stokenizer.nextToken(); 115 | token = stokenizer.getToken(); 116 | int vIdTFile = strutilTetMesh::parseString(token, iss); 117 | 118 | TVec3 p; 119 | for (int k = 0; k < 3; k++) 120 | { 121 | stokenizer.nextToken(); 122 | std::string token = stokenizer.getToken(); 123 | p[k] = strutilTetMesh::parseString(token, iss); 124 | } 125 | 126 | VertexType* v = createVertexWithIndex(); 127 | v->id() = vId; 128 | v->setPVertPos(&mVertPos); 129 | v->position() = p; 130 | 131 | tFileIdToVId.insert({ vIdTFile, vId }); 132 | ++vId; 133 | if (!stokenizer.nextToken("\t\r\n")) continue; 134 | token = stokenizer.getToken(); 135 | } 136 | 137 | //read in tets 138 | int tid = 0; 139 | for (int id = 0; id < m_nTets && is.getline(buffer, MAX_LINE); id++) 140 | { 141 | int vIds[4]; 142 | 143 | std::string line(buffer); 144 | line = strutilTetMesh::trim(line); 145 | strutilTetMesh::Tokenizer stokenizer(line, " \r\n"); 146 | 147 | stokenizer.nextToken(); 148 | std::string token = stokenizer.getToken(); 149 | 150 | if (token != "Tet") 151 | { 152 | fprintf(stderr, "File Format Error\r\n"); 153 | return; 154 | } 155 | 156 | //skip the first "4" in the line 157 | stokenizer.nextToken(); 158 | token = stokenizer.getToken(); 159 | // int tid = strutilTetMesh::parseString(token, iss); 160 | 161 | 162 | for (int k = 0; k < 4; k++) 163 | { 164 | stokenizer.nextToken(); 165 | std::string token = stokenizer.getToken(); 166 | int vIdTFile = strutilTetMesh::parseString(token, iss); 167 | vIds[k] = tFileIdToVId[vIdTFile]; 168 | } 169 | 170 | TetType* pT = createTetWithIndex(); 171 | pT->id() = tid; 172 | 173 | if (checkOrientation) { 174 | _construct_tet_orientation(pT, tid, vIds); 175 | } 176 | else { 177 | _construct_tet(pT, tid, vIds); 178 | } 179 | mTetVIds.block<4, 1>(0, tid) << vIds[0], vIds[1], vIds[2], vIds[3]; 180 | tid++; 181 | 182 | if (!stokenizer.nextToken("\t\r\n")) continue; 183 | 184 | } 185 | 186 | _construct_faces(); 187 | _construct_edges(); 188 | 189 | for (int id = 0; id < m_nEdges && is.getline(buffer, MAX_LINE); id++) 190 | { 191 | std::string line(buffer); 192 | line = strutilTetMesh::trim(line); 193 | strutilTetMesh::Tokenizer stokenizer(line, " \r\n"); 194 | 195 | stokenizer.nextToken(); 196 | std::string token = stokenizer.getToken(); 197 | 198 | if (token != "Edge") 199 | { 200 | fprintf(stderr, "File Format Error\r\n"); 201 | return; 202 | } 203 | 204 | stokenizer.nextToken(); 205 | token = stokenizer.getToken(); 206 | int id1 = strutilTetMesh::parseString(token, iss); 207 | 208 | stokenizer.nextToken(); 209 | token = stokenizer.getToken(); 210 | int id2 = strutilTetMesh::parseString(token, iss); 211 | 212 | VertexType* pV1 = idVertex(id1); 213 | VertexType* pV2 = idVertex(id2); 214 | 215 | EdgeType* pE = VertexEdge(pV1, pV2); 216 | 217 | if (!stokenizer.nextToken("\t\r\n")) 218 | { 219 | continue; 220 | } 221 | 222 | token = stokenizer.getToken(); 223 | } 224 | 225 | m_nEdges = (int)mEContainer.size(); 226 | 227 | is.close(); 228 | 229 | for (auto vIter = mVContainer.begin(); vIter != mVContainer.end(); vIter++) 230 | { 231 | VertexType* pV = *vIter; 232 | if (pV->id() > m_maxVertexId) 233 | { 234 | m_maxVertexId = pV->id(); 235 | } 236 | } 237 | 238 | // label the boundary for faces and vertices 239 | for (auto fIter = mFContainer.begin(); fIter != mFContainer.end(); ++fIter) 240 | { 241 | FaceType* pF = *fIter; 242 | if (this->FaceLeftHalfFace(pF) == NULL || this->FaceRightHalfFace(pF) == NULL) 243 | { 244 | pF->boundary() = true; 245 | HalfFaceType* pH = 246 | FaceLeftHalfFace(pF) == NULL ? FaceRightHalfFace(pF) : FaceLeftHalfFace(pF); 247 | //added by Anka, mark edge as boundary 248 | HalfEdgeType* pHE = (HalfEdgeType*)pH->half_edge(); 249 | 250 | for (int i = 0; i < 3; ++i) 251 | { 252 | EdgeType* pE = HalfEdgeEdge(pHE); 253 | int vid = pH->key(i); 254 | VertexType* v = idVertex(vid); 255 | v->boundary() = true; 256 | pE->boundary() = true; 257 | pHE = HalfEdgeNext(pHE); 258 | } 259 | } 260 | } 261 | 262 | for (auto vIter = mVContainer.begin(); vIter != mVContainer.end(); vIter++) 263 | { 264 | VertexType* pV = *vIter; 265 | pV->edges()->shrink_to_fit(); 266 | pV->tvertices()->shrink_to_fit(); 267 | } 268 | 269 | removeVProp(mVTEArrayHandle); 270 | 271 | } 272 | } 273 | } 274 | 275 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/MeshDynamic.h: -------------------------------------------------------------------------------- 1 | #ifndef _MESHLIB_DYNAMIC_MESH_H_ 2 | #define _MESHLIB_DYNAMIC_MESH_H_ 3 | 4 | #include "BaseMesh.h" 5 | namespace MF { 6 | namespace TriMesh { 7 | 8 | template 9 | class MeshDynamic:public CBaseMesh 10 | { 11 | public: 12 | /*! return the opposite vertex of an edge */ 13 | VertexType * oppVertex(VertexType * pV, EdgeType * pE); 14 | 15 | /*! return the halfedge of the specified edge of a face */ 16 | HalfEdgeType * faceEdgeHalfedge(EdgeType * pE, FaceType * pF); 17 | 18 | /*! return the oppsite vertex of an edge in a face */ 19 | VertexType * oppVertex(EdgeType * pE, FaceType * pF); 20 | 21 | /*! return halfedge of an edge ,and the source vertex of halfedge is pV */ 22 | HalfEdgeType * edgeVertexHalfedge1(EdgeType * pE, VertexType * pV); 23 | 24 | /*! return halfedge of an edge ,and the source vertex of halfedge is pV */ 25 | HalfEdgeType * edgeVertexHalfedge2(EdgeType * pE, VertexType * pV); 26 | 27 | /*! insert halfedge into vertex */ 28 | void enterHalfedge(HalfEdgeType * pHe, VertexType * pV1); 29 | 30 | /*! remove halfedge from vertex */ 31 | void removeHalfedge(HalfEdgeType * pHe, VertexType * pV1); 32 | 33 | /*! destroy face and modified its neighbour info */ 34 | void destoryFace(FaceType * pF); 35 | 36 | /*! collapse an edge to vertex vs */ 37 | void collapseEdgeVertex(EdgeType * pE); 38 | 39 | /*! collapse an edge to vertex vs */ 40 | void collapseEdgeVertexNM(EdgeType * pE); 41 | }; 42 | 43 | template 44 | typename VertexType * DynamicMesh::oppVertex(VertexType * pV, EdgeType * pE) 45 | { 46 | VertexType * pV1 = edgeVertex1(pE); 47 | VertexType * pV2 = edgeVertex2(pE); 48 | if (pV == pV1)return pV2; 49 | if (pV == pV2)return pV1; 50 | } 51 | 52 | template 53 | HalfEdgeType * DynamicMesh::faceEdgeHalfedge(EdgeType * pE, FaceType * pF) 54 | { 55 | if (edgeFace1(pE) == pF) { return (HalfEdgeType *)pE->halfedge(); } 56 | if (edgeFace2(pE) == pF) { return (HalfEdgeType *)pE->halfedge()->he_sym(); } 57 | } 58 | 59 | template 60 | VertexType * DynamicMesh::oppVertex(EdgeType * pE, FaceType * pF) 61 | { 62 | HalfEdgeType * pHe = faceEdgeHalfedge(pE, pF); 63 | return (VertexType *)pHe->he_next()->vertex(); 64 | } 65 | 66 | template 67 | HalfEdgeType * DynamicMesh::edgeVertexHalfedge1(EdgeType * pE, VertexType * pV) 68 | { 69 | if (edgeVertex1(pE) == pV) return (HalfEdgeType *)pE->halfedge(); 70 | if (edgeVertex2(pE) == pV) return (HalfEdgeType *)pE->halfedge()->he_sym(); 71 | } 72 | 73 | template 74 | HalfEdgeType * DynamicMesh::edgeVertexHalfedge2(EdgeType * pE, VertexType * pV) 75 | { 76 | if (edgeVertex1(pE) == pV) return (HalfEdgeType *)pE->halfedge()->he_sym(); 77 | if (edgeVertex2(pE) == pV) return (HalfEdgeType *)pE->halfedge(); 78 | } 79 | 80 | template 81 | void DynamicMesh::enterHalfedge(HalfEdgeType * pHe, VertexType * pV1) 82 | { 83 | VertexType * pV2 = (VertexType *)pHe->target(); 84 | pHe->he_sym() = vertexHalfedge(pV2, pV1); 85 | 86 | HalfEdgeType * pHe12 = vertexHalfedge(pV1, pV2); 87 | HalfEdgeType * pHes = (HalfEdgeType *)pHe->he_sym(); 88 | pV1->outHEs().push_back(pHe); 89 | 90 | if (pHes) { 91 | pHes->he_sym() = pHe; 92 | EdgeType * pE = (EdgeType *)pHes->edge(); 93 | pHe->edge() = pE; 94 | pE->halfedge() = pHe; 95 | } 96 | else if (pHe12 != NULL) 97 | { 98 | EdgeType * pE = (EdgeType *)pHe12->edge(); 99 | pHe->he_sym() = pHe12; 100 | pHe->edge() = pE; 101 | } 102 | else if (pHes == NULL && pHe12 == NULL) 103 | { 104 | EdgeType * pE = newEdge(); 105 | pE->halfedge() = pHe; 106 | pHe->edge() = pE; 107 | } 108 | else 109 | { 110 | std::cout << "enter pHe error occur" << "\n"; 111 | } 112 | } 113 | 114 | template 115 | void DynamicMesh::removeHalfedge(HalfEdgeType * pHe, VertexType * pV1) 116 | { 117 | VertexType * pV2 = (VertexType *)pHe->target(); 118 | EdgeType * pE = (EdgeType *)pHe->edge(); 119 | HalfEdgeType * pHes = (HalfEdgeType *)pHe->he_sym(); 120 | if (pHes) { 121 | pHes->he_sym() = NULL; 122 | if (pE->halfedge() == pHe) { pE->halfedge() = pHes; } 123 | } 124 | else { 125 | pE->isremoved() = true;//0708 126 | //deleteEdge(pE); 127 | } 128 | for (size_t i = 0; i < pV1->outHEs().size(); ++i) 129 | { 130 | if (pV1->outHEs()[i] == pHe) { pV1->outHEs().erase(i); }; 131 | } 132 | 133 | } 134 | 135 | template 136 | void DynamicMesh::destoryFace(FaceType * pF) 137 | { 138 | HalfEdgeType * pHe = (HalfEdgeType *)pF->halfedge(); 139 | HalfEdgeType * pHef = pHe; 140 | VertexType * pV1 = (VertexType *)pHe->he_prev()->target(); 141 | for (;;) { 142 | HalfEdgeType * pHen = (HalfEdgeType *)pHe->he_next(); 143 | VertexType * pV1n = (VertexType *)pHe->target(); 144 | removeHalfedge(pHe, pV1); 145 | deleteHalfEdge(pHe); 146 | pHe = pHen; 147 | pV1 = pV1n; 148 | if (pHe == pHef) break; 149 | } 150 | deleteFace(pF); 151 | } 152 | 153 | template 154 | void DynamicMesh::collapseEdgeVertex(EdgeType * pE) 155 | { 156 | HalfEdgeType * pHe1 = (HalfEdgeType *)pE->halfedge(); 157 | HalfEdgeType * pHe2 = (HalfEdgeType *)pE->halfedge()->he_sym(); 158 | VertexType * pVs = (VertexType *)pHe1->source(); 159 | VertexType * pVt = (VertexType *)pHe1->target(); 160 | 161 | if (pHe1) { destoryFace(halfedgeFace(pHe1)); } 162 | if (pHe2) { destoryFace(halfedgeFace(pHe2)); } 163 | 164 | std::vector arc; 165 | for (auto pHe : pVt->outHEs()) 166 | { 167 | HalfEdgeType * temppHe = (HalfEdgeType *)pHe->he_prev(); 168 | arc.push_back(temppHe); 169 | } 170 | 171 | for (auto pHe : arc) 172 | { 173 | removeHalfedge(pHe, (VertexType *)pHe->he_prev()->vertex()); 174 | removeHalfedge((HalfEdgeType *)pHe->he_next(), (VertexType *)pHe->vertex()); 175 | pHe->vertex() = pVs; 176 | enterHalfedge(pHe, (VertexType *)pHe->he_prev()->vertex()); 177 | enterHalfedge((HalfEdgeType *)pHe->he_next(), (VertexType *)pHe->vertex()); 178 | } 179 | //deleteVertex(pVt); 180 | } 181 | 182 | template 183 | void DynamicMesh::collapseEdgeVertexNM(EdgeType * pE) 184 | { 185 | HalfEdgeType * pHe1 = (HalfEdgeType *)pE->halfedge(); 186 | HalfEdgeType * pHe2 = (HalfEdgeType *)pE->halfedge()->he_sym(); 187 | VertexType * pVs = (VertexType *)pHe1->source(); 188 | 189 | //VertexType * pVt = pHe1 ? (VertexType *)pHe1->target() : (VertexType *)pHe2->he_prev()->target(); 190 | 191 | VertexType * pVt = (VertexType *)pHe1->target(); 192 | 193 | std::vector around_he; 194 | for (auto pHe : pVs->outHEs()) 195 | { 196 | if (pHe->target() == pVt)around_he.push_back((HalfEdgeType *)pHe); 197 | } 198 | for (auto pHe : pVt->outHEs()) 199 | { 200 | if (pHe->target() == pVs)around_he.push_back((HalfEdgeType *)pHe); 201 | } 202 | 203 | if (around_he.size() > 2) 204 | { 205 | for (auto pHe : around_he) 206 | { 207 | HalfEdgeType * boguspHe = newHalfEdge(); 208 | pHe->he_sym() = boguspHe; 209 | destoryFace((FaceType *)pHe->face()); 210 | deleteHalfEdge(boguspHe); 211 | } 212 | 213 | std::vector arc; 214 | for (auto pHe : pVt->outHEs()) 215 | { 216 | HalfEdgeType * temppHe = (HalfEdgeType *)pHe->he_prev(); 217 | arc.push_back(temppHe); 218 | } 219 | //for (auto pHe : pVt->outHEs()) { arc.push_back((HalfEdgeType *)pHe->he_prev()); } 220 | 221 | for (auto pHe : arc) 222 | { 223 | removeHalfedge(pHe, (VertexType *)pHe->he_prev()->vertex()); 224 | removeHalfedge((HalfEdgeType *)pHe->he_next(), (VertexType *)pHe->vertex()); 225 | pHe->vertex() = pVs; 226 | enterHalfedge(pHe, (VertexType *)pHe->he_prev()->vertex()); 227 | enterHalfedge((HalfEdgeType *)pHe->he_next(), (VertexType *)pHe->vertex()); 228 | } 229 | //deleteVertex(pVt); 230 | } 231 | else 232 | { 233 | collapseEdgeVertex(pE); 234 | } 235 | 236 | } 237 | }//TriMesh 238 | }//MF 239 | #endif -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Memory/MemoryPool.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | /*! 3 | * \file MemoryPool.h 4 | * \brief A simple implation of memory pool, relying on std::vector and its index; 5 | * 6 | * The access and the delete of members of memory pool rely the index, which is a size_t variation. 7 | * 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include "./MPIterator.h" 14 | 15 | #define DEFAULT_BLOCK_SIZE 4096 16 | 17 | template 18 | class MemoryPool { 19 | public: 20 | /*Default construct*/ 21 | MemoryPool(); 22 | ~MemoryPool(); 23 | 24 | /*Construct*/ 25 | MemoryPool(size_t preAllocate, size_t newBlockSize = DEFAULT_BLOCK_SIZE); 26 | /*Reserve memory*/ 27 | bool reserve(size_t preAllocate); 28 | /*Generate a new member of type T and return its pointer*/ 29 | T * newMember(size_t & index); 30 | /*Generate a new member of type T and return its pointer, and initialize it with initial value*/ 31 | T * newMember(size_t & index, const T & initialVal); 32 | /*Transform from members index to its pointer*/ 33 | T* getPointer(const size_t& index); 34 | const T * getPointer(const size_t & index) const; 35 | T & front() { 36 | int i = 0; 37 | while (deleteMask[i] && i < size()) { 38 | ++i; 39 | }; 40 | if (i == size()) 41 | return *getPointer(0); 42 | else 43 | return *getPointer(i); 44 | }; 45 | 46 | T& operator[] (int i) { 47 | return *getPointer(i); 48 | } 49 | const T& operator[] (int i) const { 50 | return *getPointer(i); 51 | } 52 | /*Deleted the memberof corresponding id, return false if it has already been deleted*/ 53 | bool deleteMember(size_t index); 54 | /*Judge if current pointer has been deleted*/ 55 | bool hasBeenDeleted(size_t index); 56 | /*Return the MemoryPool's maximal capacity*/ 57 | size_t capacity(); 58 | /*Return the MemoryPool's size*/ 59 | size_t size() const; 60 | /*Return the MemoryPool's one single block's size*/ 61 | size_t getBlockSize() { return blockSize; }; 62 | 63 | // non-copyable 64 | MemoryPool(const MemoryPool&) = delete; 65 | public: 66 | /*Return the MemoryPool's cuurent index*/ 67 | size_t getCurrentIndex(); 68 | MPIterator begin() 69 | { 70 | return MPIterator(memoryBlockPtrVec.begin(), 0, blockSize, currentIndex, deleteMask, memberTSize); 71 | } 72 | MPIterator end() 73 | { 74 | return MPIterator(memoryBlockPtrVec.end(), currentIndex, blockSize, currentIndex, deleteMask, memberTSize); 75 | } 76 | private: 77 | std::vector memoryBlockPtrVec; 78 | std::list deletedMembersList; 79 | /*Block's size*/ 80 | const size_t blockSize = DEFAULT_BLOCK_SIZE; 81 | /*Max current member's number*/ 82 | size_t currentIndex; 83 | void * getMemberPointer(size_t index); 84 | /*masks on which member has been deleted*/ 85 | std::vector deleteMask; 86 | /*size of true member type, in other word, you can cast MemoryPool to MemoryPool, 87 | * and memberTSize is still sizeof(Son), and you can iterate MemoryPool pool as MemoryPool. 88 | */ 89 | const size_t memberTSize; 90 | 91 | //std::mutex newMemberLock; 92 | //std::mutex deleteMemberLock; 93 | }; 94 | 95 | template 96 | inline MemoryPool::MemoryPool() : memberTSize(sizeof(T)) , blockSize(DEFAULT_BLOCK_SIZE) 97 | { 98 | 99 | reserve(DEFAULT_BLOCK_SIZE); 100 | deleteMask.reserve(DEFAULT_BLOCK_SIZE); 101 | currentIndex = 0; 102 | } 103 | 104 | template 105 | inline MemoryPool::~MemoryPool() 106 | { 107 | for (int i = 0; i < memoryBlockPtrVec.size(); ++i) { 108 | delete[] (T*)memoryBlockPtrVec[i]; 109 | } 110 | } 111 | 112 | template 113 | inline MemoryPool::MemoryPool(size_t preAllocate, size_t newBlockSize) 114 | : memberTSize(sizeof(T)), 115 | blockSize(newBlockSize) 116 | { 117 | size_t numBlocks = preAllocate / blockSize + 1; 118 | currentIndex = 0; 119 | deleteMask.reserve(preAllocate); 120 | 121 | for (size_t i = 0; i < numBlocks; ++i) { 122 | T * pBlock = new T[blockSize]; 123 | memoryBlockPtrVec.push_back((char *)pBlock); 124 | } 125 | } 126 | 127 | template 128 | inline bool MemoryPool::reserve(size_t preAllocate) 129 | { 130 | //std::lock_guard newMemberLockGuard(newMemberLock); 131 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 132 | deleteMask.reserve(preAllocate); 133 | 134 | if (currentIndex - deletedMembersList.size() > preAllocate) { 135 | return false; 136 | } 137 | 138 | if (blockSize * memoryBlockPtrVec.size() > preAllocate) { 139 | return true; 140 | } 141 | 142 | //blockSize = newBlockSize; 143 | size_t numBlocks = (preAllocate - blockSize * memoryBlockPtrVec.size())/ blockSize + 1; 144 | //currentIndex = 0; 145 | 146 | for (size_t i = 0; i < numBlocks; ++i) { 147 | T * pBlock = new T[blockSize]; 148 | if (pBlock == NULL) return false; 149 | memoryBlockPtrVec.push_back((char *)pBlock); 150 | } 151 | 152 | return true; 153 | } 154 | 155 | template 156 | inline T * MemoryPool::newMember(size_t & index) 157 | { 158 | //std::lock_guard newMemberLockGuard(newMemberLock); 159 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 160 | 161 | if (deletedMembersList.empty()) { 162 | if (currentIndex >= memoryBlockPtrVec.size() * blockSize) { 163 | T * pBlock = new T[blockSize]; 164 | if (pBlock == NULL) { 165 | return NULL; 166 | } 167 | memoryBlockPtrVec.push_back((char*)pBlock); 168 | } 169 | 170 | T * pNewMember = (T *)getMemberPointer(currentIndex); 171 | index = currentIndex; 172 | ++currentIndex; 173 | deleteMask.push_back(false); 174 | return (T*)pNewMember; 175 | } 176 | else 177 | { 178 | index = deletedMembersList.front(); 179 | deletedMembersList.pop_front(); 180 | T * pNewMember = (T *)getMemberPointer(index); 181 | deleteMask[index] = false; 182 | T * pT = (T *)pNewMember; 183 | //pT->~T(); 184 | *pT = T(); 185 | return pT; 186 | } 187 | } 188 | 189 | template 190 | inline T * MemoryPool::newMember(size_t & index, const T & initialVal) 191 | { 192 | //std::lock_guard newMemberLockGuard(newMemberLock); 193 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 194 | 195 | if (deletedMembersList.empty()) { 196 | if (currentIndex >= memoryBlockPtrVec.size() * blockSize) { 197 | T * pBlock = new T[blockSize]; 198 | if (pBlock == NULL) { 199 | return NULL; 200 | } 201 | memoryBlockPtrVec.push_back((char*)pBlock); 202 | } 203 | 204 | T * pNewMember = (T *)getMemberPointer(currentIndex); 205 | index = currentIndex; 206 | ++currentIndex; 207 | deleteMask.push_back(false); 208 | *pNewMember = initialVal; 209 | return (T*)pNewMember; 210 | } 211 | else 212 | { 213 | index = deletedMembersList.front(); 214 | deletedMembersList.pop_front(); 215 | T * pNewMember = (T *)getMemberPointer(index); 216 | deleteMask[index] = false; 217 | T * pT = (T *)pNewMember; 218 | //pT->~T(); 219 | *pT = initialVal; 220 | return pT; 221 | } 222 | } 223 | 224 | template 225 | inline void * MemoryPool::getMemberPointer(size_t index) 226 | { 227 | //assert(index < capacity()); 228 | size_t blockIndex = index / blockSize; 229 | size_t offSet = index % blockSize; 230 | char * pStartMember = memoryBlockPtrVec[blockIndex]; 231 | return (pStartMember + offSet * memberTSize); 232 | } 233 | 234 | template 235 | inline T * MemoryPool::getPointer(const size_t & index) 236 | { 237 | assert(index < blockSize * memoryBlockPtrVec.size()); 238 | //int blockIndex = index / blockSize; 239 | //int offSet = index % blockSize; 240 | char * & pStartMember = memoryBlockPtrVec[index / blockSize]; 241 | T * pT = (T *)(pStartMember + (index % blockSize) * memberTSize); 242 | return pT; 243 | } 244 | 245 | template 246 | inline const T* MemoryPool::getPointer(const size_t& index) const 247 | { 248 | assert(index < blockSize* memoryBlockPtrVec.size()); 249 | //int blockIndex = index / blockSize; 250 | //int offSet = index % blockSize; 251 | const char* pStartMember = memoryBlockPtrVec[index / blockSize]; 252 | const T* pT = (const T*)(pStartMember + (index % blockSize) * memberTSize); 253 | return pT; 254 | } 255 | 256 | template 257 | inline bool MemoryPool::deleteMember(size_t index) 258 | { 259 | // Access exceeds boundary 260 | assert(index < blockSize * memoryBlockPtrVec.size()); 261 | //std::lock_guard newMemberLockGuard(newMemberLock); 262 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 263 | 264 | T * pMemberToDelete = (T *)getMemberPointer(index); 265 | if (deleteMask[index]) { 266 | return false; 267 | } 268 | else { 269 | deleteMask[index] = true; 270 | deletedMembersList.push_back(index); 271 | return true; 272 | } 273 | } 274 | 275 | template 276 | inline bool MemoryPool::hasBeenDeleted(size_t index) 277 | { 278 | assert(index < blockSize * memoryBlockPtrVec.size()); 279 | //std::lock_guard newMemberLockGuard(deleteMemberLock); 280 | 281 | T * pMemberToDelete = (T *)getMemberPointer(index); 282 | return deleteMask[index]; 283 | } 284 | 285 | template 286 | inline size_t MemoryPool::capacity() 287 | { 288 | //std::lock_guard newMemberLockGuard(newMemberLock); 289 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 290 | 291 | return blockSize * memoryBlockPtrVec.size(); 292 | } 293 | 294 | template 295 | inline size_t MemoryPool::size() const 296 | { 297 | //std::lock_guard newMemberLockGuard(newMemberLock); 298 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 299 | 300 | return currentIndex - deletedMembersList.size(); 301 | } 302 | 303 | template 304 | inline size_t MemoryPool::getCurrentIndex() 305 | { 306 | //std::lock_guard newMemberLockGuard(newMemberLock); 307 | //std::lock_guard deleteMemberLockGuard(deleteMemberLock); 308 | 309 | return currentIndex; 310 | } -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Parser/strutil.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file Strutil.h 3 | * \brief String utilities 4 | * \date 12/20/2017 5 | * 6 | */ 7 | 8 | #pragma once 9 | 10 | #include 11 | #include "IOFuncDef.h" 12 | 13 | struct strutil { 14 | /* declaration */ 15 | static inline bool startsWith(const std::string& str, const std::string& substr) 16 | { 17 | return str.find(substr) == 0; 18 | }; 19 | 20 | static inline bool endsWith(const std::string& str, const std::string& substr) 21 | { 22 | return (str.rfind(substr) == (str.length() - substr.length()) && str.rfind(substr) >= 0); 23 | }; 24 | 25 | //Parse string functions 26 | /* String -> int */ 27 | static int parseStringToInt(const char * str) 28 | { 29 | int currentInt = strtol(str, NULL, 10); //decimalism 30 | return currentInt; 31 | 32 | //int currentInt; 33 | //int ReturnInfo = sscanf(str, "%d", ¤tInt); 34 | //if (ReturnInfo == 1){ 35 | // return currentInt; 36 | //} 37 | //else { 38 | // printf("The string: \"%s\" can't be parsed to int type! It's set to zero(0) by default!"); 39 | // return currentInt; 40 | //} 41 | } 42 | /* String -> float */ 43 | static float parseStringToFloat(const char * str) 44 | { 45 | float currentFloat = strtof(str, NULL); 46 | return currentFloat; 47 | 48 | //float currentFloat; 49 | //int ReturnInfo = sscanf(str, "%f", ¤tFloat); 50 | //if (ReturnInfo == 1) { 51 | // return currentFloat; 52 | //} 53 | //else { 54 | // printf("The string: \"%s\" can't be parsed to float type! It's set to zero(0) by default!"); 55 | // return currentFloat; 56 | //} 57 | } 58 | /* String -> double */ 59 | static double parseStringToDouble(const char * str) 60 | { 61 | double currentDouble = strtod(str, NULL); 62 | return currentDouble; 63 | 64 | //double currentDouble; 65 | //int ReturnInfo = sscanf(str, "%lf", ¤tDouble); 66 | //if (ReturnInfo == 1) { 67 | // return currentDouble; 68 | //} 69 | //else { 70 | // printf("The string: \"%s\" can't be parsed to Double type! It's set to zero(0) by default!\n", str); 71 | // currentDouble = 0; 72 | // return currentDouble; 73 | //} 74 | } 75 | 76 | //Return type 77 | enum ReturnType { StringOver = 1, TokenOut = 2, Success = 3, Failure = 4 }; 78 | 79 | //Delimiter class 80 | /* 81 | * the string's delimiter 82 | */ 83 | struct Delimiter { 84 | /*Default construct*/ 85 | Delimiter() : mSize(1), mDelimiter(" ") {}; 86 | /*Construct 87 | \param char* delimiters the string's delimiter 88 | \param size_t size the delimiter's size 89 | */ 90 | Delimiter(const char * delimiters) :mDelimiter(delimiters) { mSize = strlen(delimiters); }; 91 | const char * mDelimiter; 92 | size_t mSize; 93 | }; 94 | 95 | //brief String Tokenizer class 96 | /*! 97 | * String tokenizer, used to separate the whole string to tokens. 98 | */ 99 | class Tokenizer 100 | { 101 | public: 102 | /*Defalut Construct*/ 103 | Tokenizer() {}; 104 | /*Construct 105 | \param char* str the string which will be separted 106 | */ 107 | Tokenizer(const char * str) 108 | : mString(str), mOffset(0), mDelimiters() { 109 | stringLen = strlen(str); 110 | }; 111 | /*Construct 112 | \param char* str the string which will be separted 113 | \param char* delimiters the string's delimiter 114 | \param size_t size the delimiter's size 115 | */ 116 | Tokenizer(const char * str, const char * delimiters) 117 | : mString(str), mOffset(0), mDelimiters(delimiters) { 118 | stringLen = strlen(str); 119 | }; 120 | /*Init Tokenizer*/ 121 | void initToken(const char * str, const char * delimiters) { 122 | mString = str; 123 | mOffset = 0; 124 | mDelimiters = delimiters; 125 | stringLen = strlen(str); 126 | } 127 | /*Jump to next token*/ 128 | int nextToken() { 129 | /*Clear token*/ 130 | SAFE_STRCPY(mToken, ""); 131 | /*If offset >= string's length, retun StringOver*/ 132 | if (mOffset >= stringLen) return StringOver; 133 | /*Find the start charater of the next token*/ 134 | while (ifIsDelimiter(mString[mOffset])) 135 | { 136 | mOffset++; 137 | /*If offset >= string's length, retun StringOver*/ 138 | if (mOffset >= stringLen) return StringOver; 139 | } 140 | mToken[0] = mString[mOffset]; 141 | mOffset++; 142 | int index = 1; 143 | /*If offset >= string's length, retun Success*/ 144 | if (mOffset >= stringLen) { mToken[index] = '\0'; return Success; } 145 | /*Find the end charater of the next token*/ 146 | while (ifIsDelimiter(mString[mOffset]) == false) 147 | { 148 | mToken[index] = mString[mOffset]; 149 | index++; 150 | mOffset++; 151 | /*If index >= token's size, 152 | *it means we can't put '\0' int token[end], return TokenOut*/ 153 | if (index >= MAX_TOKEN_STRING_SIZE) { return TokenOut; } 154 | /*If offset >= string's length, retun Success*/ 155 | if (mOffset >= stringLen) { mToken[index] = '\0'; return Success; } 156 | } 157 | mToken[index] = '\0'; 158 | return Success; 159 | }; 160 | /*Jump to next token 161 | \param char* delimiters the string's delimiter 162 | \param size_t size the delimiter's size 163 | */ 164 | int nextToken(const char * delimiters, size_t size) 165 | { 166 | /*Clear token*/ 167 | SAFE_STRCPY(mToken, ""); 168 | /*If offset >= string's length, retun StringOver*/ 169 | if (mOffset >= stringLen) return StringOver; 170 | /*Find the start charater of the next token*/ 171 | while (ifIsDelimiter(mString[mOffset], delimiters, size)) 172 | { 173 | mOffset++; 174 | /*If offset >= string's length, retun StringOver*/ 175 | if (mOffset >= stringLen) return StringOver; 176 | } 177 | mToken[0] = mString[mOffset]; 178 | mOffset++; 179 | int index = 1; 180 | /*If offset >= string's length, retun Success*/ 181 | if (mOffset >= stringLen) { mToken[index] = '\0'; return Success; } 182 | /*Find the end charater of the next token*/ 183 | while (ifIsDelimiter(mString[mOffset], delimiters, size) == false) 184 | { 185 | mToken[index] = mString[mOffset]; 186 | index++; 187 | mOffset++; 188 | /*If index >= token's size, 189 | *it means we can't put '\0' int token[end], return TokenOut*/ 190 | if (index >= MAX_TOKEN_STRING_SIZE) { return TokenOut; } 191 | /*If offset >= string's length, retun Success*/ 192 | if (mOffset >= stringLen) { mToken[index] = '\0'; return Success; } 193 | } 194 | mToken[index] = '\0'; 195 | return Success; 196 | }; 197 | /*Judge if current char is delimiter*/ 198 | inline bool ifIsDelimiter(const char & c) 199 | { 200 | const char * currentD = mDelimiters.mDelimiter; 201 | size_t size = mDelimiters.mSize; 202 | for (int i = 0; i < size; i++) 203 | { 204 | if (c == currentD[i]) return true; 205 | } 206 | return false; 207 | } 208 | /*Judge if current char is delimiter*/ 209 | inline bool ifIsDelimiter(const char & c, const char * delimiters, size_t size) 210 | { 211 | for (int i = 0; i < size; i++) 212 | { 213 | if (c == delimiters[i]) return true; 214 | } 215 | return false; 216 | } 217 | /*Find the firstly apparent specified string by the first and last char, 218 | *look for it from current position 219 | /param char startC, the first char 220 | /param char endC, the last char 221 | */ 222 | int findString(const char & startC, const char & endC) 223 | { 224 | /*Clear token*/ 225 | SAFE_STRCPY(mToken, ""); 226 | /*If offset >= string's length, retun StringOver*/ 227 | if (mOffset >= stringLen) return StringOver; 228 | /*Find the first char of the specified string*/ 229 | size_t currentPos = mOffset; 230 | while (mString[currentPos] != startC) 231 | { 232 | currentPos++; 233 | /*If currentPos >= string's length, retun StringOver*/ 234 | if (currentPos >= stringLen) return StringOver; 235 | } 236 | currentPos++; 237 | /*If currentPos >= string's length, retun StringOver*/ 238 | if (currentPos >= stringLen) { return StringOver; } 239 | int index = 0; 240 | while (mString[currentPos] != endC) { 241 | mToken[index] = mString[currentPos]; 242 | index++; 243 | currentPos++; 244 | /*If index >= token's size, 245 | *it means we can't put '\0' int token[end], return TokenOut*/ 246 | if (index >= MAX_TOKEN_STRING_SIZE) { return TokenOut; } 247 | /*If currentPos >= string's length, retun StringOver*/ 248 | if (currentPos >= stringLen) { SAFE_STRCPY(mToken, ""); return StringOver; } 249 | } 250 | mToken[index] = '\0'; 251 | return Success; 252 | } 253 | /*Find the firstly apparent specified string by the first and last char, 254 | *look for it from given position 255 | /param char startC, the first char 256 | /param char endC, the last char 257 | /param int & position, the given position 258 | */ 259 | int findString(const char & startC, const char & endC, const int & position) 260 | { 261 | /*Clear token*/ 262 | SAFE_STRCPY(mToken, ""); 263 | /*If given position isn't a available index, return failure*/ 264 | if (position < 0 || position >= stringLen) return Failure; 265 | /*Find the first char of the specified string*/ 266 | int currentPos = position; 267 | while (mString[currentPos] != startC) 268 | { 269 | currentPos++; 270 | /*If currentPos >= string's length, retun StringOver*/ 271 | if (currentPos >= stringLen) return StringOver; 272 | } 273 | currentPos++; 274 | /*If currentPos >= string's length, retun StringOver*/ 275 | if (currentPos >= stringLen) { return StringOver; } 276 | int index = 0; 277 | while (mString[currentPos] != endC) { 278 | mToken[index] = mString[currentPos]; 279 | index++; 280 | currentPos++; 281 | /*If index >= token's size, 282 | *it means we can't put '\0' int token[end], return TokenOut*/ 283 | if (index >= MAX_TOKEN_STRING_SIZE) { return TokenOut; } 284 | /*If currentPos >= string's length, retun StringOver*/ 285 | if (currentPos >= stringLen) { SAFE_STRCPY(mToken, ""); return StringOver; } 286 | } 287 | mToken[index] = '\0'; 288 | return Success; 289 | } 290 | /*Find the firstly apparent specified string by the first and last char, 291 | *look for it from current position 292 | /param char startC, the first char 293 | /param char endC, the last char 294 | */ 295 | int findString(const char & startC, const char & endC, char * currentString) 296 | { 297 | /*Clear token*/ 298 | SAFE_STRCPY(currentString, ""); 299 | /*If offset >= string's length, retun StringOver*/ 300 | if (mOffset >= stringLen) return StringOver; 301 | /*Find the first char of the specified string*/ 302 | size_t currentPos = mOffset; 303 | while (mString[currentPos] != startC) 304 | { 305 | currentPos++; 306 | /*If currentPos >= string's length, retun StringOver*/ 307 | if (currentPos >= stringLen) return StringOver; 308 | } 309 | currentPos++; 310 | /*If currentPos >= string's length, retun StringOver*/ 311 | if (currentPos >= stringLen) { return StringOver; } 312 | int index = 0; 313 | while (mString[currentPos] != endC) { 314 | currentString[index] = mString[currentPos]; 315 | index++; 316 | currentPos++; 317 | /*If index >= token's size, 318 | *it means we can't put '\0' int token[end], return TokenOut*/ 319 | if (index >= MAX_TOKEN_STRING_SIZE) { return TokenOut; } 320 | /*If currentPos >= string's length, retun StringOver*/ 321 | if (currentPos >= stringLen) { return StringOver; } 322 | } 323 | currentString[index] = '\0'; 324 | return Success; 325 | } 326 | /*Return current token*/ 327 | const char * getToken() const { return mToken; }; 328 | /* 329 | * to reset the tokenizer. After reset it, the tokenizer can get 330 | * the tokens from the first token. 331 | */ 332 | void reset() { mOffset = 0; }; 333 | 334 | protected: 335 | size_t mOffset; 336 | const char * mString; 337 | size_t stringLen; 338 | char mToken[MAX_TOKEN_STRING_SIZE]; 339 | Delimiter mDelimiters; 340 | }; 341 | 342 | }; -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Memory/Array.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | // A container support random access, not thread safe, 4 | // with default pre allocated memory, in stack 5 | // "P" in CPArray means pre allocate 6 | // designed to contain basic numerical types, like int, double, pointer 7 | // not safe for types that require destructor 8 | 9 | template 10 | class CPArray { 11 | public: 12 | CPArray() : 13 | pMem(pPreAllocated) 14 | {}; 15 | 16 | // deep copy constructor 17 | CPArray(const CPArray & arr) : 18 | pMem(pPreAllocated) 19 | { 20 | reserve(arr.capacity()); 21 | mSize = 0; 22 | for (int i = 0; i < arr.size(); i++) 23 | { 24 | pMem[mSize] = arr[i]; 25 | ++mSize;; 26 | } 27 | }; 28 | 29 | ~CPArray() { 30 | if (pMem != pPreAllocated) { 31 | delete[] pMem; 32 | } 33 | } 34 | 35 | T& operator[](const int & i) { 36 | assert(i < mSize); 37 | return pMem[i]; 38 | } 39 | 40 | const T& operator[](const int& i) const { 41 | assert(i < mSize); 42 | return pMem[i]; 43 | } 44 | 45 | void push_back(const T & newMember) { 46 | if (mSize + 1 > mCapacity) { 47 | reserve(mCapacity + (int)(mCapacity / 2) + 3); 48 | } 49 | 50 | pMem[mSize] = newMember; 51 | ++mSize; 52 | } 53 | 54 | void emplace_back() { 55 | if (mSize + 1 > mCapacity) { 56 | reserve(mCapacity + (int)(mCapacity / 2) + 3); 57 | } 58 | 59 | pMem[mSize] = T(); 60 | ++mSize; 61 | } 62 | 63 | void push_back(T && newMember) { 64 | if (mSize + 1 > mCapacity) { 65 | reserve(mCapacity + (int)(mCapacity / 2) + 3); 66 | } 67 | 68 | pMem[mSize] = std::move(newMember); 69 | ++mSize; 70 | } 71 | 72 | // reserve memory, mention that CPArray cannot reserve memory with size less than preAllocateSize 73 | void reserve(const size_t & newCap) { 74 | if (mSize > newCap) { 75 | return; 76 | } 77 | if (newCap <= preAllocateSize) { 78 | if (pPreAllocated == pMem) { 79 | return; 80 | } 81 | else{ 82 | std::move(pMem, pMem + mSize, pPreAllocated); 83 | delete[] pMem; 84 | pMem = pPreAllocated; 85 | mCapacity = preAllocateSize; 86 | } 87 | } 88 | else{ 89 | T * newMem = new T[newCap]; 90 | std::move(pMem, pMem + mSize, newMem); 91 | mCapacity = newCap; 92 | if (pMem != pPreAllocated) { 93 | delete[] pMem; 94 | } 95 | pMem = newMem; 96 | } 97 | 98 | } 99 | 100 | void clear(bool releaseMemory=false) { 101 | mSize = 0; 102 | if (releaseMemory) { 103 | if (pMem != pPreAllocated) { 104 | delete[] pMem; 105 | pMem = pPreAllocated; 106 | mCapacity = preAllocateSize; 107 | } 108 | } 109 | } 110 | 111 | void erase(size_t i) { 112 | for (size_t j = i; int(j) < int(mSize) - 1; ++j){ 113 | pMem[j] = std::move(pMem[j+1]); 114 | } 115 | --mSize; 116 | } 117 | 118 | //erase form index i to i+n-1 119 | void eraseN(size_t i, size_t n) { 120 | for (size_t j = i; int(j) < int(mSize) - n; ++j) { 121 | pMem[j] = std::move(pMem[j + n]); 122 | } 123 | mSize -= n; 124 | } 125 | 126 | void insert(size_t i, const T & memberToInsert) { 127 | if (mSize + 1 > mCapacity) { 128 | reserve(mCapacity + (int)(mCapacity / 2) + 3); 129 | } 130 | for (size_t j = mSize; j > i + 1; --j) { 131 | pMem[j] = std::move(pMem[j - 1]); 132 | } 133 | pMem[i+1] = memberToInsert; 134 | ++mSize; 135 | } 136 | void insert(size_t i, T && memberToInsert) { 137 | if (mSize + 1 > mCapacity) { 138 | reserve(mCapacity + (int)(mCapacity / 2) + 3); 139 | } 140 | for (size_t j = mSize; j > i + 1; --j) { 141 | pMem[j] = std::move(pMem[j-1]); 142 | } 143 | pMem[i+1] = std::move(memberToInsert); 144 | ++mSize; 145 | } 146 | 147 | //insert n elemets after element with index i, only make rooms for those elements, 148 | //need to be initailized by you afterwards. 149 | void insertN(size_t i, int n) { 150 | if (mSize + n > mCapacity) { 151 | reserve(mCapacity + (int)(mCapacity / 2) + n + 3); 152 | } 153 | for (size_t j = mSize + n - 1; j > n + i; --j) { 154 | pMem[j] = std::move(pMem[j - n]); 155 | } 156 | mSize += n; 157 | } 158 | 159 | T* begin() { 160 | return pMem; 161 | } 162 | T* end() { 163 | return pMem + mSize; 164 | } 165 | 166 | T& front() { 167 | return *pMem; 168 | } 169 | 170 | const T& front() const { 171 | return *pMem; 172 | } 173 | 174 | T& back() { 175 | return pMem[mSize - 1]; 176 | } 177 | 178 | const T& back() const { 179 | return pMem[mSize - 1]; 180 | } 181 | void pop_back() { 182 | --mSize; 183 | } 184 | 185 | bool has(const T & t) { 186 | for (size_t j = 0; j < mSize; ++j) { 187 | if (t == pMem[j]) { 188 | return true; 189 | } 190 | } 191 | return false; 192 | } 193 | 194 | size_t size() const { return mSize; } 195 | size_t capacity() const { return mCapacity; } 196 | private: 197 | T pPreAllocated[preAllocateSize]; 198 | T * pMem; 199 | size_t mSize = 0; 200 | size_t mCapacity = preAllocateSize; 201 | }; 202 | 203 | // this Array does not allow dynamic memory allocation 204 | template 205 | class CPArrayStaticBase { 206 | public: 207 | CPArrayStaticBase() 208 | {}; 209 | 210 | ~CPArrayStaticBase() { 211 | } 212 | 213 | T& operator[](const int& i) { 214 | assert(i < mSize); 215 | return pPreAllocated[i]; 216 | } 217 | 218 | const T& operator[](const int& i) const { 219 | assert(i < mSize); 220 | return pPreAllocated[i]; 221 | } 222 | 223 | 224 | // thread safe when using atomic SizeType 225 | bool push_back(const T& newMember) { 226 | size_t curId = mSize++; 227 | if (curId >= mCapacity) { 228 | // overflow 229 | mSize = mCapacity; 230 | return false; 231 | } 232 | else 233 | { 234 | pPreAllocated[curId] = newMember; 235 | return true; 236 | } 237 | 238 | } 239 | 240 | // thread safe when using atomic SizeType 241 | bool push_back(T&& newMember) { 242 | size_t curId = mSize++; 243 | if (curId >= mCapacity) { 244 | // overflow 245 | curId = mCapacity; 246 | return false; 247 | } 248 | else 249 | { 250 | pPreAllocated[curId] = std::move(newMember); 251 | return true; 252 | } 253 | 254 | } 255 | 256 | void clear() { 257 | mSize = 0; 258 | } 259 | 260 | // not thread safe 261 | void erase(size_t i) { 262 | for (size_t j = i; int(j) < int(mSize) - 1; ++j) { 263 | pPreAllocated[j] = std::move(pPreAllocated[j + 1]); 264 | } 265 | --mSize; 266 | } 267 | 268 | // not thread safe 269 | //erase form index i to i+n-1 270 | void eraseN(size_t i, size_t n) { 271 | for (size_t j = i; int(j) < int(mSize) - n; ++j) { 272 | pPreAllocated[j] = std::move(pPreAllocated[j + n]); 273 | } 274 | mSize -= n; 275 | } 276 | 277 | // not thread safe 278 | bool insert(size_t i, const T& memberToInsert) { 279 | if (mSize + 1 > mCapacity) { 280 | return false; 281 | } 282 | for (size_t j = mSize; j > i + 1; --j) { 283 | pPreAllocated[j] = std::move(pPreAllocated[j - 1]); 284 | } 285 | pPreAllocated[i + 1] = memberToInsert; 286 | ++mSize; 287 | return true; 288 | } 289 | 290 | // not thread safe 291 | bool insert(size_t i, T&& memberToInsert) { 292 | if (mSize + 1 > mCapacity) { 293 | return false; 294 | } 295 | for (size_t j = mSize; j > i + 1; --j) { 296 | pPreAllocated[j] = std::move(pPreAllocated[j - 1]); 297 | } 298 | pPreAllocated[i + 1] = std::move(memberToInsert); 299 | ++mSize; 300 | return true; 301 | } 302 | 303 | //insert n elemets after element with index i, only make rooms for those elements, 304 | //need to be initailized by you afterwards. 305 | bool insertN(size_t i, int n) { 306 | if (mSize + n > mCapacity) { 307 | return false; 308 | } 309 | for (size_t j = mSize + n - 1; j > n + i; --j) { 310 | pPreAllocated[j] = std::move(pPreAllocated[j - n]); 311 | } 312 | mSize += n; 313 | return true; 314 | } 315 | 316 | T* begin() { 317 | return pPreAllocated; 318 | } 319 | T* end() { 320 | return pPreAllocated + mSize; 321 | } 322 | 323 | T& front() { 324 | return *pPreAllocated; 325 | } 326 | T& back() { 327 | return pPreAllocated[mSize - 1]; 328 | } 329 | T pop_back() { 330 | --mSize; 331 | return pPreAllocated[mSize]; 332 | } 333 | 334 | bool empty() { 335 | return mSize == 0; 336 | } 337 | 338 | bool has(const T& t) { 339 | for (int j = 0; j < mSize; ++j) { 340 | if (t == pPreAllocated[j]) { 341 | return true; 342 | } 343 | } 344 | return false; 345 | } 346 | 347 | size_t size() const { return mSize; } 348 | size_t capacity() const { return mCapacity; } 349 | private: 350 | alignas(16) T pPreAllocated[preAllocateSize]; 351 | SizeType mSize = 0; 352 | const size_t mCapacity = preAllocateSize; 353 | }; 354 | 355 | template 356 | using CPArrayStatic = CPArrayStaticBase; 357 | 358 | template 359 | using CPArrayStaticAtomic = CPArrayStaticBase>; 360 | 361 | 362 | template 363 | class CircularArray 364 | { 365 | public: 366 | CircularArray() {}; 367 | ~CircularArray() {}; 368 | 369 | int size() const { return mSize; } 370 | 371 | void clear(bool destruct = false) { 372 | while (mSize != 0) 373 | { 374 | popBack(destruct); 375 | } 376 | } 377 | 378 | bool has(const T & d) { 379 | for (int i = 0; i < size(); i++) 380 | { 381 | int actualIndex = i + mBeginIdx; 382 | if (actualIndex >= maxSize) 383 | { 384 | actualIndex -= maxSize; 385 | } 386 | if (d == mData[actualIndex]) 387 | { 388 | return true; 389 | } 390 | } 391 | return false; 392 | } 393 | 394 | bool hasBackward(const T& d) { 395 | for (int i = size()-1; i >= 0 ; i--) 396 | { 397 | int actualIndex = i + mBeginIdx; 398 | if (actualIndex >= maxSize) 399 | { 400 | actualIndex -= maxSize; 401 | } 402 | if (d == mData[actualIndex]) 403 | { 404 | return true; 405 | } 406 | } 407 | return false; 408 | } 409 | 410 | T& front() { 411 | if (!mSize) 412 | { 413 | assert(false && "Array is empty! "); 414 | } 415 | return mData[mBeginIdx]; 416 | } 417 | 418 | T& back() { 419 | if (!mSize) 420 | { 421 | assert(false && "Array is empty! "); 422 | } 423 | return mData[mEndIdx]; 424 | } 425 | 426 | void push_back(const T& newElement) { 427 | if (mSize == 0) 428 | // array is empty, in this case mBeginIdx == mEndIdx 429 | { 430 | mData[mEndIdx] = newElement; 431 | ++mSize; 432 | } 433 | else 434 | // array is not empty 435 | { 436 | moveIdxForward(mEndIdx); 437 | if (mEndIdx != mBeginIdx) 438 | // end index hasn't caught up with begin index, increase the size 439 | { 440 | mData[mEndIdx] = newElement; 441 | ++mSize; 442 | } 443 | else 444 | // end index has caught up with begin index, the array is full; overwrite the oldest element 445 | // the size won't increase in this case 446 | { 447 | moveIdxForward(mBeginIdx); 448 | mData[mEndIdx] = newElement; 449 | } 450 | } 451 | 452 | 453 | } 454 | 455 | // set destruct = true to explictly destruct the element 456 | void popFront(bool destruct = false) { 457 | 458 | if (mSize != 0) 459 | { 460 | --mSize; 461 | 462 | int mBeginIdxOld = mBeginIdx; 463 | // if its already empty, stay at where it is to make sure mEndIdx == mBeginIds 464 | if (mSize != 0) { 465 | moveIdxForward(mBeginIdx); 466 | } 467 | if (destruct) 468 | { 469 | mData[mBeginIdxOld].~T(); 470 | } 471 | else { 472 | } 473 | } 474 | else 475 | { 476 | assert(false && "Trying to pop an empty array! "); 477 | } 478 | } 479 | 480 | // set destruct = true to explictly destruct the element 481 | void popBack(bool destruct = false) { 482 | 483 | if (mSize != 0) 484 | { 485 | --mSize; 486 | int mEndIdxOld = mEndIdx; 487 | // if its already empty, stay at where it is to make sure mEndIdx == mBeginIds 488 | if (mSize != 0) { 489 | moveIdxBackward(mEndIdx); 490 | } 491 | if (destruct) 492 | { 493 | mData[mEndIdxOld].~T(); 494 | } 495 | else { 496 | } 497 | } 498 | else 499 | { 500 | assert(false && "Trying to pop an empty array! "); 501 | } 502 | } 503 | 504 | // count from the oldest element to newest element 505 | // 0th is the oldest, (size-1)th is the newest element 506 | // it won't detect the if it has exceeded the boundary 507 | // you will have to make sure idx < size() 508 | T& operator [] (int idx) { 509 | int actualIndex = idx + mBeginIdx; 510 | if (actualIndex >= maxSize) 511 | { 512 | actualIndex -= maxSize; 513 | } 514 | 515 | return mData[actualIndex]; 516 | } 517 | 518 | const T& operator [] (int idx) const { 519 | int actualIndex = idx + mBeginIdx; 520 | if (actualIndex >= maxSize) 521 | { 522 | actualIndex -= maxSize; 523 | } 524 | 525 | return mData[actualIndex]; 526 | } 527 | 528 | 529 | 530 | protected: 531 | inline void moveIdxForward(int& idx) { 532 | ++idx; 533 | if (idx >= maxSize) { 534 | idx = idx - maxSize; 535 | } 536 | } 537 | 538 | inline void moveIdxBackward(int& idx) { 539 | --idx; 540 | if (idx < 0) { 541 | idx = maxSize - 1; 542 | } 543 | } 544 | 545 | int mSize = 0; 546 | 547 | // if mBeginIdx == mEndIdx, the array can either be empty or has one element; in this case we need to rely on mSize to determine 548 | int mBeginIdx = 0; // the index of the latest element 549 | int mEndIdx = 0; // the index of the newest element 550 | 551 | alignas(16) T mData[maxSize]; 552 | }; 553 | 554 | template 555 | inline std::ostream& operator<<(std::ostream& os, const CircularArray& arr) 556 | { 557 | for (size_t i = 0; i < arr.size(); i++) 558 | { 559 | os << " " << arr[i]; 560 | }; 561 | return os; 562 | } 563 | 564 | template 565 | inline std::ostream& operator<<(std::ostream& os, const CPArrayStaticBase& arr) 566 | { 567 | for (size_t i = 0; i < arr.size(); i++) 568 | { 569 | os << " " << arr[i]; 570 | }; 571 | return os; 572 | } 573 | 574 | template 575 | inline std::ostream& operator<<(std::ostream& os, const CPArray& arr) 576 | { 577 | for (size_t i = 0; i < arr.size(); i++) 578 | { 579 | os << " " << arr[i]; 580 | }; 581 | return os; 582 | } -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/Parser/traits_io.h: -------------------------------------------------------------------------------- 1 | /*! \file Traits_IO.h 2 | * \brief input/output the traits 3 | * \author David Gu 4 | * \date documented on 6/23/2011 5 | * 6 | */ 7 | 8 | #ifndef _TRAITS_IO_H_ 9 | #define _TRAITS_IO_H_ 10 | 11 | #include 12 | #include 13 | 14 | #include "Mesh/BaseMesh.h" 15 | #include "Mesh/Vertex.h" 16 | #include "Mesh/HalfEdge.h" 17 | #include "Mesh/Edge.h" 18 | #include "Mesh/Face.h" 19 | #include "mesh/iterators.h" 20 | #include "mesh/boundary.h" 21 | #include "Parser/parser.h" 22 | 23 | #define VERTEX_RGB (0x01<<0) 24 | #define VERTEX_UV (0x01<<1) 25 | #define VERTEX_Z (0x01<<2) 26 | #define VERTEX_MU (0x01<<3) 27 | #define VERTEX_FATHER (0x01<<4) 28 | #define VERTEX_LAMBDA (0x01<<5) 29 | #define VERTEX_NORMAL (0x01<<6) 30 | #define VERTEX_U (0x01<<7) 31 | #define EDGE_LENGTH (0x01<<8) 32 | #define EDGE_SHARP (0x01<<9) 33 | #define EDGE_DU (0x01<<10) 34 | #define EDGE_DUV (0x01<<11) 35 | 36 | #define FACE_RGB (0x01<<16) 37 | #define FACE_NORMAL (0x01<<17) 38 | #define FACE_U (0x01<<18) 39 | 40 | namespace MeshLib 41 | { 42 | 43 | template 44 | void _read_vertex_target_k( M * pMesh ) 45 | { 46 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 47 | { 48 | V * pV = *viter; 49 | CParser parser( pV->string() ); 50 | 51 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 52 | { 53 | CToken * token = *iter; 54 | if( token->m_key == "k" ) 55 | { 56 | std::string line = strutil::trim( token->m_value, "()"); 57 | pV->target_k() = strutil::parseString( line ); 58 | } 59 | } 60 | } 61 | }; 62 | 63 | 64 | template 65 | void _write_vertex_uv( M * pMesh ) 66 | { 67 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 68 | { 69 | V * pV = *viter; 70 | CPoint2 uv = pV->uv(); 71 | 72 | CParser parser( pV->string() ); 73 | parser._removeToken( "uv" ); 74 | 75 | parser._toString( pV->string() ); 76 | 77 | std::stringstream iss; 78 | 79 | iss << "uv=(" << uv[0] << " " << uv[1] << ")"; 80 | 81 | if( pV->string().size() > 0 ) 82 | { 83 | pV->string() += " "; 84 | } 85 | pV->string() += iss.str(); 86 | } 87 | }; 88 | 89 | template 90 | void _write_vertex_huv( M * pMesh ) 91 | { 92 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 93 | { 94 | M::CVertex * pV = *viter; 95 | CPoint2 uv = pV->huv(); 96 | 97 | CParser parser( pV->string() ); 98 | parser._removeToken( "uv" ); 99 | 100 | parser._toString( pV->string() ); 101 | 102 | std::stringstream iss; 103 | 104 | iss << "uv=(" << uv[0] << " " << uv[1] << ")"; 105 | 106 | if( pV->string().size() > 0 ) 107 | { 108 | pV->string() += " "; 109 | } 110 | pV->string() += iss.str(); 111 | } 112 | }; 113 | 114 | template 115 | void _read_vertex_uv( M * pMesh ) 116 | { 117 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 118 | { 119 | V * pV = *viter; 120 | CParser parser( pV->string() ); 121 | 122 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 123 | { 124 | CToken * token = *iter; 125 | if( token->m_key == "uv" ) 126 | { 127 | CPoint2 uv; 128 | token->m_value >> uv; 129 | pV->uv() = uv; 130 | } 131 | } 132 | } 133 | }; 134 | 135 | template 136 | void __read_vertex_uv( M * pMesh ) 137 | { 138 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 139 | { 140 | M::CVertex * pV = *viter; 141 | CParser parser( pV->string() ); 142 | 143 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 144 | { 145 | CToken * token = *iter; 146 | if( token->m_key == "uv" ) 147 | { 148 | CPoint2 uv; 149 | token->m_value >> uv; 150 | pV->uv() = uv; 151 | } 152 | } 153 | } 154 | }; 155 | 156 | template 157 | void _read_vertex_z( M * pMesh ) 158 | { 159 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 160 | { 161 | V * pV = *viter; 162 | CParser parser( pV->string() ); 163 | 164 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 165 | { 166 | CToken * token = *iter; 167 | if( token->m_key == "z" ) 168 | { 169 | CPoint2 uv; 170 | token->m_value >> uv; 171 | pV->z() = std::complex( uv[0], uv[1] ); 172 | } 173 | } 174 | } 175 | }; 176 | 177 | 178 | 179 | template 180 | void _read_vertex_huv( M * pMesh ) 181 | { 182 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 183 | { 184 | M::CVertex * pV = *viter; 185 | CParser parser( pV->string() ); 186 | 187 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 188 | { 189 | CToken * token = *iter; 190 | if( token->m_key == "uv" ) 191 | { 192 | CPoint2 uv; 193 | token->m_value >> uv; 194 | pV->huv() = uv; 195 | } 196 | } 197 | } 198 | }; 199 | 200 | template 201 | void _read_vertex_father( M * pMesh ) 202 | { 203 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 204 | { 205 | V * pV = *viter; 206 | CParser parser( pV->string() ); 207 | 208 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 209 | { 210 | CToken * token = *iter; 211 | if( token->m_key == "father" ) 212 | { 213 | std::string line = strutil::trim( token->m_value, "()"); 214 | pV->father() = strutil::parseString( line ); 215 | } 216 | } 217 | } 218 | }; 219 | 220 | template 221 | void _read_vertex_father_trait( M * pMesh ) 222 | { 223 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 224 | { 225 | M::CVertex * pV = *viter; 226 | CParser parser( pV->string() ); 227 | 228 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 229 | { 230 | CToken * token = *iter; 231 | if( token->m_key == "father" ) 232 | { 233 | std::string line = strutil::trim( token->m_value, "()"); 234 | pV->father() = strutil::parseString( line ); 235 | } 236 | } 237 | } 238 | }; 239 | 240 | 241 | template 242 | void _read_vertex_mu( M * pMesh ) 243 | { 244 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 245 | { 246 | V * pV = *viter; 247 | CParser parser( pV->string() ); 248 | 249 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 250 | { 251 | CToken * token = *iter; 252 | if( token->m_key == "mu" ) 253 | { 254 | CPoint2 uv; 255 | token->m_value >> uv; 256 | pV->mu() = std::complex( uv[0], uv[1] ); 257 | } 258 | } 259 | } 260 | }; 261 | 262 | template 263 | void _read_vertex_normal( M * pMesh ) 264 | { 265 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 266 | { 267 | V * pV = *viter; 268 | CParser parser( pV->string() ); 269 | 270 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 271 | { 272 | CToken * token = *iter; 273 | if( token->m_key == "normal" ) 274 | { 275 | CPoint normal; 276 | token->m_value >> normal; 277 | pV->normal() = normal; 278 | } 279 | } 280 | } 281 | }; 282 | 283 | 284 | template 285 | void _read_vertex_rgb( M * pMesh ) 286 | { 287 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 288 | { 289 | V * pV = *viter; 290 | CParser parser( pV->string() ); 291 | 292 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 293 | { 294 | CToken * token = *iter; 295 | if( token->m_key == "rgb" ) 296 | { 297 | CPoint rgb; 298 | token->m_value >> rgb; 299 | pV->rgb() = rgb; 300 | } 301 | } 302 | } 303 | }; 304 | 305 | template 306 | void _read_vertex_rgb_trait( M * pMesh ) 307 | { 308 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 309 | { 310 | M::CVertex * pV = *viter; 311 | CParser parser( pV->string() ); 312 | 313 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 314 | { 315 | CToken * token = *iter; 316 | if( token->m_key == "rgb" ) 317 | { 318 | CPoint rgb; 319 | token->m_value >> rgb; 320 | pV->rgb() = rgb; 321 | } 322 | } 323 | } 324 | }; 325 | 326 | template 327 | void _read_edge_length( M * pMesh ) 328 | { 329 | for( M::MeshEdgeIterator eiter( pMesh ); !eiter.end(); eiter ++ ) 330 | { 331 | E * pE = *eiter; 332 | 333 | CParser parser( pE->string() ); 334 | 335 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 336 | { 337 | CToken * token = *iter; 338 | if( token->m_key == "l" ) 339 | { 340 | std::string line = strutil::trim( token->m_value, "()"); 341 | pE->length() = strutil::parseString(line) ; 342 | } 343 | } 344 | } 345 | }; 346 | 347 | template 348 | void _read_edge_length_trait( M * pMesh ) 349 | { 350 | for( M::MeshEdgeIterator eiter( pMesh ); !eiter.end(); eiter ++ ) 351 | { 352 | M::CEdge * pE = *eiter; 353 | 354 | CParser parser( pE->string() ); 355 | 356 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 357 | { 358 | CToken * token = *iter; 359 | if( token->m_key == "l" ) 360 | { 361 | std::string line = strutil::trim( token->m_value, "()"); 362 | pE->length() = strutil::parseString(line) ; 363 | } 364 | } 365 | } 366 | }; 367 | 368 | template 369 | void _read_edge_sharp( M * pMesh ) 370 | { 371 | for( M::MeshEdgeIterator eiter( pMesh ); !eiter.end(); eiter ++ ) 372 | { 373 | E * pE = *eiter; 374 | 375 | CParser parser( pE->string() ); 376 | pE->sharp() = false; 377 | 378 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 379 | { 380 | CToken * token = *iter; 381 | if( token->m_key == "sharp" ) 382 | { 383 | pE->sharp() = true; 384 | } 385 | } 386 | } 387 | }; 388 | 389 | template 390 | void _write_vertex_z( M * pMesh ) 391 | { 392 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 393 | { 394 | V * pV = *viter; 395 | CParser parser( pV->string() ); 396 | parser._removeToken( "z" ); 397 | 398 | parser._toString( pV->string() ); 399 | 400 | std::stringstream iss; 401 | 402 | iss << "z=(" << pV->z().real() << " " << pV->z().imag() << ")"; 403 | 404 | if( pV->string().size() > 0 ) 405 | { 406 | pV->string() += " "; 407 | } 408 | pV->string() += iss.str(); 409 | } 410 | }; 411 | 412 | 413 | template 414 | void _write_vertex_mu( M * pMesh ) 415 | { 416 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 417 | { 418 | V * pV = *viter; 419 | CParser parser( pV->string() ); 420 | parser._removeToken( "mu" ); 421 | 422 | parser._toString( pV->string() ); 423 | 424 | std::stringstream iss; 425 | 426 | iss << "mu=(" << pV->mu().real() << " " << pV->mu().imag() << ")"; 427 | 428 | if( pV->string().size() > 0 ) 429 | { 430 | pV->string() += " "; 431 | } 432 | pV->string() += iss.str(); 433 | } 434 | }; 435 | 436 | template 437 | void _write_vertex_u( M * pMesh ) 438 | { 439 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 440 | { 441 | V * pV = *viter; 442 | CPoint rgb = pV->rgb(); 443 | 444 | CParser parser( pV->string() ); 445 | parser._removeToken( "u" ); 446 | parser._toString( pV->string() ); 447 | CPoint u = pV->u(); 448 | std::stringstream iss; 449 | iss << "u=(" << u[0] << " " << u[1] << " " << u[2] << ")"; 450 | 451 | if( pV->string().size() > 0 ) 452 | { 453 | pV->string() += " "; 454 | } 455 | pV->string() += iss.str(); 456 | } 457 | }; 458 | 459 | 460 | template 461 | void _write_vertex_rgb( M * pMesh ) 462 | { 463 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 464 | { 465 | V * pV = *viter; 466 | CPoint rgb = pV->rgb(); 467 | 468 | CParser parser( pV->string() ); 469 | parser._removeToken( "rgb" ); 470 | 471 | parser._toString( pV->string() ); 472 | 473 | std::stringstream iss; 474 | 475 | iss << "rgb=(" << rgb[0] << " " << rgb[1] << " " << rgb[2] << ")"; 476 | 477 | if( pV->string().size() > 0 ) 478 | { 479 | pV->string() += " "; 480 | } 481 | pV->string() += iss.str(); 482 | } 483 | }; 484 | 485 | template 486 | void _write_vertex_rgb_trait( M * pMesh ) 487 | { 488 | for( M::MeshVertexIterator viter( pMesh ); !viter.end(); viter ++ ) 489 | { 490 | M::CVertex * pV = *viter; 491 | CPoint rgb = pV->rgb(); 492 | 493 | CParser parser( pV->string() ); 494 | parser._removeToken( "rgb" ); 495 | 496 | parser._toString( pV->string() ); 497 | 498 | std::stringstream iss; 499 | 500 | iss << "rgb=(" << rgb[0] << " " << rgb[1] << " " << rgb[2] << ")"; 501 | 502 | if( pV->string().size() > 0 ) 503 | { 504 | pV->string() += " "; 505 | } 506 | pV->string() += iss.str(); 507 | } 508 | }; 509 | 510 | 511 | template 512 | void _write_edge_sharp( M * pMesh ) 513 | { 514 | for( M::MeshEdgeIterator eiter( pMesh ); !eiter.end(); eiter ++ ) 515 | { 516 | E * pE = *eiter; 517 | CParser parser( pE->string() ); 518 | parser._removeToken( "sharp" ); 519 | parser._toString( pE->string() ); 520 | 521 | std::string line; 522 | std::stringstream iss(line); 523 | if( pE->sharp() ) 524 | { 525 | iss << "sharp"; 526 | } 527 | if( pE->string().length() > 0 ) 528 | { 529 | pE->string() += " "; 530 | } 531 | pE->string() += iss.str(); 532 | 533 | }; 534 | }; 535 | 536 | 537 | 538 | 539 | template 540 | void _write_edge_du( M * pMesh ) 541 | { 542 | for( M::MeshEdgeIterator eiter( pMesh ); !eiter.end(); eiter ++ ) 543 | { 544 | E * pE = *eiter; 545 | CParser parser( pE->string() ); 546 | parser._removeToken( "du" ); 547 | 548 | parser._toString( pE->string() ); 549 | 550 | std::stringstream iss; 551 | 552 | iss << "du=(" << pE->du() << ")"; 553 | 554 | if( pE->string().size() > 0 ) 555 | { 556 | pE->string() += " "; 557 | } 558 | pE->string() += iss.str(); 559 | } 560 | }; 561 | 562 | 563 | template 564 | void _input_traits( M * pMesh ) 565 | { 566 | if( M->m_input_traits |= VERTEX_UV ) 567 | { 568 | _read_vertex_uv( pMesh ); 569 | } 570 | 571 | if( M->m_input_traits |= VERTEX_NORMAL ) 572 | { 573 | _read_vertex_normal( pMesh ); 574 | } 575 | 576 | if( M->m_input_traits |= VERTEX_RGB ) 577 | { 578 | _read_vertex_rgb( pMesh ); 579 | } 580 | 581 | if( M->m_input_traits |= EDGE_LENGTH ) 582 | { 583 | _read_edge_length( pMesh ); 584 | } 585 | 586 | if( M->m_input_traits |= EDGE_SHARP ) 587 | { 588 | _read_edge_sharp( pMesh ); 589 | } 590 | 591 | }; 592 | 593 | template 594 | void _output_traits( M * pMesh ) 595 | { 596 | if( M->m_m_output_traits |= VERTEX_UV ) 597 | { 598 | _write_vertex_uv( pMesh ); 599 | } 600 | 601 | if( M->m_m_output_traits |= VERTEX_MU ) 602 | { 603 | _write_vertex_mu( pMesh ); 604 | } 605 | 606 | if( M->m_m_output_traits |= VERTEX_RGB ) 607 | { 608 | _write_vertex_rgb( pMesh ); 609 | } 610 | 611 | if( M->m_m_output_traits |= VERTEX_U ) 612 | { 613 | _write_vertex_u( pMesh ); 614 | } 615 | 616 | if( M->m_m_output_traits |= EDGE_DU ) 617 | { 618 | _write_edge_du( pMesh ); 619 | } 620 | 621 | if( M->m_m_output_traits |= EDGE_SHARP ) 622 | { 623 | _write_edge_sharp( pMesh ); 624 | } 625 | }; 626 | 627 | 628 | template 629 | void _write_edge_length_trait( M * pMesh ) 630 | { 631 | for( M::MeshEdgeIterator eiter( pMesh ); !eiter.end(); eiter ++ ) 632 | { 633 | M::CEdge * pE = *eiter; 634 | CParser parser( pE->string() ); 635 | parser._removeToken( "l" ); 636 | parser._toString( pE->string() ); 637 | 638 | std::stringstream iss; 639 | iss << "l=("<< std::setprecision(12) << pE->length() << ")"; 640 | if( pE->string().size() > 0 ) 641 | { 642 | pE->string() += " "; 643 | } 644 | pE->string() += iss.str(); 645 | } 646 | }; 647 | 648 | 649 | template 650 | void _write_edge_sharp_trait( M * pMesh ) 651 | { 652 | for( M::MeshEdgeIterator eiter( pMesh ); !eiter.end(); eiter ++ ) 653 | { 654 | M::CEdge * pE = *eiter; 655 | CParser parser( pE->string() ); 656 | parser._removeToken( "sharp" ); 657 | parser._toString( pE->string() ); 658 | 659 | std::string line; 660 | std::stringstream iss(line); 661 | if( pE->sharp() ) 662 | { 663 | iss << "sharp"; 664 | } 665 | if( pE->string().length() > 0 ) 666 | { 667 | pE->string() += " "; 668 | } 669 | pE->string() += iss.str(); 670 | 671 | }; 672 | }; 673 | 674 | 675 | template 676 | void _read_face_mu( M * pMesh ) 677 | { 678 | for( M::MeshFaceIterator fiter( pMesh ); !fiter.end(); fiter ++ ) 679 | { 680 | M::CFace * pF = *fiter; 681 | CParser parser( pF->string() ); 682 | 683 | for( std::list::iterator iter = parser.tokens().begin() ; iter != parser.tokens().end(); ++ iter ) 684 | { 685 | CToken * token = *iter; 686 | if( token->m_key == "mu" ) 687 | { 688 | CPoint2 uv; 689 | token->m_value >> uv; 690 | pF->mu() = std::complex( uv[0], uv[1] ); 691 | } 692 | } 693 | } 694 | }; 695 | 696 | template 697 | void _write_face_mu( M * pMesh ) 698 | { 699 | for( M::MeshFaceIterator fiter( pMesh ); !fiter.end(); fiter ++ ) 700 | { 701 | M::CFace * pF = *fiter; 702 | CParser parser( pF->string() ); 703 | parser._removeToken( "mu" ); 704 | 705 | parser._toString( pF->string() ); 706 | 707 | std::stringstream iss; 708 | 709 | iss << "mu=(" << pF->mu().real() << " " << pF->mu().imag() << ")"; 710 | 711 | if( pF->string().size() > 0 ) 712 | { 713 | pF->string() += " "; 714 | } 715 | pF->string() += iss.str(); 716 | } 717 | }; 718 | 719 | } 720 | #endif _TRAITS_IO_H_ -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/Iterators.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * \file Iterators.h 3 | * \brief Iterators for accessing geometric objects on a mesh 4 | * 5 | */ 6 | 7 | #ifndef _ITERATORS_H_ 8 | #define _ITERATORS_H_ 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "HalfEdge.h" 15 | #include "BaseMesh.h" 16 | 17 | namespace MeshLib{ 18 | 19 | //v -> v 20 | 21 | /*! 22 | \brief VertexVertexIterator, transverse all the neighboring vertices of a vertex ccwly. 23 | */ 24 | template 25 | class VertexVertexIterator 26 | { 27 | public: 28 | /*! 29 | VertexVertexIterator constructor 30 | \param v the current vertex 31 | */ 32 | VertexVertexIterator( VertexType * v ) 33 | { 34 | m_vertex = v; 35 | m_halfedge = (HalfEdgeType*)m_vertex->most_clw_out_halfedge(); 36 | }; 37 | 38 | /*! 39 | VertexVertexIterator destructor 40 | */ 41 | ~VertexVertexIterator(){}; 42 | 43 | /*! 44 | VertexVertexIterator prefix operator ++, goes to the next neighboring vertex CCWly 45 | */ 46 | 47 | void operator++() //prefix 48 | { 49 | assert( m_halfedge != NULL ); 50 | 51 | if( !m_vertex->boundary() ) 52 | { 53 | if( m_halfedge != m_vertex->most_ccw_out_halfedge() ) 54 | { 55 | m_halfedge = (HalfEdgeType*)m_halfedge->ccw_rotate_about_source(); 56 | } 57 | else 58 | { 59 | m_halfedge = NULL; 60 | } 61 | return; 62 | } 63 | 64 | if( m_vertex->boundary() ) 65 | { 66 | if( m_halfedge == (HalfEdgeType*)m_vertex->most_ccw_in_halfedge() ) 67 | { 68 | m_halfedge = NULL; 69 | return; 70 | } 71 | 72 | HalfEdgeType * he = (HalfEdgeType*)m_halfedge->ccw_rotate_about_source(); 73 | 74 | if( he == NULL ) 75 | { 76 | m_halfedge = (HalfEdgeType*)m_vertex->most_ccw_in_halfedge(); 77 | } 78 | else 79 | { 80 | m_halfedge = he; 81 | } 82 | } 83 | 84 | return; 85 | }; 86 | 87 | 88 | /*! 89 | VertexVertexIterator postfix operator ++, goes to the next neighboring vertex CCWly 90 | */ 91 | void operator++(int) //postfix 92 | { 93 | assert( m_halfedge != NULL ); 94 | 95 | if( !m_vertex->boundary() ) 96 | { 97 | if( m_halfedge != (HalfEdgeType*)m_vertex->most_ccw_out_halfedge() ) 98 | { 99 | m_halfedge = (HalfEdgeType*)m_halfedge->ccw_rotate_about_source(); 100 | } 101 | else 102 | { 103 | m_halfedge = NULL; 104 | } 105 | return; 106 | } 107 | 108 | if( m_vertex->boundary() ) 109 | { 110 | if( m_halfedge == (HalfEdgeType*)m_vertex->most_ccw_in_halfedge() ) 111 | { 112 | m_halfedge = NULL; 113 | return; 114 | } 115 | 116 | HalfEdgeType * he = (HalfEdgeType*)m_halfedge->ccw_rotate_about_source(); 117 | 118 | if( he == NULL ) 119 | { 120 | m_halfedge = (HalfEdgeType*)m_vertex->most_ccw_in_halfedge(); 121 | } 122 | else 123 | { 124 | m_halfedge = he; 125 | } 126 | } 127 | 128 | return; 129 | }; 130 | 131 | /*! 132 | The neighboring vertex, pointed by the current iterator 133 | */ 134 | 135 | VertexType * value() 136 | { 137 | if( !m_vertex->boundary() ) 138 | { 139 | return (VertexType*)m_halfedge->target(); 140 | } 141 | 142 | if( m_halfedge != (HalfEdgeType*)m_vertex->most_ccw_in_halfedge() ) 143 | { 144 | return (VertexType*)m_halfedge->target(); 145 | } 146 | 147 | if( m_halfedge == (HalfEdgeType*)m_vertex->most_ccw_in_halfedge() ) 148 | { 149 | return (VertexType*)m_halfedge->source(); 150 | } 151 | return NULL; 152 | }; 153 | 154 | /*! 155 | The neighboring vertex, pointed by the current iterator 156 | */ 157 | VertexType * operator*() { return value(); }; 158 | 159 | /*! 160 | Indicate whether all the neighboring vertices have been accessed. 161 | */ 162 | bool end(){ return m_halfedge == NULL; }; 163 | 164 | /*! 165 | Reset the iterator. 166 | */ 167 | void reset() { m_halfedge = (HalfEdgeType*)m_vertex->most_clw_out_halfedge(); }; 168 | 169 | private: 170 | /*! 171 | Current vertex 172 | */ 173 | VertexType * m_vertex; 174 | /*! 175 | Current halfedge. 176 | */ 177 | HalfEdgeType * m_halfedge; 178 | }; 179 | 180 | 181 | //v -> edge 182 | /*! 183 | \brief VertexEdgeIterator, transverse all the neighboring edges of a vertex ccwly. 184 | */ 185 | 186 | template 187 | class VertexEdgeIterator 188 | { 189 | public: 190 | /*! 191 | VertexEdgeIterator constructor 192 | \param v the current vertex 193 | */ 194 | VertexEdgeIterator( VertexType * v ) 195 | { 196 | m_vertex = v; 197 | m_halfedge = (HalfEdgeType*)m_vertex->most_clw_out_halfedge(); 198 | }; 199 | 200 | /*! 201 | VertexVertexIterator destructor 202 | */ 203 | ~VertexEdgeIterator(){}; 204 | /*! 205 | VertexVertexIterator prefix operator ++, goes to the next neighboring vertex CCWly 206 | */ 207 | 208 | void operator++() //prefix 209 | { 210 | assert( m_halfedge != NULL ); 211 | 212 | if( !m_vertex->boundary() ) 213 | { 214 | if( m_halfedge != (HalfEdgeType*)m_vertex->most_ccw_out_halfedge() ) 215 | { 216 | m_halfedge = (HalfEdgeType*)m_halfedge->ccw_rotate_about_source(); 217 | } 218 | else 219 | { 220 | m_halfedge = NULL; 221 | } 222 | return; 223 | } 224 | 225 | if( m_vertex->boundary() ) 226 | { 227 | if( m_halfedge == (HalfEdgeType*)m_vertex->most_ccw_in_halfedge() ) 228 | { 229 | m_halfedge = NULL; 230 | return; 231 | } 232 | 233 | HalfEdgeType * he = (HalfEdgeType*)m_halfedge->ccw_rotate_about_source(); 234 | 235 | if( he == NULL ) 236 | { 237 | m_halfedge = (HalfEdgeType*)m_vertex->most_ccw_in_halfedge(); 238 | } 239 | else 240 | { 241 | m_halfedge = he; 242 | } 243 | } 244 | 245 | return; 246 | }; 247 | /*! 248 | VertexVertexIterator postfix operator ++, goes to the next neighboring vertex CCWly 249 | */ 250 | void operator++(int) //postfix 251 | { 252 | assert( m_halfedge != NULL ); 253 | 254 | if( !m_vertex->boundary() ) 255 | { 256 | if( m_halfedge != (HalfEdgeType*)m_vertex->most_ccw_out_halfedge() ) 257 | { 258 | m_halfedge = (HalfEdgeType*)m_halfedge->ccw_rotate_about_source(); 259 | } 260 | else 261 | { 262 | m_halfedge = NULL; 263 | } 264 | return; 265 | } 266 | 267 | if( m_vertex->boundary() ) 268 | { 269 | if( m_halfedge == (HalfEdgeType*)m_vertex->most_ccw_in_halfedge() ) 270 | { 271 | m_halfedge = NULL; 272 | return; 273 | } 274 | 275 | HalfEdgeType * he = (HalfEdgeType*)m_halfedge->ccw_rotate_about_source(); 276 | 277 | if( he == NULL ) 278 | { 279 | m_halfedge = (HalfEdgeType*)m_vertex->most_ccw_in_halfedge(); 280 | } 281 | else 282 | { 283 | m_halfedge = he; 284 | } 285 | } 286 | 287 | return; 288 | }; 289 | /*! 290 | The neighboring edge, pointed by the current iterator 291 | */ 292 | 293 | EdgeType * value() 294 | { 295 | assert( m_halfedge != NULL ); 296 | return (EdgeType*)m_halfedge->edge(); 297 | }; 298 | 299 | /*! 300 | The neighboring edge, pointed by the current iterator 301 | */ 302 | EdgeType * operator*() { return value(); }; 303 | /*! 304 | Indicate whether all the neighboring edges have been accessed. 305 | */ 306 | bool end(){ return m_halfedge == NULL; }; 307 | /*! 308 | Reset the VerexEdgeIterator. 309 | */ 310 | void reset() { m_halfedge = (HalfEdgeType*)m_vertex->most_clw_out_halfedge(); }; 311 | 312 | private: 313 | /*! current vertex 314 | */ 315 | VertexType * m_vertex; 316 | /*! current halfedge 317 | */ 318 | HalfEdgeType * m_halfedge; 319 | }; 320 | 321 | 322 | 323 | // v->face 324 | /*! 325 | \brief VertexFaceIterator, transverse all the neighboring faces of a vertex ccwly. 326 | */ 327 | template 328 | class VertexFaceIterator 329 | { 330 | public: 331 | /*! 332 | VertexFaceIterator constructor 333 | \param v the current vertex 334 | */ 335 | VertexFaceIterator( VertexType * & v ) 336 | { 337 | m_vertex = v; 338 | m_halfedge = (HalfEdgeType*)m_vertex->most_clw_out_halfedge(); 339 | }; 340 | /*! 341 | VertexFaceIterator destructor 342 | */ 343 | ~VertexFaceIterator(){}; 344 | /*! 345 | VertexFaceIterator prefix operator ++, goes to the next neighboring face CCWly 346 | */ 347 | void operator++() //prefix 348 | { 349 | assert( m_halfedge != NULL ); 350 | 351 | if( m_halfedge == (HalfEdgeType*)m_vertex->most_ccw_out_halfedge() ) 352 | { 353 | m_halfedge = NULL; 354 | return; 355 | } 356 | m_halfedge = (HalfEdgeType*)m_halfedge->ccw_rotate_about_source(); 357 | }; 358 | /*! 359 | VertexFaceIterator prefix operator ++, goes to the next neighboring face CCWly 360 | */ 361 | 362 | void operator++(int) //postfix 363 | { 364 | assert( m_halfedge != NULL ); 365 | 366 | if( m_halfedge == (HalfEdgeType*)m_vertex->most_ccw_out_halfedge() ) 367 | { 368 | m_halfedge = NULL; 369 | return; 370 | } 371 | m_halfedge = (HalfEdgeType*)m_halfedge->ccw_rotate_about_source(); 372 | }; 373 | /*! 374 | The neighboring face, pointed by the current iterator 375 | */ 376 | FaceType * value() { return (FaceType*) m_halfedge->face(); }; 377 | /*! 378 | The neighboring face, pointed by the current iterator 379 | */ 380 | FaceType * operator*() { return value(); }; 381 | /*! 382 | Indicate whether all the neighboring faces have been accessed. 383 | */ 384 | bool end(){ return m_halfedge == NULL; }; 385 | /*! 386 | Reset the VertexFaceIterator 387 | */ 388 | void reset() { m_halfedge = (HalfEdgeType*)m_vertex->most_clw_out_halfedge(); }; 389 | 390 | private: 391 | /*! 392 | current vertex 393 | */ 394 | VertexType * m_vertex; 395 | /*! 396 | current halfedge 397 | */ 398 | HalfEdgeType * m_halfedge; 399 | }; 400 | 401 | // f -> halfedge 402 | /*! 403 | \brief FaceHalfedgeIterator, transverse all the halfedges of a face CCWly. 404 | */ 405 | 406 | template 407 | class FaceHalfedgeIterator 408 | { 409 | public: 410 | /*! 411 | FaceHalfedgeIterator constructor 412 | \param f the current face 413 | */ 414 | FaceHalfedgeIterator( FaceType * f ) 415 | { 416 | m_face = f; 417 | m_halfedge = (HalfEdgeType*)f->halfedge(); 418 | }; 419 | /*! 420 | FaceHalfedgeIterator destructor 421 | */ 422 | ~FaceHalfedgeIterator(){}; 423 | /*! 424 | VertexVertexIterator prefix operator ++, goes to the next halfedge CCWly 425 | */ 426 | void operator++() //prefix 427 | { 428 | assert( m_halfedge != NULL ); 429 | m_halfedge = (HalfEdgeType*)m_halfedge->he_next(); 430 | 431 | if( m_halfedge == m_face->halfedge() ) 432 | { 433 | m_halfedge = NULL; 434 | return; 435 | }; 436 | } 437 | 438 | /*! 439 | VertexVertexIterator prefix operator ++, goes to the next halfedge CCWly 440 | */ 441 | void operator++(int) //postfix 442 | { 443 | assert( m_halfedge != NULL ); 444 | m_halfedge = (HalfEdgeType*)m_halfedge->he_next(); 445 | 446 | if( m_halfedge == m_face->halfedge() ) 447 | { 448 | m_halfedge = NULL; 449 | return; 450 | }; 451 | } 452 | 453 | /*! 454 | The halfedge, pointed by the current iterator 455 | */ 456 | HalfEdgeType * value() { return m_halfedge; }; 457 | /*! 458 | The halfedge, pointed by the current iterator 459 | */ 460 | HalfEdgeType * operator*() { return value(); }; 461 | 462 | /*! 463 | Indicate whether all the halfedges have been accessed. 464 | */ 465 | bool end(){ return m_halfedge == NULL; }; 466 | 467 | private: 468 | /*! 469 | current face 470 | */ 471 | FaceType * m_face; 472 | /*! 473 | current halfedge 474 | */ 475 | HalfEdgeType * m_halfedge; 476 | }; 477 | 478 | 479 | // f -> edge 480 | /*! 481 | \brief FaceEdgeIterator, transverse all the edges of a face CCWly. 482 | */ 483 | template 484 | class FaceEdgeIterator 485 | { 486 | public: 487 | /*! 488 | FaceEdgeIterator constructor 489 | \param f the current face 490 | */ 491 | FaceEdgeIterator( FaceType * f ) 492 | { 493 | m_face = f; 494 | m_halfedge = (HalfEdgeType*)f->halfedge(); 495 | }; 496 | 497 | /*! 498 | FaceEdgeIterator destructor 499 | */ 500 | ~FaceEdgeIterator(){}; 501 | /*! 502 | FaceEdgeIterator prefix operator ++, goes to the next edge CCWly 503 | */ 504 | void operator++() //prefix 505 | { 506 | assert( m_halfedge != NULL ); 507 | m_halfedge = (HalfEdgeType*)m_halfedge->he_next(); 508 | 509 | if( m_halfedge == (HalfEdgeType*)m_face->halfedge() ) 510 | { 511 | m_halfedge = NULL; 512 | return; 513 | }; 514 | } 515 | 516 | /*! 517 | FaceEdgeIterator prefix operator ++, goes to the next edge CCWly 518 | */ 519 | void operator++(int) //postfix 520 | { 521 | assert( m_halfedge != NULL ); 522 | m_halfedge = (HalfEdgeType*)m_halfedge->he_next(); 523 | 524 | if( m_halfedge == m_face->halfedge() ) 525 | { 526 | m_halfedge = NULL; 527 | return; 528 | }; 529 | } 530 | /*! 531 | The edge, pointed by the current iterator 532 | */ 533 | EdgeType * value() { return (EdgeType*) m_halfedge->edge(); }; 534 | /*! 535 | The edge, pointed by the current iterator 536 | */ 537 | EdgeType * operator*() { return value(); }; 538 | /*! 539 | Indicate whether all the edges have been transversed. 540 | */ 541 | bool end(){ return m_halfedge == NULL; }; 542 | 543 | private: 544 | /*! Current face. */ 545 | FaceType * m_face; 546 | /*! Current halfedge. */ 547 | HalfEdgeType * m_halfedge; 548 | }; 549 | 550 | 551 | // f -> vertex 552 | /*! 553 | \brief FaceVertexIterator, transverse all the vertices of a face CCWly. 554 | */ 555 | template 556 | class FaceVertexIterator 557 | { 558 | public: 559 | /*! 560 | FaceVertexIterator constructor 561 | \param f the current face 562 | */ 563 | FaceVertexIterator( FaceType * f ) 564 | { 565 | m_face = f; 566 | m_halfedge = (HalfEdgeType*)f->halfedge(); 567 | }; 568 | /*! 569 | FaceVertexIterator destructor 570 | */ 571 | 572 | ~FaceVertexIterator(){}; 573 | /*! 574 | FaceVertexIterator prefix operator ++, goes to the next vertex CCWly 575 | */ 576 | void operator++() //prefix 577 | { 578 | assert( m_halfedge != NULL ); 579 | m_halfedge = (HalfEdgeType*)m_halfedge->he_next(); 580 | 581 | if( m_halfedge == (HalfEdgeType*)m_face->halfedge() ) 582 | { 583 | m_halfedge = NULL; 584 | return; 585 | }; 586 | } 587 | 588 | /*! 589 | FaceVertexIterator prefix operator ++, goes to the next vertex CCWly 590 | */ 591 | void operator++(int) //postfix 592 | { 593 | assert( m_halfedge != NULL ); 594 | m_halfedge = (HalfEdgeType*)m_halfedge->he_next(); 595 | 596 | if( m_halfedge == (HalfEdgeType*)m_face->halfedge() ) 597 | { 598 | m_halfedge = NULL; 599 | return; 600 | }; 601 | } 602 | /*! 603 | The vertex, pointed by the current iterator 604 | */ 605 | VertexType * value() { return (VertexType*) m_halfedge->target(); }; 606 | /*! 607 | The vertex, pointed by the current iterator 608 | */ 609 | VertexType * operator*() { return value(); }; 610 | /*! 611 | Indicate whether all the vertices have been accessed. 612 | */ 613 | bool end(){ return m_halfedge == NULL; }; 614 | 615 | private: 616 | /*! Current face. 617 | */ 618 | FaceType * m_face; 619 | /*! Current halfedge. 620 | */ 621 | HalfEdgeType * m_halfedge; 622 | }; 623 | 624 | 625 | // mesh->v 626 | /*! 627 | \brief MeshVertexIterator, transverse all the vertices in the mesh. 628 | */ 629 | 630 | template 631 | class MeshVertexIterator 632 | { 633 | public: 634 | /*! 635 | MeshVertexIterator constructor, 636 | \param pMesh the current mesh 637 | */ 638 | MeshVertexIterator( CBaseMesh * pMesh ): 639 | _iter(pMesh->vertices().begin()) 640 | { 641 | m_pMesh = pMesh; 642 | 643 | } 644 | /*! 645 | The vertex, pointed by the current iterator 646 | */ 647 | VertexType * value() { return *_iter; }; 648 | /*! 649 | The vertex, pointed by the current iterator 650 | */ 651 | 652 | VertexType * operator*(){ return value(); }; 653 | /*! 654 | MeshVertexIterator prefix operator ++, goes to the next vertex 655 | */ 656 | void operator++() { ++ _iter; }; //prefix 657 | /*! 658 | MeshVertexIterator prefix operator ++, goes to the next vertex 659 | */ 660 | void operator++(int) { ++ _iter; }; //postfix 661 | /*! 662 | Indicate whether all the vertices have been accessed. 663 | */ 664 | bool end() { return _iter == m_pMesh->vertices().end(); } 665 | 666 | private: 667 | /*! 668 | Current mesh. 669 | */ 670 | CBaseMesh * m_pMesh; 671 | MPIterator _iter; 672 | 673 | }; 674 | 675 | // mesh->f 676 | /*! 677 | \brief MeshFaceIterator, transverse all the faces in the mesh. 678 | */ 679 | template 680 | class MeshFaceIterator 681 | { 682 | public: 683 | /*! 684 | MeshFaceIterator constructor, 685 | \param pMesh the current mesh 686 | */ 687 | MeshFaceIterator( CBaseMesh * pMesh ): 688 | _iter(pMesh->faces().begin()) 689 | { 690 | m_pMesh = pMesh; 691 | } 692 | /*! 693 | The face, pointed by the current iterator 694 | */ 695 | FaceType * value() { return *_iter; }; 696 | /*! 697 | The face, pointed by the current iterator 698 | */ 699 | FaceType * operator*(){ return value(); }; 700 | 701 | /*! 702 | MeshFaceIterator prefix operator ++, goes to the next vertex 703 | */ 704 | void operator++() { ++ _iter; }; //prefix 705 | /*! 706 | MeshFaceIterator postfix operator ++, goes to the next vertex 707 | */ 708 | void operator++(int) { ++ _iter; }; //postfix 709 | /*! 710 | Indicate whether all the faces have been accessed. 711 | */ 712 | bool end() { return _iter == m_pMesh->faces().end(); } 713 | 714 | private: 715 | /*! Current mesh. 716 | */ 717 | CBaseMesh * m_pMesh; 718 | /*! Current face memorypool iterator. 719 | */ 720 | MPIterator _iter; 721 | 722 | }; 723 | 724 | //Mesh->e 725 | /*! 726 | \brief MeshEdgeIterator, transverse all the edges in the mesh. 727 | */ 728 | template 729 | class MeshEdgeIterator 730 | { 731 | public: 732 | /*! 733 | MeshEdgeIterator constructor, 734 | \param pMesh the current mesh 735 | */ 736 | MeshEdgeIterator( CBaseMesh * pMesh ): 737 | _iter(pMesh->edges().begin()) 738 | { 739 | m_pMesh = pMesh; 740 | } 741 | /*! 742 | The edge, pointed by the current iterator 743 | */ 744 | EdgeType * value() { return *_iter; }; 745 | /*! 746 | The edge, pointed by the current iterator 747 | */ 748 | EdgeType * operator*(){ return value(); }; 749 | /*! 750 | MeshEdgeIterator prefix operator ++, goes to the next edge 751 | */ 752 | void operator++() { ++ _iter; }; //prefix 753 | /*! 754 | MeshEdgeIterator postfix operator ++, goes to the next edge 755 | */ 756 | void operator++(int) {_iter++; }; //postfix 757 | /*! 758 | Indicate whether all the edges have been accessed. 759 | */ 760 | bool end() { return _iter == m_pMesh->edges().end(); } 761 | 762 | 763 | private: 764 | /*! 765 | current mesh 766 | */ 767 | CBaseMesh * m_pMesh; 768 | /*! 769 | current edge memorypool iterator 770 | */ 771 | MPIterator _iter; 772 | }; 773 | 774 | // Mesh->he 775 | /*! 776 | \brief MeshHalfEdgeIterator, transverse all the halfedges in the mesh. 777 | */ 778 | template 779 | class MeshHalfEdgeIterator 780 | { 781 | public: 782 | /*! 783 | MeshHalfedgeIterator constructor, 784 | \param pMesh the current mesh 785 | */ 786 | MeshHalfEdgeIterator( CBaseMesh * pMesh ): 787 | _iter(pMesh->edges().begin()) 788 | { 789 | m_pMesh = pMesh; 790 | m_id = 0; 791 | } 792 | /*! 793 | The halfedge, pointed by the current iterator 794 | */ 795 | HalfEdgeType * value() { EdgeType * e = *_iter; return (HalfEdgeType*)e->halfedge(m_id); }; 796 | /*! 797 | The halfedge, pointed by the current iterator 798 | */ 799 | HalfEdgeType * operator*(){ return value(); }; 800 | /*! 801 | MeshVertexIterator prefix operator ++, goes to the next halfedge 802 | */ 803 | void operator++() //prefix 804 | { 805 | ++m_id; 806 | 807 | switch( m_id ) 808 | { 809 | case 1: 810 | { 811 | EdgeType * e = *_iter; 812 | if( e->halfedge(m_id) == NULL ) 813 | { 814 | m_id = 0; 815 | ++ _iter; 816 | } 817 | } 818 | break; 819 | case 2: 820 | m_id = 0; 821 | ++_iter; 822 | break; 823 | } 824 | }; 825 | /*! 826 | MeshVertexIterator postfix operator ++, goes to the next vertex 827 | */ 828 | void operator++(int) //postfix 829 | { 830 | ++m_id; 831 | 832 | switch( m_id ) 833 | { 834 | case 1: 835 | { 836 | EdgeType * e = *_iter; 837 | if( e->halfedge(m_id) == NULL ) 838 | { 839 | m_id = 0; 840 | ++ _iter; 841 | } 842 | } 843 | break; 844 | case 2: 845 | m_id = 0; 846 | ++_iter; 847 | break; 848 | } 849 | }; 850 | /*! 851 | Indicate whether all the halfedges have been accessed 852 | */ 853 | bool end() { return _iter == m_pMesh->edges().end(); } 854 | 855 | 856 | private: 857 | /*! 858 | Current halfedge 859 | */ 860 | HalfEdgeType * m_he; 861 | /*! 862 | Current mesh 863 | */ 864 | CBaseMesh * m_pMesh; 865 | /*! 866 | Current edge memorypool iterator 867 | */ 868 | MPIterator _iter; 869 | int m_id; 870 | }; 871 | 872 | 873 | } //Iterators 874 | 875 | #endif 876 | -------------------------------------------------------------------------------- /MeshFrame/MeshFrame/TriMesh/Iterators2.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "BaseMesh.h" 8 | #include "HalfEdge.h" 9 | 10 | namespace MF { 11 | namespace TriMesh { 12 | template 13 | struct CIteratorCore { 14 | public: 15 | typedef CMeshBase MeshType; 16 | typedef MeshType* MeshPtr; 17 | typedef VertexType* VPtr; 18 | typedef EdgeType* EPtr; 19 | typedef FaceType* FPtr; 20 | typedef HalfEdgeType* HEPtr; 21 | 22 | public: 23 | class VOutHEIterator : public std::iterator { 24 | public: 25 | VOutHEIterator(const VPtr& pV) : _pV(pV), _iter(pV->outHEs().begin()) {}; 26 | VOutHEIterator(const VPtr& pV, CHalfEdge** iter) : _pV(pV), _iter(iter) {}; 27 | 28 | VOutHEIterator& operator++() { ++_iter; return *this; }; 29 | VOutHEIterator operator++(int) { VOutHEIterator tmp(_pV, _iter); ++_iter; return tmp; }; 30 | 31 | bool operator==(const VOutHEIterator& otherIter) { return _iter == otherIter._iter; } 32 | bool operator!=(const VOutHEIterator& otherIter) { return _iter != otherIter._iter; } 33 | HEPtr operator*() { return (HEPtr)(*_iter); } 34 | HEPtr value() { return (HEPtr)(*_iter); } 35 | 36 | VOutHEIterator begin() { return VOutHEIterator(_pV); } 37 | VOutHEIterator end() { return VOutHEIterator(_pV, _pV->outHEs().end()); } 38 | 39 | HEPtr* get() { return _iter; } 40 | private: 41 | CHalfEdge** _iter; 42 | VPtr _pV; 43 | }; 44 | 45 | /* 46 | * Iterator to access the out halfedge of a vertex in counter-clockwise direction. 47 | * Avalible only in manifold surface. 48 | * It is faster than the VoutHEIterator, so try to use this in manifold case. 49 | * \param pV the pointer to the vertex 50 | */ 51 | class VCcwOutHEIterator : public std::iterator { 52 | public: 53 | VCcwOutHEIterator(const VPtr& pV) : _pV(pV), _pHE(MeshType::vertexMostClwOutHalfEdge(pV)) {}; 54 | VCcwOutHEIterator(const VPtr& pV, const HEPtr& pHE) : _pV(pV), _pHE(pHE) {}; 55 | 56 | VCcwOutHEIterator& operator++() { 57 | _pHE = _pHE == MeshType::vertexMostCcwOutHalfEdge(_pV) ? NULL : MeshType::vertexNextCcwOutHalfEdge(_pHE); 58 | return *this; 59 | }; 60 | VCcwOutHEIterator operator++(int) { 61 | VCcwOutHEIterator tmp = *this; 62 | _pHE = _pHE == MeshType::vertexMostCcwOutHalfEdge(_pV) ? NULL : MeshType::vertexNextCcwOutHalfEdge(_pHE); 63 | return tmp; 64 | }; 65 | 66 | bool operator==(const VCcwOutHEIterator& otherIter) { return _pHE == otherIter._pHE; } 67 | bool operator!=(const VCcwOutHEIterator& otherIter) { return _pHE != otherIter._pHE; } 68 | HEPtr operator*() { return _pHE; } 69 | HEPtr value() { return _pHE; } 70 | 71 | VCcwOutHEIterator begin() { return VCcwOutHEIterator(_pV); } 72 | VCcwOutHEIterator end() { return VCcwOutHEIterator(_pV, NULL); }//why null???may be a he ? 73 | 74 | HEPtr get() { return _pHE; }//get what?? 75 | private: 76 | VPtr _pV; 77 | HEPtr _pHE; 78 | }; 79 | 80 | /* 81 | * Iterator to access the out halfedge of a vertex in clockwise direction. 82 | * Avalible only in manifold surface. 83 | * It is faster than the VoutHEIterator, so try to use this in manifold case. 84 | * \param pV the pointer to the vertex 85 | */ 86 | class VClwInHEIterator : public std::iterator { 87 | public: 88 | VClwInHEIterator(const VPtr& pV) : _pV(pV), _pHE(MeshType::vertexMostCcwInHalfEdge(pV)) {}; 89 | VClwInHEIterator(const VPtr& pV, const HEPtr& pHE) : _pV(pV), _pHE(pHE) {}; 90 | 91 | VClwInHEIterator& operator++() { 92 | _pHE = _pHE == MeshType::vertexMostClwInHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextClwInHalfEdge(_pHE); 93 | return *this; 94 | }; 95 | VClwInHEIterator operator++(int) { 96 | VClwInHEIterator tmp(_pV, _pHE); 97 | _pHE = _pHE == MeshType::vertexMostClwInHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextClwInHalfEdge(_pHE); 98 | return tmp; 99 | }; 100 | 101 | bool operator==(const VClwInHEIterator& otherIter) { return _pHE == otherIter._pHE; } 102 | bool operator!=(const VClwInHEIterator& otherIter) { return _pHE != otherIter._pHE; } 103 | HEPtr operator*() { return _pHE; } 104 | HEPtr value() { return _pHE; } 105 | 106 | VClwInHEIterator begin() { return VClwInHEIterator(_pV); } 107 | VClwInHEIterator end() { return VClwInHEIterator(_pV, NULL); } 108 | 109 | HEPtr get() { return _pHE; } 110 | private: 111 | VPtr _pV; 112 | HEPtr _pHE; 113 | }; 114 | 115 | class VCcwFIterator : public std::iterator { 116 | public: 117 | VCcwFIterator(const VPtr& pV) : _pV(pV), _pHE(MeshType::vertexMostClwOutHalfEdge(pV)) {}; 118 | 119 | VCcwFIterator& operator++() { 120 | _pHE = _pHE == MeshType::vertexMostCcwOutHalfEdge(_pV) ? NULL : MeshType::vertexNextCcwOutHalfEdge(_pHE); 121 | return *this; 122 | }; 123 | VCcwFIterator operator++(int) { 124 | VCcwFIterator tmp = *this; 125 | _pHE = _pHE == MeshType::vertexMostCcwOutHalfEdge(_pV) ? NULL : MeshType::vertexNextCcwOutHalfEdge(_pHE); 126 | return tmp; 127 | }; 128 | 129 | bool operator==(const VCcwFIterator& otherIter) { return _pHE == otherIter._pHE; } 130 | bool operator!=(const VCcwFIterator& otherIter) { return _pHE != otherIter._pHE; } 131 | FPtr operator*() { return halfedgeFace(_pHE); } 132 | FPtr value() { return halfedgeFace(_pHE); } 133 | 134 | VCcwFIterator begin() { return VCcwFIterator(_pV); } 135 | VCcwFIterator end() { return VCcwFIterator(_pV, NULL); }//why null???may be a he ? 136 | 137 | HEPtr get() { return _pHE; } 138 | private: 139 | VCcwFIterator(const VPtr& pV, const HEPtr& pHE) : _pV(pV), _pHE(pHE) {}; 140 | VPtr _pV; 141 | HEPtr _pHE; 142 | }; 143 | 144 | class VClwFIterator : public std::iterator { 145 | public: 146 | VClwFIterator(const VPtr& pV) : _pV(pV), _pHE(MeshType::vertexMostCcwInHalfEdge(pV)) {}; 147 | VClwFIterator(const VPtr& pV, const HEPtr& pHE) : _pV(pV), _pHE(pHE) {}; 148 | 149 | VClwFIterator& operator++() { 150 | _pHE = _pHE == MeshType::vertexMostClwInHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextClwInHalfEdge(_pHE); 151 | return *this; 152 | }; 153 | VClwFIterator operator++(int) { 154 | VClwFIterator tmp(_pV, _pHE); 155 | _pHE = _pHE == MeshType::vertexMostClwInHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextClwInHalfEdge(_pHE); 156 | return tmp; 157 | }; 158 | 159 | bool operator==(const VClwFIterator& otherIter) { return _pHE == otherIter._pHE; } 160 | bool operator!=(const VClwFIterator& otherIter) { return _pHE != otherIter._pHE; } 161 | FPtr operator*() { return halfedgeFace(_pHE); } 162 | FPtr value() { return halfedgeFace(_pHE); } 163 | 164 | VClwFIterator begin() { return VClwFIterator(_pV); } 165 | VClwFIterator end() { return VClwFIterator(_pV, NULL); } 166 | 167 | HEPtr get() { return _pHE; } 168 | private: 169 | VPtr _pV; 170 | HEPtr _pHE; 171 | }; 172 | 173 | class VCcwEIterator : public std::iterator { 174 | public: 175 | VCcwEIterator(const VPtr& pV) : _pV(pV), _pHE(MeshType::vertexMostClwOutHalfEdge(pV)) {}; 176 | 177 | VCcwEIterator& operator++() { 178 | if (MeshType::isBoundary(_pV)) { 179 | if (_pHE == MeshType::vertexMostCcwOutHalfEdge(_pV)) { 180 | _pHE = (HEPtr)_pHE->he_prev(); 181 | reachBoundary = true; 182 | } 183 | else if (reachBoundary) { 184 | _pHE = NULL; 185 | } 186 | else { 187 | _pHE = MeshType::vertexNextCcwOutHalfEdge(_pHE); 188 | } 189 | } 190 | else { 191 | _pHE = _pHE == MeshType::vertexMostCcwOutHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextCcwOutHalfEdge(_pHE); 192 | } 193 | return *this; 194 | }; 195 | VCcwEIterator operator++(int) { 196 | VCcwEIterator tmp(_pV, _pHE); 197 | if (isboundary(_pV)) { 198 | if (_pHE == MeshType::vertexMostCcwInHalfEdge(_pV)) { 199 | _pHE = (HEPtr)_pHE->he_prev(); 200 | reachBoundary = true; 201 | } 202 | else if (reachBoundary) { 203 | _pHE = NULL; 204 | } 205 | else { 206 | _pHE = MeshType::vertexNextCcwInHalfEdge(_pHE); 207 | } 208 | } 209 | else { 210 | _pHE = _pHE == MeshType::vertexMostCcwInHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextClwInHalfEdge(_pHE); 211 | } 212 | return tmp; 213 | }; 214 | 215 | bool operator==(const VCcwEIterator& otherIter) { return _pHE == otherIter._pHE; } 216 | bool operator!=(const VCcwEIterator& otherIter) { return _pHE != otherIter._pHE; } 217 | EPtr operator*() { return MeshType::halfedgeEdge(_pHE); } 218 | EPtr value() { return MeshType::halfedgeEdge(_pHE); } 219 | 220 | VCcwEIterator begin() { return VCcwEIterator(_pV); } 221 | VCcwEIterator end() { return VCcwEIterator(_pV, NULL); } 222 | 223 | HEPtr get() { return _pHE; } 224 | private: 225 | VCcwEIterator(const VPtr& pV, const HEPtr& pHE) : _pV(pV), _pHE(pHE) {}; 226 | VPtr _pV; 227 | HEPtr _pHE; 228 | bool reachBoundary = false; 229 | }; 230 | 231 | class VClwEIterator : public std::iterator { 232 | public: 233 | VClwEIterator(const VPtr& pV) : _pV(pV), _pHE(MeshType::vertexMostCcwInHalfEdge(pV)) {}; 234 | 235 | VClwEIterator& operator++() { 236 | if (MeshType::isBoundary(_pV)) { 237 | if (_pHE == MeshType::vertexMostClwInHalfEdge(_pV)) { 238 | _pHE = (HEPtr)_pHE->he_next(); 239 | reachBoundary = true; 240 | } 241 | else if (reachBoundary) { 242 | _pHE = NULL; 243 | } 244 | else { 245 | _pHE = MeshType::vertexNextClwInHalfEdge(_pHE); 246 | } 247 | } 248 | else { 249 | _pHE = _pHE == MeshType::vertexMostClwInHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextClwInHalfEdge(_pHE); 250 | } 251 | return *this; 252 | }; 253 | VClwEIterator operator++(int) { 254 | VClwEIterator tmp(_pV, _pHE); 255 | if (isboundary(_pV)) { 256 | if (_pHE == MeshType::vertexMostClwInHalfEdge(_pV)) { 257 | _pHE = (HEPtr)_pHE->he_next(); 258 | reachBoundary = true; 259 | } 260 | else if (reachBoundary) { 261 | _pHE = NULL; 262 | } 263 | else { 264 | _pHE = MeshType::vertexNextCcwInHalfEdge(_pHE); 265 | } 266 | } 267 | else { 268 | _pHE = _pHE == MeshType::vertexMostClwInHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextClwInHalfEdge(_pHE); 269 | } 270 | return tmp; 271 | }; 272 | 273 | bool operator==(const VClwEIterator& otherIter) { return _pHE == otherIter._pHE; } 274 | bool operator!=(const VClwEIterator& otherIter) { return _pHE != otherIter._pHE; } 275 | EPtr operator*() { return MeshType::halfedgeEdge(_pHE); } 276 | EPtr value() { return MeshType::halfedgeEdge(_pHE); } 277 | 278 | VClwEIterator begin() { return VClwEIterator(_pV); } 279 | VClwEIterator end() { return VClwEIterator(_pV, NULL); } 280 | 281 | HEPtr get() { return _pHE; } 282 | private: 283 | VClwEIterator(const VPtr& pV, const HEPtr& pHE) : _pV(pV), _pHE(pHE) {}; 284 | VPtr _pV; 285 | HEPtr _pHE; 286 | bool reachBoundary = false; 287 | }; 288 | 289 | class VVIterator : public std::iterator { 290 | public: 291 | VVIterator(VPtr pV) : _pV(pV), _iter(pV->outHEs().begin()) {}; 292 | 293 | VVIterator& operator++() { 294 | if (MeshType::isBoundary(_pV)) { 295 | if (_pLastV != NULL) { 296 | ++_iter; 297 | _pLastV = NULL; 298 | } 299 | else { 300 | CHalfEdge* pLastHE = (*_iter)->he_prev();; 301 | if (pLastHE->he_sym() != NULL) 302 | ++_iter; 303 | else { 304 | _pLastV = MeshType::halfedgeSource((HEPtr)pLastHE); 305 | } 306 | } 307 | } 308 | else { 309 | ++_iter; 310 | } 311 | 312 | return *this; 313 | }; 314 | VVIterator operator++(int) { 315 | VVIterator tmp(_pV, _iter); 316 | if (MeshType::isBoundary(_pV)) { 317 | if (_pLastV != NULL) { 318 | ++_iter; 319 | _pLastV = NULL; 320 | } 321 | else { 322 | CHalfEdge* pLastHE = (*_iter)->he_prev();; 323 | if (pLastHE->he_sym() != NULL) 324 | ++_iter; 325 | else { 326 | _pLastV = MeshType::halfedgeSource((HEPtr)pLastHE); 327 | } 328 | } 329 | } 330 | else { 331 | ++_iter; 332 | } 333 | return tmp; 334 | }; 335 | 336 | bool operator==(const VVIterator& otherIter) { return _iter == otherIter._iter; } 337 | bool operator!=(const VVIterator& otherIter) { return _iter != otherIter._iter; } 338 | VPtr operator*() { 339 | if (_pLastV == NULL) 340 | return (VPtr)(*_iter)->target(); 341 | else 342 | return _pLastV; 343 | } 344 | VPtr value() { 345 | if (_pLastV == NULL) 346 | return (VPtr)(*_iter)->target(); 347 | else 348 | return _pLastV; 349 | } 350 | 351 | VVIterator begin() { return VVIterator(_pV); } 352 | VVIterator end() { return VVIterator(_pV, _pV->outHEs().end()); } 353 | private: 354 | VVIterator(VPtr pV, CHalfEdge** iter) : _pV(pV), _iter(iter) {}; 355 | CHalfEdge** _iter; 356 | VPtr _pV; 357 | VPtr _pLastV = NULL; 358 | }; 359 | 360 | class VCcwVIterator : public std::iterator { 361 | public: 362 | VCcwVIterator(const VPtr& pV) : _pV(pV), _pHE(MeshType::vertexMostClwOutHalfEdge(pV)) {}; 363 | 364 | VCcwVIterator& operator++() { 365 | if (MeshType::isBoundary(_pV)) { 366 | if (_pHE == MeshType::vertexMostCcwOutHalfEdge(_pV)) { 367 | _pHE = (HEPtr)_pHE->he_prev(); 368 | reachBoundary = true; 369 | } 370 | else if (reachBoundary) { 371 | _pHE = NULL; 372 | } 373 | else { 374 | _pHE = MeshType::vertexNextCcwOutHalfEdge(_pHE); 375 | } 376 | } 377 | else { 378 | _pHE = _pHE == MeshType::vertexMostCcwOutHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextCcwOutHalfEdge(_pHE); 379 | } 380 | return *this; 381 | }; 382 | VCcwVIterator operator++(int) { 383 | VCcwVIterator tmp(_pV, _pHE); 384 | if (isboundary(_pV)) { 385 | if (_pHE == MeshType::vertexMostCcwInHalfEdge(_pV)) { 386 | _pHE = (HEPtr)_pHE->he_prev(); 387 | reachBoundary = true; 388 | } 389 | else if (reachBoundary) { 390 | _pHE = NULL; 391 | } 392 | else { 393 | _pHE = MeshType::vertexNextCcwInHalfEdge(_pHE); 394 | } 395 | } 396 | else { 397 | _pHE = _pHE == MeshType::vertexMostCcwInHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextClwInHalfEdge(_pHE); 398 | } 399 | return tmp; 400 | }; 401 | bool operator==(const VCcwVIterator& otherIter) { return _pHE == otherIter._pHE; } 402 | bool operator!=(const VCcwVIterator& otherIter) { return _pHE != otherIter._pHE; } 403 | VPtr operator*() { 404 | if (reachBoundary) 405 | return MeshType::halfedgeSource(_pHE); 406 | else 407 | return MeshType::halfedgeTarget(_pHE); 408 | } 409 | VPtr value() { 410 | if (reachBoundary) 411 | return MeshType::halfedgeSource(_pHE); 412 | else 413 | return MeshType::halfedgeTarget(_pHE); 414 | } 415 | 416 | VCcwVIterator begin() { return VCcwVIterator(_pV); } 417 | VCcwVIterator end() { return VCcwVIterator(_pV, NULL); } 418 | 419 | private: 420 | VCcwVIterator(const VPtr& pV, const HEPtr& pHE) : _pV(pV), _pHE(pHE) {}; 421 | VPtr _pV; 422 | HEPtr _pHE; 423 | bool reachBoundary = false; 424 | }; 425 | 426 | class VClwVIterator : public std::iterator { 427 | public: 428 | VClwVIterator(const VPtr& pV) : _pV(pV), _pHE(MeshType::vertexMostCcwInHalfEdge(pV)) {}; 429 | 430 | VClwVIterator& operator++() { 431 | if (MeshType::isBoundary(_pV)) { 432 | if (_pHE == MeshType::vertexMostClwInHalfEdge(_pV)) { 433 | _pHE = (HEPtr)_pHE->he_next(); 434 | reachBoundary = true; 435 | } 436 | else if (reachBoundary) { 437 | _pHE = NULL; 438 | } 439 | else { 440 | _pHE = MeshType::vertexNextClwInHalfEdge(_pHE); 441 | } 442 | } 443 | else { 444 | _pHE = _pHE == MeshType::vertexMostClwInHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextClwInHalfEdge(_pHE); 445 | } 446 | return *this; 447 | }; 448 | VClwVIterator operator++(int) { 449 | VClwVIterator tmp(_pV, _pHE); 450 | if (isboundary(_pV)) { 451 | if (_pHE == MeshType::vertexMostClwInHalfEdge(_pV)) { 452 | _pHE = (HEPtr)_pHE->he_next(); 453 | reachBoundary = true; 454 | } 455 | else if (reachBoundary) { 456 | _pHE = NULL; 457 | } 458 | else { 459 | _pHE = MeshType::vertexNextCcwInHalfEdge(_pHE); 460 | } 461 | } 462 | else { 463 | _pHE = _pHE == MeshType::vertexMostClwInHalfEdge(_pV) ? _pHE = NULL : MeshType::vertexNextClwInHalfEdge(_pHE); 464 | } 465 | return tmp; 466 | }; 467 | 468 | bool operator==(const VClwVIterator& otherIter) { return _pHE == otherIter._pHE; } 469 | bool operator!=(const VClwVIterator& otherIter) { return _pHE != otherIter._pHE; } 470 | VPtr operator*() { 471 | if (reachBoundary) 472 | return MeshType::halfedgeTarget(_pHE); 473 | else 474 | return MeshType::halfedgeSource(_pHE); 475 | } 476 | VPtr value() { 477 | if (reachBoundary) 478 | return MeshType::halfedgeTarget(_pHE); 479 | else 480 | return MeshType::halfedgeSource(_pHE); 481 | } 482 | 483 | VClwVIterator begin() { return VClwVIterator(_pV); } 484 | VClwVIterator end() { return VClwVIterator(_pV, NULL); } 485 | 486 | HEPtr get() { return _pHE; } 487 | private: 488 | VClwVIterator(const VPtr& pV, const HEPtr& pHE) : _pV(pV), _pHE(pHE) {}; 489 | VPtr _pV; 490 | HEPtr _pHE; 491 | bool reachBoundary = false; 492 | }; 493 | 494 | class VEIterator : public std::iterator 495 | { 496 | public: 497 | VEIterator(VPtr pV) : _pV(pV), _iter(pV->outHEs().begin()) {}; 498 | 499 | VEIterator& operator++() { 500 | if (MeshType::isBoundary(_pV)) { 501 | if (_pLastE != NULL) { 502 | ++_iter; 503 | _pLastE = NULL; 504 | } 505 | else { 506 | CHalfEdge* pLastHE = (*_iter)->he_prev();; 507 | if (pLastHE->he_sym() != NULL) 508 | ++_iter; 509 | else { 510 | _pLastE = MeshType::halfedgeEdge((HEPtr)pLastHE); 511 | } 512 | } 513 | } 514 | else { 515 | ++_iter; 516 | } 517 | 518 | return *this; 519 | }; 520 | VEIterator operator++(int) { 521 | VEIterator tmp(_pV, _iter); if (MeshType::isBoundary(_pV)) { 522 | if (_pLastE != NULL) { 523 | ++_iter; 524 | _pLastE = NULL; 525 | } 526 | else { 527 | CHalfEdge* pLastHE = (*_iter)->he_prev();; 528 | if (pLastHE->he_sym() != NULL) 529 | ++_iter; 530 | else { 531 | _pLastE = MeshType::halfedgeEdge((HEPtr)pLastHE); 532 | } 533 | } 534 | } 535 | else { 536 | ++_iter; 537 | } 538 | return tmp; 539 | }; 540 | 541 | bool operator==(const VEIterator& otherIter) { return _iter == otherIter._iter; } 542 | bool operator!=(const VEIterator& otherIter) { return _iter != otherIter._iter; } 543 | 544 | EPtr operator*() { 545 | if (_pLastE == NULL) 546 | return MeshType::halfedgeEdge((HEPtr)*_iter); 547 | else 548 | return _pLastE; 549 | } 550 | EPtr value() { 551 | if (_pLastE == NULL) 552 | return MeshType::halfedgeEdge((HEPtr)*_iter); 553 | else 554 | return _pLastE; 555 | } 556 | 557 | VEIterator begin() { return VEIterator(_pV); } 558 | VEIterator end() { return VEIterator(_pV, _pV->outHEs().end()); } 559 | 560 | private: 561 | VEIterator(VPtr pV, CHalfEdge** iter) : _pV(pV), _iter(iter) {}; 562 | CHalfEdge** _iter; 563 | VPtr _pV; 564 | EPtr _pLastE = NULL; 565 | }; 566 | 567 | class VFIterator : public std::iterator { 568 | public: 569 | VFIterator(VPtr pV) : _pV(pV), _iter(pV->outHEs().begin()) {}; 570 | 571 | VFIterator& operator++() { ++_iter; return *this; }; 572 | VFIterator operator++(int) { VFIterator tmp(_pV, _iter); ++_iter; return tmp; }; 573 | 574 | bool operator==(const VFIterator& otherIter) { return _iter == otherIter._iter; } 575 | bool operator!=(const VFIterator& otherIter) { return _iter != otherIter._iter; } 576 | FPtr operator*() { return (FPtr)(*_iter)->face(); } 577 | FPtr value() { return (FPtr)(*_iter)->face(); } 578 | 579 | VFIterator begin() { return VFIterator(_pV); } 580 | VFIterator end() { return VFIterator(_pV, _pV->outHEs().end()); } 581 | 582 | HEPtr* get() { return _iter; } 583 | private: 584 | VFIterator(VPtr pV, CHalfEdge** iter) : _pV(pV), _iter(iter) {}; 585 | CHalfEdge** _iter; 586 | VPtr _pV; 587 | }; 588 | 589 | // bad orgnized 590 | class FHEIterator : public std::iterator {// here inherited? 591 | public: 592 | FHEIterator(FPtr pF) : _pF(pF), _pHE((HEPtr)pF->halfedge()) {};//here type cast 593 | 594 | FHEIterator& operator++() 595 | { 596 | _pHE = (HEPtr)_pHE->he_next(); 597 | if (_pHE == (HEPtr)_pF->halfedge()) _pHE = NULL; 598 | return *this; 599 | }; 600 | FHEIterator operator++(int) { FHEIterator tmp(_pF, _pHE); ++_pHE; return tmp; }; 601 | 602 | bool operator==(const FHEIterator& otherIter) { return _pHE == otherIter._pHE; } 603 | bool operator!=(const FHEIterator& otherIter) { return _pHE != otherIter._pHE; } 604 | HEPtr operator*() { return _pHE; } 605 | HEPtr value() { return _pHE; } 606 | 607 | FHEIterator begin() { return FHEIterator(_pF); } 608 | FHEIterator end() { return FHEIterator(_pF, NULL); } 609 | //FHEIterator end() { return FHIterator(_pF, (HEPtr)pF->halfedge()->he_prev())); } 610 | 611 | HEPtr* get() { return _pHE; } 612 | private: 613 | FHEIterator(FPtr pF, HEPtr iter) : _pF(pF), _pHE(iter) {}; 614 | HEPtr _pHE; 615 | FPtr _pF; 616 | }; 617 | 618 | //class FEIterator 619 | class FEIterator : public std::iterator { 620 | public: 621 | FEIterator(FPtr pF) : _pF(pF), _pHE((HEPtr)pF->halfedge()) {}; 622 | FEIterator(FPtr pF, HEPtr iter) : _pF(pF), _pHE(iter) {}; 623 | 624 | FEIterator& operator++() 625 | { 626 | _pHE = (HEPtr)_pHE->he_next(); 627 | if (_pHE == (HEPtr)_pF->halfedge()) _pHE = NULL; 628 | return *this; 629 | }; 630 | FEIterator operator++(int) { FEIterator tmp(_pF, _pHE); ++_pHE; return tmp; }; 631 | 632 | bool operator==(const FEIterator& otherIter) { return _pHE == otherIter._pHE; } 633 | bool operator!=(const FEIterator& otherIter) { return _pHE != otherIter._pHE; } 634 | EPtr operator*() { return (EPtr)_pHE->edge(); } 635 | EPtr value() { return (EPtr)_pHE->edge(); } 636 | 637 | FEIterator begin() { return FEIterator(_pF); } 638 | FEIterator end() { return FEIterator(_pF, NULL); } 639 | //FEIterator end() { return FEIterator(_pF, (HEPtr)pF->halfedge()->he_prev()); } 640 | 641 | HEPtr* get() { return _pHE; } 642 | private: 643 | HEPtr _pHE; 644 | FPtr _pF; 645 | }; 646 | 647 | //class FVItertor 648 | class FVIterator : public std::iterator { 649 | public: 650 | FVIterator(const FPtr& pF) : _pF(pF), _pHE(MeshType::faceHalfedge(pF)) {}; 651 | 652 | FVIterator& operator++() 653 | { 654 | _pHE = (HEPtr)_pHE->he_next(); 655 | if (_pHE == (HEPtr)_pF->halfedge()) _pHE = NULL; 656 | return *this; 657 | }; 658 | FVIterator operator++(int) { FVIterator tmp(_pF, _pHE); ++_pHE; return tmp; }; 659 | 660 | bool operator==(const FVIterator& otherIter) { return _pHE == otherIter._pHE; } 661 | bool operator!=(const FVIterator& otherIter) { return _pHE != otherIter._pHE; } 662 | VPtr operator*() { return (VPtr)_pHE->vertex(); } 663 | VPtr value() { return (VPtr)_pHE->vertex(); } 664 | 665 | FVIterator begin() { return FVIterator(_pF); } 666 | FVIterator end() { return FVIterator(_pF, NULL); } 667 | HEPtr get() { return _pHE; } 668 | private: 669 | FVIterator(const FPtr& pF, const HEPtr& iter) : _pF(pF), _pHE(iter) {}; 670 | HEPtr _pHE; 671 | FPtr _pF; 672 | }; 673 | 674 | 675 | //we need pmesh 676 | class MVIterator : public std::iterator { 677 | public: 678 | MVIterator(MeshPtr pM) : _pM(pM), _iter(pM->vertices().begin()) {}; 679 | 680 | MVIterator& operator++() { ++_iter; return *this; }; 681 | MVIterator operator++(int) { MVIterator tmp(_pM, _iter); ++_iter; return tmp; }; 682 | 683 | bool operator==(const MVIterator& otherIter) { return _iter == otherIter._iter; } 684 | bool operator!=(const MVIterator& otherIter) { return _iter != otherIter._iter; } 685 | VPtr operator*() { return *_iter; } 686 | VPtr value() { return *_iter; } 687 | 688 | MVIterator begin() { return MVIterator(_pM); } 689 | MVIterator end() { return MVIterator(_pM, _pM->vertices().end()); } 690 | 691 | private: 692 | MVIterator(MeshPtr pM, MPIterator iter) : _pM(pM), _iter(iter) {}; 693 | MPIterator _iter; 694 | MeshPtr _pM; 695 | }; 696 | 697 | class MFIterator : public std::iterator { 698 | public: 699 | MFIterator(MeshPtr pM) : _pM(pM), _iter(pM->faces().begin()) {}; 700 | 701 | MFIterator& operator++() { ++_iter; return *this; }; 702 | MFIterator operator++(int) { MFIterator tmp(_pM, _iter); ++_iter; return tmp; }; 703 | 704 | bool operator==(const MFIterator& otherIter) { return _iter == otherIter._iter; } 705 | bool operator!=(const MFIterator& otherIter) { return _iter != otherIter._iter; } 706 | FPtr operator*() { return *_iter; } 707 | FPtr value() { return *_iter; } 708 | 709 | MFIterator begin() { return MFIterator(_pM); } 710 | MFIterator end() { return MFIterator(_pM, _pM->faces().end()); } 711 | 712 | private: 713 | MFIterator(MeshPtr pM, MPIterator iter) : _pM(pM), _iter(iter) {}; 714 | MPIterator _iter; 715 | MeshPtr _pM; 716 | }; 717 | 718 | class MEIterator : public std::iterator { 719 | public: 720 | MEIterator(MeshPtr pM) : _pM(pM), _iter(pM->edges().begin()) {}; 721 | 722 | MEIterator& operator++() { ++_iter; return *this; }; 723 | MEIterator operator++(int) { MEIterator tmp(_pM, _iter); ++_iter; return tmp; }; 724 | 725 | bool operator==(const MEIterator& otherIter) { return _iter == otherIter._iter; } 726 | bool operator!=(const MEIterator& otherIter) { return _iter != otherIter._iter; } 727 | EPtr operator*() { return *_iter; } 728 | EPtr value() { return *_iter; } 729 | 730 | MEIterator begin() { return MEIterator(_pM); } 731 | MEIterator end() { return MEIterator(_pM, _pM->edges().end()); } 732 | 733 | private: 734 | MEIterator(MeshPtr pM, MPIterator& iter) : _pM(pM), _iter(iter) {}; 735 | MPIterator _iter; 736 | MeshPtr _pM; 737 | }; 738 | 739 | //class MHEIterator 740 | 741 | }; 742 | 743 | template 744 | struct CIterators : public CIteratorCore 745 | {}; 746 | } 747 | } --------------------------------------------------------------------------------