| 
						
						
							
								
							
						
						
					 | 
					@ -117,7 +117,7 @@ int check_mesh_edge_convex(Mesh3d* m, HE_edge<double>* he) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					void normalize_mesh(Mesh3d& mesh, std::string outputfile); | 
					 | 
					 | 
					void normalize_mesh(Mesh3d& mesh, std::string outputfile); | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					void generate_feature_sample(Mesh3d& mesh, std::string outputfile); | 
					 | 
					 | 
					int generate_feature_sample(Mesh3d& mesh,std::string inputfile, std::string outputfile, FeatureSampleConfig& config); | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					int main(int argc, char** argv) | 
					 | 
					 | 
					int main(int argc, char** argv) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					{ | 
					 | 
					 | 
					{ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -130,24 +130,17 @@ int main(int argc, char** argv) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							if (!config.Validate()) { | 
					 | 
					 | 
							if (!config.Validate()) { | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								throw std::runtime_error("Invalid configuration"); | 
					 | 
					 | 
								throw std::runtime_error("Invalid configuration"); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							} | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
							int n_nonfeature_sample = 50000; | 
					 | 
					 | 
							// int n_nonfeature_sample = 50000;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
							int n_feature_sample = 0; | 
					 | 
					 | 
							// int n_feature_sample = 0;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
							int min_sample_perpatch = 50; | 
					 | 
					 | 
							// int min_sample_perpatch = 50;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
							double sigma = -1.0; | 
					 | 
					 | 
							// double sigma = -1.0;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
							double sigma_n = -1.0; | 
					 | 
					 | 
							// double sigma_n = -1.0;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
							int processing_mode = config.processing.mode; | 
					 | 
					 | 
							int processing_mode = config.processing.mode; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							auto& inputfile = config.files.input_mesh; | 
					 | 
					 | 
							auto& inputfile = config.files.input_mesh; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							auto& outputfile = config.files.output_file; | 
					 | 
					 | 
							auto& outputfile = config.files.output_file; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							//output pts by colors
 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							int last_dot = (int)outputfile.find_last_of("."); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							auto output_prefix = outputfile.substr(0, last_dot); | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							int flag_csg = 0; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
							bool flag_sample_pts = true; //simply generate mask and csg tree of a given point cloud 
 | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
							if (config.files.input_pointcloud.empty()) | 
					 | 
					 | 
							 | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
							{ | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								flag_sample_pts = false; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							std::string inputext = GetFileExtension(inputfile); | 
					 | 
					 | 
							std::string inputext = GetFileExtension(inputfile); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							Mesh3d mesh; | 
					 | 
					 | 
							Mesh3d mesh; | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -156,17 +149,7 @@ int main(int argc, char** argv) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							else if (inputext == "off") | 
					 | 
					 | 
							else if (inputext == "off") | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								mesh.load_off(inputfile.c_str()); | 
					 | 
					 | 
								mesh.load_off(inputfile.c_str()); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							std::cout << "verts: " << mesh.get_vertices_list()->size() << " face:  " << mesh.get_faces_list()->size() << std::endl; | 
					 | 
					 | 
							std::cout << "verts: " << mesh.get_vertices_list()->size() << " face:  " << mesh.get_faces_list()->size() << std::endl; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							bool flag_verbose = false; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							if (config.processing.verbose) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							{ | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								flag_verbose = (bool)config.processing.verbose; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							 | 
					 | 
					 | 
							 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							bool flag_strict = false; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							if (config.processing.strict_mode) | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							{ | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								flag_strict = true; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							} | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							if (processing_mode == 0) | 
					 | 
					 | 
							if (processing_mode == 0) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							{ | 
					 | 
					 | 
							{ | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -175,6 +158,7 @@ int main(int argc, char** argv) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							} | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							else if (processing_mode == 1) | 
					 | 
					 | 
							else if (processing_mode == 1) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							{ | 
					 | 
					 | 
							{ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
								return generate_feature_sample(mesh, inputfile, outputfile, config); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							} | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						} | 
					 | 
					 | 
						} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
					@ -228,32 +212,31 @@ void normalize_mesh(Mesh3d& mesh, std::string outputfile) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					} | 
					 | 
					 | 
					} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					void generate_feature_sample(Mesh3d& mesh, std::string outputfile) | 
					 | 
					 | 
					int generate_feature_sample(Mesh3d& mesh, std::string inputfile, std::string outputfile, FeatureSampleConfig& config) | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					 | 
					 | 
					{ | 
					 | 
					 | 
					{ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						//first sample feature parts then non-feature parts
 | 
					 | 
					 | 
						//first sample feature parts then non-feature parts
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						//mask: 
 | 
					 | 
					 | 
						//mask: 
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						//feature: 0
 | 
					 | 
					 | 
						//feature: 0
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						//non feature: 1,2,3...indicating coloring
 | 
					 | 
					 | 
						//non feature: 1,2,3...indicating coloring
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						assert(!config.files.input_feature.empty() && !config.files.output_mask.empty()); | 
					 | 
					 | 
						assert(!config.files.input_feature.empty() && !config.files.output_mask.empty()); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						auto& inputfeaturefile = config.files.input_feature; | 
					 | 
					 | 
						auto& inputfeaturefile = config.files.input_feature; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						auto& outputmaskfile = config.files.output_mask; | 
					 | 
					 | 
						auto& outputmaskfile = config.files.output_mask; | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
						if (config.sampling.feature_samples) | 
					 | 
					 | 
						int n_feature_sample = config.sampling.feature_samples ? config.sampling.feature_samples : 0; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
							n_feature_sample = config.sampling.feature_samples; | 
					 | 
					 | 
						int n_nonfeature_sample = config.sampling.nonfeature_samples ? config.sampling.nonfeature_samples : 50000; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
						if (config.sampling.nonfeature_samples) | 
					 | 
					 | 
						int min_sample_perpatch = 50; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
							n_nonfeature_sample = config.sampling.nonfeature_samples; | 
					 | 
					 | 
						double sigma = config.sampling.sigma ? config.sampling.sigma : -1.0; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
						if (config.sampling.sigma) | 
					 | 
					 | 
						double sigma_n = config.sampling.sigma_normal ? config.sampling.sigma_normal : -1.0; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
							sigma = config.sampling.sigma; | 
					 | 
					 | 
					
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
						if (config.sampling.sigma_normal) | 
					 | 
					 | 
						//output pts by colors
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
							sigma_n = config.sampling.sigma_normal; | 
					 | 
					 | 
						int last_dot = (int)outputfile.find_last_of("."); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
						bool flag_repair_turn_features = true; | 
					 | 
					 | 
						auto output_prefix = outputfile.substr(0, last_dot); | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
						if (config.processing.repair_turn) | 
					 | 
					 | 
						int flag_csg = 0; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
							flag_repair_turn_features = true; | 
					 | 
					 | 
						bool flag_sample_pts = false ? config.files.input_pointcloud.empty():true; //simply generate mask and csg tree of a given point cloud 
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					
 | 
					 | 
					 | 
						bool flag_verbose = (bool)config.processing.verbose ? config.processing.verbose : false; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
						bool flag_repair_tree_features = false; | 
					 | 
					 | 
						bool flag_strict = (bool)config.processing.strict_mode ? config.processing.strict_mode : false; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
						if (config.processing.repair_tree) | 
					 | 
					 | 
						bool flag_repair_turn_features = config.processing.repair_turn; | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
						{ | 
					 | 
					 | 
						bool flag_repair_tree_features = true ?config.processing.repair_tree:false;	 | 
				
			
			
				
				
			
		
	
		
		
			
				
					 | 
					 | 
							flag_repair_tree_features = true; | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						} | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					 | 
					 | 
						 | 
					 | 
					 | 
						 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						 | 
					 | 
					 | 
						 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						if (config.processing.generate_csg) | 
					 | 
					 | 
						if (config.processing.generate_csg) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -267,6 +250,7 @@ void generate_feature_sample(Mesh3d& mesh, std::string outputfile) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						std::vector<size_t> sample_pts_tris; //used for assign labels of sample pts
 | 
					 | 
					 | 
						std::vector<size_t> sample_pts_tris; //used for assign labels of sample pts
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						if (!flag_sample_pts) | 
					 | 
					 | 
						if (!flag_sample_pts) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
						{ | 
					 | 
					 | 
						{ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
							// 从点云文件中加载点云数据
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							auto& inputpcfile = config.files.input_pointcloud; | 
					 | 
					 | 
							auto& inputpcfile = config.files.input_pointcloud; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							load_xyz_file(inputpcfile.c_str(), sample_pts, sample_pt_normals); | 
					 | 
					 | 
							load_xyz_file(inputpcfile.c_str(), sample_pts, sample_pt_normals); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -285,12 +269,16 @@ void generate_feature_sample(Mesh3d& mesh, std::string outputfile) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							} | 
					 | 
					 | 
							} | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							else | 
					 | 
					 | 
							else | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							{ | 
					 | 
					 | 
							{ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
								// 如果未提供点云面文件,则从网格中提取顶点和面信息。
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								//search id by aabb
 | 
					 | 
					 | 
								//search id by aabb
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								std::vector<std::array<double, 3>> tri_verts; | 
					 | 
					 | 
								std::vector<std::array<double, 3>> tri_verts; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								std::vector<std::vector<size_t>> tri_faces; | 
					 | 
					 | 
								std::vector<std::vector<size_t>> tri_faces; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
								// 从给定的网格 mesh 中提取顶点和面信息。
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								get_mesh_vert_faces(mesh, tri_verts, tri_faces); | 
					 | 
					 | 
								get_mesh_vert_faces(mesh, tri_verts, tri_faces); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
								// 将提取的顶点和面信息转换为 Eigen 库的矩阵格式。
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								Eigen::MatrixXd input_pts(tri_verts.size(), 3); | 
					 | 
					 | 
								Eigen::MatrixXd input_pts(tri_verts.size(), 3); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								Eigen::MatrixXi input_faces(tri_faces.size(), 3); | 
					 | 
					 | 
								Eigen::MatrixXi input_faces(tri_faces.size(), 3); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
								// 将顶点信息从 tri_verts 复制到 input_pts。
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								for (size_t i = 0; i < tri_verts.size(); i++) | 
					 | 
					 | 
								for (size_t i = 0; i < tri_verts.size(); i++) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								{ | 
					 | 
					 | 
								{ | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
									for (size_t j = 0; j < 3; j++) | 
					 | 
					 | 
									for (size_t j = 0; j < 3; j++) | 
				
			
			
		
	
	
		
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
					@ -310,6 +298,7 @@ void generate_feature_sample(Mesh3d& mesh, std::string outputfile) | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								std::vector<vec3d> closest; | 
					 | 
					 | 
								std::vector<vec3d> closest; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								std::vector<double> dist; | 
					 | 
					 | 
								std::vector<double> dist; | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					 | 
					 | 
					 | 
								// 计算样本点与输入网格之间的最短距离。
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
								compute_shortest_dist_AABB(input_pts, input_faces, sample_pts, closest, dist, sample_pts_tris); | 
					 | 
					 | 
								compute_shortest_dist_AABB(input_pts, input_faces, sample_pts, closest, dist, sample_pts_tris); | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
					
 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					 | 
					 | 
							} | 
					 | 
					 | 
							} | 
				
			
			
		
	
	
		
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
					
  |