You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

438 lines
15 KiB

//#include "mex.hpp"
//#include "mexAdapter.hpp"
//#include "MatlabDataArray.hpp"
//
//#include <iostream>
//#include <cstdint>
//#include <fstream>
//
//#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
//#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
//
//#include <CGAL/Delaunay_triangulation_3.h>
//#include <CGAL/Delaunay_triangulation_cell_base_3.h>
//#include <CGAL/Triangulation_vertex_base_with_info_3.h>
//
//#include <CGAL/Surface_mesh.h>
//#include <CGAL/convex_hull_3.h>
//
//#include <CGAL/Polygon_mesh_processing/corefinement.h>
////#include <CGAL/Polygon_mesh_processing/remesh.h>
////#include <CGAL/Polygon_mesh_processing/border.h>
//
//typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
//typedef CGAL::Exact_predicates_exact_constructions_kernel EK;
//
//typedef CGAL::Triangulation_vertex_base_with_info_3<CGAL::IO::Color, K> Vb;
//typedef CGAL::Delaunay_triangulation_cell_base_3<K> Cb;
//typedef CGAL::Triangulation_data_structure_3<Vb, Cb> Tds;
//typedef CGAL::Delaunay_triangulation_3<K, Tds> DT;
//
//typedef K::Point_3 Point;
//typedef K::Segment_3 Segment;
//typedef K::Ray_3 Ray;
//typedef K::Vector_3 Vector;
//typedef std::pair<EK::Vector_3, EK::Vector_3> Vector_pair;
//
//typedef CGAL::Surface_mesh<Point> Surface_mesh;
//typedef Surface_mesh::Edge_index Edge_index;
//typedef boost::graph_traits<Surface_mesh>::vertex_descriptor vertex_descriptor;
//typedef boost::graph_traits<Surface_mesh>::edge_descriptor edge_descriptor;
//
//typedef Surface_mesh::Property_map<vertex_descriptor, EK::Point_3> Exact_point_map;
//
//#ifdef CGAL_CONCURRENT_MESH_3
//typedef CGAL::Parallel_tag Concurrency_tag;
//#else
//typedef CGAL::Sequential_tag Concurrency_tag;
//#endif
//
//namespace PMP = CGAL::Polygon_mesh_processing;
//namespace params = PMP::parameters;
//namespace cparas = CGAL::parameters;
//
//
//const int RAY_LENGTH = 100;
//const auto ConvertToSeg = [&](const CGAL::Object seg_obj) -> Segment
//{
// //One of these will succeed and one will have a NULL pointer
// const Segment* dseg = CGAL::object_cast<Segment>(&seg_obj);
// const Ray* dray = CGAL::object_cast<Ray>(&seg_obj);
// if (dseg) { //Okay, we have a segment
// return *dseg;
// }
// else { //Must be a ray
// const auto& source = dray->source();
// const auto dsx = source.x();
// const auto dsy = source.y();
// const auto dsz = source.z();
// const auto& dir = dray->direction();
// const auto tpoint = Point(dsx + RAY_LENGTH * dir.dx(),
// dsy + RAY_LENGTH * dir.dy(),
// dsz + RAY_LENGTH * dir.dz());
// return Segment(
// dray->source(),
// tpoint
// );
// }
//};
//
//struct Exact_vertex_point_map
//{
// // typedef for the property map
// typedef boost::property_traits<Exact_point_map>::value_type value_type;
// typedef boost::property_traits<Exact_point_map>::reference reference;
// typedef boost::property_traits<Exact_point_map>::key_type key_type;
// typedef boost::read_write_property_map_tag category;
// // exterior references
// Exact_point_map exact_point_map;
// Surface_mesh* tm_ptr;
// // Converters
// CGAL::Cartesian_converter<K, EK> to_exact;
// CGAL::Cartesian_converter<EK, K> to_input;
// Exact_vertex_point_map()
// : tm_ptr(nullptr)
// {}
// Exact_vertex_point_map(const Exact_point_map& ep, Surface_mesh& tm)
// : exact_point_map(ep)
// , tm_ptr(&tm)
// {
// for (Surface_mesh::Vertex_index v : vertices(tm))
// exact_point_map[v] = to_exact(tm.point(v));
// }
// friend
// reference get(const Exact_vertex_point_map& map, key_type k)
// {
// CGAL_precondition(map.tm_ptr != nullptr);
// return map.exact_point_map[k];
// }
// friend
// void put(const Exact_vertex_point_map& map, key_type k, const EK::Point_3& p)
// {
// CGAL_precondition(map.tm_ptr != nullptr);
// map.exact_point_map[k] = p;
// // create the input point from the exact one
// map.tm_ptr->point(k) = map.to_input(p);
// }
//};
//
//class MexFunction : public matlab::mex::Function {
//public:
// void operator()(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs)
// {
// checkArguments(outputs, inputs);
//
// matlab::data::TypedArray<double> pnts = std::move(inputs[0]);
// matlab::data::TypedArray<int> idx = std::move(inputs[1]);
// double nelx = inputs[2][0];
// double nely = inputs[3][0];
// double nelz = inputs[4][0];
//
// std::vector<Point> bb_pnts, seeds;
// DT dt;
// preparation(nelx, nely, nelz, pnts, bb_pnts, dt, seeds);
//
// matlab::data::ArrayFactory factory;
// matlab::data::CellArray c_edges = factory.createCellArray({ idx.getDimensions()[0], 1 });
// matlab::data::CellArray c_norms = factory.createCellArray({ idx.getDimensions()[0], 1 });
// mexVD(c_edges, c_norms, idx, bb_pnts, seeds, dt);
//
// outputs[0] = c_edges;
// outputs[1] = c_norms;
// }
//
// void preparation(double nelx, double nely, double nelz, matlab::data::TypedArray<double> seeds,
// std::vector<Point> & bb_pnts, DT & dt, std::vector<Point> & points)
// {
// // bounding-box
// double halfx = nelx / 2.;
// double halfy = nely / 2.;
// double halfz = nelz / 2.;
//
// bb_pnts.push_back(Point(-halfx, -halfy, -halfz));
// bb_pnts.push_back(Point(halfx, -halfy, -halfz));
// bb_pnts.push_back(Point(halfx, halfy, -halfz));
// bb_pnts.push_back(Point(-halfx, halfy, -halfz));
// bb_pnts.push_back(Point(-halfx, -halfy, halfz));
// bb_pnts.push_back(Point(halfx, -halfy, halfz));
// bb_pnts.push_back(Point(halfx, halfy, halfz));
// bb_pnts.push_back(Point(-halfx, halfy, halfz));
//
// // seeds & DT
// unsigned int pnts_num = seeds.getDimensions()[0];
// for (int i = 0; i < pnts_num; ++i)
// {
// double x = seeds[i][0];
// double y = seeds[i][1];
// double z = seeds[i][2];
// points.push_back(Point(x, y, z));
// }
// dt = DT(points.begin(), points.end());
// assert(dt.is_valid());
// }
//
// void cur_voronoi_cell(Point p, DT dt, std::vector<Point> & vor_pnts)
// {
// // Starts at an arbitrary facet incident to edge *fei.
// std::vector<DT::Facet> incident_facet;
// DT::Vertex_handle vh = dt.nearest_vertex(p);
// dt.finite_incident_facets(vh, std::back_inserter(incident_facet));
//
// for (size_t j = 0; j < incident_facet.size(); j++)
// {
// DT::Facet fi = incident_facet[j];
// CGAL::Object dualedge = dt.dual(fi);
//
// // either segment or ray
// const auto this_seg = ConvertToSeg(dualedge);
//
// vor_pnts.push_back(this_seg.source());
// vor_pnts.push_back(this_seg.target());
// }
// }
//
// bool point_equal(Point p1, Point p2, double tol)
// {
// return (abs(p1.x() - p2.x()) < tol &&
// abs(p1.y() - p2.y()) < tol &&
// abs(p1.z() - p2.z()) < tol);
// }
//
//
// std::vector<Segment> merge_conlinear(std::vector<Segment> segs,
// std::vector<Vector_pair> incident_fnorms, std::vector<Vector_pair>& newnorms)
// {
// std::vector<Segment> newlines;
//
// while (!segs.empty())
// {
// Segment s1 = segs[0];
// Vector v1(s1);
//
// segs.erase(segs.begin());
//
// Vector_pair f1 = incident_fnorms[0];
// incident_fnorms.erase(incident_fnorms.begin());
//
// int j = 0;
// int len = segs.size();
// bool found = 0;
// while (j < len)
// {
// Segment s2 = segs[j];
// Vector v2(s2);
// Vector v3(s1.point(0), s2.point(0));
//
// //Vector v = CGAL::cross_product(v1, v2);
// //double len = v.squared_length();
//
// if (CGAL::cross_product(v1, v2).squared_length() < 1e-10 &&
// CGAL::cross_product(v3, v2).squared_length() < 1e-10) // colinear or parallel
// {
// for (int ii = 0; ii < 2; ++ii)
// for (int jj = 0; jj < 2; ++jj)
// if (point_equal(s1.point(ii), s2.point(jj), 1e-5) && !found)
// {
// s1 = Segment(s1.point(1 - ii), s2.point(1 - jj));
// found = 1;
//
// segs.erase(segs.begin() + j);
// incident_fnorms.erase(incident_fnorms.begin() + j);
// }
// }
// len = segs.size();
//
// if (found)
// {
// j = 0;
// found = 0;
// }
// else
// j++;
// }
// newlines.push_back(s1);
// newnorms.push_back(f1);
// }
// return newlines;
// }
//
// void mexVD(matlab::data::CellArray& c_edges, matlab::data::CellArray& c_norms,
// matlab::data::TypedArray<int> query_idx,
// std::vector<Point> bb_pnts, std::vector<Point> seeds, DT dt)
// {
// std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
// matlab::data::ArrayFactory factory;
//
// /*
// * step.0 generate bounding box
// */
// Surface_mesh bmesh;
// CGAL::convex_hull_3(bb_pnts.begin(), bb_pnts.end(), bmesh);
// Exact_point_map mesh2_exact_points =
// bmesh.add_property_map<vertex_descriptor, EK::Point_3>("v:exact_point").first;
// Exact_vertex_point_map mesh2_vpm(mesh2_exact_points, bmesh);
//
// /*
// * step.1 get each voronoi-cell
// */
// int npnts = seeds.size();
//
// for (int i = 0; i < query_idx.getDimensions()[0]; ++i)
// {
// int k = query_idx[i] - 1;
// if (k < 0 || k >= npnts) {
// matlabPtr->feval(u"error", 0, std::vector<matlab::data::Array>({
// factory.createScalar("The input idx is out of boundary!") }));
// }
// Point p = seeds[k];
//
// std::vector<Point> vor_pnts; // all points of this voronoi-cell
// cur_voronoi_cell(p, dt, vor_pnts);
//
// /*
// * step.2 intersection with bbx
// */
// Surface_mesh sm; //define polyhedron to hold convex hull
// CGAL::convex_hull_3(vor_pnts.begin(), vor_pnts.end(), sm);
//
// Exact_point_map mesh1_exact_points =
// sm.add_property_map<vertex_descriptor, EK::Point_3>("v:exact_point").first;
// Exact_vertex_point_map mesh1_vpm(mesh1_exact_points, sm);
//
// bool flag = PMP::corefine_and_compute_intersection( sm,
// bmesh,
// sm,
// params::vertex_point_map(mesh1_vpm),
// params::vertex_point_map(mesh2_vpm),
// params::vertex_point_map(mesh1_vpm));
// if (!flag) {
// matlabPtr->feval(u"error", 0, std::vector<matlab::data::Array>({
// factory.createScalar("None intersection for cell-"+std::to_string(k+1)) }));
// }
//
// /*
// * step.3 get segments of each voronoi cell
// */
// std::vector<Segment> feature_lines; // to preserve
// std::vector<Vector_pair> incident_fnorms;
//
// auto fnormals = sm.add_property_map<Surface_mesh::Face_index, EK::Vector_3>("f:normals",
// CGAL::NULL_VECTOR).first;
// PMP::compute_face_normals(sm, fnormals, params::vertex_point_map(mesh1_vpm));
//
// for (Edge_index ei : sm.edges())
// {
// Surface_mesh::Halfedge_index h1 = sm.halfedge(ei, 0);
// Surface_mesh::Halfedge_index h2 = sm.halfedge(ei, 1);
//
// Surface_mesh::Vertex_index v0 = sm.source(h1);
// Surface_mesh::Vertex_index v1 = sm.source(h2);
// Point p1 = sm.point(v0);
// Point p2 = sm.point(v1);
//
// // skip if this segs is too short
// if (point_equal(p1, p2, 1e-5))
// continue;
//
// Surface_mesh::Face_index f1 = face(h1, sm);
// Surface_mesh::Face_index f2 = face(h2, sm);
// EK::Vector_3 n1 = fnormals[f1];
// EK::Vector_3 n2 = fnormals[f2];
//
// if (n1.squared_length() < 1e-10 || n2.squared_length() < 1e-10) {
// matlabPtr->feval(u"error", 0, std::vector<matlab::data::Array>({
// factory.createScalar("The face norm may be (0,0,0) for cell-" +
// std::to_string(k + 1)) }));
// }
// double ang = CGAL::to_double(CGAL::approximate_angle(n1, n2));
//
// if (abs(ang) > 1e-5 && abs(abs(ang) - 180) > 1e-5)
// {
// feature_lines.push_back(Segment(p1, p2));
//
// std::pair<EK::Vector_3, EK::Vector_3> fn;
// fn.first = n1;
// fn.second = n2;
// incident_fnorms.push_back(fn);
// }
// }
// std::vector<Vector_pair> final_fnorms;
// std::vector<Segment> final_lines = merge_conlinear(feature_lines,
// incident_fnorms, final_fnorms);
// //std::vector<Segment> final_lines = feature_lines;
//
// /*
// * step.4 change to matlab version
// */
// matlab::data::TypedArray<double> linesMat = factory.createArray<double>({ final_lines.size(), 6 });
// matlab::data::TypedArray<double> fnormMat = factory.createArray<double>({ final_lines.size(), 6 });
// for (int j = 0; j < final_lines.size(); ++j)
// {
// linesMat[j][0] = final_lines[j].point(0).x();
// linesMat[j][1] = final_lines[j].point(0).y();
// linesMat[j][2] = final_lines[j].point(0).z();
// linesMat[j][3] = final_lines[j].point(1).x();
// linesMat[j][4] = final_lines[j].point(1).y();
// linesMat[j][5] = final_lines[j].point(1).z();
//
// fnormMat[j][0] = CGAL::to_double(final_fnorms[j].first.x());
// fnormMat[j][1] = CGAL::to_double(final_fnorms[j].first.y());
// fnormMat[j][2] = CGAL::to_double(final_fnorms[j].first.z());
// fnormMat[j][3] = CGAL::to_double(final_fnorms[j].second.x());
// fnormMat[j][4] = CGAL::to_double(final_fnorms[j].second.y());
// fnormMat[j][5] = CGAL::to_double(final_fnorms[j].second.z());
// }
// c_edges[i] = linesMat;
// c_norms[i] = fnormMat;
// }
//
// }
//
// void checkArguments(matlab::mex::ArgumentList outputs, matlab::mex::ArgumentList inputs) {
// std::shared_ptr<matlab::engine::MATLABEngine> matlabPtr = getEngine();
// matlab::data::ArrayFactory factory;
//
// if (inputs.size() != 5) {
// matlabPtr->feval(u"error",
// 0, std::vector<matlab::data::Array>({ factory.createScalar("Four inputs required") }));
// }
//
// if (inputs[0].getDimensions()[1] != 3) {
// matlabPtr->feval(u"error", 0, std::vector<matlab::data::Array>({
// factory.createScalar("Seeds input 1 must be NX3 dimension") }));
// }
//
// if (inputs[0].getType() != matlab::data::ArrayType::DOUBLE ||
// inputs[0].getType() == matlab::data::ArrayType::COMPLEX_DOUBLE) {
// matlabPtr->feval(u"error", 0, std::vector<matlab::data::Array>({
// factory.createScalar("Seeds Input 1 must be a noncomplex scalar double") }));
// }
//
// if (inputs[1].getType() != matlab::data::ArrayType::INT32) {
// matlabPtr->feval(u"error", 0, std::vector<matlab::data::Array>({
// factory.createScalar("Index Input 2 must be type INT32") }));
// }
//
// if (inputs[1].getDimensions()[1] != 1) {
// matlabPtr->feval(u"error", 0, std::vector<matlab::data::Array>({
// factory.createScalar("Index Input 2 must be NX1 dimension") }));
// }
//
// for (int j = 2; j < 5; ++j)
// {
// if (inputs[j].getDimensions()[0] != 1 || inputs[j].getDimensions()[1] != 1) {
// matlabPtr->feval(u"error", 0, std::vector<matlab::data::Array>({
// factory.createScalar("nelx/nely/nelz input 3/4/5 must be a scalar") }));
// }
// if (inputs[j].getType() != matlab::data::ArrayType::DOUBLE ||
// inputs[j].getType() == matlab::data::ArrayType::COMPLEX_DOUBLE) {
// matlabPtr->feval(u"error", 0, std::vector<matlab::data::Array>({
// factory.createScalar("nelx/nely/nelz input 3/4/5 must be a noncomplex scalar double") }));
// }
// }
// if (outputs.size() > 2) {
// matlabPtr->feval(u"error", 0, std::vector<matlab::data::Array>({
// factory.createScalar("Only two output is returned") }));
// }
// }
//};