From b973334a27cfea06128da9bac1909e162182877e Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Thu, 28 May 2015 11:41:21 +0200 Subject: [PATCH 01/20] Fix trailer error: Stop condition: x x_half; x_full.push_back(0.); - for (real x=avg_edge_length; x Date: Thu, 28 May 2015 11:44:13 +0200 Subject: [PATCH 02/20] delete trash code --- src/trializer.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/trializer.cpp b/src/trializer.cpp index 20717c4..7caf6a5 100644 --- a/src/trializer.cpp +++ b/src/trializer.cpp @@ -39,8 +39,6 @@ namespace DSC2D { } x_half.push_back(width+avg_edge_length); x_half.push_back(width+2*avg_edge_length); - int idx = 0; - for (int k = 0; k Date: Wed, 17 Jun 2015 16:56:00 +0200 Subject: [PATCH 03/20] Add Iterative for loop for DSC --- .../xcshareddata/DSC.xccheckout | 16 ++++++++-------- src/DSC.h | 10 ++++++++++ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout b/DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout index 8d162f9..d3fa876 100644 --- a/DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout +++ b/DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout @@ -10,29 +10,29 @@ DSC IDESourceControlProjectOriginsDictionary - 729B663A-C65E-4FE1-83C0-A42968F5E064 - https://github.com/asny/2D-DSC.git + F29B5E51A5B97DCCD0EC2FAF945213024A5D39C4 + https://github.com/tuannt8/2D-DSC.git IDESourceControlProjectPath - DSC.xcodeproj/project.xcworkspace + DSC.xcodeproj IDESourceControlProjectRelativeInstallPathDictionary - 729B663A-C65E-4FE1-83C0-A42968F5E064 + F29B5E51A5B97DCCD0EC2FAF945213024A5D39C4 ../.. IDESourceControlProjectURL - https://github.com/asny/2D-DSC.git + https://github.com/tuannt8/2D-DSC.git IDESourceControlProjectVersion - 110 + 111 IDESourceControlProjectWCCIdentifier - 729B663A-C65E-4FE1-83C0-A42968F5E064 + F29B5E51A5B97DCCD0EC2FAF945213024A5D39C4 IDESourceControlProjectWCConfigurations IDESourceControlRepositoryExtensionIdentifierKey public.vcs.git IDESourceControlWCCIdentifierKey - 729B663A-C65E-4FE1-83C0-A42968F5E064 + F29B5E51A5B97DCCD0EC2FAF945213024A5D39C4 IDESourceControlWCCName 2D-DSC diff --git a/src/DSC.h b/src/DSC.h index 0dbe807..3240f0d 100644 --- a/src/DSC.h +++ b/src/DSC.h @@ -335,6 +335,16 @@ namespace DSC2D { //************** ITERATORS *************** public: + HMesh::IDIteratorPair vertices() const { + return mesh->vertices(); + } + HMesh::IDIteratorPair faces() const { + return mesh->faces(); + } + HMesh::IDIteratorPair halfedges() const { + return mesh->halfedges(); + } + HMesh::VertexIDIterator vertices_begin() const { return mesh->vertices_begin(); From 83d8fed51b34c5be1d03e5b917e08ac1aa7f9834 Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Wed, 23 May 2018 16:22:05 +0200 Subject: [PATCH 04/20] Add CMakeList --- CMakeLists.txt | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..739aed2 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,20 @@ +project(2D-DSC) + + +if (APPLE) + # TODO for Mac +endif (APPLE) + +if (UNIX) + # TODO for UNix +endif (UNIX) +if(WIN32) + # TODO for Windows +endif() + + +aux_source_directory(./src SRC) + +include_directories(../GEL/src/GEL) + +add_library(2D-DSC SHARED ${SRC}) \ No newline at end of file From 72ed6f01968ec755306c3e6fee63ed85c270bf3e Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Fri, 25 May 2018 11:46:01 +0200 Subject: [PATCH 05/20] CMake project for DSC lib --- CMakeLists.txt | 7 +- src/DSC.cpp | 744 +++++++++++++++++++++++++++++++++++++--- src/DSC.h | 243 +++++++++++-- src/design_domain.h | 3 + src/object_generator.h | 8 + src/trializer.cpp | 6 +- src/velocity_function.h | 3 +- 7 files changed, 944 insertions(+), 70 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 739aed2..1da58c5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ +cmake_minimum_required(VERSION 3.6) project(2D-DSC) +set(CMAKE_CXX_STANDARD 14) if (APPLE) # TODO for Mac @@ -17,4 +19,7 @@ aux_source_directory(./src SRC) include_directories(../GEL/src/GEL) -add_library(2D-DSC SHARED ${SRC}) \ No newline at end of file +link_directories(../GEL) + +add_library(2D-DSC SHARED ${SRC}) +target_link_libraries(2D-DSC GEL) \ No newline at end of file diff --git a/src/DSC.cpp b/src/DSC.cpp index 30ccb7e..cee954c 100644 --- a/src/DSC.cpp +++ b/src/DSC.cpp @@ -15,10 +15,37 @@ // See licence.txt for a copy of the GNU General Public License. #include "DSC.h" -#include "draw.h" + +#ifdef TUAN_MULTI_RES +#include "image.h" +#endif + +#include +#include + +#define TETRA_PAK + namespace DSC2D -{ +{ + const DSC2D::vec3 BACKGROUND_COLOR = DSC2D::vec3(0.7); // DSC2D::vec3(1.0); + const DSC2D::vec3 INVISIBLE = DSC2D::vec3(-1.); + const DSC2D::vec3 DARK_RED = DSC2D::vec3(0.66,0.11,0.15); + const DSC2D::vec3 RED = DSC2D::vec3(0.96,0.11,0.15); + const DSC2D::vec3 DARK_BLUE = DSC2D::vec3(0.14,0.16,0.88); + const DSC2D::vec3 BLUE = DSC2D::vec3(0.45,0.7,0.9); + const DSC2D::vec3 GREEN = DSC2D::vec3(0.05,1.,0.15); + const DSC2D::vec3 ORANGE = DSC2D::vec3(0.9,0.4,0.); + const DSC2D::vec3 BLACK = DSC2D::vec3(0.); + const DSC2D::vec3 DARK_GRAY = DSC2D::vec3(0.5); + const DSC2D::vec3 GRAY = DSC2D::vec3(0.8); + + typedef DSC2D::DeformableSimplicialComplex dsc_obj; + typedef dsc_obj::node_key Node_key; + typedef dsc_obj::face_key Face_key; + typedef dsc_obj::edge_key Edge_key; + typedef std::vector Vec2_array; + DeformableSimplicialComplex::DeformableSimplicialComplex(real AVG_EDGE_LENGTH, const std::vector& points, const std::vector& faces, DesignDomain *domain): design_domain(domain) { set_avg_edge_length(AVG_EDGE_LENGTH); @@ -26,17 +53,29 @@ namespace DSC2D COS_MIN_ANGLE = cos(MIN_ANGLE); DEG_ANGLE = 0.2*MIN_ANGLE; +#ifdef TETRA_PAK MAX_LENGTH = 2.; - MIN_LENGTH = 0.5; + MIN_LENGTH = 0.5;// 0.01;// 0.05 // 0.5; DEG_LENGTH = 0.2*MIN_LENGTH; MAX_AREA = 5.; - MIN_AREA = 0.2; + MIN_AREA = 0.2; //0.001;//0.01;// 0.2; + DEG_AREA = 0.2*MIN_AREA; +#else + MAX_LENGTH = 2.; + MIN_LENGTH = 0.5;// 0.01;// 0.05 // 0.5; + DEG_LENGTH = 0.2*MIN_LENGTH; + + MAX_AREA = 5.; + MIN_AREA = 0.2; //0.001;//0.01;// 0.2; + + DEG_AREA = 0.2*MIN_AREA; +#endif INTERFACE_COLOR = DARK_RED; CROSSING_COLOR = RED; - OUTSIDE_COLOR = BLACK; + OUTSIDE_COLOR = ORANGE; DEFAULT_COLOR = DARK_BLUE; OUTSIDE_FACE_COLOR = INVISIBLE; DEFAULT_FACE_COLOR = BLUE; @@ -47,15 +86,38 @@ namespace DSC2D vertex_labels = HMesh::VertexAttributeVector(get_no_vertices(), OUTSIDE); edge_labels = HMesh::HalfEdgeAttributeVector(get_no_halfedges(), OUTSIDE); face_labels = HMesh::FaceAttributeVector(get_no_faces(), OUTSIDE); + face_att = HMesh::FaceAttributeVector>(get_no_faces(), + std::vector(NB_FORCES, Vec2(0.))); + internal_node_forces = HMesh::VertexAttributeVector(get_no_vertices(), + vec2(0.0f)); + external_node_forces = HMesh::VertexAttributeVector(get_no_vertices(), + vec2(0.0f)); + bStable = HMesh::VertexAttributeVector(get_no_vertices(), 1); + + dts = HMesh::VertexAttributeVector(get_no_vertices(), 0.0); + node_att_i = HMesh::VertexAttributeVector>(get_no_vertices(), + std::vector(NB_FORCES, 0) ); + + edge_att_i = HMesh::HalfEdgeAttributeVector>(get_no_halfedges(), + std::vector(NB_FORCES, 0)); } void DeformableSimplicialComplex::cleanup_attributes(HMesh::IDRemap& cleanup_map) { mesh->cleanup(cleanup_map); vertex_labels.cleanup(cleanup_map.vmap); + + // edge_att_i.cleanup(cleanup_map.hmap); edge_labels.cleanup(cleanup_map.hmap); face_labels.cleanup(cleanup_map.fmap); +// face_att.cleanup(cleanup_map.fmap); destination.cleanup(cleanup_map.vmap); + internal_node_forces.cleanup(cleanup_map.vmap); + external_node_forces.cleanup(cleanup_map.vmap); + bStable.cleanup(cleanup_map.vmap); + dts.cleanup(cleanup_map.vmap); + + // node_att_i.cleanup(cleanup_map.vmap); } @@ -65,7 +127,7 @@ namespace DSC2D for(auto vi = vertices_begin(); vi != vertices_end(); ++vi) { switch (vertex_labels[*vi]) { - case INTERFACE: + case INTERFACE_DSC: colors[*vi] = INTERFACE_COLOR; break; case CROSSING: @@ -88,7 +150,7 @@ namespace DSC2D for(auto hei = halfedges_begin(); hei != halfedges_end(); ++hei) { switch (edge_labels[*hei]) { - case INTERFACE: + case INTERFACE_DSC: colors[*hei] = INTERFACE_COLOR; break; case OUTSIDE: @@ -153,8 +215,19 @@ namespace DSC2D void DeformableSimplicialComplex::resize_complex() { +#ifdef TUAN_SEG thickening_interface(); + // thinning_interface(); + + thickening(); + + thinning(); + + fix_complex(); +#else + thickening_interface(); + thinning_interface(); thickening(); @@ -162,6 +235,7 @@ namespace DSC2D thinning(); fix_complex(); +#endif /* TUAN_SEG */ } real DeformableSimplicialComplex::intersection_with_link(const node_key& vid, vec2 destination) const @@ -178,9 +252,9 @@ namespace DSC2D min_t = Util::min(t, min_t); } } -#ifdef DEBUG - assert(min_t < INFINITY); -#endif +//#ifdef DEBUG +// assert(min_t < INFINITY); +//#endif return min_t; } @@ -195,14 +269,29 @@ namespace DSC2D } real max_l = l*intersection_with_link(vid, destination) - 1e-4 * AVG_LENGTH; - l = Util::max(Util::min(0.5*max_l, l), 0.); - set_pos(vid, pos + l*Util::normalize(destination - pos)); - if(Util::length(destination - get_pos(vid)) < 1e-4 * AVG_LENGTH) + if (max_l < INFINITY) { - return true; + l = Util::max(Util::min(0.5*max_l, l), 0.); + set_pos(vid, pos + l*Util::normalize(destination - pos)); + + if(Util::length(destination - get_pos(vid)) < 1e-4 * AVG_LENGTH) + { + return true; + } + return false; } - return false; + else + { + return false; + } + + } + + DeformableSimplicialComplex * DeformableSimplicialComplex::clone(){ + DeformableSimplicialComplex * new_dsc = new DeformableSimplicialComplex; + + return new_dsc; } void DeformableSimplicialComplex::deform() @@ -235,8 +324,9 @@ namespace DSC2D bool DeformableSimplicialComplex::is_movable(node_key vid) const { + return !boundary(*mesh, vid) && (is_interface(vid) || is_crossing(vid)); //return unsafe_editable(vid) && is_interface(vid); - return unsafe_editable(vid) && (is_interface(vid) || is_crossing(vid)); + //return unsafe_editable(vid) && (is_interface(vid) || is_crossing(vid)); } bool DeformableSimplicialComplex::is_movable(edge_key eid) const @@ -264,6 +354,51 @@ namespace DSC2D return unsafe_editable(eid) && !is_interface(eid); } + bool DeformableSimplicialComplex::save(const char * filePath) + { + std::ofstream myfile(filePath); + if (myfile.is_open()) { + myfile << get_no_vertices() << " " << get_no_faces() << "\n"; + + // Write vertices + std::map index_map; + int idx = 0; + for (auto vkey : vertices()) + { + index_map.insert(std::make_pair(vkey.get_index(), idx++)); + auto p = get_pos(vkey); + myfile << p[0] << " " << p[1] << "\n"; + } + + // write face + for (auto fkey : faces()) + { + auto verts = get_verts(fkey); + myfile << index_map[(int)verts[0].get_index()] << " " + << index_map[(int)verts[1].get_index()] << " " + << index_map[(int)verts[2].get_index()] << " " + << get_label(fkey) << "\n"; + } + + myfile.close(); + return true; + }else{ + return false; + } + } + + bool DeformableSimplicialComplex::load(char * filePath) + { + std::ifstream myfile(filePath); + if (myfile.is_open()) { + + myfile.close(); + return true; + }else{ + return false; + } + } + real DeformableSimplicialComplex::max_move_distance() const { real dist, max_dist = 0.; @@ -316,6 +451,16 @@ namespace DSC2D return vec2(mesh->pos(vid)[0], mesh->pos(vid)[1]); } + std::vector DeformableSimplicialComplex::get_pos(edge_key eid) const + { + std::vector positions; + + auto hew = walker(eid); + positions.push_back(get_pos(hew.opp().vertex())); + positions.push_back(get_pos(hew.vertex())); + return positions; + } + std::vector DeformableSimplicialComplex::get_pos(face_key fid) const { std::vector positions; @@ -341,12 +486,12 @@ namespace DSC2D return positions; } - std::vector DeformableSimplicialComplex::get_verts(node_key vid, bool interface) const + std::vector DeformableSimplicialComplex::get_verts(node_key vid, bool _interface) const { std::vector vids; for (auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) { - if(!interface || is_interface(hew.halfedge())) + if(!_interface || is_interface(hew.halfedge())) { vids.push_back(hew.vertex()); } @@ -421,13 +566,19 @@ namespace DSC2D for(auto vi = vertices_begin(); vi != vertices_end(); ++vi) { - init_attributes(*vi); + init_attributes(*vi, true); } } - void DeformableSimplicialComplex::init_attributes(node_key vid) + void DeformableSimplicialComplex::init_attributes(node_key vid, bool keep) { destination[vid] = get_pos(vid); + internal_node_forces[vid] = vec2(0.0); + external_node_forces[vid] = vec2(0.0); + + + bStable[vid] = 1; + } void DeformableSimplicialComplex::init_attributes(face_key fid, int label) @@ -438,6 +589,13 @@ namespace DSC2D } } + void DeformableSimplicialComplex::set_default_dt(double dt_) + { + default_dt = dt_; + for (auto nkey : vertices()) { + dts[nkey] = default_dt; + } + } void DeformableSimplicialComplex::update_attributes(node_key vid, int label) { @@ -461,7 +619,7 @@ namespace DSC2D } else if(inter > 0) { - vertex_labels[vid] = INTERFACE; + vertex_labels[vid] = INTERFACE_DSC; } else if(!boundary(*mesh, vid)) { @@ -492,8 +650,8 @@ namespace DSC2D if (fa1 != fa2) { - edge_labels[heid] = INTERFACE; - edge_labels[hew.opp().halfedge()] = INTERFACE; + edge_labels[heid] = INTERFACE_DSC; + edge_labels[hew.opp().halfedge()] = INTERFACE_DSC; } else { @@ -538,9 +696,9 @@ namespace DSC2D } } - - bool DeformableSimplicialComplex::split(edge_key eid) + bool DeformableSimplicialComplex::split_adpat_mesh(edge_key eid) { + if (!unsafe_editable(eid)) { return false; } @@ -551,6 +709,15 @@ namespace DSC2D face_key f2 = hew.opp().face(); node_key v2 = hew.opp().next().vertex(); + auto l1 = get_label(f1); + auto l2 = get_label(f2); + + if (!mesh->in_use(f1) or !mesh->in_use(f2) + or !mesh->in_use(v1) or !mesh->in_use(v2)) + { + return false; + } + // Split node_key vid = mesh->split_edge(eid); face_key newf1 = mesh->split_face_by_edge(f1, vid, v1); @@ -565,30 +732,89 @@ namespace DSC2D init_attributes(hew.halfedge()); } } - init_attributes(newf1, get_label(f1)); - init_attributes(newf2, get_label(f2)); + init_attributes(newf1, l1); + init_attributes(newf2, l2); + update_locally(vid); + + // add stablity check + bStable[vid] = 0; + return true; } - bool DeformableSimplicialComplex::split(face_key fid) + bool DeformableSimplicialComplex::split(edge_key eid) { - int fa = get_label(fid); - node_key vid = mesh->split_face_by_vertex(fid); - init_attributes(vid); + if (!unsafe_editable(eid)) { + return false; + } + + auto hew = walker(eid); + face_key f1 = hew.face(); + node_key v1 = hew.next().vertex(); + face_key f2 = hew.opp().face(); + node_key v2 = hew.opp().next().vertex(); + + // Split + node_key vid = mesh->split_edge(eid); + face_key newf1 = mesh->split_face_by_edge(f1, vid, v1); + face_key newf2 = mesh->split_face_by_edge(f2, vid, v2); + // Update attributes + init_attributes(vid); for(auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) { - init_attributes(hew.halfedge()); - init_attributes(hew.face(), fa); + if(hew.halfedge() != eid && hew.opp().halfedge() != eid) + { + init_attributes(hew.halfedge()); + } } + init_attributes(newf1, get_label(f1)); + init_attributes(newf2, get_label(f2)); update_locally(vid); + return true; } + bool DeformableSimplicialComplex::split(face_key fid) + { +// bool success = split(sorted_face_edges(fid).back()); +// return success; + // check quality + + /* + TUAN: if the triangle is obtuse, split long edge + */ + auto hew = walker(fid); + if (max_angle(fid, hew) > 120*M_PI / 180.) + { + return split(sorted_face_edges(fid).back()); + } + else + //-- + { + + int fa = get_label(fid); + node_key vid = mesh->split_face_by_vertex(fid); + + init_attributes(vid); + + + for(auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) + { + init_attributes(hew.halfedge()); + init_attributes(hew.face(), fa); + } + + update_locally(vid); + + return true; + } + } + real DeformableSimplicialComplex::min_quality(const std::vector& eids, const vec2& pos_old, const vec2& pos_new) { real min_q = INFINITY; @@ -613,6 +839,15 @@ namespace DSC2D { return true; } + /*TUAN add: Do not move crossing vertex, even one of the iinterface is straight*/ + else + { + if (is_crossing(hew.opp().vertex())) + { + return false; + } + } + // end } else { if(unsafe_editable(hew.opp().vertex())) @@ -620,6 +855,7 @@ namespace DSC2D return true; } } + if(is_interface(hew.halfedge())) { vec2 p0 = get_pos(hew.opp().vertex()); @@ -716,6 +952,7 @@ namespace DSC2D bool DeformableSimplicialComplex::collapse(HMesh::Walker hew, real weight) { + node_key vid = hew.vertex(); vec2 p = (1.-weight) * get_pos(hew.vertex()) + weight * get_pos(hew.opp().vertex()); vec2 d = (1.-weight) * get_destination(hew.vertex()) + weight * get_destination(hew.opp().vertex()); @@ -776,9 +1013,57 @@ namespace DSC2D return Util::min(Util::min(Util::length(p[0] - p[1]), Util::length(p[1] - p[2])), Util::length(p[0] - p[2])); } + real DeformableSimplicialComplex::max_angle(face_key fid, HMesh::Walker &hmax) + { + double min_cos = INFINITY; + + for (auto hew = walker(fid); !hew.full_circle(); hew = hew.circulate_face_ccw()) + { + auto p = get_pos(hew.next().vertex()); + auto p1 = get_pos(hew.vertex()); + auto p2 = get_pos(hew.opp().vertex()); + + double cos_a = Util::cos_angle(p1, p, p2); + if (cos_a < min_cos) + { + min_cos = cos_a; + hmax = hew; + } + } + + return acos(min_cos); + } + + HMesh::Walker DeformableSimplicialComplex::max_angle_point(face_key fid) + { + HMesh::Walker h_max = walker(fid); + double min_cos = INFINITY; + + for (auto hew = walker(fid); !hew.full_circle(); hew = hew.circulate_face_ccw()) + { + auto p = get_pos(hew.vertex()); + auto p1 = get_pos(hew.next().vertex()); + auto p2 = get_pos(hew.next().next().vertex()); + + double cos_a = Util::cos_angle(p1, p, p2); + if (cos_a < min_cos) + { + min_cos = cos_a; + h_max = hew; + } + } + + return h_max; + } + real DeformableSimplicialComplex::min_angle(face_key fid) { std::vector p = get_pos(fid); + if (p.size() != 3) + { + throw std::invalid_argument("Get tri vertex error"); + return 0; + } return Util::min_angle(p[0], p[1], p[2]); } @@ -802,7 +1087,6 @@ namespace DSC2D #ifdef DEBUG if (split(f)) { - std::cout << "Split needle" << std::endl; } #else split(f); @@ -831,10 +1115,108 @@ namespace DSC2D { if(mesh->in_use(*fi)) { + /* Tuan + In case of obtuse triangle, collapse edge is not enough. + We need merge the triangles + See: https://goo.gl/oMxXcX The degenerated triangle should be handle by adding point + to the long edge + */ + + bool modified = false; + + HMesh::Walker hew = walker(*fi); + if(max_angle(*fi, hew) > M_PI * 165. / 180.) + { + { +// auto midpoint = (get_pos(hew.vertex()) + get_pos(hew.opp().vertex()))/2; +// auto pp = get_pos(hew.next().vertex()); +// if ((midpoint-pp).length() > MIN_LENGTH*AVG_LENGTH) +// { +// try +// { +// if(mesh->in_use(*fi) && ( +// (min_angle(*fi) < DEG_ANGLE || area(*fi) < DEG_AREA*AVG_AREA) && !collapse(*fi, true)) +// ) +// { +// collapse(*fi, false); +// } +// } +// catch (std::exception & e) +// { +// cout << e.what(); +// } +// +// continue; +// } + } + if (!unsafe_editable(hew.halfedge())) { + continue; + } + + modified = true; + + // add point to edge + face_key f1 = hew.face(); + node_key v1 = hew.next().vertex(); + face_key f2 = hew.opp().face(); + node_key v2 = hew.opp().next().vertex(); + + + // Split + node_key vid = mesh->split_edge(hew.halfedge()); + face_key newf1 = mesh->split_face_by_edge(f1, vid, v1); + face_key newf2 = mesh->split_face_by_edge(f2, vid, v2); + + // Update attributes + auto eid = hew.halfedge(); + init_attributes(vid); + for(auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) + { + if(hew.halfedge() != eid && hew.opp().halfedge() != eid) + { + init_attributes(hew.halfedge()); + } + } + init_attributes(newf1, get_label(f1)); + init_attributes(newf2, get_label(f2)); + + update_locally(vid); + + // merge vid and v1 + set_pos(vid, get_pos(v1)); + auto hw = walker(v1); + for (; !hw.full_circle(); hw = hw.circulate_vertex_ccw()) + { + if (hw.vertex() == vid) + { + break; + } + } + mesh->collapse_edge(hw.halfedge()); + update_locally(hw.vertex()); + } + else + { + try + { + if(mesh->in_use(*fi) && ( + (min_angle(*fi) < DEG_ANGLE || area(*fi) < DEG_AREA*AVG_AREA) && !collapse(*fi, true)) + ) + { + collapse(*fi, false); + } + } + catch (std::exception & e) + { + std::cout << e.what(); + } + } + /** Old code if((min_angle(*fi) < DEG_ANGLE || area(*fi) < DEG_AREA*AVG_AREA) && !collapse(*fi, true)) { collapse(*fi, false); } + */ } } } @@ -876,9 +1258,9 @@ namespace DSC2D } } - vec2 DeformableSimplicialComplex::get_barycenter(node_key vid, bool interface) const + vec2 DeformableSimplicialComplex::get_barycenter(node_key vid, bool _interface) const { - if(interface && !is_interface(vid)) + if(_interface && !is_interface(vid)) { return get_pos(vid); } @@ -888,7 +1270,7 @@ namespace DSC2D for (auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) { - if(is_interface(hew.halfedge()) || !interface) + if(is_interface(hew.halfedge()) || !_interface) { avg_pos += get_pos(hew.vertex()); n++; @@ -1103,7 +1485,10 @@ namespace DSC2D for (auto e : edges) { auto hew = walker(e); - if(length(e) > MAX_LENGTH*AVG_LENGTH || is_crossing(hew.vertex()) || is_crossing(hew.opp().vertex())) + if(length(e) > MAX_LENGTH*AVG_LENGTH + // || is_crossing(hew.vertex()) + // || is_crossing(hew.opp().vertex()) + ) { bool success = split(e); #ifdef DEBUG @@ -1183,6 +1568,8 @@ namespace DSC2D for(auto fi = faces_begin(); fi != faces_end(); fi++) { + + if(mesh->in_use(*fi) && area(*fi) < MIN_AREA*AVG_AREA) { bool success = collapse(*fi, true); @@ -1262,5 +1649,284 @@ namespace DSC2D HMesh::MinAngleEnergy energy_fun(MIN_ANGLE); priority_queue_optimization(energy_fun); } + + void DeformableSimplicialComplex::split_edge(DeformableSimplicialComplex::edge_key ek) { + split(ek); + } + + void DeformableSimplicialComplex::remove_degenerate_needle2(Face_key fkey) + { + + auto edges = sorted_face_edges(fkey); + int l = get_label(fkey); + + { + + } + + return; + + { + auto hew1 = walker(edges[2]); + auto hew2 = walker(edges[1]); + face_key f_out1 = hew1.opp().face(); + face_key f_out2 = hew2.opp().face(); + node_key n_out1 = hew1.opp().next().vertex(); + node_key n_out2 = hew2.opp().next().vertex(); + + if (!mesh->in_use(f_out1) or !mesh->in_use(f_out2) + or !mesh->in_use(n_out1) or !mesh->in_use(n_out2)) + { + return; + } + + // Split the two edges + node_key n1 = mesh->split_edge(hew1.halfedge()); + node_key n2 = mesh->split_edge(hew2.halfedge()); + // Split the faces + face_key new_f1 = mesh->split_face_by_edge(f_out1, n_out1, n1); + face_key new_f2 = mesh->split_face_by_edge(f_out2, n_out2, n2); + face_key new_f_in = mesh->split_face_by_edge(fkey, n1, n2); + + // collapse edge n1-n2 + auto hem = walker(n1); + for (; !hem.full_circle(); hem = hem.circulate_vertex_ccw()) + { + if (hem.vertex() == n2) + { + break; + } + } + mesh->collapse_edge(hem.halfedge(), true); + + // Update attribute + init_attributes(n2); + for(auto hew = walker(n2); !hew.full_circle(); hew = hew.circulate_vertex_cw()) + { + //if(hew.halfedge() != n2 && hew.opp().halfedge() != n2) + { + init_attributes(hew.halfedge()); + } + } + init_attributes(new_f1, get_label(f_out1)); + init_attributes(new_f2, get_label(f_out2)); + init_attributes(new_f_in, l); + + update_locally(n2); + } + return; + } + + void DeformableSimplicialComplex::remove_degenerate_needle(Face_key fkey) + { + + auto edges = sorted_face_edges(fkey); + int l = get_label(fkey); + + if(is_interface(edges[2]) || is_interface(edges[1])) + { + return; + } + + { + auto hew1 = walker(edges[2]); + auto hew2 = walker(edges[1]); + face_key f_out1 = hew1.opp().face(); + face_key f_out2 = hew2.opp().face(); + node_key n_out1 = hew1.opp().next().vertex(); + node_key n_out2 = hew2.opp().next().vertex(); + + if (!mesh->in_use(f_out1) or !mesh->in_use(f_out2) + or !mesh->in_use(n_out1) or !mesh->in_use(n_out2)) + { + return; + } + + // Split the two edges + node_key n1 = mesh->split_edge(hew1.halfedge()); + node_key n2 = mesh->split_edge(hew2.halfedge()); + // Split the faces + face_key new_f1 = mesh->split_face_by_edge(f_out1, n_out1, n1); + face_key new_f2 = mesh->split_face_by_edge(f_out2, n_out2, n2); + face_key new_f_in = mesh->split_face_by_edge(fkey, n1, n2); + + // collapse edge n1-n2 + auto hem = walker(n1); + for (; !hem.full_circle(); hem = hem.circulate_vertex_ccw()) + { + if (hem.vertex() == n2) + { + break; + } + } + mesh->collapse_edge(hem.halfedge(), true); + + // Update attribute + init_attributes(n2); + for(auto hew = walker(n2); !hew.full_circle(); hew = hew.circulate_vertex_cw()) + { + //if(hew.halfedge() != n2 && hew.opp().halfedge() != n2) + { + init_attributes(hew.halfedge()); + } + } + init_attributes(new_f1, get_label(f_out1)); + init_attributes(new_f2, get_label(f_out2)); + init_attributes(new_f_in, l); + + update_locally(n2); + } + return; + + node_key vn1, vn2; + {// Split edge 0 + auto eid = edges[2]; + auto hew = walker(eid); + face_key f1 = hew.face(); + node_key v1 = hew.next().vertex(); + face_key f2 = hew.opp().face(); + node_key v2 = hew.opp().next().vertex(); + + node_key vid = mesh->split_edge(eid); + face_key newf1 = mesh->split_face_by_edge(f1, vid, v1); + face_key newf2 = mesh->split_face_by_edge(f2, vid, v2); + + // Update attributes + init_attributes(vid); + for(auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) + { + if(hew.halfedge() != eid && hew.opp().halfedge() != eid) + { + init_attributes(hew.halfedge()); + } + } + init_attributes(newf1, get_label(f1)); + init_attributes(newf2, get_label(f2)); + + update_locally(vid); + + vn1 = vid; + } + + {// Split edge 0 + auto eid = edges[1]; + auto hew = walker(eid); + face_key f1 = hew.face(); + node_key v1 = hew.next().vertex(); + face_key f2 = hew.opp().face(); + node_key v2 = hew.opp().next().vertex(); + + node_key vid = mesh->split_edge(eid); + face_key newf1 = mesh->split_face_by_edge(f1, vid, v1); + face_key newf2 = mesh->split_face_by_edge(f2, vid, v2); + + // Update attributes + init_attributes(vid); + for(auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) + { + if(hew.halfedge() != eid && hew.opp().halfedge() != eid) + { + init_attributes(hew.halfedge()); + } + } + init_attributes(newf1, get_label(f1)); + init_attributes(newf2, get_label(f2)); + + update_locally(vid); + + vn2 = vid; + } + + // merge v2 and v1 + auto pt = (get_pos(vn1) + get_pos(vn2)) / 2.0; + auto hew = walker(vn1); + for (; !hew.full_circle(); hew = hew.circulate_vertex_ccw()) + { + if (hew.vertex() == vn2) + { + break; + } + } + + update_attributes(hew.halfedge(), OUTSIDE, OUTSIDE); + update_attributes(hew.prev().halfedge(), OUTSIDE, OUTSIDE); + update_attributes(hew.opp().next().halfedge(), OUTSIDE, OUTSIDE); + update_attributes(hew.next().halfedge(), OUTSIDE, OUTSIDE); + update_attributes(hew.opp().prev().halfedge(), OUTSIDE, OUTSIDE); + update_attributes(hew.opp().vertex(), OUTSIDE); + + mesh->collapse_edge(hew.halfedge()); + + update_locally(vn2); + set_pos(vn2, pt); + set_destination(vn2, pt); + } + + void DeformableSimplicialComplex::increase_resolution_range(){ + MAX_LENGTH = 2.; + MIN_LENGTH = MIN_LENGTH / 2.0; + DEG_LENGTH = 0.2*MIN_LENGTH; + + MAX_AREA = 5.; + MIN_AREA = MIN_AREA / 4; + + DEG_AREA = 0.2*MIN_AREA; + } + + void DeformableSimplicialComplex::set_uniform_smallest_feature(double length) + { + // Length + MAX_LENGTH = 1; + MIN_LENGTH = length / AVG_LENGTH /2.0; + DEG_LENGTH = MIN_LENGTH;// 0.2*MIN_LENGTH; + + // Area + MAX_AREA = 1; + MIN_AREA = MIN_LENGTH*MIN_LENGTH; + DEG_AREA = MIN_AREA; //0.2*MIN_AREA; + } + + void DeformableSimplicialComplex::set_smallest_feature_size(double length) + { + // Length + MAX_LENGTH = 10.; + MIN_LENGTH = length / AVG_LENGTH /2.0; + DEG_LENGTH = MIN_LENGTH;// 0.2*MIN_LENGTH; + + // Area + MAX_AREA = 10.; + MIN_AREA = MIN_LENGTH*MIN_LENGTH; + DEG_AREA = MIN_AREA; //0.2*MIN_AREA; + } -} \ No newline at end of file + void DeformableSimplicialComplex::refine_without_change_interface(){ + /** + Restore original parametters + */ + MAX_LENGTH = 2.; + MIN_LENGTH = 0.5;// 0.01;// 0.05 // 0.5; + DEG_LENGTH = 0.2*MIN_LENGTH; + + MAX_AREA = 5.; + MIN_AREA = 0.2; //0.001;//0.01;// 0.2; + + DEG_AREA = 0.2*MIN_AREA; + + /** + Collapse all small triangle + */ + thinning(); + + smooth(); + + max_min_angle(); + } + + void DeformableSimplicialComplex::clean_attributes() { + HMesh::IDRemap cleanup_map; + cleanup_attributes(cleanup_map); + + init_attributes(); + update_attributes(); + } +} diff --git a/src/DSC.h b/src/DSC.h index 3240f0d..a31b023 100644 --- a/src/DSC.h +++ b/src/DSC.h @@ -28,18 +28,39 @@ #include #endif +//#define TUAN_SEG -namespace DSC2D { +// #define TUAN_MULTI_RES + +#ifdef TUAN_MULTI_RES +class image; +#endif + +#define NB_FORCES 10 + +struct node_atrr{ +}; + +namespace DSC2D { + typedef DSC2D::vec2 Vec2; + typedef DSC2D::vec3 Vec3; + /** The base class representing a simplicial complex. */ class DeformableSimplicialComplex { +#ifdef TUAN_MULTI_RES + public: + image * img; + int pixel_spread = 4; // To avoid computing energy near edge + double collapse_ene_thres = 0.15; +#endif friend class ObjectGenerator; public: - enum LABEL_OPT {NO_LABEL = -3, OUTSIDE = 0, INTERFACE = -1, CROSSING = -2}; + enum LABEL_OPT {NO_LABEL = -3, OUTSIDE = 0, INTERFACE_DSC = -1, CROSSING = -2}; enum OBJECTS_TYPE {FILLED_HALF, FILLED, SQUARE, BLOB, BLOBS}; typedef HMesh::VertexID node_key; @@ -59,7 +80,7 @@ namespace DSC2D { pri(_pri), h(_h), time(_time) {} }; - protected: + protected:public: // testing real AVG_LENGTH; real AVG_AREA; @@ -83,19 +104,40 @@ namespace DSC2D { vec3 OUTSIDE_FACE_COLOR; vec3 DEFAULT_FACE_COLOR; - private: + public: HMesh::Manifold *mesh; DesignDomain *design_domain; HMesh::VertexAttributeVector destination; + HMesh::VertexAttributeVector internal_node_forces; + HMesh::VertexAttributeVector external_node_forces; + HMesh::VertexAttributeVector bStable; + + + HMesh::VertexAttributeVector> forces; + + double default_dt = 0.0; + HMesh::VertexAttributeVector dts; + void set_default_dt(double dt_); + + HMesh::VertexAttributeVector vertex_labels; HMesh::HalfEdgeAttributeVector edge_labels; HMesh::FaceAttributeVector face_labels; + + public: + HMesh::FaceAttributeVector> face_att; + + // attibute + HMesh::VertexAttributeVector> node_att_i; + HMesh::HalfEdgeAttributeVector> edge_att_i; //************** INITIALISATION *************** public: + + /** Creates a simplicial complex with size (SIZE_X_, SIZE_Y_). The input parameters specifies the design domain, the initial object(s) and the discretization. The latter is defined by the parameter AVG_EDGE_LENGTH, which tells how long edges are on average. */ @@ -112,7 +154,10 @@ namespace DSC2D { */ void create_simplicial_complex(const std::vector& points, const std::vector& faces); + DeformableSimplicialComplex(){}; + //************** DISPLAY FUNCTIONS *************** +#pragma mark - Display fuctions public: /** Returns the vertex colors. @@ -128,9 +173,11 @@ namespace DSC2D { Returns the face colors. */ virtual HMesh::FaceAttributeVector get_face_colors() const; + //************** ATTRIBUTE FUNCTIONS *************** - protected: +#pragma mark - attribute functions + public: /** Clean up the attribute vectors (the lists that stores the attributes of each vertex, edge and face). Should be called after removing primitives. @@ -145,7 +192,7 @@ namespace DSC2D { /** Initialise the attribute vectors for the vertex with ID vid. Should be called after a new vertex has been created. */ - virtual void init_attributes(node_key vid); + virtual void init_attributes(node_key vid, bool keep = false); /** Initialise the attribute vectors for the edge with ID eid. Should be called after a new edge has been created. @@ -188,6 +235,7 @@ namespace DSC2D { //************** GETTERS *************** +#pragma mark - Getters public: /** @@ -253,6 +301,11 @@ namespace DSC2D { */ std::vector get_pos(face_key fid) const; + /** + Returns the positions of the vertices of the edge with ID fid. + */ + std::vector get_pos(edge_key fid) const; + /** Returns the new position of the vertex with ID vid. */ @@ -266,7 +319,7 @@ namespace DSC2D { /** Returns the IDs of the neighbouring vertices of the vertex with ID vid. If the interface parameter is true, it only returns the neighbouring vertices which are also interface. */ - std::vector get_verts(node_key vid, bool interface = false) const; + std::vector get_verts(node_key vid, bool _interface = false) const; /** Returns the IDs of the vertices of the face with ID fid. @@ -308,8 +361,49 @@ namespace DSC2D { */ std::vector get_interface_labels(node_key vid) const; + /** + Node force + */ + vec2 get_node_internal_force(node_key vid) const{ + return internal_node_forces[vid]; + } + + vec2 get_node_external_force(node_key vid) const{ + return external_node_forces[vid]; + } + + const HMesh::VertexAttributeVector & get_internal_force () const{ + return internal_node_forces; + } + + const HMesh::VertexAttributeVector & get_external_force () const{ + return external_node_forces; + } + + vec2 get_node_force(node_key vid, int index){ + return forces[vid][index]; + } + + void set_node_force(node_key vid, vec2 f, int index){ + forces[vid][index] = f; + } + + void add_node_force(node_key vid, vec2 f, int index){ + forces[vid][index] += f; + } + + /* + Time step + */ + void set_time(node_key vid, double new_t){ + dts[vid] = new_t; + }; + double time_step(node_key const vid) const{ + return dts[vid]; + } //************** SETTERS *************** +#pragma mark - Setter protected: /** @@ -318,6 +412,44 @@ namespace DSC2D { void set_pos(node_key vid, vec2 p); public: + + /** + Internal force + */ + void set_node_internal_force(node_key vid, vec2 force){ + internal_node_forces[vid] = force; + } + + void add_node_internal_force(node_key vid, vec2 force){ +#ifdef DEBUG + assert(!Util::isnan(force[0]) && !Util::isnan(force[1])); +#endif + internal_node_forces[vid] += force; + } + + /** + External force + */ + void set_node_external_force(node_key vid, vec2 force){ + external_node_forces[vid] = force; + } + + void add_node_external_force(node_key vid, vec2 force){ + external_node_forces[vid] += force; + } + + void set_label(face_key fid, int new_label){ + face_labels[fid] = new_label; + } + + void set_phase_attr(face_key fid, vec2 new_attr, int idx){ + face_att[fid][idx] = new_attr; + }; + + vec2 get_phase_attr(face_key fid, int idx){ + return face_att[fid][idx]; + } + /** Sets the destination of the vertex with ID vid to dest. To actually move the vertices to their destination, call the deform function. @@ -334,17 +466,8 @@ namespace DSC2D { } //************** ITERATORS *************** +#pragma mark - Iterators public: - HMesh::IDIteratorPair vertices() const { - return mesh->vertices(); - } - HMesh::IDIteratorPair faces() const { - return mesh->faces(); - } - HMesh::IDIteratorPair halfedges() const { - return mesh->halfedges(); - } - HMesh::VertexIDIterator vertices_begin() const { return mesh->vertices_begin(); @@ -370,6 +493,18 @@ namespace DSC2D { return mesh->faces_begin(); } + HMesh::IDIteratorPair vertices() const { + return mesh->vertices(); + } + + HMesh::IDIteratorPair halfedges() const { + return mesh->halfedges(); + } + + HMesh::IDIteratorPair faces() const { + return mesh->faces(); + } + HMesh::FaceIDIterator faces_end() const { return mesh->faces_end(); @@ -391,6 +526,7 @@ namespace DSC2D { } //************** PRECONDITIONS *************** +#pragma mark - Preconditions public: /** Returns whether the vertex with ID vid is situated at a crossing of interfaces. @@ -413,7 +549,7 @@ namespace DSC2D { */ bool is_interface(node_key vid) { - return vertex_labels[vid] == INTERFACE; + return vertex_labels[vid] == INTERFACE_DSC; } /** @@ -421,7 +557,7 @@ namespace DSC2D { */ bool is_interface(node_key vid) const { - return vertex_labels[vid] == INTERFACE; + return vertex_labels[vid] == INTERFACE_DSC; } /** @@ -429,7 +565,7 @@ namespace DSC2D { */ bool is_interface(edge_key eid) { - return edge_labels[eid] == INTERFACE; + return edge_labels[eid] == INTERFACE_DSC; } /** @@ -437,7 +573,7 @@ namespace DSC2D { */ bool is_interface(edge_key eid) const { - return edge_labels[eid] == INTERFACE; + return edge_labels[eid] == INTERFACE_DSC; } /** @@ -498,7 +634,7 @@ namespace DSC2D { */ virtual bool is_movable(edge_key eid) const; - protected: + public: /** Returns whether the vertex with ID vid is editable, but not safe to interface changes i.e. if you edit the vertex you may change the interface. @@ -521,13 +657,14 @@ namespace DSC2D { virtual bool safe_editable(edge_key eid) const; //************** MESH FUNCTIONS *************** +#pragma mark - Mesh functions public: /** Move the vertices in the simplicial complex to their new position. The new position is set by the update_pos function. */ void deform(); - private: + public: /** Moves a the vertex with ID vid to its new position. Returns whether the vertex was succesfully moved to its new position. @@ -559,8 +696,15 @@ namespace DSC2D { */ bool collapse(HMesh::Walker hew, real weight); + /** + Splits the edge eid by inserting a vertex at the center of the edge and splitting the two neighbouring faces of the edge. Returns whether it suceeds or not. + For mesh adaptation. We need stability of the vertex. + */ + bool split_adpat_mesh(edge_key eid); + //************** QUALITY CONTROL *************** +#pragma mark - Quality control protected: /** @@ -584,11 +728,13 @@ namespace DSC2D { */ void max_min_angle(); + public: /** Performs Laplacian smoothing on all safe editable vertices. */ void smooth(real t = 1.); - + + private: /** Remove needles, triangles with one very short edge, by splitting the face (inserting a vertex at the barycenter of the face). */ @@ -610,6 +756,7 @@ namespace DSC2D { void remove_degenerate_faces(); //************** DETAIL CONTROL *************** +#pragma mark - Detail control public: /** @@ -624,7 +771,7 @@ namespace DSC2D { void thickening_interface(); /** - Collapse interface edges that are too long. + Collapse interface edges that are too short. */ void thinning_interface(); @@ -640,7 +787,8 @@ namespace DSC2D { void thickening(); //************** UTIL *************** - private: +#pragma mark - Utilities + private: public: /** Checks that the mesh is valid, i.e. that each face has three vertices and that the area of a face is positive (the face is not degenerate). @@ -652,6 +800,17 @@ namespace DSC2D { */ real min_angle(face_key fid); + /** + Returns the max angle of the face with ID fid. + */ + real max_angle(face_key fid, HMesh::Walker &hmax); + + /** + Returns the vertex of max angle. + The half edge point to that vertex + */ + HMesh::Walker max_angle_point(face_key fid); + /** Returns the minimum edge length of the edges of the face with ID fid. */ @@ -668,6 +827,12 @@ namespace DSC2D { bool is_collapsable(HMesh::Walker hew, bool safe); public: + /** + Load and save + */ + bool save(const char * filePath); + bool load(char * filePath); + /** Returns the length of the edge with ID eid. */ @@ -708,7 +873,7 @@ namespace DSC2D { Calculates the average position of the neighbouring vertices to the vertex with ID vid. If interface is true, the average position is only calculated among the neighbouring vertices that are interface. */ - vec2 get_barycenter(node_key vid, bool interface) const; + vec2 get_barycenter(node_key vid, bool _interface) const; /** Calculates the average position of the vertices to the face with ID fid. @@ -759,7 +924,29 @@ namespace DSC2D { Calculates the intersection with the link of the vertex with ID vid and the line from the position of this vertex towards destination and to infinity. It returns t which is where on the line the intersection occurs. If t=0, the interesection occured at the position of the vertex with ID vid or never occured. If t=1 the intersection occured at the destination point. If 01 the intersection occured farther away from the vertex position than destination. */ real intersection_with_link(const node_key& vid, vec2 destination) const; + +#pragma mark - TESTING + public: + void increase_resolution_range(); // reduce smallest edge by 2. For multi resolution + void refine_without_change_interface(); + + void remove_degenerate_needle(face_key fkey); + void remove_degenerate_needle2(face_key fkey); + /** + Set coefficients. Smallest feature size in pixel + */ + void set_smallest_feature_size(double length); + void set_uniform_smallest_feature(double length); + + double get_min_length_ratio(){return MIN_LENGTH;} + + + void split_edge(edge_key ek); + void clean_attributes(); + + + DeformableSimplicialComplex * clone(); }; -} \ No newline at end of file +} diff --git a/src/design_domain.h b/src/design_domain.h index 0e96db9..4151dca 100644 --- a/src/design_domain.h +++ b/src/design_domain.h @@ -25,12 +25,15 @@ namespace DSC2D { */ class DesignDomain { + public: std::vector corners; // Specified in a clockwise order real volume = -1.; public: enum DESIGN_DOMAIN_TYPE {RECTANGLE, L, ESO}; + + DesignDomain(){} /** Creates a design domain defined by the design domain type and size. It is possible to specify a boundary gap which translates the entire domain by the amount specified by the input parameter. */ diff --git a/src/object_generator.h b/src/object_generator.h index f92a9d3..8d3f3b4 100644 --- a/src/object_generator.h +++ b/src/object_generator.h @@ -51,6 +51,14 @@ namespace DSC2D { create_object(dsc, corners, label); } + + static void label_tris(DeformableSimplicialComplex& dsc, + std::vector faces, + int label){ + for (auto f : faces){ + dsc.update_attributes(f, label); + } + } }; diff --git a/src/trializer.cpp b/src/trializer.cpp index 7caf6a5..ab9e148 100644 --- a/src/trializer.cpp +++ b/src/trializer.cpp @@ -39,6 +39,8 @@ namespace DSC2D { } x_half.push_back(width+avg_edge_length); x_half.push_back(width+2*avg_edge_length); + int idx = 0; + for (int k = 0; k namespace DSC2D { @@ -192,4 +193,4 @@ namespace DSC2D { }; -} \ No newline at end of file +} From 641e3985d81a62cb5d35eacbc6bb763ce46a0846 Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Tue, 29 May 2018 15:55:05 +0200 Subject: [PATCH 06/20] Update new adaptive scheme --- src/DSC.cpp | 82 +++++++++++++++++++++++++++++++++++++++++------------ src/DSC.h | 22 ++++++++------ 2 files changed, 77 insertions(+), 27 deletions(-) diff --git a/src/DSC.cpp b/src/DSC.cpp index cee954c..2b42cab 100644 --- a/src/DSC.cpp +++ b/src/DSC.cpp @@ -25,7 +25,6 @@ #define TETRA_PAK - namespace DSC2D { const DSC2D::vec3 BACKGROUND_COLOR = DSC2D::vec3(0.7); // DSC2D::vec3(1.0); @@ -215,17 +214,6 @@ namespace DSC2D void DeformableSimplicialComplex::resize_complex() { -#ifdef TUAN_SEG - thickening_interface(); - - // thinning_interface(); - - thickening(); - - thinning(); - - fix_complex(); -#else thickening_interface(); thinning_interface(); @@ -235,7 +223,6 @@ namespace DSC2D thinning(); fix_complex(); -#endif /* TUAN_SEG */ } real DeformableSimplicialComplex::intersection_with_link(const node_key& vid, vec2 destination) const @@ -293,8 +280,54 @@ namespace DSC2D return new_dsc; } + + void DeformableSimplicialComplex::recursive_split(HMesh::AttributeVector faces_to_split) + { + for(int i = 0; i < faces_to_split.size(); i++) + { + if(faces_to_split[face_key(i)]) + split_triangle_sub(face_key(i), faces_to_split); + } + } + + bool DeformableSimplicialComplex::split_triangle_sub(face_key f, HMesh::AttributeVector & faces_to_split) + { + auto eid = sorted_face_edges(f); + auto longest_e = eid[2]; + + while(1) + { + // Check the other edge + auto hew = walker(longest_e); + if(hew.face() != f) + hew = hew.opp(); + + auto other_tri = hew.opp().face(); + if(other_tri == HMesh::InvalidFaceID) + break; + + auto eid2 = sorted_face_edges(other_tri); + auto longest_e2 = eid[2]; + if(longest_e2 != longest_e) + { + if(!split_triangle_sub(other_tri, faces_to_split)) + break; + }else{ + break; + } + } + + + split(longest_e); + + // Update the list + if(f.get_index() < faces_to_split.size()) + faces_to_split[f] = 0; + + return true; + } - void DeformableSimplicialComplex::deform() + void DeformableSimplicialComplex::deform(bool adaptive) { bool work = true; int count = 0; @@ -313,7 +346,8 @@ namespace DSC2D count++; } - resize_complex(); + if(!adaptive) + resize_complex(); HMesh::IDRemap cleanup_map; cleanup_attributes(cleanup_map); @@ -796,7 +830,14 @@ namespace DSC2D else //-- { - +// // Check quality first +// bool should_split = true; +// { +// auto pts = get_pos(fid); +// auto v = (pts[0] + pts[1] + pts[2])/3.0; + +// } + int fa = get_label(fid); node_key vid = mesh->split_face_by_vertex(fid); @@ -950,9 +991,14 @@ namespace DSC2D return false; } - bool DeformableSimplicialComplex::collapse(HMesh::Walker hew, real weight) + bool DeformableSimplicialComplex::collapse(HMesh::Walker hew, real weight, bool safe) { - + if(! (precond_collapse_edge(*mesh, hew.halfedge()) + && is_collapsable(hew, safe) + && unsafe_editable(hew.halfedge()) + )) + return false; + node_key vid = hew.vertex(); vec2 p = (1.-weight) * get_pos(hew.vertex()) + weight * get_pos(hew.opp().vertex()); vec2 d = (1.-weight) * get_destination(hew.vertex()) + weight * get_destination(hew.opp().vertex()); diff --git a/src/DSC.h b/src/DSC.h index a31b023..5fbf5f6 100644 --- a/src/DSC.h +++ b/src/DSC.h @@ -52,12 +52,6 @@ namespace DSC2D { */ class DeformableSimplicialComplex { -#ifdef TUAN_MULTI_RES - public: - image * img; - int pixel_spread = 4; // To avoid computing energy near edge - double collapse_ene_thres = 0.15; -#endif friend class ObjectGenerator; public: enum LABEL_OPT {NO_LABEL = -3, OUTSIDE = 0, INTERFACE_DSC = -1, CROSSING = -2}; @@ -154,7 +148,7 @@ namespace DSC2D { */ void create_simplicial_complex(const std::vector& points, const std::vector& faces); - DeformableSimplicialComplex(){}; + DeformableSimplicialComplex(){} //************** DISPLAY FUNCTIONS *************** #pragma mark - Display fuctions @@ -290,6 +284,11 @@ namespace DSC2D { { return static_cast(mesh->no_faces()); } + + int get_no_faces_allocated() const + { + return static_cast(mesh->allocated_faces()); + } /** Returns the position of the vertex with ID vid. @@ -367,6 +366,8 @@ namespace DSC2D { vec2 get_node_internal_force(node_key vid) const{ return internal_node_forces[vid]; } + + vec2 get_node_external_force(node_key vid) const{ return external_node_forces[vid]; @@ -662,7 +663,7 @@ namespace DSC2D { /** Move the vertices in the simplicial complex to their new position. The new position is set by the update_pos function. */ - void deform(); + void deform(bool adaptive = false); public: @@ -694,7 +695,7 @@ namespace DSC2D { /** Collapses the edge with pointed to by the walker hew and updates attributes. The weight determines position and destination of the surviving node which are a weight between the two original nodes. Returns whether it suceeds or not. */ - bool collapse(HMesh::Walker hew, real weight); + bool collapse(HMesh::Walker hew, real weight, bool safe = false); /** Splits the edge eid by inserting a vertex at the center of the edge and splitting the two neighbouring faces of the edge. Returns whether it suceeds or not. @@ -947,6 +948,9 @@ namespace DSC2D { DeformableSimplicialComplex * clone(); + + void recursive_split(HMesh::AttributeVector faces_to_split); + bool split_triangle_sub(face_key f, HMesh::AttributeVector & faces_to_split); }; } From 092dbea0d4225ea3d28adab440d55a879a256f20 Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Thu, 31 May 2018 16:38:27 +0200 Subject: [PATCH 07/20] remove xcode project --- DSC.xcodeproj/project.pbxproj | 399 ------------------ .../contents.xcworkspacedata | 7 - .../xcshareddata/DSC.xccheckout | 41 -- 3 files changed, 447 deletions(-) delete mode 100644 DSC.xcodeproj/project.pbxproj delete mode 100644 DSC.xcodeproj/project.xcworkspace/contents.xcworkspacedata delete mode 100644 DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout diff --git a/DSC.xcodeproj/project.pbxproj b/DSC.xcodeproj/project.pbxproj deleted file mode 100644 index ebc0767..0000000 --- a/DSC.xcodeproj/project.pbxproj +++ /dev/null @@ -1,399 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXBuildFile section */ - 7A470AE617F5282C001FC0CB /* log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A470AE417F5282C001FC0CB /* log.cpp */; }; - 7A51F3CC17D6393200A8F8F2 /* average_function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3C317D6393200A8F8F2 /* average_function.cpp */; }; - 7A51F3CD17D6393200A8F8F2 /* normal_function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3C517D6393200A8F8F2 /* normal_function.cpp */; }; - 7A51F3CE17D6393200A8F8F2 /* rotate_function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3C717D6393200A8F8F2 /* rotate_function.cpp */; }; - 7A51F3CF17D6393200A8F8F2 /* demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3C917D6393200A8F8F2 /* demo.cpp */; }; - 7A51F3D017D6393200A8F8F2 /* user_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3CA17D6393200A8F8F2 /* user_interface.cpp */; }; - 7A51F3DB17D639C900A8F8F2 /* DSC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3A517D6386100A8F8F2 /* DSC.cpp */; }; - 7A51F3DC17D639C900A8F8F2 /* DSC.h in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3A617D6386100A8F8F2 /* DSC.h */; }; - 7A51F3DF17D639C900A8F8F2 /* util.h in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3A917D6386100A8F8F2 /* util.h */; }; - 7A51F3E117D639C900A8F8F2 /* velocity_function.h in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3AB17D6386100A8F8F2 /* velocity_function.h */; }; - 7A51F3E217D639D800A8F8F2 /* GEL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A51F3B417D638B500A8F8F2 /* GEL.framework */; }; - 7A51F3E317D639FD00A8F8F2 /* libDSC.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A51F3D517D6399200A8F8F2 /* libDSC.a */; }; - 7A51F3E417D63A0800A8F8F2 /* GEL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A51F3B417D638B500A8F8F2 /* GEL.framework */; }; - 7A51F3E517D63A0E00A8F8F2 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A51F3B217D6388800A8F8F2 /* OpenGL.framework */; }; - 7A51F3E617D63A0E00A8F8F2 /* GLUT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A51F3B017D6388200A8F8F2 /* GLUT.framework */; }; - 7A82D64717E23E9400C19874 /* object_generator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A82D64517E23E9400C19874 /* object_generator.cpp */; }; - 7A82D64817E23E9400C19874 /* object_generator.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A82D64617E23E9400C19874 /* object_generator.h */; }; - 7A82D64B17E23EAC00C19874 /* trializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A82D64917E23EAC00C19874 /* trializer.cpp */; }; - 7A82D64C17E23EAC00C19874 /* trializer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A82D64A17E23EAC00C19874 /* trializer.h */; }; - 7A82D64F17E272BB00C19874 /* design_domain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A82D64D17E272BB00C19874 /* design_domain.cpp */; }; - 7A82D65017E272BB00C19874 /* design_domain.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A82D64E17E272BB00C19874 /* design_domain.h */; }; - 7A9C20DB17DFBE080064171E /* draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A9C20D917DFBE070064171E /* draw.cpp */; }; -/* End PBXBuildFile section */ - -/* Begin PBXCopyFilesBuildPhase section */ - 7A51F3B817D6391500A8F8F2 /* CopyFiles */ = { - isa = PBXCopyFilesBuildPhase; - buildActionMask = 2147483647; - dstPath = /usr/share/man/man1/; - dstSubfolderSpec = 0; - files = ( - ); - runOnlyForDeploymentPostprocessing = 1; - }; -/* End PBXCopyFilesBuildPhase section */ - -/* Begin PBXFileReference section */ - 7A470AE417F5282C001FC0CB /* log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = log.cpp; sourceTree = ""; }; - 7A470AE517F5282C001FC0CB /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = ""; }; - 7A51F3A517D6386100A8F8F2 /* DSC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DSC.cpp; path = src/DSC.cpp; sourceTree = SOURCE_ROOT; }; - 7A51F3A617D6386100A8F8F2 /* DSC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DSC.h; path = src/DSC.h; sourceTree = SOURCE_ROOT; }; - 7A51F3A917D6386100A8F8F2 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util.h; path = src/util.h; sourceTree = SOURCE_ROOT; }; - 7A51F3AB17D6386100A8F8F2 /* velocity_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = velocity_function.h; path = src/velocity_function.h; sourceTree = SOURCE_ROOT; }; - 7A51F3B017D6388200A8F8F2 /* GLUT.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLUT.framework; path = System/Library/Frameworks/GLUT.framework; sourceTree = SDKROOT; }; - 7A51F3B217D6388800A8F8F2 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; - 7A51F3B417D638B500A8F8F2 /* GEL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GEL.framework; path = ../../../../../Library/Frameworks/GEL.framework; sourceTree = ""; }; - 7A51F3BA17D6391500A8F8F2 /* DEMO */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = DEMO; sourceTree = BUILT_PRODUCTS_DIR; }; - 7A51F3C317D6393200A8F8F2 /* average_function.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = average_function.cpp; sourceTree = ""; }; - 7A51F3C417D6393200A8F8F2 /* average_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = average_function.h; sourceTree = ""; }; - 7A51F3C517D6393200A8F8F2 /* normal_function.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = normal_function.cpp; sourceTree = ""; }; - 7A51F3C617D6393200A8F8F2 /* normal_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = normal_function.h; sourceTree = ""; }; - 7A51F3C717D6393200A8F8F2 /* rotate_function.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rotate_function.cpp; sourceTree = ""; }; - 7A51F3C817D6393200A8F8F2 /* rotate_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rotate_function.h; sourceTree = ""; }; - 7A51F3C917D6393200A8F8F2 /* demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = demo.cpp; sourceTree = ""; }; - 7A51F3CA17D6393200A8F8F2 /* user_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_interface.cpp; sourceTree = ""; }; - 7A51F3CB17D6393200A8F8F2 /* user_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user_interface.h; sourceTree = ""; }; - 7A51F3D517D6399200A8F8F2 /* libDSC.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDSC.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 7A82D64517E23E9400C19874 /* object_generator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = object_generator.cpp; path = src/object_generator.cpp; sourceTree = SOURCE_ROOT; }; - 7A82D64617E23E9400C19874 /* object_generator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = object_generator.h; path = src/object_generator.h; sourceTree = SOURCE_ROOT; }; - 7A82D64917E23EAC00C19874 /* trializer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = trializer.cpp; path = src/trializer.cpp; sourceTree = SOURCE_ROOT; }; - 7A82D64A17E23EAC00C19874 /* trializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = trializer.h; path = src/trializer.h; sourceTree = SOURCE_ROOT; }; - 7A82D64D17E272BB00C19874 /* design_domain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = design_domain.cpp; path = src/design_domain.cpp; sourceTree = SOURCE_ROOT; }; - 7A82D64E17E272BB00C19874 /* design_domain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = design_domain.h; path = src/design_domain.h; sourceTree = SOURCE_ROOT; }; - 7A9C20D917DFBE070064171E /* draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = draw.cpp; sourceTree = ""; }; - 7A9C20DA17DFBE080064171E /* draw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = draw.h; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 7A51F3B717D6391500A8F8F2 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 7A51F3E417D63A0800A8F8F2 /* GEL.framework in Frameworks */, - 7A51F3E517D63A0E00A8F8F2 /* OpenGL.framework in Frameworks */, - 7A51F3E617D63A0E00A8F8F2 /* GLUT.framework in Frameworks */, - 7A51F3E317D639FD00A8F8F2 /* libDSC.a in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7A51F3D217D6399200A8F8F2 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 7A51F3E217D639D800A8F8F2 /* GEL.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 7A51F38E17D6383500A8F8F2 = { - isa = PBXGroup; - children = ( - 7A51F3B417D638B500A8F8F2 /* GEL.framework */, - 7A51F3B217D6388800A8F8F2 /* OpenGL.framework */, - 7A51F3B017D6388200A8F8F2 /* GLUT.framework */, - 7A51F39917D6383500A8F8F2 /* DSC */, - 7A51F3BB17D6391500A8F8F2 /* DEMO */, - 7A51F39817D6383500A8F8F2 /* Products */, - ); - sourceTree = ""; - }; - 7A51F39817D6383500A8F8F2 /* Products */ = { - isa = PBXGroup; - children = ( - 7A51F3BA17D6391500A8F8F2 /* DEMO */, - 7A51F3D517D6399200A8F8F2 /* libDSC.a */, - ); - name = Products; - sourceTree = ""; - }; - 7A51F39917D6383500A8F8F2 /* DSC */ = { - isa = PBXGroup; - children = ( - 7A51F3A517D6386100A8F8F2 /* DSC.cpp */, - 7A51F3A617D6386100A8F8F2 /* DSC.h */, - 7A51F3A917D6386100A8F8F2 /* util.h */, - 7A51F3AB17D6386100A8F8F2 /* velocity_function.h */, - 7A82D64517E23E9400C19874 /* object_generator.cpp */, - 7A82D64617E23E9400C19874 /* object_generator.h */, - 7A82D64917E23EAC00C19874 /* trializer.cpp */, - 7A82D64A17E23EAC00C19874 /* trializer.h */, - 7A82D64D17E272BB00C19874 /* design_domain.cpp */, - 7A82D64E17E272BB00C19874 /* design_domain.h */, - ); - path = DSC; - sourceTree = ""; - }; - 7A51F3BB17D6391500A8F8F2 /* DEMO */ = { - isa = PBXGroup; - children = ( - 7A470AE417F5282C001FC0CB /* log.cpp */, - 7A470AE517F5282C001FC0CB /* log.h */, - 7A9C20D917DFBE070064171E /* draw.cpp */, - 7A9C20DA17DFBE080064171E /* draw.h */, - 7A51F3C317D6393200A8F8F2 /* average_function.cpp */, - 7A51F3C417D6393200A8F8F2 /* average_function.h */, - 7A51F3C517D6393200A8F8F2 /* normal_function.cpp */, - 7A51F3C617D6393200A8F8F2 /* normal_function.h */, - 7A51F3C717D6393200A8F8F2 /* rotate_function.cpp */, - 7A51F3C817D6393200A8F8F2 /* rotate_function.h */, - 7A51F3C917D6393200A8F8F2 /* demo.cpp */, - 7A51F3CA17D6393200A8F8F2 /* user_interface.cpp */, - 7A51F3CB17D6393200A8F8F2 /* user_interface.h */, - ); - path = DEMO; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 7A51F3D317D6399200A8F8F2 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 7A82D64817E23E9400C19874 /* object_generator.h in Headers */, - 7A82D64C17E23EAC00C19874 /* trializer.h in Headers */, - 7A82D65017E272BB00C19874 /* design_domain.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 7A51F3B917D6391500A8F8F2 /* DEMO */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7A51F3C017D6391500A8F8F2 /* Build configuration list for PBXNativeTarget "DEMO" */; - buildPhases = ( - 7A51F3B617D6391500A8F8F2 /* Sources */, - 7A51F3B717D6391500A8F8F2 /* Frameworks */, - 7A51F3B817D6391500A8F8F2 /* CopyFiles */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = DEMO; - productName = DEMO; - productReference = 7A51F3BA17D6391500A8F8F2 /* DEMO */; - productType = "com.apple.product-type.tool"; - }; - 7A51F3D417D6399200A8F8F2 /* DSC */ = { - isa = PBXNativeTarget; - buildConfigurationList = 7A51F3D617D6399200A8F8F2 /* Build configuration list for PBXNativeTarget "DSC" */; - buildPhases = ( - 7A51F3D117D6399200A8F8F2 /* Sources */, - 7A51F3D217D6399200A8F8F2 /* Frameworks */, - 7A51F3D317D6399200A8F8F2 /* Headers */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = DSC; - productName = DSC; - productReference = 7A51F3D517D6399200A8F8F2 /* libDSC.a */; - productType = "com.apple.product-type.library.static"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - 7A51F38F17D6383500A8F8F2 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0460; - ORGANIZATIONNAME = "Asger Nyman Christiansen"; - }; - buildConfigurationList = 7A51F39217D6383500A8F8F2 /* Build configuration list for PBXProject "DSC" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = 7A51F38E17D6383500A8F8F2; - productRefGroup = 7A51F39817D6383500A8F8F2 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 7A51F3D417D6399200A8F8F2 /* DSC */, - 7A51F3B917D6391500A8F8F2 /* DEMO */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXSourcesBuildPhase section */ - 7A51F3B617D6391500A8F8F2 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7A51F3CC17D6393200A8F8F2 /* average_function.cpp in Sources */, - 7A51F3CD17D6393200A8F8F2 /* normal_function.cpp in Sources */, - 7A470AE617F5282C001FC0CB /* log.cpp in Sources */, - 7A51F3CE17D6393200A8F8F2 /* rotate_function.cpp in Sources */, - 7A51F3CF17D6393200A8F8F2 /* demo.cpp in Sources */, - 7A51F3D017D6393200A8F8F2 /* user_interface.cpp in Sources */, - 7A9C20DB17DFBE080064171E /* draw.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 7A51F3D117D6399200A8F8F2 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 7A51F3DB17D639C900A8F8F2 /* DSC.cpp in Sources */, - 7A51F3DC17D639C900A8F8F2 /* DSC.h in Sources */, - 7A51F3DF17D639C900A8F8F2 /* util.h in Sources */, - 7A51F3E117D639C900A8F8F2 /* velocity_function.h in Sources */, - 7A82D64717E23E9400C19874 /* object_generator.cpp in Sources */, - 7A82D64B17E23EAC00C19874 /* trializer.cpp in Sources */, - 7A82D64F17E272BB00C19874 /* design_domain.cpp in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - 7A51F39E17D6383500A8F8F2 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.8; - ONLY_ACTIVE_ARCH = YES; - SDKROOT = macosx; - }; - name = Debug; - }; - 7A51F39F17D6383500A8F8F2 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_64_BIT)"; - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_ENABLE_OBJC_ARC = YES; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_ENABLE_OBJC_EXCEPTIONS = YES; - GCC_WARN_64_TO_32_BIT_CONVERSION = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.8; - SDKROOT = macosx; - }; - name = Release; - }; - 7A51F3C117D6391500A8F8F2 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; - HEADER_SEARCH_PATHS = /Library/Frameworks/GEL.framework/Headers; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7A51F3C217D6391500A8F8F2 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; - HEADER_SEARCH_PATHS = /Library/Frameworks/GEL.framework/Headers; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - 7A51F3D717D6399200A8F8F2 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - EXECUTABLE_PREFIX = lib; - FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; - HEADER_SEARCH_PATHS = /Library/Frameworks/GEL.framework/Headers; - LIBRARY_SEARCH_PATHS = /Library/Frameworks; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 7A51F3D817D6399200A8F8F2 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - EXECUTABLE_PREFIX = lib; - FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; - HEADER_SEARCH_PATHS = /Library/Frameworks/GEL.framework/Headers; - LIBRARY_SEARCH_PATHS = /Library/Frameworks; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 7A51F39217D6383500A8F8F2 /* Build configuration list for PBXProject "DSC" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7A51F39E17D6383500A8F8F2 /* Debug */, - 7A51F39F17D6383500A8F8F2 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7A51F3C017D6391500A8F8F2 /* Build configuration list for PBXNativeTarget "DEMO" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7A51F3C117D6391500A8F8F2 /* Debug */, - 7A51F3C217D6391500A8F8F2 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 7A51F3D617D6399200A8F8F2 /* Build configuration list for PBXNativeTarget "DSC" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 7A51F3D717D6399200A8F8F2 /* Debug */, - 7A51F3D817D6399200A8F8F2 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = 7A51F38F17D6383500A8F8F2 /* Project object */; -} diff --git a/DSC.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/DSC.xcodeproj/project.xcworkspace/contents.xcworkspacedata deleted file mode 100644 index dffa503..0000000 --- a/DSC.xcodeproj/project.xcworkspace/contents.xcworkspacedata +++ /dev/null @@ -1,7 +0,0 @@ - - - - - diff --git a/DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout b/DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout deleted file mode 100644 index d3fa876..0000000 --- a/DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout +++ /dev/null @@ -1,41 +0,0 @@ - - - - - IDESourceControlProjectFavoriteDictionaryKey - - IDESourceControlProjectIdentifier - 625E65FF-825D-4F34-8774-56989970BC68 - IDESourceControlProjectName - DSC - IDESourceControlProjectOriginsDictionary - - F29B5E51A5B97DCCD0EC2FAF945213024A5D39C4 - https://github.com/tuannt8/2D-DSC.git - - IDESourceControlProjectPath - DSC.xcodeproj - IDESourceControlProjectRelativeInstallPathDictionary - - F29B5E51A5B97DCCD0EC2FAF945213024A5D39C4 - ../.. - - IDESourceControlProjectURL - https://github.com/tuannt8/2D-DSC.git - IDESourceControlProjectVersion - 111 - IDESourceControlProjectWCCIdentifier - F29B5E51A5B97DCCD0EC2FAF945213024A5D39C4 - IDESourceControlProjectWCConfigurations - - - IDESourceControlRepositoryExtensionIdentifierKey - public.vcs.git - IDESourceControlWCCIdentifierKey - F29B5E51A5B97DCCD0EC2FAF945213024A5D39C4 - IDESourceControlWCCName - 2D-DSC - - - - From 0eb296cf5231f88b54b89883cce057a505cafb41 Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Mon, 17 Sep 2018 13:06:53 +0200 Subject: [PATCH 08/20] Update for segmentation --- src/DSC.cpp | 42 +++++++++++------------------------------- src/DSC.h | 5 +++++ 2 files changed, 16 insertions(+), 31 deletions(-) diff --git a/src/DSC.cpp b/src/DSC.cpp index 2b42cab..b4a9ccf 100644 --- a/src/DSC.cpp +++ b/src/DSC.cpp @@ -87,18 +87,9 @@ namespace DSC2D face_labels = HMesh::FaceAttributeVector(get_no_faces(), OUTSIDE); face_att = HMesh::FaceAttributeVector>(get_no_faces(), std::vector(NB_FORCES, Vec2(0.))); - internal_node_forces = HMesh::VertexAttributeVector(get_no_vertices(), - vec2(0.0f)); - external_node_forces = HMesh::VertexAttributeVector(get_no_vertices(), - vec2(0.0f)); bStable = HMesh::VertexAttributeVector(get_no_vertices(), 1); - dts = HMesh::VertexAttributeVector(get_no_vertices(), 0.0); - node_att_i = HMesh::VertexAttributeVector>(get_no_vertices(), - std::vector(NB_FORCES, 0) ); - - edge_att_i = HMesh::HalfEdgeAttributeVector>(get_no_halfedges(), - std::vector(NB_FORCES, 0)); + } void DeformableSimplicialComplex::cleanup_attributes(HMesh::IDRemap& cleanup_map) @@ -106,17 +97,13 @@ namespace DSC2D mesh->cleanup(cleanup_map); vertex_labels.cleanup(cleanup_map.vmap); - // edge_att_i.cleanup(cleanup_map.hmap); edge_labels.cleanup(cleanup_map.hmap); face_labels.cleanup(cleanup_map.fmap); -// face_att.cleanup(cleanup_map.fmap); + destination.cleanup(cleanup_map.vmap); - internal_node_forces.cleanup(cleanup_map.vmap); - external_node_forces.cleanup(cleanup_map.vmap); bStable.cleanup(cleanup_map.vmap); - dts.cleanup(cleanup_map.vmap); + - // node_att_i.cleanup(cleanup_map.vmap); } @@ -346,6 +333,8 @@ namespace DSC2D count++; } + std::cout << "Deform DSC in " << count << " steps" << std::endl; + if(!adaptive) resize_complex(); @@ -607,9 +596,6 @@ namespace DSC2D void DeformableSimplicialComplex::init_attributes(node_key vid, bool keep) { destination[vid] = get_pos(vid); - internal_node_forces[vid] = vec2(0.0); - external_node_forces[vid] = vec2(0.0); - bStable[vid] = 1; @@ -623,13 +609,7 @@ namespace DSC2D } } - void DeformableSimplicialComplex::set_default_dt(double dt_) - { - default_dt = dt_; - for (auto nkey : vertices()) { - dts[nkey] = default_dt; - } - } + void DeformableSimplicialComplex::update_attributes(node_key vid, int label) { @@ -724,7 +704,7 @@ namespace DSC2D void DeformableSimplicialComplex::update_attributes() { - for(auto fi = faces_begin(); fi != faces_end(); ++fi) + for(auto fi = faces_begin(); fi != faces_end(); ++fi) { update_attributes(*fi); } @@ -880,7 +860,7 @@ namespace DSC2D { return true; } - /*TUAN add: Do not move crossing vertex, even one of the iinterface is straight*/ + /*TUAN add: Do not move crossing vertex, even one of the interface is straight*/ else { if (is_crossing(hew.opp().vertex())) @@ -995,7 +975,7 @@ namespace DSC2D { if(! (precond_collapse_edge(*mesh, hew.halfedge()) && is_collapsable(hew, safe) - && unsafe_editable(hew.halfedge()) +// && unsafe_editable(hew.halfedge()) // Tuan: boundary should becollapsable )) return false; @@ -1936,12 +1916,12 @@ namespace DSC2D { // Length MAX_LENGTH = 10.; - MIN_LENGTH = length / AVG_LENGTH /2.0; + MIN_LENGTH = length / AVG_LENGTH; DEG_LENGTH = MIN_LENGTH;// 0.2*MIN_LENGTH; // Area MAX_AREA = 10.; - MIN_AREA = MIN_LENGTH*MIN_LENGTH; + MIN_AREA = MIN_LENGTH*MIN_LENGTH*0.5; DEG_AREA = MIN_AREA; //0.2*MIN_AREA; } diff --git a/src/DSC.h b/src/DSC.h index 5fbf5f6..2543f77 100644 --- a/src/DSC.h +++ b/src/DSC.h @@ -284,6 +284,11 @@ namespace DSC2D { { return static_cast(mesh->no_faces()); } + + int get_no_nodes_allocated() const + { + return static_cast(mesh->allocated_vertices()); + } int get_no_faces_allocated() const { From 1689ddb7a05f3b868b3a53d0c8e355d5348cbb56 Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Wed, 19 Sep 2018 13:38:43 +0200 Subject: [PATCH 09/20] Fix crash in topOpt. Init the attribute again will reset the degree of freedom --- src/DSC.cpp | 8 +++++--- src/DSC.h | 2 +- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/DSC.cpp b/src/DSC.cpp index 2b42cab..4f9e6bd 100644 --- a/src/DSC.cpp +++ b/src/DSC.cpp @@ -352,7 +352,9 @@ namespace DSC2D HMesh::IDRemap cleanup_map; cleanup_attributes(cleanup_map); - init_attributes(); +// Tuan commented out: It crash topology opt +// init_attributes(); +// End comment out update_attributes(); } @@ -600,11 +602,11 @@ namespace DSC2D for(auto vi = vertices_begin(); vi != vertices_end(); ++vi) { - init_attributes(*vi, true); + init_attributes(*vi); } } - void DeformableSimplicialComplex::init_attributes(node_key vid, bool keep) + void DeformableSimplicialComplex::init_attributes(node_key vid) { destination[vid] = get_pos(vid); internal_node_forces[vid] = vec2(0.0); diff --git a/src/DSC.h b/src/DSC.h index 5fbf5f6..7ac1318 100644 --- a/src/DSC.h +++ b/src/DSC.h @@ -186,7 +186,7 @@ namespace DSC2D { /** Initialise the attribute vectors for the vertex with ID vid. Should be called after a new vertex has been created. */ - virtual void init_attributes(node_key vid, bool keep = false); + virtual void init_attributes(node_key vid); /** Initialise the attribute vectors for the edge with ID eid. Should be called after a new edge has been created. From 5975908f342e78430e6783547f536345c4223529 Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Fri, 5 Oct 2018 12:32:18 +0200 Subject: [PATCH 10/20] Xcode project back --- .gitignore | 1 + DSC.xcodeproj/project.pbxproj | 399 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/DSC.xccheckout | 41 ++ .../UserInterfaceState.xcuserstate | Bin 0 -> 22685 bytes .../xcschemes/DSC.xcscheme | 82 ++++ .../xcschemes/xcschememanagement.plist | 27 ++ 7 files changed, 557 insertions(+) create mode 100644 DSC.xcodeproj/project.pbxproj create mode 100644 DSC.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout create mode 100644 DSC.xcodeproj/project.xcworkspace/xcuserdata/tuannt8.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/DSC.xcscheme create mode 100644 DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/.gitignore b/.gitignore index 0d023b3..7615ea0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +Build/ DSC.xcodeproj/xcuserdata/asny.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/DSC.xcodeproj/project.pbxproj b/DSC.xcodeproj/project.pbxproj new file mode 100644 index 0000000..ebc0767 --- /dev/null +++ b/DSC.xcodeproj/project.pbxproj @@ -0,0 +1,399 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 7A470AE617F5282C001FC0CB /* log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A470AE417F5282C001FC0CB /* log.cpp */; }; + 7A51F3CC17D6393200A8F8F2 /* average_function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3C317D6393200A8F8F2 /* average_function.cpp */; }; + 7A51F3CD17D6393200A8F8F2 /* normal_function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3C517D6393200A8F8F2 /* normal_function.cpp */; }; + 7A51F3CE17D6393200A8F8F2 /* rotate_function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3C717D6393200A8F8F2 /* rotate_function.cpp */; }; + 7A51F3CF17D6393200A8F8F2 /* demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3C917D6393200A8F8F2 /* demo.cpp */; }; + 7A51F3D017D6393200A8F8F2 /* user_interface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3CA17D6393200A8F8F2 /* user_interface.cpp */; }; + 7A51F3DB17D639C900A8F8F2 /* DSC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3A517D6386100A8F8F2 /* DSC.cpp */; }; + 7A51F3DC17D639C900A8F8F2 /* DSC.h in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3A617D6386100A8F8F2 /* DSC.h */; }; + 7A51F3DF17D639C900A8F8F2 /* util.h in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3A917D6386100A8F8F2 /* util.h */; }; + 7A51F3E117D639C900A8F8F2 /* velocity_function.h in Sources */ = {isa = PBXBuildFile; fileRef = 7A51F3AB17D6386100A8F8F2 /* velocity_function.h */; }; + 7A51F3E217D639D800A8F8F2 /* GEL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A51F3B417D638B500A8F8F2 /* GEL.framework */; }; + 7A51F3E317D639FD00A8F8F2 /* libDSC.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A51F3D517D6399200A8F8F2 /* libDSC.a */; }; + 7A51F3E417D63A0800A8F8F2 /* GEL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A51F3B417D638B500A8F8F2 /* GEL.framework */; }; + 7A51F3E517D63A0E00A8F8F2 /* OpenGL.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A51F3B217D6388800A8F8F2 /* OpenGL.framework */; }; + 7A51F3E617D63A0E00A8F8F2 /* GLUT.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7A51F3B017D6388200A8F8F2 /* GLUT.framework */; }; + 7A82D64717E23E9400C19874 /* object_generator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A82D64517E23E9400C19874 /* object_generator.cpp */; }; + 7A82D64817E23E9400C19874 /* object_generator.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A82D64617E23E9400C19874 /* object_generator.h */; }; + 7A82D64B17E23EAC00C19874 /* trializer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A82D64917E23EAC00C19874 /* trializer.cpp */; }; + 7A82D64C17E23EAC00C19874 /* trializer.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A82D64A17E23EAC00C19874 /* trializer.h */; }; + 7A82D64F17E272BB00C19874 /* design_domain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A82D64D17E272BB00C19874 /* design_domain.cpp */; }; + 7A82D65017E272BB00C19874 /* design_domain.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A82D64E17E272BB00C19874 /* design_domain.h */; }; + 7A9C20DB17DFBE080064171E /* draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 7A9C20D917DFBE070064171E /* draw.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 7A51F3B817D6391500A8F8F2 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 7A470AE417F5282C001FC0CB /* log.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = log.cpp; sourceTree = ""; }; + 7A470AE517F5282C001FC0CB /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = ""; }; + 7A51F3A517D6386100A8F8F2 /* DSC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DSC.cpp; path = src/DSC.cpp; sourceTree = SOURCE_ROOT; }; + 7A51F3A617D6386100A8F8F2 /* DSC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DSC.h; path = src/DSC.h; sourceTree = SOURCE_ROOT; }; + 7A51F3A917D6386100A8F8F2 /* util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = util.h; path = src/util.h; sourceTree = SOURCE_ROOT; }; + 7A51F3AB17D6386100A8F8F2 /* velocity_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = velocity_function.h; path = src/velocity_function.h; sourceTree = SOURCE_ROOT; }; + 7A51F3B017D6388200A8F8F2 /* GLUT.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GLUT.framework; path = System/Library/Frameworks/GLUT.framework; sourceTree = SDKROOT; }; + 7A51F3B217D6388800A8F8F2 /* OpenGL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGL.framework; path = System/Library/Frameworks/OpenGL.framework; sourceTree = SDKROOT; }; + 7A51F3B417D638B500A8F8F2 /* GEL.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GEL.framework; path = ../../../../../Library/Frameworks/GEL.framework; sourceTree = ""; }; + 7A51F3BA17D6391500A8F8F2 /* DEMO */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = DEMO; sourceTree = BUILT_PRODUCTS_DIR; }; + 7A51F3C317D6393200A8F8F2 /* average_function.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = average_function.cpp; sourceTree = ""; }; + 7A51F3C417D6393200A8F8F2 /* average_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = average_function.h; sourceTree = ""; }; + 7A51F3C517D6393200A8F8F2 /* normal_function.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = normal_function.cpp; sourceTree = ""; }; + 7A51F3C617D6393200A8F8F2 /* normal_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = normal_function.h; sourceTree = ""; }; + 7A51F3C717D6393200A8F8F2 /* rotate_function.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rotate_function.cpp; sourceTree = ""; }; + 7A51F3C817D6393200A8F8F2 /* rotate_function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rotate_function.h; sourceTree = ""; }; + 7A51F3C917D6393200A8F8F2 /* demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = demo.cpp; sourceTree = ""; }; + 7A51F3CA17D6393200A8F8F2 /* user_interface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = user_interface.cpp; sourceTree = ""; }; + 7A51F3CB17D6393200A8F8F2 /* user_interface.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = user_interface.h; sourceTree = ""; }; + 7A51F3D517D6399200A8F8F2 /* libDSC.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libDSC.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 7A82D64517E23E9400C19874 /* object_generator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = object_generator.cpp; path = src/object_generator.cpp; sourceTree = SOURCE_ROOT; }; + 7A82D64617E23E9400C19874 /* object_generator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = object_generator.h; path = src/object_generator.h; sourceTree = SOURCE_ROOT; }; + 7A82D64917E23EAC00C19874 /* trializer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = trializer.cpp; path = src/trializer.cpp; sourceTree = SOURCE_ROOT; }; + 7A82D64A17E23EAC00C19874 /* trializer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = trializer.h; path = src/trializer.h; sourceTree = SOURCE_ROOT; }; + 7A82D64D17E272BB00C19874 /* design_domain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = design_domain.cpp; path = src/design_domain.cpp; sourceTree = SOURCE_ROOT; }; + 7A82D64E17E272BB00C19874 /* design_domain.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = design_domain.h; path = src/design_domain.h; sourceTree = SOURCE_ROOT; }; + 7A9C20D917DFBE070064171E /* draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = draw.cpp; sourceTree = ""; }; + 7A9C20DA17DFBE080064171E /* draw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = draw.h; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 7A51F3B717D6391500A8F8F2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7A51F3E417D63A0800A8F8F2 /* GEL.framework in Frameworks */, + 7A51F3E517D63A0E00A8F8F2 /* OpenGL.framework in Frameworks */, + 7A51F3E617D63A0E00A8F8F2 /* GLUT.framework in Frameworks */, + 7A51F3E317D639FD00A8F8F2 /* libDSC.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7A51F3D217D6399200A8F8F2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7A51F3E217D639D800A8F8F2 /* GEL.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 7A51F38E17D6383500A8F8F2 = { + isa = PBXGroup; + children = ( + 7A51F3B417D638B500A8F8F2 /* GEL.framework */, + 7A51F3B217D6388800A8F8F2 /* OpenGL.framework */, + 7A51F3B017D6388200A8F8F2 /* GLUT.framework */, + 7A51F39917D6383500A8F8F2 /* DSC */, + 7A51F3BB17D6391500A8F8F2 /* DEMO */, + 7A51F39817D6383500A8F8F2 /* Products */, + ); + sourceTree = ""; + }; + 7A51F39817D6383500A8F8F2 /* Products */ = { + isa = PBXGroup; + children = ( + 7A51F3BA17D6391500A8F8F2 /* DEMO */, + 7A51F3D517D6399200A8F8F2 /* libDSC.a */, + ); + name = Products; + sourceTree = ""; + }; + 7A51F39917D6383500A8F8F2 /* DSC */ = { + isa = PBXGroup; + children = ( + 7A51F3A517D6386100A8F8F2 /* DSC.cpp */, + 7A51F3A617D6386100A8F8F2 /* DSC.h */, + 7A51F3A917D6386100A8F8F2 /* util.h */, + 7A51F3AB17D6386100A8F8F2 /* velocity_function.h */, + 7A82D64517E23E9400C19874 /* object_generator.cpp */, + 7A82D64617E23E9400C19874 /* object_generator.h */, + 7A82D64917E23EAC00C19874 /* trializer.cpp */, + 7A82D64A17E23EAC00C19874 /* trializer.h */, + 7A82D64D17E272BB00C19874 /* design_domain.cpp */, + 7A82D64E17E272BB00C19874 /* design_domain.h */, + ); + path = DSC; + sourceTree = ""; + }; + 7A51F3BB17D6391500A8F8F2 /* DEMO */ = { + isa = PBXGroup; + children = ( + 7A470AE417F5282C001FC0CB /* log.cpp */, + 7A470AE517F5282C001FC0CB /* log.h */, + 7A9C20D917DFBE070064171E /* draw.cpp */, + 7A9C20DA17DFBE080064171E /* draw.h */, + 7A51F3C317D6393200A8F8F2 /* average_function.cpp */, + 7A51F3C417D6393200A8F8F2 /* average_function.h */, + 7A51F3C517D6393200A8F8F2 /* normal_function.cpp */, + 7A51F3C617D6393200A8F8F2 /* normal_function.h */, + 7A51F3C717D6393200A8F8F2 /* rotate_function.cpp */, + 7A51F3C817D6393200A8F8F2 /* rotate_function.h */, + 7A51F3C917D6393200A8F8F2 /* demo.cpp */, + 7A51F3CA17D6393200A8F8F2 /* user_interface.cpp */, + 7A51F3CB17D6393200A8F8F2 /* user_interface.h */, + ); + path = DEMO; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXHeadersBuildPhase section */ + 7A51F3D317D6399200A8F8F2 /* Headers */ = { + isa = PBXHeadersBuildPhase; + buildActionMask = 2147483647; + files = ( + 7A82D64817E23E9400C19874 /* object_generator.h in Headers */, + 7A82D64C17E23EAC00C19874 /* trializer.h in Headers */, + 7A82D65017E272BB00C19874 /* design_domain.h in Headers */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXHeadersBuildPhase section */ + +/* Begin PBXNativeTarget section */ + 7A51F3B917D6391500A8F8F2 /* DEMO */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7A51F3C017D6391500A8F8F2 /* Build configuration list for PBXNativeTarget "DEMO" */; + buildPhases = ( + 7A51F3B617D6391500A8F8F2 /* Sources */, + 7A51F3B717D6391500A8F8F2 /* Frameworks */, + 7A51F3B817D6391500A8F8F2 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DEMO; + productName = DEMO; + productReference = 7A51F3BA17D6391500A8F8F2 /* DEMO */; + productType = "com.apple.product-type.tool"; + }; + 7A51F3D417D6399200A8F8F2 /* DSC */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7A51F3D617D6399200A8F8F2 /* Build configuration list for PBXNativeTarget "DSC" */; + buildPhases = ( + 7A51F3D117D6399200A8F8F2 /* Sources */, + 7A51F3D217D6399200A8F8F2 /* Frameworks */, + 7A51F3D317D6399200A8F8F2 /* Headers */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = DSC; + productName = DSC; + productReference = 7A51F3D517D6399200A8F8F2 /* libDSC.a */; + productType = "com.apple.product-type.library.static"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 7A51F38F17D6383500A8F8F2 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0460; + ORGANIZATIONNAME = "Asger Nyman Christiansen"; + }; + buildConfigurationList = 7A51F39217D6383500A8F8F2 /* Build configuration list for PBXProject "DSC" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = 7A51F38E17D6383500A8F8F2; + productRefGroup = 7A51F39817D6383500A8F8F2 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 7A51F3D417D6399200A8F8F2 /* DSC */, + 7A51F3B917D6391500A8F8F2 /* DEMO */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + 7A51F3B617D6391500A8F8F2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7A51F3CC17D6393200A8F8F2 /* average_function.cpp in Sources */, + 7A51F3CD17D6393200A8F8F2 /* normal_function.cpp in Sources */, + 7A470AE617F5282C001FC0CB /* log.cpp in Sources */, + 7A51F3CE17D6393200A8F8F2 /* rotate_function.cpp in Sources */, + 7A51F3CF17D6393200A8F8F2 /* demo.cpp in Sources */, + 7A51F3D017D6393200A8F8F2 /* user_interface.cpp in Sources */, + 7A9C20DB17DFBE080064171E /* draw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 7A51F3D117D6399200A8F8F2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7A51F3DB17D639C900A8F8F2 /* DSC.cpp in Sources */, + 7A51F3DC17D639C900A8F8F2 /* DSC.h in Sources */, + 7A51F3DF17D639C900A8F8F2 /* util.h in Sources */, + 7A51F3E117D639C900A8F8F2 /* velocity_function.h in Sources */, + 7A82D64717E23E9400C19874 /* object_generator.cpp in Sources */, + 7A82D64B17E23EAC00C19874 /* trializer.cpp in Sources */, + 7A82D64F17E272BB00C19874 /* design_domain.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 7A51F39E17D6383500A8F8F2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + 7A51F39F17D6383500A8F8F2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_64_BIT)"; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.8; + SDKROOT = macosx; + }; + name = Release; + }; + 7A51F3C117D6391500A8F8F2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; + HEADER_SEARCH_PATHS = /Library/Frameworks/GEL.framework/Headers; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7A51F3C217D6391500A8F8F2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; + HEADER_SEARCH_PATHS = /Library/Frameworks/GEL.framework/Headers; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 7A51F3D717D6399200A8F8F2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; + HEADER_SEARCH_PATHS = /Library/Frameworks/GEL.framework/Headers; + LIBRARY_SEARCH_PATHS = /Library/Frameworks; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7A51F3D817D6399200A8F8F2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + EXECUTABLE_PREFIX = lib; + FRAMEWORK_SEARCH_PATHS = /Library/Frameworks; + HEADER_SEARCH_PATHS = /Library/Frameworks/GEL.framework/Headers; + LIBRARY_SEARCH_PATHS = /Library/Frameworks; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 7A51F39217D6383500A8F8F2 /* Build configuration list for PBXProject "DSC" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7A51F39E17D6383500A8F8F2 /* Debug */, + 7A51F39F17D6383500A8F8F2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7A51F3C017D6391500A8F8F2 /* Build configuration list for PBXNativeTarget "DEMO" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7A51F3C117D6391500A8F8F2 /* Debug */, + 7A51F3C217D6391500A8F8F2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 7A51F3D617D6399200A8F8F2 /* Build configuration list for PBXNativeTarget "DSC" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7A51F3D717D6399200A8F8F2 /* Debug */, + 7A51F3D817D6399200A8F8F2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 7A51F38F17D6383500A8F8F2 /* Project object */; +} diff --git a/DSC.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/DSC.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..dffa503 --- /dev/null +++ b/DSC.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout b/DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout new file mode 100644 index 0000000..8d162f9 --- /dev/null +++ b/DSC.xcodeproj/project.xcworkspace/xcshareddata/DSC.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 625E65FF-825D-4F34-8774-56989970BC68 + IDESourceControlProjectName + DSC + IDESourceControlProjectOriginsDictionary + + 729B663A-C65E-4FE1-83C0-A42968F5E064 + https://github.com/asny/2D-DSC.git + + IDESourceControlProjectPath + DSC.xcodeproj/project.xcworkspace + IDESourceControlProjectRelativeInstallPathDictionary + + 729B663A-C65E-4FE1-83C0-A42968F5E064 + ../.. + + IDESourceControlProjectURL + https://github.com/asny/2D-DSC.git + IDESourceControlProjectVersion + 110 + IDESourceControlProjectWCCIdentifier + 729B663A-C65E-4FE1-83C0-A42968F5E064 + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 729B663A-C65E-4FE1-83C0-A42968F5E064 + IDESourceControlWCCName + 2D-DSC + + + + diff --git a/DSC.xcodeproj/project.xcworkspace/xcuserdata/tuannt8.xcuserdatad/UserInterfaceState.xcuserstate b/DSC.xcodeproj/project.xcworkspace/xcuserdata/tuannt8.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..e524211052f5d592043b0b015599ec94dbb07816 GIT binary patch literal 22685 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 Q7DZWq1xf9!E|f3%fB2!QNB{r; literal 0 HcmV?d00001 diff --git a/DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/DSC.xcscheme b/DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/DSC.xcscheme new file mode 100644 index 0000000..a4363a7 --- /dev/null +++ b/DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/DSC.xcscheme @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/xcschememanagement.plist b/DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..b3910c4 --- /dev/null +++ b/DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,27 @@ + + + + + SchemeUserState + + DEMO.xcscheme + + orderHint + 3 + + DSC.xcscheme + + orderHint + 0 + + + SuppressBuildableAutocreation + + 7A51F3D417D6399200A8F8F2 + + primary + + + + + From 0d7d9394e97aaf950b789b7988ecc63c70cbaa16 Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Wed, 10 Oct 2018 10:04:59 +0200 Subject: [PATCH 11/20] Ignore userdata in Xcode project --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 7615ea0..5a3680e 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ DSC.xcodeproj/project.xcworkspace/xcuserdata/asny.xcuserdatad/UserInterfaceState DSC.xcodeproj/xcuserdata/asny.xcuserdatad/xcdebugger/Breakpoints.xcbkptlist DSC.xcodeproj/xcuserdata/asny.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist + +*userdata* \ No newline at end of file From 20630e2cae8ef38c05787ba715b677414080b01b Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Wed, 10 Oct 2018 13:04:24 +0200 Subject: [PATCH 12/20] DSC for topOpt --- .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../UserInterfaceState.xcuserstate | Bin 22685 -> 24690 bytes src/DSC.cpp | 843 ++---------------- src/DSC.h | 312 ++----- src/design_domain.cpp | 120 ++- src/design_domain.h | 311 ++++++- src/draw.cpp | 551 ++++++++++++ src/draw.h | 153 ++++ src/object_generator.cpp | 35 +- src/object_generator.h | 18 +- src/trializer.cpp | 34 +- src/util.h | 74 +- src/velocity_function.h | 15 +- 13 files changed, 1413 insertions(+), 1061 deletions(-) create mode 100644 DSC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 src/draw.cpp create mode 100644 src/draw.h diff --git a/DSC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/DSC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/DSC.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/DSC.xcodeproj/project.xcworkspace/xcuserdata/tuannt8.xcuserdatad/UserInterfaceState.xcuserstate b/DSC.xcodeproj/project.xcworkspace/xcuserdata/tuannt8.xcuserdatad/UserInterfaceState.xcuserstate index e524211052f5d592043b0b015599ec94dbb07816..acf9dd7d7a3b3de4b2ba88eafa273856e11fe0ee 100644 GIT binary patch delta 11573 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

@}BY>xn1s*_mP*%N6W{^>*V9)Q{~g;Gv#yS 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%0De?MwCCQA?l^5 zeNnGO9gI2@bvWwns1s42MxBrPEb8;9%TeD(eHV2t>bg>^bSrx*3zYqo1C)c5qm`4C zQYFnR1qLjxwNpM!8bCTKTMUopQahR#~sysXVCsMESj{xyq_aQ{`|ESE?GP z8n3EQO;lB>YE+X|^ZcqOR8Oj&QY}&~Q7uy~SFKRJrn;cU>IAhiy~i>VxVx)gPfjy@Lsb@bKf`!OwIJTaLuBV!iEyc+Xv%ttX7VlKvf z5pyZ#`uPmdblY^>bua4n>h|eg(Y>mBP4|xOxbA}PE8RD` zE4r(?8@gM%pLBP0zv{7GtdG{m=(T#iK2e{nPtm98{T_X~zK1?v-(NpaKUhChKUP0c zU!||nPu9=WGyN?69Q{1~68&oZX8jBL9r|7RJ^BOsgZe}I!}>S%r}UrcuN#QLV8}GI zHncT7X6RrTXc%EAHPjeZ88#X=8@3p>8MYhVFdQ+wZTO$zJ;PDMDZ_cgXNJ!WUmCtL z+%Vko8-6m}i6yb3*ygcevFh09SZ%C6))ecEO^r>9^~CyOb7S*j^JDwO4vifiJ0i9? zc6{v0*tN0m#2%0RIrcZB$>=n8GG-aO8oL{N8hyrGW1cbJ*vHt+p!eB%P+2IFhS_l;kgz~nV`HTg%HYD`N^>r5L=b*4?G2Gds4r>4uMUrcvR zznlIr-8X}om__F1=4i9ltT!9Yab~O8ZcZ|%m|f;}=Jw`}=Fa9-=1t}X^H%foaS$hs zlf^0GlyRfus^ccbO^JIv?r7ZExN~tA;x5K}<2%N8j_(rREq+n_v+?WV*T>iTg_$J{>!kvV>Jd2<uphUdu%EV{wO{euzq9{fzhS>^zhl2^ zzi0n5(VCc*I5u%n;!BC2I>133GKb2cacCVzhuL9qBskI?nU2Gny_mE! zX;0GrqytH>CHY@ZI+pZt(#517l5Qm3PP&tHH|bu|{bZahPgW*tlC{bDWMgt%vNhS3 zoSQs8Igq?B`7KyJYb&hq8bCx-$I-hVZbS`o( zbuM?Vbgpr(b8dI;aPD^Qb?$e*>OACp!+FH{ZHg?Vr9Wj*3QK87c_-!Fl=o9krkqZ> zlyW8IYRa{gn<=+b?xg&h+B`KpRg;>KnwXlLnwsiPO;62CZIjwF)tA~UH9xgaYQNM0 zse@97q|Q#QOMN%>noHrza22}BToYYYu1T(Gt{E=on&n#Rdd^kr+UROGvo+Do?aW=P`I3o-~iwli_LY>FCMw zbo2D^WP7STb)I9M)1FJ7tDb9~A3e7`cRlw!_r2Ily%F9>ugV+eP4p&vQ@w6)D{otG zdv8Z?XRpuO%R9t7(mTpq>MiqDc_(?NdZ&A5dgpr=c~@p9WZSdTvpZ#X$?l%*&(6-x z?w#EyyC}OjdsKF5c3F0L_Jr)p?3LLEvoHH(z8Ig`=kPgwEq(2LoqPj)gM1@>qkLn0 zV||l-kNc+k{JvSfIliZTOMJ_G%YEy7&-pg^w)*z_4)_lG4*3rIj`-g3z2`gXJL@~= zyWsmg$DPwYr(;g%oUS=5b2jE|PR`kq^L);&T$&q}8`)S3VSXhO{1dfo{A_y9mH!_K C$1Xhp diff --git a/src/DSC.cpp b/src/DSC.cpp index 823334a..65f6635 100644 --- a/src/DSC.cpp +++ b/src/DSC.cpp @@ -15,36 +15,10 @@ // See licence.txt for a copy of the GNU General Public License. #include "DSC.h" - -#ifdef TUAN_MULTI_RES -#include "image.h" -#endif - -#include -#include - -#define TETRA_PAK +#include "draw.h" namespace DSC2D -{ - const DSC2D::vec3 BACKGROUND_COLOR = DSC2D::vec3(0.7); // DSC2D::vec3(1.0); - const DSC2D::vec3 INVISIBLE = DSC2D::vec3(-1.); - const DSC2D::vec3 DARK_RED = DSC2D::vec3(0.66,0.11,0.15); - const DSC2D::vec3 RED = DSC2D::vec3(0.96,0.11,0.15); - const DSC2D::vec3 DARK_BLUE = DSC2D::vec3(0.14,0.16,0.88); - const DSC2D::vec3 BLUE = DSC2D::vec3(0.45,0.7,0.9); - const DSC2D::vec3 GREEN = DSC2D::vec3(0.05,1.,0.15); - const DSC2D::vec3 ORANGE = DSC2D::vec3(0.9,0.4,0.); - const DSC2D::vec3 BLACK = DSC2D::vec3(0.); - const DSC2D::vec3 DARK_GRAY = DSC2D::vec3(0.5); - const DSC2D::vec3 GRAY = DSC2D::vec3(0.8); - - typedef DSC2D::DeformableSimplicialComplex dsc_obj; - typedef dsc_obj::node_key Node_key; - typedef dsc_obj::face_key Face_key; - typedef dsc_obj::edge_key Edge_key; - typedef std::vector Vec2_array; - +{ DeformableSimplicialComplex::DeformableSimplicialComplex(real AVG_EDGE_LENGTH, const std::vector& points, const std::vector& faces, DesignDomain *domain): design_domain(domain) { set_avg_edge_length(AVG_EDGE_LENGTH); @@ -52,29 +26,17 @@ namespace DSC2D COS_MIN_ANGLE = cos(MIN_ANGLE); DEG_ANGLE = 0.2*MIN_ANGLE; -#ifdef TETRA_PAK - MAX_LENGTH = 2.; - MIN_LENGTH = 0.5;// 0.01;// 0.05 // 0.5; - DEG_LENGTH = 0.2*MIN_LENGTH; - - MAX_AREA = 5.; - MIN_AREA = 0.2; //0.001;//0.01;// 0.2; - - DEG_AREA = 0.2*MIN_AREA; -#else MAX_LENGTH = 2.; - MIN_LENGTH = 0.5;// 0.01;// 0.05 // 0.5; + MIN_LENGTH = 0.5; DEG_LENGTH = 0.2*MIN_LENGTH; MAX_AREA = 5.; - MIN_AREA = 0.2; //0.001;//0.01;// 0.2; - + MIN_AREA = 0.2; DEG_AREA = 0.2*MIN_AREA; -#endif INTERFACE_COLOR = DARK_RED; CROSSING_COLOR = RED; - OUTSIDE_COLOR = ORANGE; + OUTSIDE_COLOR = BLACK; DEFAULT_COLOR = DARK_BLUE; OUTSIDE_FACE_COLOR = INVISIBLE; DEFAULT_FACE_COLOR = BLUE; @@ -85,25 +47,15 @@ namespace DSC2D vertex_labels = HMesh::VertexAttributeVector(get_no_vertices(), OUTSIDE); edge_labels = HMesh::HalfEdgeAttributeVector(get_no_halfedges(), OUTSIDE); face_labels = HMesh::FaceAttributeVector(get_no_faces(), OUTSIDE); - face_att = HMesh::FaceAttributeVector>(get_no_faces(), - std::vector(NB_FORCES, Vec2(0.))); - bStable = HMesh::VertexAttributeVector(get_no_vertices(), 1); - - } void DeformableSimplicialComplex::cleanup_attributes(HMesh::IDRemap& cleanup_map) { mesh->cleanup(cleanup_map); vertex_labels.cleanup(cleanup_map.vmap); - edge_labels.cleanup(cleanup_map.hmap); face_labels.cleanup(cleanup_map.fmap); - destination.cleanup(cleanup_map.vmap); - bStable.cleanup(cleanup_map.vmap); - - } @@ -113,7 +65,7 @@ namespace DSC2D for(auto vi = vertices_begin(); vi != vertices_end(); ++vi) { switch (vertex_labels[*vi]) { - case INTERFACE_DSC: + case INTERFACE: colors[*vi] = INTERFACE_COLOR; break; case CROSSING: @@ -136,7 +88,7 @@ namespace DSC2D for(auto hei = halfedges_begin(); hei != halfedges_end(); ++hei) { switch (edge_labels[*hei]) { - case INTERFACE_DSC: + case INTERFACE: colors[*hei] = INTERFACE_COLOR; break; case OUTSIDE: @@ -174,7 +126,7 @@ namespace DSC2D mesh->build(points.size()/3, &points[0], temp.size(), &temp[0], &faces[0]); } - void DeformableSimplicialComplex::validity_check() + void DeformableSimplicialComplex::validity_check() const { for (auto fi = faces_begin(); fi != faces_end(); fi++) { int i = 0; @@ -202,7 +154,7 @@ namespace DSC2D void DeformableSimplicialComplex::resize_complex() { thickening_interface(); - + thinning_interface(); thickening(); @@ -226,9 +178,9 @@ namespace DSC2D min_t = Util::min(t, min_t); } } -//#ifdef DEBUG -// assert(min_t < INFINITY); -//#endif +#ifdef DEBUG + assert(min_t < INFINITY); +#endif return min_t; } @@ -237,93 +189,32 @@ namespace DSC2D vec2 pos = get_pos(vid); vec2 destination = get_destination(vid); real l = Util::length(destination - pos); - if (l < 1e-4 * AVG_LENGTH) + if (l < 1e-6 * AVG_LENGTH) { return true; } - real max_l = l*intersection_with_link(vid, destination) - 1e-4 * AVG_LENGTH; + real max_l = l*intersection_with_link(vid, destination) - 1e-6 * AVG_LENGTH; + l = Util::max(Util::min(0.5*max_l, l), 0.); + set_pos(vid, pos + l*Util::normalize(destination - pos)); - if (max_l < INFINITY) - { - l = Util::max(Util::min(0.5*max_l, l), 0.); - set_pos(vid, pos + l*Util::normalize(destination - pos)); - - if(Util::length(destination - get_pos(vid)) < 1e-4 * AVG_LENGTH) - { - return true; - } - return false; - } - else - { - return false; - } - - } - - DeformableSimplicialComplex * DeformableSimplicialComplex::clone(){ - DeformableSimplicialComplex * new_dsc = new DeformableSimplicialComplex; - - return new_dsc; - } - - void DeformableSimplicialComplex::recursive_split(HMesh::AttributeVector faces_to_split) - { - for(int i = 0; i < faces_to_split.size(); i++) - { - if(faces_to_split[face_key(i)]) - split_triangle_sub(face_key(i), faces_to_split); - } - } - - bool DeformableSimplicialComplex::split_triangle_sub(face_key f, HMesh::AttributeVector & faces_to_split) - { - auto eid = sorted_face_edges(f); - auto longest_e = eid[2]; - - while(1) + if(Util::length(destination - get_pos(vid)) < 1e-6 * AVG_LENGTH) { - // Check the other edge - auto hew = walker(longest_e); - if(hew.face() != f) - hew = hew.opp(); - - auto other_tri = hew.opp().face(); - if(other_tri == HMesh::InvalidFaceID) - break; - - auto eid2 = sorted_face_edges(other_tri); - auto longest_e2 = eid[2]; - if(longest_e2 != longest_e) - { - if(!split_triangle_sub(other_tri, faces_to_split)) - break; - }else{ - break; - } + return true; } - - - split(longest_e); - - // Update the list - if(f.get_index() < faces_to_split.size()) - faces_to_split[f] = 0; - - return true; + return false; } - void DeformableSimplicialComplex::deform(bool adaptive) + void DeformableSimplicialComplex::deform() { bool work = true; int count = 0; - while(work && count < 10) + while(work && count < 50) { work = false; for (auto vi = vertices_begin(); vi != vertices_end(); vi++) { - if(is_movable(*vi)) + if(is_movable(*vi)&&is_interface(*vi)) { work = work | !move_vertex(*vi); } @@ -332,26 +223,20 @@ namespace DSC2D fix_complex(); count++; } - - std::cout << "Deform DSC in " << count << " steps" << std::endl; - - if(!adaptive) - resize_complex(); + + resize_complex(); HMesh::IDRemap cleanup_map; cleanup_attributes(cleanup_map); -// Tuan commented out: It crash topology opt -// init_attributes(); -// End comment out + init_attributes(); update_attributes(); } bool DeformableSimplicialComplex::is_movable(node_key vid) const { - return !boundary(*mesh, vid) && (is_interface(vid) || is_crossing(vid)); //return unsafe_editable(vid) && is_interface(vid); - //return unsafe_editable(vid) && (is_interface(vid) || is_crossing(vid)); + return unsafe_editable(vid) && (is_interface(vid) || is_crossing(vid)); } bool DeformableSimplicialComplex::is_movable(edge_key eid) const @@ -379,51 +264,6 @@ namespace DSC2D return unsafe_editable(eid) && !is_interface(eid); } - bool DeformableSimplicialComplex::save(const char * filePath) - { - std::ofstream myfile(filePath); - if (myfile.is_open()) { - myfile << get_no_vertices() << " " << get_no_faces() << "\n"; - - // Write vertices - std::map index_map; - int idx = 0; - for (auto vkey : vertices()) - { - index_map.insert(std::make_pair(vkey.get_index(), idx++)); - auto p = get_pos(vkey); - myfile << p[0] << " " << p[1] << "\n"; - } - - // write face - for (auto fkey : faces()) - { - auto verts = get_verts(fkey); - myfile << index_map[(int)verts[0].get_index()] << " " - << index_map[(int)verts[1].get_index()] << " " - << index_map[(int)verts[2].get_index()] << " " - << get_label(fkey) << "\n"; - } - - myfile.close(); - return true; - }else{ - return false; - } - } - - bool DeformableSimplicialComplex::load(char * filePath) - { - std::ifstream myfile(filePath); - if (myfile.is_open()) { - - myfile.close(); - return true; - }else{ - return false; - } - } - real DeformableSimplicialComplex::max_move_distance() const { real dist, max_dist = 0.; @@ -451,6 +291,19 @@ namespace DSC2D return p; } + std::vector DeformableSimplicialComplex::get_design_variable_destinations() + { + std::vector p; + for (auto vi = vertices_begin(); vi != vertices_end(); vi++) + { + if(is_movable(*vi)) + { + p.push_back(get_destination(*vi)); + } + } + return p; + } + std::vector DeformableSimplicialComplex::get_interface_edge_positions() { std::vector p; @@ -465,6 +318,21 @@ namespace DSC2D } return p; } + + std::vector DeformableSimplicialComplex::get_interface_edge_destinations() + { + std::vector p; + for (auto eit = halfedges_begin(); eit != halfedges_end(); eit++) + { + if(is_interface(*eit)) + { + auto hew = walker(*eit); + p.push_back(get_destination(hew.vertex())); + p.push_back(get_destination(hew.opp().vertex())); + } + } + return p; + } vec2 DeformableSimplicialComplex::get_center() { @@ -476,16 +344,6 @@ namespace DSC2D return vec2(mesh->pos(vid)[0], mesh->pos(vid)[1]); } - std::vector DeformableSimplicialComplex::get_pos(edge_key eid) const - { - std::vector positions; - - auto hew = walker(eid); - positions.push_back(get_pos(hew.opp().vertex())); - positions.push_back(get_pos(hew.vertex())); - return positions; - } - std::vector DeformableSimplicialComplex::get_pos(face_key fid) const { std::vector positions; @@ -496,6 +354,13 @@ namespace DSC2D return positions; } + std::vector DeformableSimplicialComplex::get_pos(edge_key eid) const + { + auto hew = walker(eid); + + return {get_pos(hew.vertex()), get_pos(hew.opp().vertex())}; + } + vec2 DeformableSimplicialComplex::get_destination(node_key vid) const { return vec2(destination[vid]); @@ -511,12 +376,12 @@ namespace DSC2D return positions; } - std::vector DeformableSimplicialComplex::get_verts(node_key vid, bool _interface) const + std::vector DeformableSimplicialComplex::get_verts(node_key vid, bool interface) const { std::vector vids; for (auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) { - if(!_interface || is_interface(hew.halfedge())) + if(!interface || is_interface(hew.halfedge())) { vids.push_back(hew.vertex()); } @@ -569,10 +434,10 @@ namespace DSC2D void DeformableSimplicialComplex::set_destination(const node_key& vid, const vec2& dest) { - if(is_movable(vid)) + // if(is_movable(vid)) { vec2 vec = dest - get_pos(vid); - clamp_vector(vid, vec); + // clamp_vector(vid, vec); destination[vid] = get_pos(vid) + vec; } } @@ -598,9 +463,6 @@ namespace DSC2D void DeformableSimplicialComplex::init_attributes(node_key vid) { destination[vid] = get_pos(vid); - - bStable[vid] = 1; - } void DeformableSimplicialComplex::init_attributes(face_key fid, int label) @@ -611,7 +473,6 @@ namespace DSC2D } } - void DeformableSimplicialComplex::update_attributes(node_key vid, int label) { @@ -635,7 +496,7 @@ namespace DSC2D } else if(inter > 0) { - vertex_labels[vid] = INTERFACE_DSC; + vertex_labels[vid] = INTERFACE; } else if(!boundary(*mesh, vid)) { @@ -666,8 +527,8 @@ namespace DSC2D if (fa1 != fa2) { - edge_labels[heid] = INTERFACE_DSC; - edge_labels[hew.opp().halfedge()] = INTERFACE_DSC; + edge_labels[heid] = INTERFACE; + edge_labels[hew.opp().halfedge()] = INTERFACE; } else { @@ -706,64 +567,17 @@ namespace DSC2D void DeformableSimplicialComplex::update_attributes() { - for(auto fi = faces_begin(); fi != faces_end(); ++fi) + for(auto fi = faces_begin(); fi != faces_end(); ++fi) { update_attributes(*fi); } } - bool DeformableSimplicialComplex::split_adpat_mesh(edge_key eid) - { - - if (!unsafe_editable(eid)) { - return false; - } - - auto hew = walker(eid); - face_key f1 = hew.face(); - node_key v1 = hew.next().vertex(); - face_key f2 = hew.opp().face(); - node_key v2 = hew.opp().next().vertex(); - - auto l1 = get_label(f1); - auto l2 = get_label(f2); - - if (!mesh->in_use(f1) or !mesh->in_use(f2) - or !mesh->in_use(v1) or !mesh->in_use(v2)) - { - return false; - } - - // Split - node_key vid = mesh->split_edge(eid); - face_key newf1 = mesh->split_face_by_edge(f1, vid, v1); - face_key newf2 = mesh->split_face_by_edge(f2, vid, v2); - - // Update attributes - init_attributes(vid); - for(auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) - { - if(hew.halfedge() != eid && hew.opp().halfedge() != eid) - { - init_attributes(hew.halfedge()); - } - } - init_attributes(newf1, l1); - init_attributes(newf2, l2); - - - update_locally(vid); - - // add stablity check - bStable[vid] = 0; - - return true; - } bool DeformableSimplicialComplex::split(edge_key eid) { - - if (!unsafe_editable(eid)) { + if (!unsafe_editable(eid)) + { return false; } @@ -791,54 +605,27 @@ namespace DSC2D init_attributes(newf2, get_label(f2)); update_locally(vid); - return true; } bool DeformableSimplicialComplex::split(face_key fid) { -// bool success = split(sorted_face_edges(fid).back()); -// return success; - // check quality + int fa = get_label(fid); + node_key vid = mesh->split_face_by_vertex(fid); - /* - TUAN: if the triangle is obtuse, split long edge - */ - auto hew = walker(fid); - if (max_angle(fid, hew) > 120*M_PI / 180.) + init_attributes(vid); + + for(auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) { - return split(sorted_face_edges(fid).back()); - } - else - //-- - { -// // Check quality first -// bool should_split = true; -// { -// auto pts = get_pos(fid); -// auto v = (pts[0] + pts[1] + pts[2])/3.0; - -// } - - int fa = get_label(fid); - node_key vid = mesh->split_face_by_vertex(fid); - - init_attributes(vid); - - - for(auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) - { - init_attributes(hew.halfedge()); - init_attributes(hew.face(), fa); - } - - update_locally(vid); - - return true; + init_attributes(hew.halfedge()); + init_attributes(hew.face(), fa); } + + update_locally(vid); + return true; } - real DeformableSimplicialComplex::min_quality(const std::vector& eids, const vec2& pos_old, const vec2& pos_new) + real DeformableSimplicialComplex::min_quality(const std::vector& eids, const vec2& pos_old, const vec2& pos_new) const { real min_q = INFINITY; for (auto e : eids) @@ -854,7 +641,7 @@ namespace DSC2D return min_q; } - bool DeformableSimplicialComplex::is_collapsable(HMesh::Walker hew, bool safe) + bool DeformableSimplicialComplex::is_collapsable(HMesh::Walker hew, bool safe) const { if(safe) { @@ -862,15 +649,6 @@ namespace DSC2D { return true; } - /*TUAN add: Do not move crossing vertex, even one of the interface is straight*/ - else - { - if (is_crossing(hew.opp().vertex())) - { - return false; - } - } - // end } else { if(unsafe_editable(hew.opp().vertex())) @@ -878,7 +656,6 @@ namespace DSC2D return true; } } - if(is_interface(hew.halfedge())) { vec2 p0 = get_pos(hew.opp().vertex()); @@ -973,14 +750,8 @@ namespace DSC2D return false; } - bool DeformableSimplicialComplex::collapse(HMesh::Walker hew, real weight, bool safe) + bool DeformableSimplicialComplex::collapse(HMesh::Walker hew, real weight) { - if(! (precond_collapse_edge(*mesh, hew.halfedge()) - && is_collapsable(hew, safe) -// && unsafe_editable(hew.halfedge()) // Tuan: boundary should becollapsable - )) - return false; - node_key vid = hew.vertex(); vec2 p = (1.-weight) * get_pos(hew.vertex()) + weight * get_pos(hew.opp().vertex()); vec2 d = (1.-weight) * get_destination(hew.vertex()) + weight * get_destination(hew.opp().vertex()); @@ -1035,63 +806,15 @@ namespace DSC2D return Util::length(get_destination(hew.vertex()) - get_destination(hew.opp().vertex())); } - real DeformableSimplicialComplex::min_edge_length(face_key fid) + real DeformableSimplicialComplex::min_edge_length(face_key fid) const { std::vector p = get_pos(fid); return Util::min(Util::min(Util::length(p[0] - p[1]), Util::length(p[1] - p[2])), Util::length(p[0] - p[2])); } - real DeformableSimplicialComplex::max_angle(face_key fid, HMesh::Walker &hmax) - { - double min_cos = INFINITY; - - for (auto hew = walker(fid); !hew.full_circle(); hew = hew.circulate_face_ccw()) - { - auto p = get_pos(hew.next().vertex()); - auto p1 = get_pos(hew.vertex()); - auto p2 = get_pos(hew.opp().vertex()); - - double cos_a = Util::cos_angle(p1, p, p2); - if (cos_a < min_cos) - { - min_cos = cos_a; - hmax = hew; - } - } - - return acos(min_cos); - } - - HMesh::Walker DeformableSimplicialComplex::max_angle_point(face_key fid) - { - HMesh::Walker h_max = walker(fid); - double min_cos = INFINITY; - - for (auto hew = walker(fid); !hew.full_circle(); hew = hew.circulate_face_ccw()) - { - auto p = get_pos(hew.vertex()); - auto p1 = get_pos(hew.next().vertex()); - auto p2 = get_pos(hew.next().next().vertex()); - - double cos_a = Util::cos_angle(p1, p, p2); - if (cos_a < min_cos) - { - min_cos = cos_a; - h_max = hew; - } - } - - return h_max; - } - - real DeformableSimplicialComplex::min_angle(face_key fid) + real DeformableSimplicialComplex::min_angle(face_key fid) const { std::vector p = get_pos(fid); - if (p.size() != 3) - { - throw std::invalid_argument("Get tri vertex error"); - return 0; - } return Util::min_angle(p[0], p[1], p[2]); } @@ -1115,6 +838,7 @@ namespace DSC2D #ifdef DEBUG if (split(f)) { + std::cout << "Split needle" << std::endl; } #else split(f); @@ -1143,108 +867,10 @@ namespace DSC2D { if(mesh->in_use(*fi)) { - /* Tuan - In case of obtuse triangle, collapse edge is not enough. - We need merge the triangles - See: https://goo.gl/oMxXcX The degenerated triangle should be handle by adding point - to the long edge - */ - - bool modified = false; - - HMesh::Walker hew = walker(*fi); - if(max_angle(*fi, hew) > M_PI * 165. / 180.) - { - { -// auto midpoint = (get_pos(hew.vertex()) + get_pos(hew.opp().vertex()))/2; -// auto pp = get_pos(hew.next().vertex()); -// if ((midpoint-pp).length() > MIN_LENGTH*AVG_LENGTH) -// { -// try -// { -// if(mesh->in_use(*fi) && ( -// (min_angle(*fi) < DEG_ANGLE || area(*fi) < DEG_AREA*AVG_AREA) && !collapse(*fi, true)) -// ) -// { -// collapse(*fi, false); -// } -// } -// catch (std::exception & e) -// { -// cout << e.what(); -// } -// -// continue; -// } - } - if (!unsafe_editable(hew.halfedge())) { - continue; - } - - modified = true; - - // add point to edge - face_key f1 = hew.face(); - node_key v1 = hew.next().vertex(); - face_key f2 = hew.opp().face(); - node_key v2 = hew.opp().next().vertex(); - - - // Split - node_key vid = mesh->split_edge(hew.halfedge()); - face_key newf1 = mesh->split_face_by_edge(f1, vid, v1); - face_key newf2 = mesh->split_face_by_edge(f2, vid, v2); - - // Update attributes - auto eid = hew.halfedge(); - init_attributes(vid); - for(auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) - { - if(hew.halfedge() != eid && hew.opp().halfedge() != eid) - { - init_attributes(hew.halfedge()); - } - } - init_attributes(newf1, get_label(f1)); - init_attributes(newf2, get_label(f2)); - - update_locally(vid); - - // merge vid and v1 - set_pos(vid, get_pos(v1)); - auto hw = walker(v1); - for (; !hw.full_circle(); hw = hw.circulate_vertex_ccw()) - { - if (hw.vertex() == vid) - { - break; - } - } - mesh->collapse_edge(hw.halfedge()); - update_locally(hw.vertex()); - } - else - { - try - { - if(mesh->in_use(*fi) && ( - (min_angle(*fi) < DEG_ANGLE || area(*fi) < DEG_AREA*AVG_AREA) && !collapse(*fi, true)) - ) - { - collapse(*fi, false); - } - } - catch (std::exception & e) - { - std::cout << e.what(); - } - } - /** Old code if((min_angle(*fi) < DEG_ANGLE || area(*fi) < DEG_AREA*AVG_AREA) && !collapse(*fi, true)) { collapse(*fi, false); } - */ } } } @@ -1286,9 +912,9 @@ namespace DSC2D } } - vec2 DeformableSimplicialComplex::get_barycenter(node_key vid, bool _interface) const + vec2 DeformableSimplicialComplex::get_barycenter(node_key vid, bool interface) const { - if(_interface && !is_interface(vid)) + if(interface && !is_interface(vid)) { return get_pos(vid); } @@ -1298,7 +924,7 @@ namespace DSC2D for (auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) { - if(is_interface(hew.halfedge()) || !_interface) + if(is_interface(hew.halfedge()) || !interface) { avg_pos += get_pos(hew.vertex()); n++; @@ -1513,10 +1139,7 @@ namespace DSC2D for (auto e : edges) { auto hew = walker(e); - if(length(e) > MAX_LENGTH*AVG_LENGTH - // || is_crossing(hew.vertex()) - // || is_crossing(hew.opp().vertex()) - ) + if(length(e) > MAX_LENGTH*AVG_LENGTH || is_crossing(hew.vertex()) || is_crossing(hew.opp().vertex())) { bool success = split(e); #ifdef DEBUG @@ -1596,8 +1219,6 @@ namespace DSC2D for(auto fi = faces_begin(); fi != faces_end(); fi++) { - - if(mesh->in_use(*fi) && area(*fi) < MIN_AREA*AVG_AREA) { bool success = collapse(*fi, true); @@ -1611,7 +1232,7 @@ namespace DSC2D } } - + bool operator<(const DeformableSimplicialComplex::PQElem& e0, const DeformableSimplicialComplex::PQElem& e1) { return e0.pri > e1.pri; @@ -1630,7 +1251,6 @@ namespace DSC2D if((energy<0) && (t < 10000)){ Q.push(PQElem(energy, h, t)); } - } void DeformableSimplicialComplex::add_one_ring_to_queue(HMesh::HalfEdgeAttributeVector& touched, std::priority_queue& Q, node_key v, const HMesh::EnergyFun& efun) @@ -1677,284 +1297,5 @@ namespace DSC2D HMesh::MinAngleEnergy energy_fun(MIN_ANGLE); priority_queue_optimization(energy_fun); } - - void DeformableSimplicialComplex::split_edge(DeformableSimplicialComplex::edge_key ek) { - split(ek); - } - - void DeformableSimplicialComplex::remove_degenerate_needle2(Face_key fkey) - { - - auto edges = sorted_face_edges(fkey); - int l = get_label(fkey); - - { - - } - - return; - - { - auto hew1 = walker(edges[2]); - auto hew2 = walker(edges[1]); - face_key f_out1 = hew1.opp().face(); - face_key f_out2 = hew2.opp().face(); - node_key n_out1 = hew1.opp().next().vertex(); - node_key n_out2 = hew2.opp().next().vertex(); - - if (!mesh->in_use(f_out1) or !mesh->in_use(f_out2) - or !mesh->in_use(n_out1) or !mesh->in_use(n_out2)) - { - return; - } - - // Split the two edges - node_key n1 = mesh->split_edge(hew1.halfedge()); - node_key n2 = mesh->split_edge(hew2.halfedge()); - // Split the faces - face_key new_f1 = mesh->split_face_by_edge(f_out1, n_out1, n1); - face_key new_f2 = mesh->split_face_by_edge(f_out2, n_out2, n2); - face_key new_f_in = mesh->split_face_by_edge(fkey, n1, n2); - - // collapse edge n1-n2 - auto hem = walker(n1); - for (; !hem.full_circle(); hem = hem.circulate_vertex_ccw()) - { - if (hem.vertex() == n2) - { - break; - } - } - mesh->collapse_edge(hem.halfedge(), true); - - // Update attribute - init_attributes(n2); - for(auto hew = walker(n2); !hew.full_circle(); hew = hew.circulate_vertex_cw()) - { - //if(hew.halfedge() != n2 && hew.opp().halfedge() != n2) - { - init_attributes(hew.halfedge()); - } - } - init_attributes(new_f1, get_label(f_out1)); - init_attributes(new_f2, get_label(f_out2)); - init_attributes(new_f_in, l); - - update_locally(n2); - } - return; - } - - void DeformableSimplicialComplex::remove_degenerate_needle(Face_key fkey) - { - - auto edges = sorted_face_edges(fkey); - int l = get_label(fkey); - - if(is_interface(edges[2]) || is_interface(edges[1])) - { - return; - } - - { - auto hew1 = walker(edges[2]); - auto hew2 = walker(edges[1]); - face_key f_out1 = hew1.opp().face(); - face_key f_out2 = hew2.opp().face(); - node_key n_out1 = hew1.opp().next().vertex(); - node_key n_out2 = hew2.opp().next().vertex(); - - if (!mesh->in_use(f_out1) or !mesh->in_use(f_out2) - or !mesh->in_use(n_out1) or !mesh->in_use(n_out2)) - { - return; - } - - // Split the two edges - node_key n1 = mesh->split_edge(hew1.halfedge()); - node_key n2 = mesh->split_edge(hew2.halfedge()); - // Split the faces - face_key new_f1 = mesh->split_face_by_edge(f_out1, n_out1, n1); - face_key new_f2 = mesh->split_face_by_edge(f_out2, n_out2, n2); - face_key new_f_in = mesh->split_face_by_edge(fkey, n1, n2); - - // collapse edge n1-n2 - auto hem = walker(n1); - for (; !hem.full_circle(); hem = hem.circulate_vertex_ccw()) - { - if (hem.vertex() == n2) - { - break; - } - } - mesh->collapse_edge(hem.halfedge(), true); - - // Update attribute - init_attributes(n2); - for(auto hew = walker(n2); !hew.full_circle(); hew = hew.circulate_vertex_cw()) - { - //if(hew.halfedge() != n2 && hew.opp().halfedge() != n2) - { - init_attributes(hew.halfedge()); - } - } - init_attributes(new_f1, get_label(f_out1)); - init_attributes(new_f2, get_label(f_out2)); - init_attributes(new_f_in, l); - - update_locally(n2); - } - return; - - node_key vn1, vn2; - {// Split edge 0 - auto eid = edges[2]; - auto hew = walker(eid); - face_key f1 = hew.face(); - node_key v1 = hew.next().vertex(); - face_key f2 = hew.opp().face(); - node_key v2 = hew.opp().next().vertex(); - - node_key vid = mesh->split_edge(eid); - face_key newf1 = mesh->split_face_by_edge(f1, vid, v1); - face_key newf2 = mesh->split_face_by_edge(f2, vid, v2); - - // Update attributes - init_attributes(vid); - for(auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) - { - if(hew.halfedge() != eid && hew.opp().halfedge() != eid) - { - init_attributes(hew.halfedge()); - } - } - init_attributes(newf1, get_label(f1)); - init_attributes(newf2, get_label(f2)); - - update_locally(vid); - - vn1 = vid; - } - - {// Split edge 0 - auto eid = edges[1]; - auto hew = walker(eid); - face_key f1 = hew.face(); - node_key v1 = hew.next().vertex(); - face_key f2 = hew.opp().face(); - node_key v2 = hew.opp().next().vertex(); - - node_key vid = mesh->split_edge(eid); - face_key newf1 = mesh->split_face_by_edge(f1, vid, v1); - face_key newf2 = mesh->split_face_by_edge(f2, vid, v2); - - // Update attributes - init_attributes(vid); - for(auto hew = walker(vid); !hew.full_circle(); hew = hew.circulate_vertex_cw()) - { - if(hew.halfedge() != eid && hew.opp().halfedge() != eid) - { - init_attributes(hew.halfedge()); - } - } - init_attributes(newf1, get_label(f1)); - init_attributes(newf2, get_label(f2)); - - update_locally(vid); - - vn2 = vid; - } - - // merge v2 and v1 - auto pt = (get_pos(vn1) + get_pos(vn2)) / 2.0; - auto hew = walker(vn1); - for (; !hew.full_circle(); hew = hew.circulate_vertex_ccw()) - { - if (hew.vertex() == vn2) - { - break; - } - } - - update_attributes(hew.halfedge(), OUTSIDE, OUTSIDE); - update_attributes(hew.prev().halfedge(), OUTSIDE, OUTSIDE); - update_attributes(hew.opp().next().halfedge(), OUTSIDE, OUTSIDE); - update_attributes(hew.next().halfedge(), OUTSIDE, OUTSIDE); - update_attributes(hew.opp().prev().halfedge(), OUTSIDE, OUTSIDE); - update_attributes(hew.opp().vertex(), OUTSIDE); - - mesh->collapse_edge(hew.halfedge()); - - update_locally(vn2); - set_pos(vn2, pt); - set_destination(vn2, pt); - } - - void DeformableSimplicialComplex::increase_resolution_range(){ - MAX_LENGTH = 2.; - MIN_LENGTH = MIN_LENGTH / 2.0; - DEG_LENGTH = 0.2*MIN_LENGTH; - - MAX_AREA = 5.; - MIN_AREA = MIN_AREA / 4; - - DEG_AREA = 0.2*MIN_AREA; - } - - void DeformableSimplicialComplex::set_uniform_smallest_feature(double length) - { - // Length - MAX_LENGTH = 1; - MIN_LENGTH = length / AVG_LENGTH /2.0; - DEG_LENGTH = MIN_LENGTH;// 0.2*MIN_LENGTH; - - // Area - MAX_AREA = 1; - MIN_AREA = MIN_LENGTH*MIN_LENGTH; - DEG_AREA = MIN_AREA; //0.2*MIN_AREA; - } - - void DeformableSimplicialComplex::set_smallest_feature_size(double length) - { - // Length - MAX_LENGTH = 10.; - MIN_LENGTH = length / AVG_LENGTH; - DEG_LENGTH = MIN_LENGTH;// 0.2*MIN_LENGTH; - - // Area - MAX_AREA = 10.; - MIN_AREA = MIN_LENGTH*MIN_LENGTH*0.5; - DEG_AREA = MIN_AREA; //0.2*MIN_AREA; - } - void DeformableSimplicialComplex::refine_without_change_interface(){ - /** - Restore original parametters - */ - MAX_LENGTH = 2.; - MIN_LENGTH = 0.5;// 0.01;// 0.05 // 0.5; - DEG_LENGTH = 0.2*MIN_LENGTH; - - MAX_AREA = 5.; - MIN_AREA = 0.2; //0.001;//0.01;// 0.2; - - DEG_AREA = 0.2*MIN_AREA; - - /** - Collapse all small triangle - */ - thinning(); - - smooth(); - - max_min_angle(); - } - - void DeformableSimplicialComplex::clean_attributes() { - HMesh::IDRemap cleanup_map; - cleanup_attributes(cleanup_map); - - init_attributes(); - update_attributes(); - } } diff --git a/src/DSC.h b/src/DSC.h index 66fd838..eb02e5a 100644 --- a/src/DSC.h +++ b/src/DSC.h @@ -28,23 +28,9 @@ #include #endif -//#define TUAN_SEG - -// #define TUAN_MULTI_RES - -#ifdef TUAN_MULTI_RES -class image; -#endif - -#define NB_FORCES 10 - -struct node_atrr{ - -}; +#define EPSILON 1e-9 namespace DSC2D { - typedef DSC2D::vec2 Vec2; - typedef DSC2D::vec3 Vec3; /** @@ -54,7 +40,7 @@ namespace DSC2D { { friend class ObjectGenerator; public: - enum LABEL_OPT {NO_LABEL = -3, OUTSIDE = 0, INTERFACE_DSC = -1, CROSSING = -2}; + enum LABEL_OPT {NO_LABEL = -3, OUTSIDE = 0, INTERFACE = -1, CROSSING = -2}; enum OBJECTS_TYPE {FILLED_HALF, FILLED, SQUARE, BLOB, BLOBS}; typedef HMesh::VertexID node_key; @@ -74,7 +60,7 @@ namespace DSC2D { pri(_pri), h(_h), time(_time) {} }; - protected:public: // testing + protected: real AVG_LENGTH; real AVG_AREA; @@ -98,40 +84,19 @@ namespace DSC2D { vec3 OUTSIDE_FACE_COLOR; vec3 DEFAULT_FACE_COLOR; - public: + private: HMesh::Manifold *mesh; DesignDomain *design_domain; HMesh::VertexAttributeVector destination; - HMesh::VertexAttributeVector internal_node_forces; - HMesh::VertexAttributeVector external_node_forces; - HMesh::VertexAttributeVector bStable; - - - HMesh::VertexAttributeVector> forces; - - double default_dt = 0.0; - HMesh::VertexAttributeVector dts; - void set_default_dt(double dt_); - - HMesh::VertexAttributeVector vertex_labels; HMesh::HalfEdgeAttributeVector edge_labels; HMesh::FaceAttributeVector face_labels; - - public: - HMesh::FaceAttributeVector> face_att; - - // attibute - HMesh::VertexAttributeVector> node_att_i; - HMesh::HalfEdgeAttributeVector> edge_att_i; //************** INITIALISATION *************** public: - - /** Creates a simplicial complex with size (SIZE_X_, SIZE_Y_). The input parameters specifies the design domain, the initial object(s) and the discretization. The latter is defined by the parameter AVG_EDGE_LENGTH, which tells how long edges are on average. */ @@ -148,10 +113,7 @@ namespace DSC2D { */ void create_simplicial_complex(const std::vector& points, const std::vector& faces); - DeformableSimplicialComplex(){} - //************** DISPLAY FUNCTIONS *************** -#pragma mark - Display fuctions public: /** Returns the vertex colors. @@ -167,11 +129,9 @@ namespace DSC2D { Returns the face colors. */ virtual HMesh::FaceAttributeVector get_face_colors() const; - //************** ATTRIBUTE FUNCTIONS *************** -#pragma mark - attribute functions - public: + protected: /** Clean up the attribute vectors (the lists that stores the attributes of each vertex, edge and face). Should be called after removing primitives. @@ -225,11 +185,10 @@ namespace DSC2D { /** Updates face, edge and vertex attributes. */ - void update_attributes(); + void update_attributes(); // It should be protected, but keep it public for the backforward compatibility. (Haojie). //************** GETTERS *************** -#pragma mark - Getters public: /** @@ -240,6 +199,56 @@ namespace DSC2D { return AVG_LENGTH; } + real get_min_edge_length() const + { + return MIN_LENGTH; + } + + real get_deg_edge_length() const + { + return DEG_LENGTH; + } + + real get_max_edge_length() const + { + return MAX_LENGTH; + } + + real get_avg_area() const + { + return AVG_AREA; + } + + real get_min_area() const + { + return MIN_AREA; + } + + real get_deg_area() const + { + return DEG_AREA; + } + + real get_max_area() const + { + return MAX_AREA; + } + + real get_min_angle() const + { + return MIN_ANGLE; + } + + real get_deg_angle() const + { + return DEG_ANGLE; + } + + real get_cos_min_angle() const + { + return COS_MIN_ANGLE; + } + /** Returns the approximate center of the simplicial complex. */ @@ -285,30 +294,20 @@ namespace DSC2D { return static_cast(mesh->no_faces()); } - int get_no_nodes_allocated() const - { - return static_cast(mesh->allocated_vertices()); - } - - int get_no_faces_allocated() const - { - return static_cast(mesh->allocated_faces()); - } - /** Returns the position of the vertex with ID vid. */ vec2 get_pos(node_key vid) const; /** - Returns the positions of the vertices of the face with ID fid. + Returns the positions of the vertices of the edge with ID eid. */ - std::vector get_pos(face_key fid) const; + std::vector get_pos(edge_key eid) const; /** - Returns the positions of the vertices of the edge with ID fid. + Returns the positions of the vertices of the face with ID fid. */ - std::vector get_pos(edge_key fid) const; + std::vector get_pos(face_key fid) const; /** Returns the new position of the vertex with ID vid. @@ -323,7 +322,7 @@ namespace DSC2D { /** Returns the IDs of the neighbouring vertices of the vertex with ID vid. If the interface parameter is true, it only returns the neighbouring vertices which are also interface. */ - std::vector get_verts(node_key vid, bool _interface = false) const; + std::vector get_verts(node_key vid, bool interface = false) const; /** Returns the IDs of the vertices of the face with ID fid. @@ -365,51 +364,8 @@ namespace DSC2D { */ std::vector get_interface_labels(node_key vid) const; - /** - Node force - */ - vec2 get_node_internal_force(node_key vid) const{ - return internal_node_forces[vid]; - } - - - - vec2 get_node_external_force(node_key vid) const{ - return external_node_forces[vid]; - } - - const HMesh::VertexAttributeVector & get_internal_force () const{ - return internal_node_forces; - } - - const HMesh::VertexAttributeVector & get_external_force () const{ - return external_node_forces; - } - - vec2 get_node_force(node_key vid, int index){ - return forces[vid][index]; - } - - void set_node_force(node_key vid, vec2 f, int index){ - forces[vid][index] = f; - } - - void add_node_force(node_key vid, vec2 f, int index){ - forces[vid][index] += f; - } - - /* - Time step - */ - void set_time(node_key vid, double new_t){ - dts[vid] = new_t; - }; - double time_step(node_key const vid) const{ - return dts[vid]; - } //************** SETTERS *************** -#pragma mark - Setter protected: /** @@ -418,44 +374,6 @@ namespace DSC2D { void set_pos(node_key vid, vec2 p); public: - - /** - Internal force - */ - void set_node_internal_force(node_key vid, vec2 force){ - internal_node_forces[vid] = force; - } - - void add_node_internal_force(node_key vid, vec2 force){ -#ifdef DEBUG - assert(!Util::isnan(force[0]) && !Util::isnan(force[1])); -#endif - internal_node_forces[vid] += force; - } - - /** - External force - */ - void set_node_external_force(node_key vid, vec2 force){ - external_node_forces[vid] = force; - } - - void add_node_external_force(node_key vid, vec2 force){ - external_node_forces[vid] += force; - } - - void set_label(face_key fid, int new_label){ - face_labels[fid] = new_label; - } - - void set_phase_attr(face_key fid, vec2 new_attr, int idx){ - face_att[fid][idx] = new_attr; - }; - - vec2 get_phase_attr(face_key fid, int idx){ - return face_att[fid][idx]; - } - /** Sets the destination of the vertex with ID vid to dest. To actually move the vertices to their destination, call the deform function. @@ -472,7 +390,6 @@ namespace DSC2D { } //************** ITERATORS *************** -#pragma mark - Iterators public: HMesh::VertexIDIterator vertices_begin() const { @@ -499,18 +416,6 @@ namespace DSC2D { return mesh->faces_begin(); } - HMesh::IDIteratorPair vertices() const { - return mesh->vertices(); - } - - HMesh::IDIteratorPair halfedges() const { - return mesh->halfedges(); - } - - HMesh::IDIteratorPair faces() const { - return mesh->faces(); - } - HMesh::FaceIDIterator faces_end() const { return mesh->faces_end(); @@ -532,7 +437,6 @@ namespace DSC2D { } //************** PRECONDITIONS *************** -#pragma mark - Preconditions public: /** Returns whether the vertex with ID vid is situated at a crossing of interfaces. @@ -555,7 +459,7 @@ namespace DSC2D { */ bool is_interface(node_key vid) { - return vertex_labels[vid] == INTERFACE_DSC; + return vertex_labels[vid] == INTERFACE; } /** @@ -563,7 +467,7 @@ namespace DSC2D { */ bool is_interface(node_key vid) const { - return vertex_labels[vid] == INTERFACE_DSC; + return vertex_labels[vid] == INTERFACE; } /** @@ -571,7 +475,7 @@ namespace DSC2D { */ bool is_interface(edge_key eid) { - return edge_labels[eid] == INTERFACE_DSC; + return edge_labels[eid] == INTERFACE; } /** @@ -579,7 +483,7 @@ namespace DSC2D { */ bool is_interface(edge_key eid) const { - return edge_labels[eid] == INTERFACE_DSC; + return edge_labels[eid] == INTERFACE; } /** @@ -640,7 +544,7 @@ namespace DSC2D { */ virtual bool is_movable(edge_key eid) const; - public: + protected: /** Returns whether the vertex with ID vid is editable, but not safe to interface changes i.e. if you edit the vertex you may change the interface. @@ -663,14 +567,13 @@ namespace DSC2D { virtual bool safe_editable(edge_key eid) const; //************** MESH FUNCTIONS *************** -#pragma mark - Mesh functions public: /** Move the vertices in the simplicial complex to their new position. The new position is set by the update_pos function. */ - void deform(bool adaptive = false); + void deform(); - public: + private: /** Moves a the vertex with ID vid to its new position. Returns whether the vertex was succesfully moved to its new position. @@ -700,17 +603,10 @@ namespace DSC2D { /** Collapses the edge with pointed to by the walker hew and updates attributes. The weight determines position and destination of the surviving node which are a weight between the two original nodes. Returns whether it suceeds or not. */ - bool collapse(HMesh::Walker hew, real weight, bool safe = false); - - /** - Splits the edge eid by inserting a vertex at the center of the edge and splitting the two neighbouring faces of the edge. Returns whether it suceeds or not. - For mesh adaptation. We need stability of the vertex. - */ - bool split_adpat_mesh(edge_key eid); + bool collapse(HMesh::Walker hew, real weight); //************** QUALITY CONTROL *************** -#pragma mark - Quality control protected: /** @@ -734,13 +630,11 @@ namespace DSC2D { */ void max_min_angle(); - public: /** Performs Laplacian smoothing on all safe editable vertices. */ void smooth(real t = 1.); - - private: + /** Remove needles, triangles with one very short edge, by splitting the face (inserting a vertex at the barycenter of the face). */ @@ -762,7 +656,6 @@ namespace DSC2D { void remove_degenerate_faces(); //************** DETAIL CONTROL *************** -#pragma mark - Detail control public: /** @@ -777,7 +670,7 @@ namespace DSC2D { void thickening_interface(); /** - Collapse interface edges that are too short. + Collapse interface edges that are too long. */ void thinning_interface(); @@ -793,52 +686,34 @@ namespace DSC2D { void thickening(); //************** UTIL *************** -#pragma mark - Utilities - private: public: + protected: /** Checks that the mesh is valid, i.e. that each face has three vertices and that the area of a face is positive (the face is not degenerate). */ - void validity_check(); + void validity_check() const; /** Returns the minimum angle of the face with ID fid. */ - real min_angle(face_key fid); - - /** - Returns the max angle of the face with ID fid. - */ - real max_angle(face_key fid, HMesh::Walker &hmax); - - /** - Returns the vertex of max angle. - The half edge point to that vertex - */ - HMesh::Walker max_angle_point(face_key fid); + real min_angle(face_key fid) const; /** Returns the minimum edge length of the edges of the face with ID fid. */ - real min_edge_length(face_key fid); + real min_edge_length(face_key fid) const; /** * Returns the new minimum face quality (minimum angle) when moving a node from old_pos to new_pos. The edges in the link of the node should be passed in eids. */ - real min_quality(const std::vector& eids, const vec2& pos_old, const vec2& pos_new); + real min_quality(const std::vector& eids, const vec2& pos_old, const vec2& pos_new) const; /** Returns whether the half edge is possible to collapse. */ - bool is_collapsable(HMesh::Walker hew, bool safe); + bool is_collapsable(HMesh::Walker hew, bool safe) const; public: - /** - Load and save - */ - bool save(const char * filePath); - bool load(char * filePath); - /** Returns the length of the edge with ID eid. */ @@ -864,11 +739,15 @@ namespace DSC2D { */ std::vector get_design_variable_positions(); + std::vector get_design_variable_destinations(); + /** Returns the positions of the interface edges. */ std::vector get_interface_edge_positions(); + std::vector get_interface_edge_destinations(); + /** Returns the maximum distance a vertex is supposed to be moved (the distance between its new and old position). Should be called before move_vertices(). @@ -879,7 +758,7 @@ namespace DSC2D { Calculates the average position of the neighbouring vertices to the vertex with ID vid. If interface is true, the average position is only calculated among the neighbouring vertices that are interface. */ - vec2 get_barycenter(node_key vid, bool _interface) const; + vec2 get_barycenter(node_key vid, bool interface) const; /** Calculates the average position of the vertices to the face with ID fid. @@ -930,32 +809,7 @@ namespace DSC2D { Calculates the intersection with the link of the vertex with ID vid and the line from the position of this vertex towards destination and to infinity. It returns t which is where on the line the intersection occurs. If t=0, the interesection occured at the position of the vertex with ID vid or never occured. If t=1 the intersection occured at the destination point. If 01 the intersection occured farther away from the vertex position than destination. */ real intersection_with_link(const node_key& vid, vec2 destination) const; - -#pragma mark - TESTING - public: - void increase_resolution_range(); // reduce smallest edge by 2. For multi resolution - void refine_without_change_interface(); - - void remove_degenerate_needle(face_key fkey); - void remove_degenerate_needle2(face_key fkey); - /** - Set coefficients. Smallest feature size in pixel - */ - void set_smallest_feature_size(double length); - void set_uniform_smallest_feature(double length); - - double get_min_length_ratio(){return MIN_LENGTH;} - - - void split_edge(edge_key ek); - void clean_attributes(); - - - DeformableSimplicialComplex * clone(); - - void recursive_split(HMesh::AttributeVector faces_to_split); - bool split_triangle_sub(face_key f, HMesh::AttributeVector & faces_to_split); }; -} +}; diff --git a/src/design_domain.cpp b/src/design_domain.cpp index 7b0ddc9..aab6db4 100644 --- a/src/design_domain.cpp +++ b/src/design_domain.cpp @@ -56,6 +56,21 @@ namespace DSC2D { void DesignDomain::clamp_vector(const vec2& p, vec2& v) const { +// if (!is_inside(p)) +// { +// vec2 pc = p; +// clamp_position(pc); +// +// real distance_now = sqr_length(p - pc); +// real distance_future = sqr_length(p + v - pc); +// +// if (distance_future > distance_now) +// { +// v = vec2(0, 0); +// } +// return; +// } + if(!is_inside(p+v)) { vec2 c0, c1; @@ -64,8 +79,34 @@ namespace DSC2D { { c0 = corners[i]; c1 = corners[(i+1)%corners.size()]; + + // Haojie Added + real x = Util::cross(c0-p, c1-c0); + real y = Util::cross(v, c1-c0); + if(std::abs(y) < EPSILON) // v and the segment are parallel if true + { + if(std::abs(x) < EPSILON) // v and the segment are collinear if true + { + if ( dot(c0-p, c1-p) <= 0 ) + { + if( (p+v-c1).length() <= (p+v-c0).length()) + { + v = c1 - p; + } + else + { + v = c0 - p; + } + + return; + } + } + } + // Haojie finished the added code segement. + t = Util::intersection_ray_ray(p, v, c0, c1 - c0); - if(t >= 0. && t < 1.) + // if(t >= 0. && t < 1.) + if ( ( t>=0 && t < 1. ) || std::abs(t)< EPSILON ) { v = t*v; } @@ -78,12 +119,22 @@ namespace DSC2D { return Util::is_inside(p, corners); } + bool DesignDomain::on_boundary(const vec2& p) const + { + return Util::on_boundary(p, corners); + } + std::vector DesignDomain::get_corners() const { return corners; } - vec2 DesignDomain::get_center() + std::vector > DesignDomain::get_subdomain_corners() const + { + return subdomain_corners; + } + + vec2 DesignDomain::get_center() const { vec2 center(0.); for (int i = 0; i < corners.size(); i++) @@ -95,29 +146,62 @@ namespace DSC2D { real DesignDomain::get_volume() { +// if(volume < 0.) +// { +// volume = 0.; +// std::vector c(corners); +// vec2 c0, c1, c2; +// while(c.size() > 2) +// { +// int i = 0; +// do { +//#ifdef DEBUG +// assert(i < c.size()); +//#endif +// c0 = c[i]; +// c1 = c[(i+1)%c.size()]; +// c2 = c[(i+2)%c.size()]; +// i++; +// } while (Util::is_left_of(c0,c1,c2)); +// +// volume += std::abs(Util::signed_area(c0, c1, c2)); +// c.erase(c.begin() + (i%c.size())); +// } +// } + if(volume < 0.) { - volume = 0.; std::vector c(corners); - vec2 c0, c1, c2; - while(c.size() > 2) + c.push_back(corners[0]); + + double sum1 = 0; + double sum2 = 0; + + for (int i=0; i c(corners); + c.push_back(corners[0]); + + double perimeter = 0; + + for (int i=0; i corners; // Specified in a clockwise order + std::vector > subdomain_corners; real volume = -1.; + std::string name; + double mWidth; + double mHeight; public: - enum DESIGN_DOMAIN_TYPE {RECTANGLE, L, ESO}; - + enum DESIGN_DOMAIN_TYPE {RECTANGLE, L, ESO, PORTAL}; - DesignDomain(){} /** Creates a design domain defined by the design domain type and size. It is possible to specify a boundary gap which translates the entire domain by the amount specified by the input parameter. */ - DesignDomain(DESIGN_DOMAIN_TYPE design, int SIZE_X, int SIZE_Y, real boundary) + + DesignDomain(DESIGN_DOMAIN_TYPE design, int SIZE_X, int SIZE_Y, real boundary1, real boundary2) { - switch (design) { + mWidth = SIZE_X; + mHeight = SIZE_Y; + switch (design) + { case RECTANGLE: + name = "RECTANGLE"; corners.push_back(vec2(0.,0.)); corners.push_back(vec2(0., SIZE_Y)); corners.push_back(vec2(SIZE_X, SIZE_Y)); corners.push_back(vec2(SIZE_X, 0.)); + subdomain_corners.push_back(corners); break; case L: + name = "L"; corners.push_back(vec2(0.,0.)); corners.push_back(vec2(0., SIZE_Y)); corners.push_back(vec2(0.4*SIZE_X, SIZE_Y)); corners.push_back(vec2(0.4*SIZE_X, 0.4*SIZE_Y)); corners.push_back(vec2(SIZE_X, 0.4*SIZE_Y)); corners.push_back(vec2(SIZE_X, 0.)); + subdomain_corners.push_back(corners); break; case ESO: + name = "ESO"; corners.push_back(vec2(0.,0.)); corners.push_back(vec2(0., 3.*SIZE_Y/7.)); corners.push_back(vec2(30.*SIZE_X/32., 3.*SIZE_Y/7.)); @@ -63,31 +73,309 @@ namespace DSC2D { corners.push_back(vec2(31.*SIZE_X/32., 3.*SIZE_Y/7.)); corners.push_back(vec2(SIZE_X, 3.*SIZE_Y/7.)); corners.push_back(vec2(SIZE_X, 0.)); + subdomain_corners.push_back(corners); + break; + case PORTAL: + name = "PORTAL"; + corners.push_back(vec2(0.,0.)); + corners.push_back(vec2(0., SIZE_Y)); + corners.push_back(vec2(SIZE_X, SIZE_Y)); + corners.push_back(vec2(SIZE_X, 0)); + corners.push_back(vec2(0.95*SIZE_X, 0)); + corners.push_back(vec2(0.5*SIZE_X, 0.65*SIZE_Y)); + corners.push_back(vec2(0.05*SIZE_X, 0)); + subdomain_corners.push_back({vec2(0.5*SIZE_X, 0.65*SIZE_Y), vec2(0.05*SIZE_X, 0), vec2(0.,0.), vec2(0., SIZE_Y), vec2(0.5*SIZE_X, SIZE_Y)}); + subdomain_corners.push_back({ vec2(0.5*SIZE_X, 0.65*SIZE_Y), vec2(0.5*SIZE_X, SIZE_Y), vec2(SIZE_X, SIZE_Y), vec2(SIZE_X, 0.), vec2(0.95*SIZE_X, 0) }); break; } for(auto &c : corners) { - c[0] += boundary; - c[1] += boundary; + c[0] += boundary1; + c[1] += boundary2; + } + + for(auto &subdomain : subdomain_corners) + { + for(auto &sub_corner : subdomain) + { + sub_corner[0] += boundary1; + sub_corner[1] += boundary2; + } + } + } + + DesignDomain(std::string design, int SIZE_X, int SIZE_Y, real boundary1, real boundary2) + { + mWidth = SIZE_X; + mHeight = SIZE_Y; + if (design == "RECTANGLE") + { + name = "RECTANGLE"; + corners.push_back(vec2(0.,0.)); + corners.push_back(vec2(0., SIZE_Y)); + corners.push_back(vec2(SIZE_X, SIZE_Y)); + corners.push_back(vec2(SIZE_X, 0.)); + subdomain_corners.push_back(corners); + } + else if(design == "L") + { + name = "L"; + corners.push_back(vec2(0.,0.)); + corners.push_back(vec2(0., SIZE_Y)); + corners.push_back(vec2(0.4*SIZE_X, SIZE_Y)); + corners.push_back(vec2(0.4*SIZE_X, 0.4*SIZE_Y)); + corners.push_back(vec2(SIZE_X, 0.4*SIZE_Y)); + corners.push_back(vec2(SIZE_X, 0.)); + subdomain_corners.push_back(corners); + } + else if(design == "ESO") + { + name = "ESO"; + corners.push_back(vec2(0.,0.)); + corners.push_back(vec2(0., 3.*SIZE_Y/7.)); + corners.push_back(vec2(30.*SIZE_X/32., 3.*SIZE_Y/7.)); + corners.push_back(vec2(30.*SIZE_X/32., SIZE_Y)); + corners.push_back(vec2(31.*SIZE_X/32., SIZE_Y)); + corners.push_back(vec2(31.*SIZE_X/32., 3.*SIZE_Y/7.)); + corners.push_back(vec2(SIZE_X, 3.*SIZE_Y/7.)); + corners.push_back(vec2(SIZE_X, 0.)); + subdomain_corners.push_back(corners); + } + else if(design == "PORTAL") + { + name = "PORTAL"; + corners.push_back(vec2(0.,0.)); + corners.push_back(vec2(0., SIZE_Y)); + corners.push_back(vec2(SIZE_X, SIZE_Y)); + corners.push_back(vec2(SIZE_X, 0)); + corners.push_back(vec2(0.95*SIZE_X, 0)); + corners.push_back(vec2(0.5*SIZE_X, 0.65*SIZE_Y)); + corners.push_back(vec2(0.05*SIZE_X, 0)); + subdomain_corners.push_back({vec2(0.5*SIZE_X, 0.65*SIZE_Y), vec2(0.05*SIZE_X, 0), vec2(0.,0.), vec2(0., SIZE_Y), vec2(0.5*SIZE_X, SIZE_Y)}); + subdomain_corners.push_back({ vec2(0.5*SIZE_X, 0.65*SIZE_Y), vec2(0.5*SIZE_X, SIZE_Y), vec2(SIZE_X, SIZE_Y), vec2(SIZE_X, 0.), vec2(0.95*SIZE_X, 0) }); + } + else + { + std::cerr << "No available domain type!" << std::endl; + std::exit(1); + } + + for(auto &c : corners) + { + c[0] += boundary1; + c[1] += boundary2; + } + + for(auto &subdomain : subdomain_corners) + { + for(auto &sub_corner : subdomain) + { + sub_corner[0] += boundary1; + sub_corner[1] += boundary2; + } + } + } + + DesignDomain(DESIGN_DOMAIN_TYPE design, int SIZE_X, int SIZE_Y, real boundary) : DesignDomain(design, SIZE_X, SIZE_Y, boundary, boundary) + { + + } + +// DesignDomain(DESIGN_DOMAIN_TYPE design, int SIZE_X, int SIZE_Y, real boundary) +// { +// mWidth = SIZE_X; +// mHeight = SIZE_Y; +// switch (design) +// { +// case RECTANGLE: +// name = "RECTANGLE"; +// corners.push_back(vec2(0.,0.)); +// corners.push_back(vec2(0., SIZE_Y)); +// corners.push_back(vec2(SIZE_X, SIZE_Y)); +// corners.push_back(vec2(SIZE_X, 0.)); +// subdomain_corners.push_back(corners); +// break; +// case L: +// name = "L"; +// corners.push_back(vec2(0.,0.)); +// corners.push_back(vec2(0., SIZE_Y)); +// corners.push_back(vec2(0.4*SIZE_X, SIZE_Y)); +// corners.push_back(vec2(0.4*SIZE_X, 0.4*SIZE_Y)); +// corners.push_back(vec2(SIZE_X, 0.4*SIZE_Y)); +// corners.push_back(vec2(SIZE_X, 0.)); +// subdomain_corners.push_back(corners); +// break; +// case ESO: +// name = "ESO"; +// corners.push_back(vec2(0.,0.)); +// corners.push_back(vec2(0., 3.*SIZE_Y/7.)); +// corners.push_back(vec2(30.*SIZE_X/32., 3.*SIZE_Y/7.)); +// corners.push_back(vec2(30.*SIZE_X/32., SIZE_Y)); +// corners.push_back(vec2(31.*SIZE_X/32., SIZE_Y)); +// corners.push_back(vec2(31.*SIZE_X/32., 3.*SIZE_Y/7.)); +// corners.push_back(vec2(SIZE_X, 3.*SIZE_Y/7.)); +// corners.push_back(vec2(SIZE_X, 0.)); +// subdomain_corners.push_back(corners); +// break; +// case PORTAL: +// name = "PORTAL"; +// corners.push_back(vec2(0.,0.)); +// corners.push_back(vec2(0., SIZE_Y)); +// corners.push_back(vec2(SIZE_X, SIZE_Y)); +// corners.push_back(vec2(SIZE_X, 0)); +// corners.push_back(vec2(0.95*SIZE_X, 0)); +// corners.push_back(vec2(0.5*SIZE_X, 0.65*SIZE_Y)); +// corners.push_back(vec2(0.05*SIZE_X, 0)); +// subdomain_corners.push_back({vec2(0.5*SIZE_X, 0.65*SIZE_Y), vec2(0.05*SIZE_X, 0), vec2(0.,0.), vec2(0., SIZE_Y), vec2(0.5*SIZE_X, SIZE_Y)}); +// subdomain_corners.push_back({ vec2(0.5*SIZE_X, 0.65*SIZE_Y), vec2(0.5*SIZE_X, SIZE_Y), vec2(SIZE_X, SIZE_Y), vec2(SIZE_X, 0.), vec2(0.95*SIZE_X, 0) }); +// break; +// } +// +// for(auto &c : corners) +// { +// c[0] += boundary; +// c[1] += boundary; +// } +// +// for(auto &subdomain : subdomain_corners) +// { +// for(auto &sub_corner : subdomain) +// { +// sub_corner[0] += boundary; +// sub_corner[1] += boundary; +// } +// } +// } + + DesignDomain(std::string design, int SIZE_X, int SIZE_Y, real boundary) : DesignDomain(design, SIZE_X, SIZE_Y, boundary, boundary) + { + + } +// DesignDomain(std::string design, int SIZE_X, int SIZE_Y, real boundary) +// { +// mWidth = SIZE_X; +// mHeight = SIZE_Y; +// if (design == "RECTANGLE") +// { +// name = "RECTANGLE"; +// corners.push_back(vec2(0.,0.)); +// corners.push_back(vec2(0., SIZE_Y)); +// corners.push_back(vec2(SIZE_X, SIZE_Y)); +// corners.push_back(vec2(SIZE_X, 0.)); +// subdomain_corners.push_back(corners); +// } +// else if(design == "L") +// { +// name = "L"; +// corners.push_back(vec2(0.,0.)); +// corners.push_back(vec2(0., SIZE_Y)); +// corners.push_back(vec2(0.4*SIZE_X, SIZE_Y)); +// corners.push_back(vec2(0.4*SIZE_X, 0.4*SIZE_Y)); +// corners.push_back(vec2(SIZE_X, 0.4*SIZE_Y)); +// corners.push_back(vec2(SIZE_X, 0.)); +// subdomain_corners.push_back(corners); +// } +// else if(design == "ESO") +// { +// name = "ESO"; +// corners.push_back(vec2(0.,0.)); +// corners.push_back(vec2(0., 3.*SIZE_Y/7.)); +// corners.push_back(vec2(30.*SIZE_X/32., 3.*SIZE_Y/7.)); +// corners.push_back(vec2(30.*SIZE_X/32., SIZE_Y)); +// corners.push_back(vec2(31.*SIZE_X/32., SIZE_Y)); +// corners.push_back(vec2(31.*SIZE_X/32., 3.*SIZE_Y/7.)); +// corners.push_back(vec2(SIZE_X, 3.*SIZE_Y/7.)); +// corners.push_back(vec2(SIZE_X, 0.)); +// subdomain_corners.push_back(corners); +// } +// else if(design == "PORTAL") +// { +// name = "PORTAL"; +// corners.push_back(vec2(0.,0.)); +// corners.push_back(vec2(0., SIZE_Y)); +// corners.push_back(vec2(SIZE_X, SIZE_Y)); +// corners.push_back(vec2(SIZE_X, 0)); +// corners.push_back(vec2(0.95*SIZE_X, 0)); +// corners.push_back(vec2(0.5*SIZE_X, 0.65*SIZE_Y)); +// corners.push_back(vec2(0.05*SIZE_X, 0)); +// subdomain_corners.push_back({vec2(0.5*SIZE_X, 0.65*SIZE_Y), vec2(0.05*SIZE_X, 0), vec2(0.,0.), vec2(0., SIZE_Y), vec2(0.5*SIZE_X, SIZE_Y)}); +// subdomain_corners.push_back({ vec2(0.5*SIZE_X, 0.65*SIZE_Y), vec2(0.5*SIZE_X, SIZE_Y), vec2(SIZE_X, SIZE_Y), vec2(SIZE_X, 0.), vec2(0.95*SIZE_X, 0) }); +// } +// else +// { +// std::cerr << "No available domain type!" << std::endl; +// std::exit(1); +// } +// +// for(auto &c : corners) +// { +// c[0] += boundary; +// c[1] += boundary; +// } +// +// for(auto &subdomain : subdomain_corners) +// { +// for(auto &sub_corner : subdomain) +// { +// sub_corner[0] += boundary; +// sub_corner[1] += boundary; +// } +// } +// } + + DesignDomain() + { + + } + + std::string get_name() const + { + return name; + } + + double get_width() const + { + return mWidth; + } + + double get_height() const + { + return mHeight; + } + + void set_corners(std::vector input_corners) + { + for (auto corner : input_corners ) + { + corners.push_back(corner); } } + void add_corner(vec2 corner) + { + corners.push_back(corner); + } + /** Returns the corners of the design domain. */ std::vector get_corners() const; + std::vector > get_subdomain_corners() const; + /** Returns an approximate center of the design domain. */ - vec2 get_center(); + vec2 get_center() const; /** Returns the total volume of the domain. */ real get_volume(); + real get_perimeter(); + /** Clamps the position pos to be within the domain. */ @@ -102,6 +390,11 @@ namespace DSC2D { Returns whether the position p is inside the domain. */ bool is_inside(const vec2& p) const; + + /** + Returns whether the position p is on the boundary. + */ + bool on_boundary(const vec2& p) const; }; } \ No newline at end of file diff --git a/src/draw.cpp b/src/draw.cpp new file mode 100644 index 0000000..4144109 --- /dev/null +++ b/src/draw.cpp @@ -0,0 +1,551 @@ +// +// Deformabel Simplicial Complex (DSC) method +// Copyright (C) 2013 Technical University of Denmark +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See licence.txt for a copy of the GNU General Public License. + +#include "draw.h" + +#ifdef _WIN32 +#include +#include +#include +#else +#include +#include +#endif + +using namespace DSC2D; + +void Painter::save_painting(int width, int height, std::string folder, int time_step) +{ + // std::cout << folder << std::endl; + std::ostringstream s; + if (folder.length() == 0) { + s << "scr"; + } + else { + s << folder << "/dsc"; + } + + if (time_step >= 0) + { + s << std::string(Util::concat4digits("_", time_step)); + } + s << "_dsc.png"; + + glPixelStorei(GL_PACK_ALIGNMENT, 1); + int success = SOIL_save_screenshot(s.str().c_str(), SOIL_SAVE_TYPE_PNG, 0, 0, width, height); + if(!success) + { + std::cout << "ERROR: Failed to take screen shot: " << s.str().c_str() << std::endl; + return; + } + // std::cout << "Take screen shot: " << s.str().c_str() << std::endl; +} + +void Painter::save_painting(int width, int height, std::string folder, int dsc_time_step, int sub_time_step, std::string name) +{ + // std::cout << folder << std::endl; + std::ostringstream s; + if (folder.length() == 0) { + s << "scr"; + } + else { + s << folder << "/dsc"; + } + + s << std::string(Util::concat4digits("_", dsc_time_step)); + + if (sub_time_step >= 0) + { + s << std::string(Util::concat4digits(name, sub_time_step)); + } + s << ".png"; + glPixelStorei(GL_PACK_ALIGNMENT, 1); + int success = SOIL_save_screenshot(s.str().c_str(), SOIL_SAVE_TYPE_PNG, 0, 0, width, height); + if(!success) + { + std::cout << "ERROR: Failed to take screen shot: " << s.str().c_str() << std::endl; + return; + } + // std::cout << "Take screen shot: " << s.str().c_str() << std::endl; +} + +void Painter::save_painting(int width, int height, std::string folder, int dsc_time_step, int shape_opt_time_step, int sub_time_step, std::string name) +{ + // std::cout << folder << std::endl; + std::ostringstream s; + if (folder.length() == 0) { + s << "scr"; + } + else { + s << folder << "/dsc"; + } + + s << std::string(Util::concat4digits("_", dsc_time_step)); + + if (shape_opt_time_step >= 0) + { + s << std::string(Util::concat4digits("_shape_", shape_opt_time_step)); + } + + if (sub_time_step >= 0) + { + s << std::string(Util::concat4digits(name, sub_time_step)); + } + s << ".png"; + glPixelStorei(GL_PACK_ALIGNMENT, 1); + int success = SOIL_save_screenshot(s.str().c_str(), SOIL_SAVE_TYPE_PNG, 0, 0, width, height); + if(!success) + { + std::cout << "ERROR: Failed to take screen shot: " << s.str().c_str() << std::endl; + return; + } + // std::cout << "Take screen shot: " << s.str().c_str() << std::endl; +} + +void Painter::begin() +{ + glClearColor(BACKGROUND_COLOR[0], BACKGROUND_COLOR[1], BACKGROUND_COLOR[2],0); + glClear(GL_COLOR_BUFFER_BIT); +} + +void Painter::end() +{ + glFinish(); + glutSwapBuffers(); +} + + +void Painter::draw_complex(const DeformableSimplicialComplex& dsc) +{ + draw_domain(*dsc.get_design_domain()); + draw_faces(dsc); + draw_edges(dsc); + draw_vertices(dsc); +} + +void Painter::draw_destination_complex(const DeformableSimplicialComplex& dsc) +{ + draw_domain(*dsc.get_design_domain()); + draw_destination_faces(dsc); + draw_destination_edges(dsc); + draw_destination_vertices(dsc); +} + +void Painter::draw_domain(const DesignDomain& domain, vec3 color) +{ +// std::vector corners = domain.get_corners(); +// glColor3d(static_cast(color[0]), static_cast(color[1]), static_cast(color[2])); +// vec2 p0, p1, p2; +// vec3 cor; +// int j = 0, i; +// glBegin(GL_TRIANGLES); +// while (corners.size() > 2) +// { +// i = (j+1)%corners.size(); +// p0 = corners[j%corners.size()]; +// p1 = corners[i]; +// p2 = corners[(j+2)%corners.size()]; +// if (!Util::is_left_of(p0, p1, p2)) +// { +// cor = vec3(p0[0], p0[1], 0.); +// glVertex3d(static_cast(cor[0]), static_cast(cor[1]), static_cast(cor[2])); +// cor = vec3(p1[0], p1[1], 0.); +// glVertex3d(static_cast(cor[0]), static_cast(cor[1]), static_cast(cor[2])); +// cor = vec3(p2[0], p2[1], 0.); +// glVertex3d(static_cast(cor[0]), static_cast(cor[1]), static_cast(cor[2])); +// corners.erase(corners.begin() + i); +// } +// else +// { +// j = i; +// } +// } +// glEnd(); + std::vector > subdomain_corners = domain.get_subdomain_corners(); + glColor3d(static_cast(color[0]), static_cast(color[1]), static_cast(color[2])); + vec2 p0, p1, p2; + vec3 cor; + int j = 0, i; + glBegin(GL_TRIANGLES); + for (auto c = 0; c corners = subdomain_corners[c]; + while (corners.size() > 2) + { + i = (j+1)%corners.size(); + p0 = corners[j%corners.size()]; + p1 = corners[i]; + p2 = corners[(j+2)%corners.size()]; + if (!Util::is_left_of(p0, p1, p2)) + { + cor = vec3(p0[0], p0[1], 0.); + glVertex3d(static_cast(cor[0]), static_cast(cor[1]), static_cast(cor[2])); + cor = vec3(p1[0], p1[1], 0.); + glVertex3d(static_cast(cor[0]), static_cast(cor[1]), static_cast(cor[2])); + cor = vec3(p2[0], p2[1], 0.); + glVertex3d(static_cast(cor[0]), static_cast(cor[1]), static_cast(cor[2])); + corners.erase(corners.begin() + i); + } + else + { + j = i; + } + } + } + glEnd(); +} + +void Painter::draw_vertices(const DeformableSimplicialComplex& dsc) +{ + HMesh::VertexAttributeVector colors = dsc.get_vertex_colors(); + glPointSize(std::max(std::floor(POINT_SIZE*dsc.get_avg_edge_length()), 1.)); + glBegin(GL_POINTS); + vec3 p; + for(auto vi = dsc.vertices_begin(); vi != dsc.vertices_end(); ++vi) + { + if (colors[*vi] != INVISIBLE) + { + p = vec3(dsc.get_pos(*vi)[0], dsc.get_pos(*vi)[1], 0.); + glColor3d(static_cast(colors[*vi][0]), static_cast(colors[*vi][1]), static_cast(colors[*vi][2])); + glVertex3d(static_cast(p[0]), static_cast(p[1]), static_cast(p[2])); + } + } + glEnd(); +} + +void Painter::draw_destination_vertices(const DeformableSimplicialComplex& dsc) +{ + HMesh::VertexAttributeVector colors = dsc.get_vertex_colors(); + glPointSize(std::max(std::floor(POINT_SIZE*dsc.get_avg_edge_length()), 1.)); + glBegin(GL_POINTS); + vec3 p; + for(auto vi = dsc.vertices_begin(); vi != dsc.vertices_end(); ++vi) + { + if (colors[*vi] != INVISIBLE) + { + p = vec3(dsc.get_destination(*vi)[0], dsc.get_destination(*vi)[1], 0.); + glColor3d(static_cast(colors[*vi][0]), static_cast(colors[*vi][1]), static_cast(colors[*vi][2])); + glVertex3d(static_cast(p[0]), static_cast(p[1]), static_cast(p[2])); + } + } + glEnd(); +} + +void Painter::draw_interface(const DeformableSimplicialComplex& dsc, vec3 color) +{ + glPointSize(std::max(std::floor(POINT_SIZE*dsc.get_avg_edge_length()), 1.)); + glBegin(GL_POINTS); + vec3 p; + glColor3d(static_cast(color[0]), static_cast(color[1]), static_cast(color[2])); + for(auto vi = dsc.vertices_begin(); vi != dsc.vertices_end(); ++vi) + { + if (dsc.is_movable(*vi)) { + vec3 temp(dsc.get_destination(*vi)[0], dsc.get_destination(*vi)[1], 0.); + glVertex3d(static_cast(temp[0]), static_cast(temp[1]), static_cast(temp[2])); + } + } + glEnd(); + glLineWidth(std::max(std::floor(LINE_WIDTH*dsc.get_avg_edge_length()), 1.)); + vec3 p1, p2; + glBegin(GL_LINES); + for(auto hei = dsc.halfedges_begin(); hei != dsc.halfedges_end(); ++hei) + { + auto hew = dsc.walker(*hei); + if (dsc.is_movable(hew.halfedge()) && (dsc.is_movable(hew.vertex()) || dsc.is_movable(hew.opp().vertex()))) + { + p1 = vec3(dsc.get_destination(hew.vertex())[0], dsc.get_destination(hew.vertex())[1], 0.); + p2 = vec3(dsc.get_destination(hew.opp().vertex())[0], dsc.get_destination(hew.opp().vertex())[1], 0.); + glVertex3d(static_cast(p1[0]), static_cast(p1[1]), static_cast(p1[2])); + glVertex3d(static_cast(p2[0]), static_cast(p2[1]), static_cast(p2[2])); + } + } + glEnd(); +} + +void Painter::draw_arrows(const DeformableSimplicialComplex& dsc, const HMesh::VertexAttributeVector &arrows, vec3 color, bool origin_movable) +{ + glColor3d(static_cast(color[0]), static_cast(color[1]), static_cast(color[2])); + glLineWidth(std::max(std::floor(LINE_WIDTH*dsc.get_avg_edge_length()), 1.)); + vec3 arrow, a_hat, p; + for(auto vi = dsc.vertices_begin(); vi != dsc.vertices_end(); ++vi) + { + arrow = vec3(arrows[*vi][0], arrows[*vi][1], 0.f); + if(arrow.length() > EPSILON) + { + a_hat = vec3(-arrow[1], arrow[0], 0.f); + p = vec3(dsc.get_pos(*vi)[0], dsc.get_pos(*vi)[1], 0.); +#ifdef DEBUG + if (dsc.is_movable(*vi) && origin_movable) { + p = vec3(dsc.get_destination(*vi)[0], dsc.get_destination(*vi)[1], 0.); + } +#endif + glBegin(GL_LINES); + glVertex3d(static_cast(p[0]), static_cast(p[1]), static_cast(p[2])); + glVertex3d(static_cast((p + 0.7*arrow)[0]), static_cast((p + 0.7*arrow)[1]), static_cast((p + 0.7*arrow)[2])); + glEnd(); + + glBegin(GL_POLYGON); + glVertex3d(static_cast((p + arrow)[0]), static_cast((p + arrow)[1]), static_cast((p + arrow)[2])); + glVertex3d(static_cast((p + 0.6*arrow + 0.13*a_hat)[0]), static_cast((p+ 0.6*arrow + 0.13*a_hat)[1]), static_cast((p+ 0.6*arrow + 0.13*a_hat)[2])); + glVertex3d(static_cast((p + 0.6*arrow - 0.13*a_hat)[0]), static_cast((p + 0.6*arrow - 0.13*a_hat)[1]), static_cast((p + 0.6*arrow - 0.13*a_hat)[2])); + glEnd(); + } + } +} + +void Painter::draw_edge_arrows(const DeformableSimplicialComplex& dsc, const HMesh::HalfEdgeAttributeVector &arrows, vec3 color) +{ + glColor3d(static_cast(color[0]), static_cast(color[1]), static_cast(color[2])); + glLineWidth(std::max(std::floor(LINE_WIDTH*dsc.get_avg_edge_length()), 1.)); + vec3 arrow, a_hat, p; + for(auto eit = dsc.halfedges_begin(); eit != dsc.halfedges_end(); ++eit) + { + arrow = vec3(arrows[*eit][0], arrows[*eit][1], 0.f); + if(arrow.length() > EPSILON) + { + a_hat = vec3(-arrow[1], arrow[0], 0.f); + auto pt = Util::barycenter(dsc.get_pos(dsc.walker(*eit).vertex()), dsc.get_pos(dsc.walker(*eit).opp().vertex())); +#ifdef DEBUG + pt = Util::barycenter(dsc.get_destination(dsc.walker(*eit).vertex()), dsc.get_destination(dsc.walker(*eit).opp().vertex())); +#endif + p = vec3(pt[0], pt[1], 0.); + glBegin(GL_LINES); + glVertex3d(static_cast(p[0]), static_cast(p[1]), static_cast(p[2])); + glVertex3d(static_cast((p + 0.7*arrow)[0]), static_cast((p + 0.7*arrow)[1]), static_cast((p + 0.7*arrow)[2])); + glEnd(); + + glBegin(GL_POLYGON); + glVertex3d(static_cast((p + arrow)[0]), static_cast((p + arrow)[1]), static_cast((p + arrow)[2])); + glVertex3d(static_cast((p + 0.6*arrow + 0.13*a_hat)[0]), static_cast((p+ 0.6*arrow + 0.13*a_hat)[1]), static_cast((p+ 0.6*arrow + 0.13*a_hat)[2])); + glVertex3d(static_cast((p + 0.6*arrow - 0.13*a_hat)[0]), static_cast((p + 0.6*arrow - 0.13*a_hat)[1]), static_cast((p + 0.6*arrow - 0.13*a_hat)[2])); + glEnd(); + } + } +} + + +void Painter::draw_lines(const DeformableSimplicialComplex& dsc, const HMesh::VertexAttributeVector &lines, vec3 color) +{ + glColor3d(static_cast(color[0]), static_cast(color[1]), static_cast(color[2])); + glLineWidth(std::max(std::floor(LINE_WIDTH*dsc.get_avg_edge_length()), 1.)); + vec3 line, p; + for(auto vi = dsc.vertices_begin(); vi != dsc.vertices_end(); ++vi) + { + line = vec3(lines[*vi][0], lines[*vi][1], 0.f); + if(line.length() > EPSILON) + { + p = vec3(dsc.get_pos(*vi)[0], dsc.get_pos(*vi)[1], 0.); + + glBegin(GL_LINES); + glVertex3d(static_cast(p[0]), static_cast(p[1]), static_cast(p[2])); + glVertex3d(static_cast((p + line)[0]), static_cast((p + line)[1]), static_cast((p + line)[2])); + glEnd(); + } + } +} + +void Painter::draw_edges(const DeformableSimplicialComplex& dsc) +{ + HMesh::HalfEdgeAttributeVector colors = dsc.get_edge_colors(); + glLineWidth(std::max(std::floor(LINE_WIDTH*dsc.get_avg_edge_length()), 1.)); + vec3 p1, p2; + glBegin(GL_LINES); + for(auto hei = dsc.halfedges_begin(); hei != dsc.halfedges_end(); ++hei) + { + if (colors[*hei] != INVISIBLE) + { + glColor3d(static_cast(colors[*hei][0]), static_cast(colors[*hei][1]), static_cast(colors[*hei][2])); + + auto hew = dsc.walker(*hei); + p1 = vec3(dsc.get_pos(hew.vertex())[0], dsc.get_pos(hew.vertex())[1], 0.); + p2 = vec3(dsc.get_pos(hew.opp().vertex())[0], dsc.get_pos(hew.opp().vertex())[1], 0.); + glVertex3d(static_cast(p1[0]), static_cast(p1[1]), static_cast(p1[2])); + glVertex3d(static_cast(p2[0]), static_cast(p2[1]), static_cast(p2[2])); + } + } + glEnd(); +} + +void Painter::draw_destination_edges(const DeformableSimplicialComplex& dsc) +{ + HMesh::HalfEdgeAttributeVector colors = dsc.get_edge_colors(); + glLineWidth(std::max(std::floor(LINE_WIDTH*dsc.get_avg_edge_length()), 1.)); + vec3 p1, p2; + glBegin(GL_LINES); + for(auto hei = dsc.halfedges_begin(); hei != dsc.halfedges_end(); ++hei) + { + if (colors[*hei] != INVISIBLE) + { + glColor3d(static_cast(colors[*hei][0]), static_cast(colors[*hei][1]), static_cast(colors[*hei][2])); + + auto hew = dsc.walker(*hei); + p1 = vec3(dsc.get_destination(hew.vertex())[0], dsc.get_destination(hew.vertex())[1], 0.); + p2 = vec3(dsc.get_destination(hew.opp().vertex())[0], dsc.get_destination(hew.opp().vertex())[1], 0.); + glVertex3d(static_cast(p1[0]), static_cast(p1[1]), static_cast(p1[2])); + glVertex3d(static_cast(p2[0]), static_cast(p2[1]), static_cast(p2[2])); + } + } + glEnd(); +} + +void Painter::draw_faces(const DeformableSimplicialComplex& dsc) +{ + HMesh::FaceAttributeVector colors = dsc.get_face_colors(); + draw_faces(dsc, colors); +} + +void Painter::draw_destination_faces(const DeformableSimplicialComplex& dsc) +{ + HMesh::FaceAttributeVector colors = dsc.get_face_colors(); + draw_destination_faces(dsc, colors); +} + +void Painter::draw_faces(const DeformableSimplicialComplex& dsc, const HMesh::FaceAttributeVector &colors) +{ + glBegin(GL_TRIANGLES); + for(auto fi = dsc.faces_begin(); fi != dsc.faces_end(); ++fi) + { + if(colors[*fi] != INVISIBLE) + { + glColor3d(static_cast(colors[*fi][0]), static_cast(colors[*fi][1]), static_cast(colors[*fi][2])); + for (auto hew = dsc.walker(*fi); !hew.full_circle(); hew = hew.circulate_face_cw()) + { + vec2 p = dsc.get_pos(hew.vertex()); + glVertex3d(static_cast(p[0]), static_cast(p[1]), static_cast(0.)); + } + } + } + glEnd(); +} + +void Painter::draw_destination_faces(const DeformableSimplicialComplex& dsc, const HMesh::FaceAttributeVector &colors) +{ + glBegin(GL_TRIANGLES); + for(auto fi = dsc.faces_begin(); fi != dsc.faces_end(); ++fi) + { + if(colors[*fi] != INVISIBLE) + { + glColor3d(static_cast(colors[*fi][0]), static_cast(colors[*fi][1]), static_cast(colors[*fi][2])); + for (auto hew = dsc.walker(*fi); !hew.full_circle(); hew = hew.circulate_face_cw()) + { + vec2 p = dsc.get_destination(hew.vertex()); + glVertex3d(static_cast(p[0]), static_cast(p[1]), static_cast(0.)); + } + } + } + glEnd(); +} + +void Painter::draw_faces(const DeformableSimplicialComplex& dsc, const HMesh::FaceAttributeVector &values) +{ + glBegin(GL_TRIANGLES); + for(auto fi = dsc.faces_begin(); fi != dsc.faces_end(); ++fi) + { + if(values[*fi] >= 0.) + { + for (auto hew = dsc.walker(*fi); !hew.full_circle(); hew = hew.circulate_face_cw()) + { +// real val = 0.; +// int i = 0; +// for (auto hew2 = dsc.walker(hew.vertex()); !hew2.full_circle(); hew2 = hew2.circulate_vertex_cw()) { +// if(values[hew2.face()] >= 0.) +// { +// val += values[hew2.face()]; +// i++; +// } +// } +// val = val / static_cast(i); + real val = values[*fi]; + vec3 color = Util::jet_color(val); + glColor3d(static_cast(color[0]), static_cast(color[1]), static_cast(color[2])); + vec2 p = dsc.get_pos(hew.vertex()); + glVertex3d(static_cast(p[0]), static_cast(p[1]), static_cast(0.)); + } + } + } + glEnd(); +} + +void Painter::draw_destination_faces(const DeformableSimplicialComplex& dsc, const HMesh::FaceAttributeVector &values) +{ + glBegin(GL_TRIANGLES); + for(auto fi = dsc.faces_begin(); fi != dsc.faces_end(); ++fi) + { + if(values[*fi] >= 0.) + { + for (auto hew = dsc.walker(*fi); !hew.full_circle(); hew = hew.circulate_face_cw()) + { + // real val = 0.; + // int i = 0; + // for (auto hew2 = dsc.walker(hew.vertex()); !hew2.full_circle(); hew2 = hew2.circulate_vertex_cw()) { + // if(values[hew2.face()] >= 0.) + // { + // val += values[hew2.face()]; + // i++; + // } + // } + // val = val / static_cast(i); + real val = values[*fi]; + vec3 color = Util::jet_color(val); + glColor3d(static_cast(color[0]), static_cast(color[1]), static_cast(color[2])); + vec2 p = dsc.get_destination(hew.vertex()); + glVertex3d(static_cast(p[0]), static_cast(p[1]), static_cast(0.)); + } + } + } + glEnd(); +} + +void Painter::draw_faces(const DeformableSimplicialComplex& dsc, const HMesh::VertexAttributeVector &values) +{ + glBegin(GL_TRIANGLES); + for(auto fi = dsc.faces_begin(); fi != dsc.faces_end(); ++fi) + { + auto verts = dsc.get_verts(*fi); + if(!dsc.is_outside(*fi)) + { + for (auto vert : verts) + { + vec3 color = Util::jet_color(values[vert]); + glColor3d(static_cast(color[0]), static_cast(color[1]), static_cast(color[2])); + vec2 p = dsc.get_pos(vert); + glVertex3d(static_cast(p[0]), static_cast(p[1]), static_cast(0.)); + } + } + } + glEnd(); +} + +void Painter::draw_destination_faces(const DeformableSimplicialComplex& dsc, const HMesh::VertexAttributeVector &values) +{ + glBegin(GL_TRIANGLES); + for(auto fi = dsc.faces_begin(); fi != dsc.faces_end(); ++fi) + { + auto verts = dsc.get_verts(*fi); + if(!dsc.is_outside(*fi)) + { + for (auto vert : verts) + { + vec3 color = Util::jet_color(values[vert]); + glColor3d(static_cast(color[0]), static_cast(color[1]), static_cast(color[2])); + vec2 p = dsc.get_destination(vert); + glVertex3d(static_cast(p[0]), static_cast(p[1]), static_cast(0.)); + } + } + } + glEnd(); +} + diff --git a/src/draw.h b/src/draw.h new file mode 100644 index 0000000..43b8017 --- /dev/null +++ b/src/draw.h @@ -0,0 +1,153 @@ +// +// Deformabel Simplicial Complex (DSC) method +// Copyright (C) 2013 Technical University of Denmark +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// See licence.txt for a copy of the GNU General Public License. + +#pragma once + +#include "DSC.h" +#include "velocity_function.h" + +const static double POINT_SIZE = 0.2; +const static double LINE_WIDTH = 0.1; + +const static DSC2D::vec3 BACKGROUND_COLOR = DSC2D::vec3(1.); +const static DSC2D::vec3 INVISIBLE = DSC2D::vec3(-1.); +const static DSC2D::vec3 DARK_RED = DSC2D::vec3(0.66,0.11,0.15); +const static DSC2D::vec3 RED = DSC2D::vec3(0.96,0.11,0.15); +const static DSC2D::vec3 DARK_BLUE = DSC2D::vec3(0.14,0.16,0.88); +const static DSC2D::vec3 BLUE = DSC2D::vec3(0.45,0.7,0.9); +const static DSC2D::vec3 GREEN = DSC2D::vec3(0.05,1.,0.15); +const static DSC2D::vec3 ORANGE = DSC2D::vec3(0.9,0.4,0.); +const static DSC2D::vec3 BLACK = DSC2D::vec3(0.); +const static DSC2D::vec3 DARK_GRAY = DSC2D::vec3(0.5); +const static DSC2D::vec3 GRAY = DSC2D::vec3(0.8); + +/** + A painter handles all draw functionality using OpenGL. + */ +class Painter { + + +public: + /** + Saves the current painting to the selected folder. + */ + static void save_painting(int width, int height, std::string folder = std::string(""), int time_step = -1); + + static void save_painting(int width, int height, std::string folder, int dsc_time_step, int sub_time_step, std::string name); + + static void save_painting(int width, int height, std::string folder, int dsc_time_step, int shape_step, int sub_time_step, std::string name); + + /** + Begins drawing. + */ + static void begin(); + + /** + Ends drawing. + */ + static void end(); + + /** + Draws the simplicial complex. + */ + static void draw_complex(const DSC2D::DeformableSimplicialComplex& complex); + + /** + Draws the simplicial complex. + */ + static void draw_destination_complex(const DSC2D::DeformableSimplicialComplex& complex); + + /** + Draws the domain. + */ + static void draw_domain(const DSC2D::DesignDomain& domain, DSC2D::vec3 color = GRAY); + + /** + Draws the vertices with the colors defined by the get_vertex_colors function in the simplicial complex. + */ + static void draw_vertices(const DSC2D::DeformableSimplicialComplex& complex); + + /** + Draws the vertices with the colors defined by the get_vertex_colors function in the simplicial complex. + */ + static void draw_destination_vertices(const DSC2D::DeformableSimplicialComplex& complex); + + /** + Draws the edges with the colors defined by the get_edge_colors function in the simplicial complex. + */ + static void draw_edges(const DSC2D::DeformableSimplicialComplex& complex); + + /** + Draws the edges with the colors defined by the get_edge_colors function in the simplicial complex. + */ + static void draw_destination_edges(const DSC2D::DeformableSimplicialComplex& complex); + + /** + Draws the faces with the colors defined by the get_face_colors function in the simplicial complex. + */ + static void draw_faces(const DSC2D::DeformableSimplicialComplex& complex); + + /** + Draws the faces with the colors defined by the get_face_colors function in the simplicial complex. + */ + static void draw_destination_faces(const DSC2D::DeformableSimplicialComplex& complex); + + /** + Draws the faces with the colors given as input. + */ + static void draw_faces(const DSC2D::DeformableSimplicialComplex& complex, const HMesh::FaceAttributeVector &colors); + + /** + Draws the faces with the colors given as input. + */ + static void draw_destination_faces(const DSC2D::DeformableSimplicialComplex& complex, const HMesh::FaceAttributeVector &colors); + + /** + Draws the faces using the 'jet' color scheme. + */ + static void draw_faces(const DSC2D::DeformableSimplicialComplex& complex, const HMesh::FaceAttributeVector &values); + + /** + Draws the faces using the 'jet' color scheme. + */ + static void draw_destination_faces(const DSC2D::DeformableSimplicialComplex& complex, const HMesh::FaceAttributeVector &values); + + /** + Draws the faces using the 'jet' color scheme. + */ + static void draw_faces(const DSC2D::DeformableSimplicialComplex& complex, const HMesh::VertexAttributeVector &values); + + /** + Draws the faces using the 'jet' color scheme. + */ + static void draw_destination_faces(const DSC2D::DeformableSimplicialComplex& complex, const HMesh::VertexAttributeVector &values); + + /** + Draws the interface with the color given as input. + */ + static void draw_interface(const DSC2D::DeformableSimplicialComplex& complex, DSC2D::vec3 color = ORANGE); + + /** + Draws the arrows given as input with the color given as input. + */ + static void draw_arrows(const DSC2D::DeformableSimplicialComplex& complex, const HMesh::VertexAttributeVector &arrows, DSC2D::vec3 color = ORANGE, bool origin_movable = true); + static void draw_edge_arrows(const DSC2D::DeformableSimplicialComplex& dsc, const HMesh::HalfEdgeAttributeVector &arrows, DSC2D::vec3 color = ORANGE); + + /** + Draws the lines given as input with the color given as input. + */ + static void draw_lines(const DSC2D::DeformableSimplicialComplex& complex, const HMesh::VertexAttributeVector &lines, DSC2D::vec3 color = GREEN); +}; diff --git a/src/object_generator.cpp b/src/object_generator.cpp index 13189b4..f92c71a 100644 --- a/src/object_generator.cpp +++ b/src/object_generator.cpp @@ -107,15 +107,46 @@ namespace DSC2D { } } + void ObjectGenerator::label_faces(DeformableSimplicialComplex& dsc, const std::vector& labels) + { + int face_ind = 0; + for (auto fi = dsc.faces_begin(); fi != dsc.faces_end(); fi++) + { + int label = labels[face_ind]; + + if (label == 1) + { + // std::cout << "label: " << label << std::endl; + dsc.update_attributes(*fi, 1); + } + face_ind++; + } + } + void ObjectGenerator::create_object(DeformableSimplicialComplex& dsc, const std::vector& corners, int label) { - dsc.init_attributes(); // Maybe not necessary?? - + // dsc.init_attributes(); // Maybe not necessary?? fit_mesh_to_object(dsc, corners); + dsc.init_attributes(); // it should be here, because fit_mesh_object change the pos. Haojie. label_faces(dsc, corners, label); dsc.update_attributes(); // Maybe not necessary?? dsc.fix_complex(); + dsc.init_attributes(); + dsc.update_attributes(); + } + + void ObjectGenerator::create_object_from_labels(DeformableSimplicialComplex& dsc, const std::vector& corners, const std::vector& labels) + { + // dsc.init_attributes(); // Maybe not necessary?? + fit_mesh_to_object(dsc, corners); + dsc.init_attributes(); // it should be here, because fit_mesh_object change the pos. Haojie. + label_faces(dsc, labels); + dsc.update_attributes(); // Maybe not necessary?? + + dsc.fix_complex(); + dsc.init_attributes(); + dsc.update_attributes(); } } \ No newline at end of file diff --git a/src/object_generator.h b/src/object_generator.h index 8d3f3b4..975f81d 100644 --- a/src/object_generator.h +++ b/src/object_generator.h @@ -23,13 +23,17 @@ namespace DSC2D { class ObjectGenerator { - static void fit_mesh_to_object(DeformableSimplicialComplex& dsc, const std::vector& corners); - static void label_faces(DeformableSimplicialComplex& dsc, const std::vector& corners, int label); + public: + + static void label_faces(DeformableSimplicialComplex& dsc, const std::vector& labels); + + static void fit_mesh_to_object(DeformableSimplicialComplex& dsc, const std::vector& corners); + static void create_object(DeformableSimplicialComplex& dsc, const std::vector& corners, int label); - public: + static void create_object_from_labels(DeformableSimplicialComplex& dsc, const std::vector& corners, const std::vector& labels); static void create_blob(DeformableSimplicialComplex& dsc, const vec2& center, const real& radius, int label) { @@ -51,14 +55,6 @@ namespace DSC2D { create_object(dsc, corners, label); } - - static void label_tris(DeformableSimplicialComplex& dsc, - std::vector faces, - int label){ - for (auto f : faces){ - dsc.update_attributes(f, label); - } - } }; diff --git a/src/trializer.cpp b/src/trializer.cpp index ab9e148..b85082a 100644 --- a/src/trializer.cpp +++ b/src/trializer.cpp @@ -28,51 +28,43 @@ namespace DSC2D { std::vector x_half; x_full.push_back(0.); - for (int i = 0; i <= Nx; i++) { - x_full.push_back(avg_edge_length + i*b); + for (real x=avg_edge_length; x #ifdef WIN32 -#include -#include +#include "CGLA/Vec2d.h" +#include "CGLA/Vec3d.h" #else #include -#include + #include #endif @@ -199,25 +199,65 @@ namespace DSC2D */ inline bool is_inside(const vec2& p, std::vector corners) { - vec2 c0, c1, c2; - while(corners.size() > 2) + + double x = p[0]; + double y = p[1]; + + int i, j = static_cast(corners.size())-1 ; + bool oddNodes=false; + double eps = 1e-8; + + for (i=0; i=y) || (corners[j][1]< y && corners[i][1]>=y) ) && (corners[i][0]<=x ||corners[j][0]<=x) ) + { + oddNodes^=(corners[i][0]+(y-corners[i][1])/(corners[j][1]-corners[i][1])*(corners[j][0]-corners[i][0]) 2) +// { +// int i = 0; +// do { +//#ifdef DEBUG +// assert(i < corners.size()); +//#endif +// c0 = corners[i]; +// c1 = corners[(i+1)%corners.size()]; +// c2 = corners[(i+2)%corners.size()]; +// i++; +// } while (is_left_of(c0,c1,c2)); +// +// if(!is_left_of(c0, c1, p) && !is_left_of(c1, c2, p) && !is_left_of(c2, c0, p)) +// { +// return true; +// } +// corners.erase(corners.begin() + (i%corners.size())); +// } +// return false; + } + + inline bool on_boundary(const vec2& p, std::vector corners) + { + int i, j = static_cast(corners.size())-1 ; + double eps = 1e-2; + + for (i=0; i +#include #include namespace DSC2D { @@ -65,6 +67,11 @@ namespace DSC2D { return time_step; } + void set_max_time_steps(int max) + { + MAX_TIME_STEPS = max; + } + /** Returns the name of the velocity function. */ @@ -158,16 +165,18 @@ namespace DSC2D { */ virtual bool is_motion_finished(DeformableSimplicialComplex& dsc) { - if (time_step == MAX_TIME_STEPS) { + if (time_step >= MAX_TIME_STEPS) + { return true; } std::vector pos = dsc.get_design_variable_positions(); + double avg_length = dsc.get_avg_edge_length(); for (auto &p : pos) { bool match = false; for (int i = 0; i + 1 < pos_old.size(); i += 2) { - if (Util::min_dist_sqr(pos_old[i], pos_old[i+1], p) < ACCURACY*ACCURACY) + if (Util::min_dist_sqr(pos_old[i], pos_old[i+1], p) < avg_length*ACCURACY*avg_length*ACCURACY) { match = true; break; @@ -193,4 +202,4 @@ namespace DSC2D { }; -} +} \ No newline at end of file From 4d9c1be6a4c5d5fe0645198f0a7a572a2620be8e Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Mon, 22 Oct 2018 11:43:52 +0200 Subject: [PATCH 13/20] Bug in triangle generation --- .../UserInterfaceState.xcuserstate | Bin 24690 -> 29128 bytes src/DSC.cpp | 1 + src/DSC.h | 2 +- src/trializer.cpp | 36 +++++++++++------- 4 files changed, 24 insertions(+), 15 deletions(-) diff --git a/DSC.xcodeproj/project.xcworkspace/xcuserdata/tuannt8.xcuserdatad/UserInterfaceState.xcuserstate b/DSC.xcodeproj/project.xcworkspace/xcuserdata/tuannt8.xcuserdatad/UserInterfaceState.xcuserstate index acf9dd7d7a3b3de4b2ba88eafa273856e11fe0ee..380ddb8f140478c237917a845b7e859a6aad19da 100644 GIT binary patch delta 14001 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 diff --git a/src/DSC.cpp b/src/DSC.cpp index 65f6635..5338f4d 100644 --- a/src/DSC.cpp +++ b/src/DSC.cpp @@ -186,6 +186,7 @@ namespace DSC2D bool DeformableSimplicialComplex::move_vertex(node_key vid) { + vec2 pos = get_pos(vid); vec2 destination = get_destination(vid); real l = Util::length(destination - pos); diff --git a/src/DSC.h b/src/DSC.h index eb02e5a..4bc1820 100644 --- a/src/DSC.h +++ b/src/DSC.h @@ -573,7 +573,7 @@ namespace DSC2D { */ void deform(); - private: + protected: /** Moves a the vertex with ID vid to its new position. Returns whether the vertex was succesfully moved to its new position. diff --git a/src/trializer.cpp b/src/trializer.cpp index b85082a..3d1be91 100644 --- a/src/trializer.cpp +++ b/src/trializer.cpp @@ -28,43 +28,51 @@ namespace DSC2D { std::vector x_half; x_full.push_back(0.); - for (real x=avg_edge_length; x Date: Mon, 29 Oct 2018 16:08:26 +0100 Subject: [PATCH 14/20] range based for-loop --- src/DSC.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/DSC.h b/src/DSC.h index 4bc1820..0af0458 100644 --- a/src/DSC.h +++ b/src/DSC.h @@ -401,6 +401,11 @@ namespace DSC2D { return mesh->vertices_end(); } + HMesh::IDIteratorPair vertices() const + { + return mesh->vertices(); + } + HMesh::HalfEdgeIDIterator halfedges_begin() const { return mesh->halfedges_begin(); @@ -411,6 +416,11 @@ namespace DSC2D { return mesh->halfedges_end(); } + HMesh::IDIteratorPair halfedges() const + { + return mesh->halfedges(); + } + HMesh::FaceIDIterator faces_begin() const { return mesh->faces_begin(); @@ -421,6 +431,11 @@ namespace DSC2D { return mesh->faces_end(); } + HMesh::IDIteratorPair faces() const{ + return mesh->faces(); + } + + HMesh::Walker walker(node_key vid) const { return mesh->walker(vid); From 177d8e52be0f8d17448db9c225969bce508df4d5 Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Wed, 31 Oct 2018 12:13:01 +0100 Subject: [PATCH 15/20] Change edge colors --- .../tuannt8.xcuserdatad/xcschemes/xcschememanagement.plist | 5 +++++ src/DSC.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/xcschememanagement.plist b/DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/xcschememanagement.plist index b3910c4..97c4917 100644 --- a/DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/xcschememanagement.plist +++ b/DSC.xcodeproj/xcuserdata/tuannt8.xcuserdatad/xcschemes/xcschememanagement.plist @@ -9,6 +9,11 @@ orderHint 3 + DEMO.xcscheme_^#shared#^_ + + orderHint + 3 + DSC.xcscheme orderHint diff --git a/src/DSC.cpp b/src/DSC.cpp index 5338f4d..5a7fa99 100644 --- a/src/DSC.cpp +++ b/src/DSC.cpp @@ -36,7 +36,7 @@ namespace DSC2D INTERFACE_COLOR = DARK_RED; CROSSING_COLOR = RED; - OUTSIDE_COLOR = BLACK; + OUTSIDE_COLOR = GRAY; DEFAULT_COLOR = DARK_BLUE; OUTSIDE_FACE_COLOR = INVISIBLE; DEFAULT_FACE_COLOR = BLUE; From 258c034f24441ea8d76730d5bc98055f58707e85 Mon Sep 17 00:00:00 2001 From: tuannt8 Date: Wed, 16 Jan 2019 15:28:51 +0100 Subject: [PATCH 16/20] Backup before start modify boundary displacement --- src/DSC.h | 15 ++++++++++++++- src/object_generator.h | 2 +- src/velocity_function.h | 4 ++-- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/DSC.h b/src/DSC.h index 4bc1820..e30de9c 100644 --- a/src/DSC.h +++ b/src/DSC.h @@ -85,6 +85,7 @@ namespace DSC2D { vec3 DEFAULT_FACE_COLOR; private: + public: HMesh::Manifold *mesh; DesignDomain *design_domain; @@ -132,7 +133,7 @@ namespace DSC2D { //************** ATTRIBUTE FUNCTIONS *************** protected: - + public: /** Clean up the attribute vectors (the lists that stores the attributes of each vertex, edge and face). Should be called after removing primitives. */ @@ -401,6 +402,11 @@ namespace DSC2D { return mesh->vertices_end(); } + HMesh::IDIteratorPair vertices() const + { + return mesh->vertices(); + } + HMesh::HalfEdgeIDIterator halfedges_begin() const { return mesh->halfedges_begin(); @@ -421,6 +427,11 @@ namespace DSC2D { return mesh->faces_end(); } + HMesh::IDIteratorPair faces() const + { + return mesh->faces(); + } + HMesh::Walker walker(node_key vid) const { return mesh->walker(vid); @@ -609,6 +620,7 @@ namespace DSC2D { //************** QUALITY CONTROL *************** protected: + public: /** Improves the quality of the simplicial complex by smoothing, removing needles and caps, maximize the minimum angle and removing degenerate faces. */ @@ -625,6 +637,7 @@ namespace DSC2D { void priority_queue_optimization(const HMesh::EnergyFun& efun); private: + public: /** Maximize minimum angles using greedy approach by flipping edges. */ diff --git a/src/object_generator.h b/src/object_generator.h index 975f81d..d8c408d 100644 --- a/src/object_generator.h +++ b/src/object_generator.h @@ -58,4 +58,4 @@ namespace DSC2D { }; -} \ No newline at end of file +} diff --git a/src/velocity_function.h b/src/velocity_function.h index ddb35d3..43d5445 100644 --- a/src/velocity_function.h +++ b/src/velocity_function.h @@ -17,7 +17,7 @@ #pragma once #include "DSC.h" -#include +#include #include #include @@ -202,4 +202,4 @@ namespace DSC2D { }; -} \ No newline at end of file +} From 4daff08e809d30b881233573c2f723ae1c376df5 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Wed, 20 Feb 2019 10:04:30 +0100 Subject: [PATCH 17/20] New code for template builder easier handle touch --- src/util.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/util.h b/src/util.h index 420f8e5..88a2471 100644 --- a/src/util.h +++ b/src/util.h @@ -25,9 +25,13 @@ #include "CGLA/Vec3d.h" #else #include +#include #include #endif +typedef CGLA::Vec2d vec2; +typedef CGLA::Vec3d vec3; +typedef CGLA::Vec2i vec2i; namespace DSC2D { From c806f5a3e80dc0c53fde5137104b859c272abe77 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Mon, 1 Apr 2019 10:20:45 +0200 Subject: [PATCH 18/20] progress... new design flow with freeform --- src/util.h | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/util.h b/src/util.h index 88a2471..20b9534 100644 --- a/src/util.h +++ b/src/util.h @@ -169,6 +169,31 @@ namespace DSC2D return sqr_length(p - projection); } + /* + Returns the projection of point p to line segment vw + */ + inline vec2 project_point_to_line_segment(const vec2& v, const vec2& w, const vec2& p) + { + const real l2 = dot(v-w, v-w); // i.e. |w-v|^2 - avoid a sqrt + if (l2 == 0.) + { + return v; // v == w case + } + // Consider the line extending the segment, parameterized as v + t (w - v). + // We find projection of point p onto the line. + // It falls where t = [(p-v) . (w-v)] / |w-v|^2 + const real t = dot(p - v, w - v) / l2; + if (t < 0.0) + { + return v; // Beyond the 'v' end of the segment + } + else if (t > 1.0) + { + return w; // Beyond the 'w' end of the segment + } + return v + t * (w - v); // Projection falls on the segment + } + /** Returns whether you have to turn left when going from a to b to c. */ From b3aa71fc31574837128a94a1674c8ee8365ecc32 Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Thu, 2 May 2019 11:04:36 +0200 Subject: [PATCH 19/20] Seem to work --- src/DSC.cpp | 6 +++++- src/DSC.h | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/DSC.cpp b/src/DSC.cpp index 5a7fa99..2a75b13 100644 --- a/src/DSC.cpp +++ b/src/DSC.cpp @@ -575,7 +575,7 @@ namespace DSC2D } - bool DeformableSimplicialComplex::split(edge_key eid) + bool DeformableSimplicialComplex::split(edge_key eid, node_key * n) { if (!unsafe_editable(eid)) { @@ -606,6 +606,10 @@ namespace DSC2D init_attributes(newf2, get_label(f2)); update_locally(vid); + + if(n) + *n = vid; + return true; } diff --git a/src/DSC.h b/src/DSC.h index c36877f..33795bf 100644 --- a/src/DSC.h +++ b/src/DSC.h @@ -591,6 +591,7 @@ namespace DSC2D { void deform(); protected: + public: /** Moves a the vertex with ID vid to its new position. Returns whether the vertex was succesfully moved to its new position. @@ -605,7 +606,7 @@ namespace DSC2D { /** Splits the edge eid by inserting a vertex at the center of the edge and splitting the two neighbouring faces of the edge. Returns whether it suceeds or not. */ - bool split(edge_key eid); + bool split(edge_key eid, node_key * n = nullptr); /** Collapses the edge with ID eid and updates attributes. If safe is true, the collapse will affect the shape of the interface minimally. Returns whether it suceeds or not. From 9ea0b04db917c538cccec3642e797f4d31c09f7c Mon Sep 17 00:00:00 2001 From: Tuan Nguyen Date: Fri, 10 May 2019 21:57:01 +0200 Subject: [PATCH 20/20] Forbid support edit --- src/DSC.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/DSC.cpp b/src/DSC.cpp index 2a75b13..beddeb1 100644 --- a/src/DSC.cpp +++ b/src/DSC.cpp @@ -227,6 +227,8 @@ namespace DSC2D resize_complex(); +// remove_needles(); + HMesh::IDRemap cleanup_map; cleanup_attributes(cleanup_map);