commit
						f14838a475
					
				 19 changed files with 4399 additions and 0 deletions
			
			
		@ -0,0 +1,42 @@ | 
				
			|||||
 | 
					cmake_minimum_required (VERSION 3.2.0) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Project name | 
				
			||||
 | 
					project (OCCTMeshless CXX) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					list(APPEND CMAKE_PREFIX_PATH "F:/OCC/demo/opencascade-install" ) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Enable C++17 | 
				
			||||
 | 
					set(CMAKE_CXX_STANDARD 17) | 
				
			||||
 | 
					set(CMAKE_CXX_STANDARD_REQUIRED ON) | 
				
			||||
 | 
					set(CMAKE_CXX_EXTENSIONS OFF) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# OpenCascade | 
				
			||||
 | 
					find_package(OpenCASCADE REQUIRED) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Eigen3 | 
				
			||||
 | 
					set(EIGEN3_INCLUDE_DIR "F:/eigen-3.4.0") | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Configure C++ compiler's includes dir | 
				
			||||
 | 
					include_directories (SYSTEM ${OpenCASCADE_INCLUDE_DIR} ) | 
				
			||||
 | 
					include_directories(${EIGEN3_INCLUDE_DIR}) | 
				
			||||
 | 
					include_directories(${PROJECT_SOURCE_DIR}/include) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					file(GLOB HEADER_FILES "include/*.h*") | 
				
			||||
 | 
					file(GLOB SRC_FILES "src/*.cpp") | 
				
			||||
 | 
					source_group("include" FILES HEADER_FILES) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Add executable | 
				
			||||
 | 
					add_executable (${PROJECT_NAME} | 
				
			||||
 | 
					   ${SRC_FILES} | 
				
			||||
 | 
					  ${HEADER_FILES} | 
				
			||||
 | 
					) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Add linker options | 
				
			||||
 | 
					foreach (LIB ${OpenCASCADE_LIBRARIES}) | 
				
			||||
 | 
					  target_link_libraries(${PROJECT_NAME} PUBLIC ${OpenCASCADE_LIBRARY_DIR}/${LIB}.lib) | 
				
			||||
 | 
					  target_link_libraries(${PROJECT_NAME} PUBLIC ${OpenCASCADE_LIBRARY_DIR}d/${LIB}.lib) | 
				
			||||
 | 
					endforeach() | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					# Adjust runtime environment | 
				
			||||
 | 
					set_property(TARGET ${PROJECT_NAME} PROPERTY VS_DEBUGGER_ENVIRONMENT "PATH=$<$<CONFIG:DEBUG>:${OpenCASCADE_BINARY_DIR}d>$<$<NOT:$<CONFIG:DEBUG>>:${OpenCASCADE_BINARY_DIR}>;%PATH%") | 
				
			||||
@ -0,0 +1,96 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					#include "assert.hpp" | 
				
			||||
 | 
					#include "DomainDiscretization_fwd.hpp" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
						template<typename vec> | 
				
			||||
 | 
						const vec& DomainDiscretization<vec>::normal(int i) const { | 
				
			||||
 | 
							assert_msg(0 <= i && i <= size(), "Index %d out of range [0, %d)", i, size()); | 
				
			||||
 | 
							assert_msg(types_[i] < 0, "Node %d must be a boundary node, got type %d.", i, types_[i]); | 
				
			||||
 | 
							assert_msg(boundaryMap_[i] != -1, "Node %d does not have a normal. Maybe you manually set" | 
				
			||||
 | 
								" supports and positions instead of using addInternalNode* methods?", | 
				
			||||
 | 
								i); | 
				
			||||
 | 
							return normals_[boundaryMap_[i]]; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						} | 
				
			||||
 | 
						template<typename vec> | 
				
			||||
 | 
						vec& DomainDiscretization<vec>::normal(int i) { | 
				
			||||
 | 
							assert_msg(0 <= i && i <= size(), "Index %d out of range [0, %d)", i, size()); | 
				
			||||
 | 
							assert_msg(types_[i] < 0, "Node %d must be a boundary node, got type %d.", i, types_[i]); | 
				
			||||
 | 
							assert_msg(boundaryMap_[i] != -1, "Node %d does not have a normal. Maybe you manually set" | 
				
			||||
 | 
								" supports and positions instead of using addInternalNode* methods?", | 
				
			||||
 | 
								i); | 
				
			||||
 | 
							return normals_[boundaryMap_[i]]; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						template<typename vec> | 
				
			||||
 | 
						int DomainDiscretization<vec>::addInternalNode(const vec& point, int type) { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							assert_msg(type > 0, "This function is for adding internal points, but got type %d, which is " | 
				
			||||
 | 
								"not positive. Use addBoundaryNode to add boundary nodes.", | 
				
			||||
 | 
								type); | 
				
			||||
 | 
							return addNode(point, type); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						template<typename vec> | 
				
			||||
 | 
						int DomainDiscretization<vec>::addInternalNodeWithT(const vec& point, double t, int type) { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							assert_msg(type > 0, "This function is for adding internal points, but got type %d, which is " | 
				
			||||
 | 
								"not positive. Use addBoundaryNode to add boundary nodes.", | 
				
			||||
 | 
								type); | 
				
			||||
 | 
							return addNodeWithT(point, t, type); | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						/**
 | 
				
			||||
 | 
						 * Adds a boundary node with given type and normal to the domain. | 
				
			||||
 | 
						 * @param point Coordinates of the node to add. | 
				
			||||
 | 
						 * @param type Type of the point, must be negative. | 
				
			||||
 | 
						 * @param normal Outside unit normal to the boundary at point `point`. | 
				
			||||
 | 
						 * @return The index of the new node. | 
				
			||||
 | 
						 * @sa addInternalNode | 
				
			||||
 | 
						 */ | 
				
			||||
 | 
						template<typename vec> | 
				
			||||
 | 
						int DomainDiscretization<vec>::addBoundaryNode(const vec& point, int type, const vec& normal) { | 
				
			||||
 | 
							assert_msg(type < 0, "Type of boundary points must be negative, got %d.", type); | 
				
			||||
 | 
							int idx = addNode(point, type); | 
				
			||||
 | 
							boundaryMap_[idx] = normals_.size(); | 
				
			||||
 | 
							normals_.push_back(normal); | 
				
			||||
 | 
							return idx; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						template<typename vec> | 
				
			||||
 | 
						int DomainDiscretization<vec>::addBoundaryNodeWithT(const vec& point, double t, int type, const vec& normal) { | 
				
			||||
 | 
							assert_msg(type < 0, "Type of boundary points must be negative, got %d.", type); | 
				
			||||
 | 
							int idx = addNodeWithT(point, t, type); | 
				
			||||
 | 
							boundaryMap_[idx] = normals_.size(); | 
				
			||||
 | 
							normals_.push_back(normal); | 
				
			||||
 | 
							return idx; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						template<typename vec> | 
				
			||||
 | 
						int DomainDiscretization<vec>::addNode(const vec& point, int type) { | 
				
			||||
 | 
							positions_.push_back(point); | 
				
			||||
 | 
							types_.push_back(type); | 
				
			||||
 | 
							support_.emplace_back(); | 
				
			||||
 | 
							boundaryMap_.push_back(-1); | 
				
			||||
 | 
							return positions_.size() - 1; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						template<typename vec> | 
				
			||||
 | 
						int DomainDiscretization<vec>::addNodeWithT(const vec& point, double t, int type) { | 
				
			||||
 | 
							positions_.push_back(point); | 
				
			||||
 | 
							inCurve_.push_back(t); | 
				
			||||
 | 
							types_.push_back(type); | 
				
			||||
 | 
							support_.emplace_back(); | 
				
			||||
 | 
							boundaryMap_.push_back(-1); | 
				
			||||
 | 
							return positions_.size() - 1; | 
				
			||||
 | 
						} | 
				
			||||
 | 
						//bool DomainDiscretization::contains(const vec& point)const;
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,197 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					#include <vector> | 
				
			||||
 | 
					#include <Eigen/Core> | 
				
			||||
 | 
					#include "OccShape.hpp" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace  meshless { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						template<typename vec> | 
				
			||||
 | 
						class DomainDiscretization { | 
				
			||||
 | 
						protected: | 
				
			||||
 | 
							std::vector<vec> positions_; | 
				
			||||
 | 
							std::vector<int> types_; | 
				
			||||
 | 
							std::vector<std::vector<int>> support_; | 
				
			||||
 | 
							std::vector<int> boundaryMap_; | 
				
			||||
 | 
							std::vector<vec> normals_; | 
				
			||||
 | 
							OccShape shape_; | 
				
			||||
 | 
							std::vector<double> inCurve_; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						public: | 
				
			||||
 | 
							DomainDiscretization() {} | 
				
			||||
 | 
							DomainDiscretization(const OccShape& shape) { | 
				
			||||
 | 
								shape_.max_points = shape.max_points; | 
				
			||||
 | 
								shape_.seed_ = shape.seed_; | 
				
			||||
 | 
								shape_.n_samples = shape.n_samples; | 
				
			||||
 | 
								shape_.zeta = shape.zeta; | 
				
			||||
 | 
								shape_.myShape = shape.myShape; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							} | 
				
			||||
 | 
							const double getT(int i)const { | 
				
			||||
 | 
								return inCurve_[i]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							const std::vector<vec>& positions()const { | 
				
			||||
 | 
								return positions_; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							const vec& pos(int i)const { | 
				
			||||
 | 
								return positions_[i]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							vec& pos(int i) { | 
				
			||||
 | 
								return positions_[i]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							double pos(int i, int j) const { | 
				
			||||
 | 
								return positions_[i][j]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							const std::vector<std::vector<int> >& supports()const { | 
				
			||||
 | 
								return support_; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							const std::vector<int>& support(int i)const { | 
				
			||||
 | 
								return support_[i]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							std::vector<int>& support(int i) { | 
				
			||||
 | 
								return support_[i]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							int support(int i, int j) const { | 
				
			||||
 | 
								return support_[i][j]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							std::vector<vec> supportNodes(int i) const { | 
				
			||||
 | 
								auto sp = support_[i]; | 
				
			||||
 | 
								std::vector<vec> retsP; | 
				
			||||
 | 
								for(auto it : sp) { | 
				
			||||
 | 
									retsP.push_back(positions_[it]); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
								} | 
				
			||||
 | 
								return retsP; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/// Returns position of `j`-th support node of `i`-th node.
 | 
				
			||||
 | 
							vec supportNode(int i, int j) const { | 
				
			||||
 | 
								return positions_[support_[i][j]]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/// Returns Euclidean distance to the second support node.
 | 
				
			||||
 | 
							double dr(int i) const { | 
				
			||||
 | 
								return (positions_[i] - positions_[support_[i][1]]).norm(); | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/// Returns size of `i`-th node support.
 | 
				
			||||
 | 
							int supportSize(int i) const { | 
				
			||||
 | 
								return support_[i].size(); | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/// Returns a vector of support sizes for each node.
 | 
				
			||||
 | 
							//std::vector<int> supportSizes() const;
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Returns types of all nodes.
 | 
				
			||||
 | 
							const std::vector<int>& types() const { | 
				
			||||
 | 
								return types_; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/// Returns mutable types of all nodes.
 | 
				
			||||
 | 
							std::vector<int>& types() { | 
				
			||||
 | 
								return types_; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/// Returns type of `i`-th node.
 | 
				
			||||
 | 
							int type(int i) const { | 
				
			||||
 | 
								return types_[i]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/// Returns writeable type of `i`-th node.
 | 
				
			||||
 | 
							int& type(int i) { | 
				
			||||
 | 
								return types_[i]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Returns boundary map. @sa boundary_map_
 | 
				
			||||
 | 
							const std::vector<int>& bmap() const { | 
				
			||||
 | 
								return boundaryMap_; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/**
 | 
				
			||||
 | 
							 * Returns index of node `node` among only boundary nodes. The returned index is | 
				
			||||
 | 
							 * in range `[0, boundary().size())` if `node` is a boundary node, and `-1` otherwise. | 
				
			||||
 | 
							 */ | 
				
			||||
 | 
							int bmap(int node) const { | 
				
			||||
 | 
								return boundaryMap_[node]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/// Returns normals of all boundary nodes.
 | 
				
			||||
 | 
							const std::vector<vec>& normals() const { | 
				
			||||
 | 
								return normals_; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/**
 | 
				
			||||
 | 
							 * Returns outside unit normal of `i`-th node. The node must be a boundary node. | 
				
			||||
 | 
							 * @throw Assertion fails if the noe is not a boundary node, i.e.\ `type(i) < 0` must hold. | 
				
			||||
 | 
							 */ | 
				
			||||
 | 
							const vec& normal(int i) const; | 
				
			||||
 | 
							/// Returns writable outside unit normal of `i`-th node. @sa normal
 | 
				
			||||
 | 
							vec& normal(int i); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Returns indexes of all boundary nodes.
 | 
				
			||||
 | 
							std::vector<int> boundary() const { | 
				
			||||
 | 
								std::vector<int> ret; | 
				
			||||
 | 
								for(int i = 0; i < types_.size(); i++) { | 
				
			||||
 | 
									if(types_[i] < 0) { | 
				
			||||
 | 
										ret.push_back(i); | 
				
			||||
 | 
									} | 
				
			||||
 | 
								} | 
				
			||||
 | 
								return ret; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/// Returns indexes of all internal nodes.
 | 
				
			||||
 | 
							std::vector<int> interior() const { | 
				
			||||
 | 
								std::vector<int> ret; | 
				
			||||
 | 
								for(int i = 0; i < types_.size(); i++) { | 
				
			||||
 | 
									if(types_[i] > 0) { | 
				
			||||
 | 
										ret.push_back(i); | 
				
			||||
 | 
									} | 
				
			||||
 | 
								} | 
				
			||||
 | 
								return ret; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							/// Returns indexes of all nodes, i.e.\ `{0, 1, ..., N-1}`.
 | 
				
			||||
 | 
							std::vector<int> all() const { | 
				
			||||
 | 
								std::vector<int> ret; | 
				
			||||
 | 
								for(int i = 0; i < types_.size(); i++) { | 
				
			||||
 | 
									if(types_[i] != 0) { | 
				
			||||
 | 
										ret.push_back(i); | 
				
			||||
 | 
									} | 
				
			||||
 | 
								} | 
				
			||||
 | 
								return ret; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Returns `N`, the number of nodes in this discretization.
 | 
				
			||||
 | 
							int size() const { | 
				
			||||
 | 
								return positions_.size(); | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/**
 | 
				
			||||
 | 
							 * Adds a single interior node with specified type to this discretization. | 
				
			||||
 | 
							 * @param point Coordinates of the node to add. | 
				
			||||
 | 
							 * @param type Type of the node to add. Must be positive. | 
				
			||||
 | 
							 * @return The index of the new node. | 
				
			||||
 | 
							 * @sa addBoundaryNode | 
				
			||||
 | 
							 */ | 
				
			||||
 | 
							int addInternalNode(const vec& point, int type); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/**
 | 
				
			||||
 | 
							 * Adds a boundary node with given type and normal to the domain. | 
				
			||||
 | 
							 * @param point Coordinates of the node to add. | 
				
			||||
 | 
							 * @param type Type of the point, must be negative. | 
				
			||||
 | 
							 * @param normal Outside unit normal to the boundary at point `point`. | 
				
			||||
 | 
							 * @return The index of the new node. | 
				
			||||
 | 
							 * @sa addInternalNode | 
				
			||||
 | 
							 */ | 
				
			||||
 | 
							int addBoundaryNode(const vec& point, int type, const vec& normal); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							int addBoundaryNodeWithT(const vec& point, double t, int type, const vec& normal); | 
				
			||||
 | 
							int addInternalNodeWithT(const vec& point, double t, int type); | 
				
			||||
 | 
						private: | 
				
			||||
 | 
							int addNode(const vec& point, int type); | 
				
			||||
 | 
							int addNodeWithT(const vec& point, double t, int type); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						public: | 
				
			||||
 | 
							//bool discreteContains(const vec& point, )const;
 | 
				
			||||
 | 
						}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,193 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					#include "FillBoundary_fwd.hpp" | 
				
			||||
 | 
					#include "KDTree.hpp" | 
				
			||||
 | 
					#include "KDTreeMutable.hpp" | 
				
			||||
 | 
					#include <iomanip> | 
				
			||||
 | 
					#include <random> | 
				
			||||
 | 
					#include <map> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						DomainDiscretization<Eigen::Vector3d> discretizeBoundaryWithDensity(const OccShape& shape, const std::function<double(Eigen::Vector3d)>& h, int type) { | 
				
			||||
 | 
							if(type == 0)type = -1; | 
				
			||||
 | 
							std::mt19937 gen(shape.seed_); | 
				
			||||
 | 
							DomainDiscretization<Eigen::Vector3d> domainGlobal(shape); | 
				
			||||
 | 
							KDTreeMutable treeGlobal; | 
				
			||||
 | 
							TopExp_Explorer expFace(shape.myShape, TopAbs_FACE); | 
				
			||||
 | 
							int numFace = 0; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							std::cout.precision(10); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							for(; expFace.More(); expFace.Next()) { | 
				
			||||
 | 
								std::cout << "正在离散化第" << ++numFace << "张曲面" << std::endl; | 
				
			||||
 | 
								//if(numFace != 5)continue;
 | 
				
			||||
 | 
								bool reverseNormal = false; | 
				
			||||
 | 
								const TopoDS_Face& face = TopoDS::Face(expFace.Current()); | 
				
			||||
 | 
								Handle(Geom_Surface) geomSurface = BRep_Tool::Surface(face); | 
				
			||||
 | 
								if(face.Orientable() == TopAbs_REVERSED) { | 
				
			||||
 | 
									std::cout << "该面法线需反向\n"; | 
				
			||||
 | 
									reverseNormal = true; | 
				
			||||
 | 
								} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
								//开始离散化每个wire
 | 
				
			||||
 | 
								auto outerWire = BRepTools::OuterWire(face); | 
				
			||||
 | 
								int numWire = 0; | 
				
			||||
 | 
								TopExp_Explorer expWire(face, TopAbs_WIRE); | 
				
			||||
 | 
								for(; expWire.More(); expWire.Next()) { | 
				
			||||
 | 
									std::cout << "正在离散化第" << ++numWire << "个Wire" << std::endl; | 
				
			||||
 | 
									const TopoDS_Wire& wire = TopoDS::Wire(expWire.Current()); | 
				
			||||
 | 
									if(wire == outerWire) { | 
				
			||||
 | 
										std::cout << "此wire为外环\n"; | 
				
			||||
 | 
									} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
									DomainDiscretization<Eigen::Vector2d> domainParamLocalPatch(shape); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
									TopExp_Explorer expEdge(wire, TopAbs_EDGE); | 
				
			||||
 | 
									int numEdge = 0; | 
				
			||||
 | 
									int genPoints = 0; | 
				
			||||
 | 
									for(; expEdge.More(); expEdge.Next()) { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										std::cout << "正在离散化第" << ++numEdge << "条Edge" << std::endl; | 
				
			||||
 | 
										//if(numEdge != 5)continue;
 | 
				
			||||
 | 
										const TopoDS_Edge& edge = TopoDS::Edge(expEdge.Current()); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										KDTreeMutable treeLocal; | 
				
			||||
 | 
										Standard_Real firstParam, lastParam; | 
				
			||||
 | 
										Handle(Geom_Curve) geomCurve = BRep_Tool::Curve(edge, firstParam, lastParam); | 
				
			||||
 | 
										//std::cout << "param: " << firstParam << " -> " << lastParam << '\n';
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										//曲线参数点在曲面参数域上的坐标
 | 
				
			||||
 | 
										Standard_Real pCurveFirstParam, pCurveLastParam; | 
				
			||||
 | 
										Handle(Geom2d_Curve) geomPCurve = BRep_Tool::CurveOnSurface(edge, face, pCurveFirstParam, pCurveLastParam); | 
				
			||||
 | 
										Handle(Geom2d_TrimmedCurve) geomTrimmedCurve = new Geom2d_TrimmedCurve(geomPCurve, pCurveFirstParam, pCurveLastParam); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										//GeomTools::Dump(geomCurve, std::cout);
 | 
				
			||||
 | 
										//std::cout << "In param Pcurve:\n";
 | 
				
			||||
 | 
										//GeomTools::Dump(geomPCurve, std::cout);
 | 
				
			||||
 | 
										std::cout << "GeomPcurve P:" << pCurveFirstParam << ',' << pCurveLastParam << '\n'; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										std::uniform_real_distribution<> dis(pCurveFirstParam, pCurveLastParam); | 
				
			||||
 | 
										//曲线参数点
 | 
				
			||||
 | 
										double tSeedInParam = dis(gen); | 
				
			||||
 | 
										gp_Pnt2d tSeedInPCurve; | 
				
			||||
 | 
										geomPCurve->D0(tSeedInParam, tSeedInPCurve); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										//std::cout << "t in param: " << tSeedInParam << "\n";
 | 
				
			||||
 | 
										//std::cout << "t in PCurve: " << tSeedInPCurve.Coord().X() << "," << tSeedInPCurve.Coord().Y() << "\n";
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										//!这里两种计算方法得到的结果不一致,第一种更准确
 | 
				
			||||
 | 
										gp_Pnt tSeedInCurve; | 
				
			||||
 | 
										geomCurve->D0(tSeedInParam, tSeedInCurve); | 
				
			||||
 | 
										gp_Pnt tSeedInSurf; | 
				
			||||
 | 
										geomSurface->D0(tSeedInPCurve.X(), tSeedInPCurve.Y(), tSeedInSurf); | 
				
			||||
 | 
										//! Tip: use GeomLib::NormEstim() to calculate surface normal at specified (U, V) point.
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										std::cout << "t in Surface:#1 " << tSeedInCurve.Coord().X() << "," << tSeedInCurve.Coord().Y() << "," << tSeedInCurve.Coord().Z() << "\n"; | 
				
			||||
 | 
										std::cout << "t in Surface:#2 " << tSeedInSurf.Coord().X() << "," << tSeedInSurf.Coord().Y() << "," << tSeedInSurf.Coord().Z() << "\n"; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										Eigen::Vector3d eigenSeedPnt(tSeedInCurve.X(), tSeedInCurve.Y(), tSeedInCurve.Z()); | 
				
			||||
 | 
										Eigen::Vector2d eigenSeedPntParam(tSeedInPCurve.X(), tSeedInPCurve.Y()); | 
				
			||||
 | 
										domainParamLocalPatch.addInternalNodeWithT(transPnt2d(tSeedInPCurve), tSeedInParam, 1); | 
				
			||||
 | 
										treeLocal.insert(transPnt(tSeedInCurve)); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										//Insert into global structures.
 | 
				
			||||
 | 
										double checkRadiusSeed = h(eigenSeedPnt); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										double d_sq = treeGlobal.size() == 0 ? 10 * checkRadiusSeed * checkRadiusSeed : treeGlobal.query(eigenSeedPnt).second[0]; | 
				
			||||
 | 
										if(d_sq >= (shape.zeta * checkRadiusSeed) * (shape.zeta * checkRadiusSeed)) { | 
				
			||||
 | 
											//domainGlobal.addBoundaryNode(eigenSeedPnt, -1);
 | 
				
			||||
 | 
											gp_Dir tSeedNormal; | 
				
			||||
 | 
											auto retStatus = GeomLib::NormEstim(geomSurface, tSeedInPCurve, 1e-6, tSeedNormal); | 
				
			||||
 | 
											if(retStatus >= 2) { | 
				
			||||
 | 
												std::cout << "calculate wrong!\n"; | 
				
			||||
 | 
												exit(-1); | 
				
			||||
 | 
											} | 
				
			||||
 | 
											if(reverseNormal) tSeedNormal = -tSeedNormal; | 
				
			||||
 | 
											Eigen::Vector3d eigenNormal(tSeedNormal.X(), tSeedNormal.Y(), tSeedNormal.Z()); | 
				
			||||
 | 
											domainGlobal.addBoundaryNode(eigenSeedPnt, type, eigenNormal); | 
				
			||||
 | 
											treeGlobal.insert(eigenSeedPnt); | 
				
			||||
 | 
										} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
										int curNode = domainParamLocalPatch.size() - 1; | 
				
			||||
 | 
										int endNode = domainParamLocalPatch.size(); | 
				
			||||
 | 
										while(curNode < endNode && endNode < shape.max_points) { | 
				
			||||
 | 
											genPoints++; | 
				
			||||
 | 
											//std::cout << "curNode / endNode : " << curNode << '/' << endNode << '\n';
 | 
				
			||||
 | 
											auto param = domainParamLocalPatch.pos(curNode); | 
				
			||||
 | 
											double t = domainParamLocalPatch.getT(curNode); | 
				
			||||
 | 
											std::vector<double> candidates{ 1.0, -1.0 }; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
											gp_Pnt pt; | 
				
			||||
 | 
											gp_Vec der; | 
				
			||||
 | 
											geomCurve->D1(t, pt, der); | 
				
			||||
 | 
											std::cout << "pt: " << pt.X() << "," << pt.Y() << "," << pt.Z() << '\n'; | 
				
			||||
 | 
											std::cout << "der: " << der.X() << "," << der.Y() << "," << der.Z() << '\n'; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
											std::cout << "der.Mag:" << der.Magnitude() << '\n'; | 
				
			||||
 | 
											double alpha = h(transPnt(pt)) / der.Magnitude(); | 
				
			||||
 | 
											for(const auto& uCan : candidates) { | 
				
			||||
 | 
												double tNew = t + alpha * uCan; | 
				
			||||
 | 
												if(tNew > pCurveLastParam || tNew < pCurveFirstParam) { | 
				
			||||
 | 
													std::cout << "排除\n"; | 
				
			||||
 | 
													continue; | 
				
			||||
 | 
												} | 
				
			||||
 | 
												std::cout << "tNew:" << tNew << "\n"; | 
				
			||||
 | 
												gp_Pnt2d tNewSeedInPCurve; | 
				
			||||
 | 
												geomPCurve->D0(tNew, tNewSeedInPCurve); | 
				
			||||
 | 
												gp_Pnt ptNew; | 
				
			||||
 | 
												geomCurve->D0(tNew, ptNew); | 
				
			||||
 | 
												gp_Pnt ptNew2; | 
				
			||||
 | 
												geomSurface->D0(tNewSeedInPCurve.X(), tNewSeedInPCurve.Y(), ptNew2); | 
				
			||||
 | 
												std::cout << "ptNew: " << ptNew.X() << "," << ptNew.Y() << "," << ptNew.Z() << '\n'; | 
				
			||||
 | 
												std::cout << "ptNew2: " << ptNew2.X() << "," << ptNew2.Y() << "," << ptNew2.Z() << '\n'; | 
				
			||||
 | 
												double checkradius = pt.SquareDistance(ptNew); | 
				
			||||
 | 
												std::cout << "CheckRadius: " << checkradius << '\n'; | 
				
			||||
 | 
												double d_sq_loc = treeLocal.query(transPnt(ptNew)).second[0]; | 
				
			||||
 | 
												std::cout << "d_sq_loc: " << d_sq_loc << '\n'; | 
				
			||||
 | 
												if(d_sq_loc >= (shape.zeta * shape.zeta * checkradius)) { | 
				
			||||
 | 
													domainParamLocalPatch.addInternalNodeWithT(transPnt2d(tNewSeedInPCurve), tNew, 1); | 
				
			||||
 | 
													treeLocal.insert(transPnt(ptNew)); | 
				
			||||
 | 
													endNode++; | 
				
			||||
 | 
													double d_sq_global = treeGlobal.query(transPnt(ptNew)).second[0]; | 
				
			||||
 | 
													if(d_sq_global >= (shape.zeta * shape.zeta * checkradius)) { | 
				
			||||
 | 
														gp_Dir tSeedNormalNew; | 
				
			||||
 | 
														auto retStatus = GeomLib::NormEstim(geomSurface, tNewSeedInPCurve, 1e-6, tSeedNormalNew); | 
				
			||||
 | 
														if(retStatus >= 2) { | 
				
			||||
 | 
															std::cout << "calculate wrong!\n"; | 
				
			||||
 | 
															exit(-1); | 
				
			||||
 | 
														} | 
				
			||||
 | 
														if(reverseNormal) { | 
				
			||||
 | 
															tSeedNormalNew = -tSeedNormalNew; | 
				
			||||
 | 
														} | 
				
			||||
 | 
														domainGlobal.addBoundaryNode(transPnt(ptNew), type, transVec(tSeedNormalNew)); | 
				
			||||
 | 
														treeGlobal.insert(transPnt(ptNew)); | 
				
			||||
 | 
													} else { | 
				
			||||
 | 
														std::cout << "全局不添加点\n"; | 
				
			||||
 | 
													} | 
				
			||||
 | 
												} else { | 
				
			||||
 | 
													std::cout << "局部不添加点\n"; | 
				
			||||
 | 
												} | 
				
			||||
 | 
											} | 
				
			||||
 | 
											curNode++; | 
				
			||||
 | 
										} | 
				
			||||
 | 
										std::cout << "该边已经生成:" << genPoints << "个点\n"; | 
				
			||||
 | 
									} | 
				
			||||
 | 
								} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
								//fill boundary surface!
 | 
				
			||||
 | 
								KDTree paramBoundarySearch; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							} | 
				
			||||
 | 
							return domainGlobal; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,23 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					#include "OccHelper.hpp" | 
				
			||||
 | 
					#include "OccShape.hpp" | 
				
			||||
 | 
					#include "DomainDiscretization.hpp" | 
				
			||||
 | 
					#include <vector> | 
				
			||||
 | 
					#include <Eigen/Core> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						DomainDiscretization<Eigen::Vector3d> discretizeBoundaryWithDensity(const OccShape& shape, const std::function<double(Eigen::Vector3d)>& h, int type); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						DomainDiscretization<Eigen::Vector3d> discretizeBoundaryWithStep(const OccShape& shape, double step, int type) { | 
				
			||||
 | 
							auto f = [=](Eigen::Vector3d) {return step; }; | 
				
			||||
 | 
							return discretizeBoundaryWithDensity(shape, f, type); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,30 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					#include <KDTree_fwd.hpp> | 
				
			||||
 | 
					#include <assert.hpp> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
						std::pair<std::vector<int>, std::vector<double>> KDTree::query(const Eigen::Vector3d& point, int k)const { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							assert_msg(point.array().isFinite().prod() == 1, "Invalid point."); | 
				
			||||
 | 
							std::vector<int> ret_index(k); | 
				
			||||
 | 
							std::vector<double> out_dist_sqr(k); | 
				
			||||
 | 
							int actual_k = tree.knnSearch(point.data(), k, &ret_index[0], &out_dist_sqr[0]); | 
				
			||||
 | 
							assert_msg(actual_k == k, "There were not enough points in the tree, you requested %d " | 
				
			||||
 | 
								"points, the tree only contains %d points.", k, actual_k); | 
				
			||||
 | 
							return { ret_index, out_dist_sqr }; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						std::pair<std::vector<int>, std::vector<double>> KDTree::query(const Eigen::Vector3d& point, const double& radius_squared)const { | 
				
			||||
 | 
							assert_msg(point.array().isFinite().prod() == 1, "Invalid point."); | 
				
			||||
 | 
							std::vector<std::pair<int, double>> idx_dist; | 
				
			||||
 | 
							int k = tree.radiusSearch(point.data(), radius_squared, idx_dist, nanoflann::SearchParams()); | 
				
			||||
 | 
							std::vector<int> idx(k); std::vector<double> dists(k); | 
				
			||||
 | 
							for(int i = 0; i < k; ++i) { | 
				
			||||
 | 
								std::tie(idx[i], dists[i]) = idx_dist[i]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							return { idx, dists }; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,40 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					#include "assert.hpp" | 
				
			||||
 | 
					#include "KDTreeMutable_fwd.hpp" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						void KDTreeMutable::insert(const Eigen::Vector3d& point) { | 
				
			||||
 | 
							assert_msg(point.array().isFinite().prod() == 1, "Invalid point."); | 
				
			||||
 | 
							auto n = points_.kdtree_get_point_count(); | 
				
			||||
 | 
							points_.add(point); | 
				
			||||
 | 
							tree.addPoints(n, n); | 
				
			||||
 | 
							++size_; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						void KDTreeMutable::insert(const std::vector<Eigen::Vector3d>& points) { | 
				
			||||
 | 
							auto n = points_.kdtree_get_point_count(); | 
				
			||||
 | 
							for(const auto& p : points) { | 
				
			||||
 | 
								assert_msg(p.array().isFinite().prod() == 1, "One of the points is invalid."); | 
				
			||||
 | 
								points_.add(p); | 
				
			||||
 | 
							} | 
				
			||||
 | 
							size_ += points.size(); | 
				
			||||
 | 
							tree.addPoints(n, n + points.size() - 1); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						std::pair<std::vector<int>, std::vector<double>> KDTreeMutable::query(const Eigen::Vector3d& point, int k) { | 
				
			||||
 | 
							assert_msg(point.array().isFinite().prod() == 1, "Invalid query point."); | 
				
			||||
 | 
							nanoflann::KNNResultSet<double, int> resultSet(k); | 
				
			||||
 | 
							std::vector<int> ret_index(k); | 
				
			||||
 | 
							std::vector<double> out_dist_sqr(k); | 
				
			||||
 | 
							resultSet.init(&ret_index[0], &out_dist_sqr[0]); | 
				
			||||
 | 
							tree.findNeighbors(resultSet, point.data(), nanoflann::SearchParams(k)); | 
				
			||||
 | 
							assert_msg(resultSet.full(), "Not enough points in the tree, you requested %d points, " | 
				
			||||
 | 
								"but the tree contains only %d points.", | 
				
			||||
 | 
								k, size()); | 
				
			||||
 | 
							return { ret_index, out_dist_sqr }; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,69 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					#include "nanoflann.hpp" | 
				
			||||
 | 
					#include <array> | 
				
			||||
 | 
					#include <iosfwd> | 
				
			||||
 | 
					#include "PointCloud.hpp" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
						class KDTreeMutable { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						private: | 
				
			||||
 | 
							typedef nanoflann::KDTreeSingleIndexDynamicAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud>, PointCloud, 3, int> kd_tree_t; | 
				
			||||
 | 
							int size_; | 
				
			||||
 | 
							PointCloud points_; | 
				
			||||
 | 
							kd_tree_t tree; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						public: | 
				
			||||
 | 
							explicit KDTreeMutable(const std::vector<Eigen::Vector3d>& points) :points_(points), size_(points.size()), tree(3, points_, nanoflann::KDTreeSingleIndexAdaptorParams(20)) {} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							KDTreeMutable() :points_(), size_(0), tree(3, points_, nanoflann::KDTreeSingleIndexAdaptorParams(20)) {} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							void reset(const std::vector<Eigen::Vector3d>& points) { | 
				
			||||
 | 
								points_.setPts(points); | 
				
			||||
 | 
								size_ = points.size(); | 
				
			||||
 | 
								tree.reset(); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							void insert(const Eigen::Vector3d& point); | 
				
			||||
 | 
							void insert(const std::vector<Eigen::Vector3d>& points); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Check if any point exists in sphere centered at `p` with radius `r`.
 | 
				
			||||
 | 
							bool existsPointInSphere(const Eigen::Vector3d& p, double r) { | 
				
			||||
 | 
								if(size_ == 0) | 
				
			||||
 | 
									return false; | 
				
			||||
 | 
								return query(p).second[0] <= r * r; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/**
 | 
				
			||||
 | 
							 * Removes a point with given index from the tree. The indexes of the points are given | 
				
			||||
 | 
							 * sequentially at insertion and do not change. The removal is lazy and point still takes | 
				
			||||
 | 
							 * up memory. | 
				
			||||
 | 
							 */ | 
				
			||||
 | 
							void remove(int index) { | 
				
			||||
 | 
								size_ -= tree.removePoint(index); | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Returns number of points in the tree.
 | 
				
			||||
 | 
							int size() const { | 
				
			||||
 | 
								return size_; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/**
 | 
				
			||||
 | 
							 * Find `k` nearest neighbors to given point. | 
				
			||||
 | 
							 * @param point Find closest points to this point. | 
				
			||||
 | 
							 * @param k How many nearest points to find. | 
				
			||||
 | 
							 * | 
				
			||||
 | 
							 * @return A pair of two vectors of size `k` containing | 
				
			||||
 | 
							 * indices of nearest neighbors and squared distances to said neighbors. | 
				
			||||
 | 
							 * @throw Assertion fails if there are not enough points in the tree. | 
				
			||||
 | 
							 */ | 
				
			||||
 | 
							std::pair<std::vector<int>, std::vector<double>> query(const Eigen::Vector3d& point, int k = 1); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,49 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					#include <PointCloud.hpp> | 
				
			||||
 | 
					#include <nanoflann.hpp> | 
				
			||||
 | 
					#include <Eigen/Core> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
						class KDTree { | 
				
			||||
 | 
						private: | 
				
			||||
 | 
							typedef nanoflann::KDTreeSingleIndexAdaptor<nanoflann::L2_Simple_Adaptor<double, PointCloud>, PointCloud, 3, int> kd_tree_t; | 
				
			||||
 | 
							PointCloud points_; | 
				
			||||
 | 
							kd_tree_t tree; | 
				
			||||
 | 
						public: | 
				
			||||
 | 
							explicit KDTree(const std::vector<Eigen::Vector3d>& points) :points_(points), tree(3, points_, nanoflann::KDTreeSingleIndexAdaptorParams(20)) { | 
				
			||||
 | 
								tree.buildIndex(); | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							KDTree() :points_(), tree(3, points_, nanoflann::KDTreeSingleIndexAdaptorParams(20)) {} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							void reset(const std::vector<Eigen::Vector3d>& points) { | 
				
			||||
 | 
								points_.setPts(points); | 
				
			||||
 | 
								tree.buildIndex(); | 
				
			||||
 | 
							} | 
				
			||||
 | 
							std::pair<std::vector<int>, std::vector<double>> query(const Eigen::Vector3d& point, int k = 1)const; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							std::pair<std::vector<int>, std::vector<double>> query(const Eigen::Vector3d& point, const double& radius_squared) const; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							Eigen::Vector3d get(int index) const { | 
				
			||||
 | 
								return points_.get(index); | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							std::vector<Eigen::Vector3d> get(const std::vector<int>& indexes) const { | 
				
			||||
 | 
								const int n = indexes.size(); | 
				
			||||
 | 
								std::vector<Eigen::Vector3d> result(n); | 
				
			||||
 | 
								for(int i = 0; i < n; i++) { | 
				
			||||
 | 
									result[i] = points_.get(indexes[i]); | 
				
			||||
 | 
								} | 
				
			||||
 | 
								return result; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							int size() const { | 
				
			||||
 | 
								return points_.kdtree_get_point_count(); | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,65 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					// OpenCascade includes
 | 
				
			||||
 | 
					#include <Geom2d_TrimmedCurve.hxx> | 
				
			||||
 | 
					#include <BRepClass_FaceClassifier.hxx> | 
				
			||||
 | 
					#include <Interface_Static.hxx> | 
				
			||||
 | 
					#include <STEPCAFControl_Writer.hxx> | 
				
			||||
 | 
					#include <STEPControl_Reader.hxx> | 
				
			||||
 | 
					#include <TopExp.hxx> | 
				
			||||
 | 
					#include <TopoDS.hxx> | 
				
			||||
 | 
					#include <TopExp_Explorer.hxx> | 
				
			||||
 | 
					#include <iostream> | 
				
			||||
 | 
					#include <TopoDS_Shape.hxx> | 
				
			||||
 | 
					#include <Geom_Surface.hxx> | 
				
			||||
 | 
					#include <BRepAdaptor_Surface.hxx> | 
				
			||||
 | 
					#include <BRepBuilderAPI_NurbsConvert.hxx> | 
				
			||||
 | 
					#include <Brep_Tool.hxx> | 
				
			||||
 | 
					#include <GeomConvert.hxx> | 
				
			||||
 | 
					#include <BRepLib_FindSurface.hxx> | 
				
			||||
 | 
					#include <Geom_BSplineSurface.hxx> | 
				
			||||
 | 
					#include <BRepAdaptor_CompCurve.hxx> | 
				
			||||
 | 
					#include <BRepTools.hxx> | 
				
			||||
 | 
					#include <ShapeFix_Wire.hxx> | 
				
			||||
 | 
					#include <Adaptor3d_Curve.hxx> | 
				
			||||
 | 
					#include <GeomAdaptor_Curve.hxx> | 
				
			||||
 | 
					#include <BOPTools_AlgoTools3D.hxx> | 
				
			||||
 | 
					#include <BRepBuilderAPI_Sewing.hxx> | 
				
			||||
 | 
					#include <ShapeFix_Shape.hxx> | 
				
			||||
 | 
					#include <ShapeFix_Shell.hxx> | 
				
			||||
 | 
					#include <ShapeAnalysis.hxx> | 
				
			||||
 | 
					#include <TopoDS_TShape.hxx> | 
				
			||||
 | 
					#include <Geom_Plane.hxx> | 
				
			||||
 | 
					#include <Geom_CylindricalSurface.hxx> | 
				
			||||
 | 
					#include <Geom_ConicalSurface.hxx> | 
				
			||||
 | 
					#include <Geom_SphericalSurface.hxx> | 
				
			||||
 | 
					#include <Geom_ToroidalSurface.hxx> | 
				
			||||
 | 
					#include <Geom_SurfaceOfLinearExtrusion.hxx> | 
				
			||||
 | 
					#include <Geom_SurfaceOfRevolution.hxx> | 
				
			||||
 | 
					#include <Geom_BezierSurface.hxx> | 
				
			||||
 | 
					#include <Geom_BSplineSurface.hxx> | 
				
			||||
 | 
					#include <Geom_RectangularTrimmedSurface.hxx> | 
				
			||||
 | 
					#include <Geom_OffsetSurface.hxx> | 
				
			||||
 | 
					#include <TopoDS_Compound.hxx> | 
				
			||||
 | 
					#include <BRepBuilderAPI_Copy.hxx> | 
				
			||||
 | 
					#include <TColgp_Array2OfPnt.hxx> | 
				
			||||
 | 
					#include <TColStd_Array1OfReal.hxx> | 
				
			||||
 | 
					#include <TColStd_Array2OfReal.hxx> | 
				
			||||
 | 
					#include <TColStd_Array1OfInteger.hxx> | 
				
			||||
 | 
					#include <BRepBuilderAPI_MakeSolid.hxx> | 
				
			||||
 | 
					#include <GeomTools.hxx> | 
				
			||||
 | 
					#include <Geom_Circle.hxx> | 
				
			||||
 | 
					#include <BRep_Builder.hxx> | 
				
			||||
 | 
					#include <GeomLib.hxx> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Eigen::Vector3d transVec(const gp_Vec& vec) { | 
				
			||||
 | 
						return Eigen::Vector3d(vec.X(), vec.Y(), vec.Z()); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Eigen::Vector3d transPnt(const gp_Pnt& Pnt) { | 
				
			||||
 | 
						return Eigen::Vector3d(Pnt.X(), Pnt.Y(), Pnt.Z()); | 
				
			||||
 | 
					} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					Eigen::Vector2d transPnt2d(const gp_Pnt2d& Pnt) { | 
				
			||||
 | 
						return Eigen::Vector2d(Pnt.X(), Pnt.Y()); | 
				
			||||
 | 
					} | 
				
			||||
@ -0,0 +1,57 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					#include "OccHelper.hpp" | 
				
			||||
 | 
					#include "assert.hpp" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
						class OccShape { | 
				
			||||
 | 
						public: | 
				
			||||
 | 
							int max_points = 500000; | 
				
			||||
 | 
							int seed_; | 
				
			||||
 | 
							int n_samples = 15; | 
				
			||||
 | 
							double zeta = 1 - 1e-10; | 
				
			||||
 | 
							double epsilon = 0; | 
				
			||||
 | 
							TopoDS_Shape myShape; | 
				
			||||
 | 
						public: | 
				
			||||
 | 
							OccShape() {} | 
				
			||||
 | 
							OccShape(const TopoDS_Shape& myShape_) { | 
				
			||||
 | 
								max_points = 500000; | 
				
			||||
 | 
								seed_; | 
				
			||||
 | 
								n_samples = 15; | 
				
			||||
 | 
								zeta = 1 - 1e-10; | 
				
			||||
 | 
								epsilon = 0; | 
				
			||||
 | 
								myShape = myShape_; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							OccShape& maxPoints(int max_points) { | 
				
			||||
 | 
								this->max_points = max_points; | 
				
			||||
 | 
								return *this; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							OccShape& seed(int seed) { | 
				
			||||
 | 
								seed_ = seed; | 
				
			||||
 | 
								return *this; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							OccShape& numSamples(int n_samples) { | 
				
			||||
 | 
								this->n_samples = n_samples; | 
				
			||||
 | 
								return *this; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							OccShape& proximityTolerance(double zeta) { | 
				
			||||
 | 
								assert_msg((0 < zeta && zeta < 1), "Zeta must be between 0 and 1, got %f.", zeta); | 
				
			||||
 | 
								this->zeta = zeta; | 
				
			||||
 | 
								return *this; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							OccShape& boundaryProximity(double epsilon) { | 
				
			||||
 | 
								assert_msg((0 < epsilon && epsilon < 1), "Epsilon must be between 0 and 1, got %f.", epsilon); | 
				
			||||
 | 
								this->epsilon = epsilon; | 
				
			||||
 | 
								return *this; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,56 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/**
 | 
				
			||||
 | 
					 * @file | 
				
			||||
 | 
					 * Implementation of KDTree storage class. | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include <vector> | 
				
			||||
 | 
					#include <Eigen/Core> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						/// Helper class for KDTree with appropriate accessors containing a set of points. @ingroup utils
 | 
				
			||||
 | 
						struct PointCloud { | 
				
			||||
 | 
							std::vector<Eigen::Vector3d> pts; ///< Points, contained in the tree.
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Construct an empty point set.
 | 
				
			||||
 | 
							PointCloud() = default; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Construct from an array of points.
 | 
				
			||||
 | 
							PointCloud(const std::vector<Eigen::Vector3d>& pts) : pts(pts) {} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Reset contained points.
 | 
				
			||||
 | 
							void setPts(const std::vector<Eigen::Vector3d>& pts) { | 
				
			||||
 | 
								PointCloud::pts = pts; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Interface requirement: returns number of data points.
 | 
				
			||||
 | 
							inline int kdtree_get_point_count() const { | 
				
			||||
 | 
								return pts.size(); | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Interface requirement: returns `dim`-th coordinate of `idx`-th point.
 | 
				
			||||
 | 
							inline typename double kdtree_get_pt(const size_t idx, int dim) const { | 
				
			||||
 | 
								return pts[idx][dim]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Access the points.
 | 
				
			||||
 | 
							inline Eigen::Vector3d get(const size_t idx) const { | 
				
			||||
 | 
								return pts[idx]; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Add a point to the cloud.
 | 
				
			||||
 | 
							inline void add(const Eigen::Vector3d& p) { | 
				
			||||
 | 
								pts.push_back(p); | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							/// Comply with the interface.
 | 
				
			||||
 | 
							template <class BBOX> | 
				
			||||
 | 
							bool kdtree_get_bbox(BBOX& /* bb */) const { | 
				
			||||
 | 
								return false; | 
				
			||||
 | 
							} | 
				
			||||
 | 
						}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					} // namespace mm
 | 
				
			||||
 | 
					
 | 
				
			||||
@ -0,0 +1,110 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/**
 | 
				
			||||
 | 
					 * @file | 
				
			||||
 | 
					 * Implementation of custom assert and debug utilities. | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include <tinyformat.h> | 
				
			||||
 | 
					#include "print.hpp" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#ifdef _MSC_VER // Check if using MSVC
 | 
				
			||||
 | 
					#define FUNCTION_NAME __FUNCSIG__ // Use __FUNCSIG__ for function name
 | 
				
			||||
 | 
					#else | 
				
			||||
 | 
					#define FUNCTION_NAME __PRETTY_FUNCTION__ // Use __PRETTY_FUNCTION__ for other compilers
 | 
				
			||||
 | 
					#endif | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						// print macro
 | 
				
			||||
 | 
						/// @cond
 | 
				
			||||
 | 
					#define VA_NUM_ARGS(...) VA_NUM_ARGS_IMPL(__VA_ARGS__, 5, 4, 3, 2, 1, 0) | 
				
			||||
 | 
					#define VA_NUM_ARGS_IMPL(_1, _2, _3, _4, _5, N, ...) N | 
				
			||||
 | 
					#define macro_dispatcher(func, ...)     macro_dispatcher_(func, VA_NUM_ARGS(__VA_ARGS__)) | 
				
			||||
 | 
					#define macro_dispatcher_(func, nargs)  macro_dispatcher__(func, nargs) | 
				
			||||
 | 
					#define macro_dispatcher__(func, nargs) func ## nargs | 
				
			||||
 | 
					#define addflag(a) {std::cerr << "flags=[flags, " << (a) << "];" << std::endl;} | 
				
			||||
 | 
					#define prnv2(a, b) {std::cerr << a << " = " << (b) << ";" << std::endl;} | 
				
			||||
 | 
					#define prnv1(a)   {std::cerr << #a << " = " << (a) << ";" << std::endl;} | 
				
			||||
 | 
					/// @endcond
 | 
				
			||||
 | 
					/**
 | 
				
			||||
 | 
					 * Prints a variable name and value to standard output. Can take one or two parameters. | 
				
			||||
 | 
					 * Example: | 
				
			||||
 | 
					 * @code | 
				
			||||
 | 
					 * int a = 6; | 
				
			||||
 | 
					 * prn(a) // prints 'a = 6;' | 
				
			||||
 | 
					 * prn("value", a) // prints 'value = 6;' | 
				
			||||
 | 
					 * @endcode | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					#define prn(...) macro_dispatcher(prnv, __VA_ARGS__)(__VA_ARGS__) | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						using tinyformat::printf; | 
				
			||||
 | 
						using tinyformat::format; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						/// Namespace holding custom assert implementation.
 | 
				
			||||
 | 
						namespace assert_internal { | 
				
			||||
 | 
							/**
 | 
				
			||||
 | 
							 * Actual assert implementation. | 
				
			||||
 | 
							 * @param condition Condition to test, e.g.\ `n > 0`. | 
				
			||||
 | 
							 * @param file File where the assertion failed. | 
				
			||||
 | 
							 * @param func_name Function name where the assertion failed. | 
				
			||||
 | 
							 * @param line Line on which the assertion failed. | 
				
			||||
 | 
							 * @param message Message as specified in the `assert_msg` macro. | 
				
			||||
 | 
							 * @param format_list List of format field values to pass to `tinyformat::format` function. | 
				
			||||
 | 
							 */ | 
				
			||||
 | 
							bool assert_handler_implementation(const char* condition, const char* file, const char* func_name, | 
				
			||||
 | 
								int line, const char* message, tfm::FormatListRef format_list); | 
				
			||||
 | 
							/// Assert handler that unpacks varargs.
 | 
				
			||||
 | 
							template<typename... Args> | 
				
			||||
 | 
							bool assert_handler(const char* condition, const char* file, const char* func_name, int line, | 
				
			||||
 | 
								const char* message, const Args&... args) {  // unpacks first argument
 | 
				
			||||
 | 
								tfm::FormatListRef arg_list = tfm::makeFormatList(args...); | 
				
			||||
 | 
								return assert_handler_implementation(condition, file, func_name, line, message, arg_list); | 
				
			||||
 | 
							} | 
				
			||||
 | 
						}  // namespace assert_internal
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#ifdef NDEBUG | 
				
			||||
 | 
					#define assert_msg(cond, ...) ((void)sizeof(cond)) | 
				
			||||
 | 
					#else | 
				
			||||
 | 
					/**
 | 
				
			||||
 | 
					 * @brief Assert with better error reporting. | 
				
			||||
 | 
					 * @param cond Conditions to test. | 
				
			||||
 | 
					 * @param ... The second parameter is also required and represents the message to print on failure. | 
				
			||||
 | 
					 * For every %* field in message one additional parameter must be present. | 
				
			||||
 | 
					 * | 
				
			||||
 | 
					 * Example: | 
				
			||||
 | 
					 * @code | 
				
			||||
 | 
					 * assert_msg(n > 0, "n must be positive, got %d.", n); | 
				
			||||
 | 
					 * @endcode | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					#define assert_msg(cond, ...) ((void)(!(cond) && \ | 
				
			||||
 | 
					    meshless::assert_internal::assert_handler( \ | 
				
			||||
 | 
					            #cond, __FILE__, FUNCTION_NAME, __LINE__, __VA_ARGS__) && (assert(0), 1))) | 
				
			||||
 | 
					 //            #cond, __FILE__, __PRETTY_FUNCTION__, __LINE__, __VA_ARGS__) && (exit(1), 1)))
 | 
				
			||||
 | 
					#endif | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/**
 | 
				
			||||
 | 
					 * Prints given text in bold red. | 
				
			||||
 | 
					 * @param s text to print. | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
						inline void print_red(const std::string& s) { | 
				
			||||
 | 
							std::cout << "\x1b[31;1m" << s << "\x1b[37;0m"; | 
				
			||||
 | 
						} | 
				
			||||
 | 
						/**
 | 
				
			||||
 | 
						 * Prints given text in bold white. | 
				
			||||
 | 
						 * @param s text to print. | 
				
			||||
 | 
						 */ | 
				
			||||
 | 
						inline void print_white(const std::string& s) { | 
				
			||||
 | 
							std::cout << "\x1b[37;1m" << s << "\x1b[37;0m"; | 
				
			||||
 | 
						} | 
				
			||||
 | 
						/**
 | 
				
			||||
 | 
						 * Prints given text in bold green. | 
				
			||||
 | 
						 * @param s text to print. | 
				
			||||
 | 
						 */ | 
				
			||||
 | 
						inline void print_green(const std::string& s) { | 
				
			||||
 | 
							std::cout << "\x1b[32;1m" << s << "\x1b[37;0m"; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}  // namespace meshless
 | 
				
			||||
 | 
					
 | 
				
			||||
								
									
										File diff suppressed because it is too large
									
								
							
						
					@ -0,0 +1,103 @@ | 
				
			|||||
 | 
					#ifndef MEDUSA_BITS_UTILS_PRINT_HPP_ | 
				
			||||
 | 
					#define MEDUSA_BITS_UTILS_PRINT_HPP_ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/**
 | 
				
			||||
 | 
					 * @file | 
				
			||||
 | 
					 * Printing helpers for std types. | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#include <iostream> | 
				
			||||
 | 
					#include <vector> | 
				
			||||
 | 
					#include <array> | 
				
			||||
 | 
					#include <utility> | 
				
			||||
 | 
					#include <tuple> | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					 // additional ostream operators
 | 
				
			||||
 | 
					namespace std { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						/// Output pairs as `(1, 2)`. @ingroup utils
 | 
				
			||||
 | 
						template <class T, class U> | 
				
			||||
 | 
						std::ostream& operator<<(std::ostream& xx, const std::pair<T, U>& par) { | 
				
			||||
 | 
							return xx << "(" << par.first << "," << par.second << ")"; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						/// Output arrays as `[1, 2, 3]`. @ingroup utils
 | 
				
			||||
 | 
						template <class T, size_t N> | 
				
			||||
 | 
						std::ostream& operator<<(std::ostream& xx, const std::array<T, N>& arr) { | 
				
			||||
 | 
							xx << "["; | 
				
			||||
 | 
							for(size_t i = 0; i < N; ++i) { | 
				
			||||
 | 
								xx << arr[i]; | 
				
			||||
 | 
								if(i < N - 1) | 
				
			||||
 | 
									xx << ", "; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							xx << "]"; | 
				
			||||
 | 
							return xx; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						/// Output vectors as `[1, 2, 3]`. @ingroup utils
 | 
				
			||||
 | 
						template <class T, class A> | 
				
			||||
 | 
						std::ostream& operator<<(std::ostream& xx, const std::vector<T, A>& arr) { | 
				
			||||
 | 
							// do it like the matlab does it.
 | 
				
			||||
 | 
							xx << "["; | 
				
			||||
 | 
							for(size_t i = 0; i < arr.size(); ++i) { | 
				
			||||
 | 
								xx << arr[i]; | 
				
			||||
 | 
								if(i < arr.size() - 1) | 
				
			||||
 | 
									xx << ", "; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							xx << "]"; | 
				
			||||
 | 
							return xx; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						/// Output nested vectors as `[[1, 2]; [3, 4]]`. @ingroup utils
 | 
				
			||||
 | 
						template <class T, class A> | 
				
			||||
 | 
						std::ostream& operator<<(std::ostream& xx, const std::vector<std::vector<T, A>>& arr) { | 
				
			||||
 | 
							xx << "["; | 
				
			||||
 | 
							for(size_t i = 0; i < arr.size(); ++i) { | 
				
			||||
 | 
								for(size_t j = 0; j < arr[i].size(); ++j) { | 
				
			||||
 | 
									xx << arr[i][j]; | 
				
			||||
 | 
									if(j < arr[i].size() - 1) | 
				
			||||
 | 
										xx << ", "; | 
				
			||||
 | 
								} | 
				
			||||
 | 
								if(i < arr.size() - 1) | 
				
			||||
 | 
									xx << "; "; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							xx << "]"; | 
				
			||||
 | 
							return xx; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						/// @cond
 | 
				
			||||
 | 
						namespace tuple_print_internal { | 
				
			||||
 | 
							template <class Tuple, std::size_t N> | 
				
			||||
 | 
							struct TuplePrinter { | 
				
			||||
 | 
								static void print(std::ostream& os, const Tuple& t) { // recursive
 | 
				
			||||
 | 
									TuplePrinter<Tuple, N - 1>::print(os, t); | 
				
			||||
 | 
									os << ", " << std::get<N - 1>(t); | 
				
			||||
 | 
								} | 
				
			||||
 | 
							}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							template <class Tuple> | 
				
			||||
 | 
							struct TuplePrinter<Tuple, 1> { | 
				
			||||
 | 
								static void print(std::ostream& os, const Tuple& t) { // one element
 | 
				
			||||
 | 
									os << std::get<0>(t); | 
				
			||||
 | 
								} | 
				
			||||
 | 
							}; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							template <class Tuple> | 
				
			||||
 | 
							struct TuplePrinter<Tuple, 0> { | 
				
			||||
 | 
								static void print(std::ostream&, const Tuple&) {} | 
				
			||||
 | 
							}; // zero elt
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						} // namespace tuple_print_internal
 | 
				
			||||
 | 
						/// @endcond
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						/// Print a tuple as (1, 4.5, abc). @ingroup utils
 | 
				
			||||
 | 
						template <class... Args> | 
				
			||||
 | 
						std::ostream& operator<<(std::ostream& os, const std::tuple<Args...>& t) { | 
				
			||||
 | 
							os << "("; | 
				
			||||
 | 
							tuple_print_internal::TuplePrinter<decltype(t), sizeof...(Args)>::print(os, t); | 
				
			||||
 | 
							return os << ")"; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					} // namespace std
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					#endif // MEDUSA_BITS_UTILS_PRINT_HPP_
 | 
				
			||||
								
									
										File diff suppressed because it is too large
									
								
							
						
					@ -0,0 +1,54 @@ | 
				
			|||||
 | 
					#pragma once | 
				
			||||
 | 
					#include <Eigen/Core> | 
				
			||||
 | 
					#include <cstring> | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
						template <int dim> | 
				
			||||
 | 
						void writePntVTK(const std::string& path, const Eigen::MatrixXd& pnts, const std::vector<double>& attri) { | 
				
			||||
 | 
							std::ofstream out(path); | 
				
			||||
 | 
							out << "# vtk DataFile Version 3.0\n" | 
				
			||||
 | 
								"Volume Mesh\n" | 
				
			||||
 | 
								"ASCII\n" | 
				
			||||
 | 
								"DATASET UNSTRUCTURED_GRID" | 
				
			||||
 | 
								<< std::endl; | 
				
			||||
 | 
							out << "POINTS " << pnts.rows() << " float" << std::endl; | 
				
			||||
 | 
							for(int i = 0; i < pnts.rows(); ++i) { | 
				
			||||
 | 
								for(int j = 0; j < dim; ++j) { | 
				
			||||
 | 
									out << std::setprecision(4) << pnts(i, j) << " "; | 
				
			||||
 | 
								} | 
				
			||||
 | 
								for(int j = dim; j < 3; ++j) { | 
				
			||||
 | 
									out << "0 "; | 
				
			||||
 | 
								} | 
				
			||||
 | 
								out << std::endl; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							int innersize = 0; | 
				
			||||
 | 
							int interSize = 0; | 
				
			||||
 | 
							int bounSize = 0; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							out << "CELLS " << pnts.rows() << " " << pnts.rows() * (1 + 1) << std::endl; | 
				
			||||
 | 
							for(int i = 0; i < pnts.rows(); ++i) { | 
				
			||||
 | 
								out << "1 " << i << std::endl; | 
				
			||||
 | 
							} | 
				
			||||
 | 
							out << "CELL_TYPES " << pnts.rows() << std::endl; | 
				
			||||
 | 
							for(int i = 0; i < pnts.rows(); ++i) { | 
				
			||||
 | 
								out << 1 << std::endl; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							if(!attri.empty()) { | 
				
			||||
 | 
								out << "POINT_DATA " << attri.size() << "\n" | 
				
			||||
 | 
									<< "SCALARS point_scalars double 1\n" | 
				
			||||
 | 
									<< "LOOKUP_TABLE default" << std::endl; | 
				
			||||
 | 
								for(auto& d : attri) { | 
				
			||||
 | 
									out << d << std::endl; | 
				
			||||
 | 
									if(d == 1) | 
				
			||||
 | 
										innersize++; | 
				
			||||
 | 
									else | 
				
			||||
 | 
										bounSize++; | 
				
			||||
 | 
								} | 
				
			||||
 | 
							} | 
				
			||||
 | 
							std::cout << "ÄÚ²¿µã£º " << innersize << "\n"; | 
				
			||||
 | 
							std::cout << "±ß½çµã£º " << bounSize << "\n"; | 
				
			||||
 | 
						} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}; | 
				
			||||
@ -0,0 +1,26 @@ | 
				
			|||||
 | 
					#include "assert.hpp" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					/**
 | 
				
			||||
 | 
					 * @file | 
				
			||||
 | 
					 * Implementation of custom assert utilities. | 
				
			||||
 | 
					 */ | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					namespace meshless { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						namespace assert_internal { | 
				
			||||
 | 
					
 | 
				
			||||
 | 
							bool assert_handler_implementation(const char* condition, const char* file, const char* func_name, | 
				
			||||
 | 
								int line, const char* message, tfm::FormatListRef format_list) { | 
				
			||||
 | 
								std::cerr << "\x1b[37;1m";  // white bold
 | 
				
			||||
 | 
								tfm::format(std::cerr, "%s:%d: %s: Assertion `%s' failed with message:\n", | 
				
			||||
 | 
									file, line, func_name, condition); | 
				
			||||
 | 
								std::cerr << "\x1b[31;1m";  // red bold
 | 
				
			||||
 | 
								tfm::vformat(std::cerr, message, format_list); | 
				
			||||
 | 
								std::cerr << "\x1b[37;0m\n";  // no color
 | 
				
			||||
 | 
								std::cerr.flush(); | 
				
			||||
 | 
								return true; | 
				
			||||
 | 
							} | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						}  // namespace assert_internal
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					}  // namespace meshless
 | 
				
			||||
@ -0,0 +1,38 @@ | 
				
			|||||
 | 
					#include <iostream> | 
				
			||||
 | 
					#include <fstream> | 
				
			||||
 | 
					#include <Eigen/Core> | 
				
			||||
 | 
					#include "FillBoundary.hpp" | 
				
			||||
 | 
					#include "writeVTK.hpp" | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					using namespace std; | 
				
			||||
 | 
					using namespace meshless; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					int main() { | 
				
			||||
 | 
						Eigen::MatrixXd mat; | 
				
			||||
 | 
						BRep_Builder brepBuilder; | 
				
			||||
 | 
						TopoDS_Shape myShape; | 
				
			||||
 | 
						//auto status = BRepTools::Read(myShape, "F:/CADMeshless/StepAndBrepModel/DWE_ADM102_ASSIGN.brep", brepBuilder);
 | 
				
			||||
 | 
						auto status = BRepTools::Read(myShape, "F:/CADMeshless/StepAndBrepModel/Exhaust_Manifold.brep", brepBuilder); | 
				
			||||
 | 
						OccShape occShape(myShape); | 
				
			||||
 | 
						auto domain = discretizeBoundaryWithStep(occShape, 1, -1); | 
				
			||||
 | 
						Eigen::MatrixXd quaPoints; | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						quaPoints.resize(domain.positions().size(), 3); | 
				
			||||
 | 
						std::vector<double> attri; | 
				
			||||
 | 
						for(int i = 0; i < domain.positions().size(); i++) { | 
				
			||||
 | 
							if(domain.types()[i] == 1) { | 
				
			||||
 | 
								attri.push_back(1.0); | 
				
			||||
 | 
							} else { | 
				
			||||
 | 
								attri.push_back(0); | 
				
			||||
 | 
							} | 
				
			||||
 | 
							quaPoints(i, 0) = domain.positions()[i].x(); | 
				
			||||
 | 
							quaPoints(i, 1) = domain.positions()[i].y(); | 
				
			||||
 | 
							quaPoints(i, 2) = domain.positions()[i].z(); | 
				
			||||
 | 
						} | 
				
			||||
 | 
						writePntVTK<3>("Exhaust_Manifold.vtk", quaPoints, attri); | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
					
 | 
				
			||||
 | 
						return 0; | 
				
			||||
 | 
					} | 
				
			||||
					Loading…
					
					
				
		Reference in new issue