diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h index f9595ef7358..8c7b8702366 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h @@ -1037,6 +1037,54 @@ public: std::size_t patch_id_q1=tm2_patch_ids[ get(fids2, face(opposite(h2,tm2),tm2)) ]; std::size_t patch_id_q2=tm2_patch_ids[ get(fids2, face(h2,tm2)) ]; + // info on whether the patches were already classified + std::bitset<4> patch_status_was_not_already_set; + std::bitset<4> previous_bitvalue; + // info for tm1 + patch_status_was_not_already_set[0] = patch_status_not_set_tm1.test(patch_id_p1); + patch_status_was_not_already_set[1] = patch_status_not_set_tm1.test(patch_id_p2); + previous_bitvalue[0] = is_patch_inside_tm2.test(patch_id_p1); + previous_bitvalue[1] = is_patch_inside_tm2.test(patch_id_p2); + // info for tm2 + patch_status_was_not_already_set[2] = patch_status_not_set_tm2.test(patch_id_q1); + patch_status_was_not_already_set[3] = patch_status_not_set_tm2.test(patch_id_q2); + previous_bitvalue[2] = is_patch_inside_tm1.test(patch_id_q1); + previous_bitvalue[3] = is_patch_inside_tm1.test(patch_id_q2); + +#ifndef CGAL_NDEBUG + if (is_tm1_closed && is_tm2_closed) + { + if (!patch_status_was_not_already_set[0] && + !patch_status_was_not_already_set[1] && + !patch_status_was_not_already_set[2] && + !patch_status_was_not_already_set[3]) + continue; // all patches were already classified, no need to redo it + } +#endif + + // check incompatibility of patch classifications + auto inconsistent_classification = [&]() + { + if (!used_to_clip_a_surface && !used_to_classify_patches && (!is_tm1_closed || !is_tm2_closed)) + { + //make sure there is no ambiguity in tm1 + if( (patch_status_was_not_already_set[0] && previous_bitvalue[0]!=is_patch_inside_tm2[patch_id_p1] ) || + (patch_status_was_not_already_set[1] && previous_bitvalue[1]!=is_patch_inside_tm2[patch_id_p2] ) ) + { + impossible_operation.set(); + return true; + } + //make sure there is no ambiguity in tm2 + if( (patch_status_was_not_already_set[2] && previous_bitvalue[2]!=is_patch_inside_tm2[patch_id_q1] ) || + (patch_status_was_not_already_set[3] && previous_bitvalue[3]!=is_patch_inside_tm2[patch_id_q2] ) ) + { + impossible_operation.set(); + return true; + } + } + return false; + }; + //indicates that patch status will be updated patch_status_not_set_tm1.reset(patch_id_p1); patch_status_not_set_tm1.reset(patch_id_p2); @@ -1082,6 +1130,7 @@ public: if ( q2_is_between_p1p2 ) is_patch_inside_tm1.set(patch_id_q2); //case 1 else is_patch_inside_tm2.set(patch_id_p2); //case 2 + if (inconsistent_classification()) return; continue; } else{ @@ -1112,6 +1161,7 @@ public: is_patch_inside_tm1.set(patch_id_q1); is_patch_inside_tm2.set(patch_id_p2); } //else case 4 + if (inconsistent_classification()) return; continue; } else @@ -1142,6 +1192,7 @@ public: is_patch_inside_tm1.set(patch_id_q2); is_patch_inside_tm2.set(patch_id_p1); } // else case 6 + if (inconsistent_classification()) return; continue; } else{ @@ -1170,6 +1221,7 @@ public: if ( q1_is_between_p1p2 ) is_patch_inside_tm1.set(patch_id_q1); //case 7 else is_patch_inside_tm2.set(patch_id_p1); //case 8 + if (inconsistent_classification()) return; continue; } } @@ -1331,6 +1383,11 @@ public: } } } + if (inconsistent_classification()) return; + CGAL_assertion( patch_status_was_not_already_set[0] || previous_bitvalue[0]==is_patch_inside_tm2[patch_id_p1] ); + CGAL_assertion( patch_status_was_not_already_set[1] || previous_bitvalue[1]==is_patch_inside_tm2[patch_id_p2] ); + CGAL_assertion( patch_status_was_not_already_set[2] || previous_bitvalue[2]==is_patch_inside_tm1[patch_id_q1] ); + CGAL_assertion( patch_status_was_not_already_set[3] || previous_bitvalue[3]==is_patch_inside_tm1[patch_id_q2] ); } } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h index 1c2b6de4581..ad384836576 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h @@ -780,6 +780,7 @@ struct Patch_container{ Patch_description& patch=this->operator[](i); std::stringstream ss; + ss.precision(17); std::map vertexid; int id=0; for(vertex_descriptor vh : patch.interior_vertices) diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data-coref/incompatible_with_open_cube.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-coref/incompatible_with_open_cube.off new file mode 100644 index 00000000000..87267990f22 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data-coref/incompatible_with_open_cube.off @@ -0,0 +1,96 @@ +OFF +32 60 0 + +30 120 60 +30 120 30 +70 60 30 +60 120 60 +70 60 60 +60 120 30 +70 40 30 +130 60 30 +70 40 60 +30 -20 60 +60 -20 60 +30 -40 60 +30 -40 30 +130 60 60 +60 -20 30 +30 -20 30 +160 60 60 +160 -20 60 +60 -40 60 +60 -40 30 +130 -20 60 +130 -20 30 +160 -20 30 +130 40 60 +130 40 30 +160 -40 30 +160 40 30 +130 -40 30 +160 40 60 +130 -40 60 +160 -40 60 +160 60 30 +3 1 0 5 +3 0 9 3 +3 10 14 3 +3 5 0 3 +3 0 15 9 +3 3 14 5 +3 5 15 1 +3 14 15 5 +3 1 15 0 +3 3 9 10 +3 19 18 11 +3 9 18 10 +3 12 11 15 +3 12 19 11 +3 14 19 15 +3 19 12 15 +3 15 11 9 +3 11 18 9 +3 10 21 14 +3 19 29 18 +3 23 8 24 +3 19 27 29 +3 6 24 8 +3 18 29 10 +3 2 4 13 +3 29 20 10 +3 27 19 21 +3 14 21 19 +3 29 30 17 +3 22 25 21 +3 25 22 17 +3 21 25 27 +3 29 17 20 +3 30 25 17 +3 25 30 29 +3 27 25 29 +3 22 28 17 +3 4 2 8 +3 17 28 20 +3 20 23 24 +3 26 28 22 +3 21 24 22 +3 23 20 28 +3 24 26 22 +3 28 16 23 +3 31 26 7 +3 26 31 16 +3 24 7 26 +3 13 23 16 +3 31 7 16 +3 26 16 28 +3 7 13 16 +3 13 8 23 +3 24 2 7 +3 2 6 8 +3 24 6 2 +3 4 8 13 +3 7 2 13 +3 20 24 21 +3 21 10 20 + diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cmd b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cmd index d154ad0157d..99d70e20728 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cmd +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cmd @@ -1 +1,2 @@ ${CGAL_DATA_DIR}/meshes/elephant.off ${CGAL_DATA_DIR}/meshes/sphere.off ALL 1 1 1 1 +${CGAL_DATA_DIR}/meshes/open_cube.off data-coref/incompatible_with_open_cube.off ALL 0 0 0 0 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cpp index 4822f03a76a..cc012385996 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_corefinement_bool_op.cpp @@ -272,22 +272,43 @@ int main(int argc,char** argv) return 1; } - Result_checking rc; - - if (argc==8) + if (argc>8 && (argc-1)%7==0) { - rc.check=true; - rc.union_res = atoi(argv[4])!=0; - rc.inter_res = atoi(argv[5])!=0; - rc.P_minus_Q_res = atoi(argv[6])!=0; - rc.Q_minus_P_res = atoi(argv[7])!=0; + // cmd mode + for (int i=0;i(argv[i+1], argv[i+2], scenario, rc); + } } + else + { + Result_checking rc; - int scenario = -1; - if (argc>=5 && std::string(argv[3])!=std::string("ALL")) - scenario = atoi(argv[4]); + if (argc==8) + { + rc.check=true; + rc.union_res = atoi(argv[4])!=0; + rc.inter_res = atoi(argv[5])!=0; + rc.P_minus_Q_res = atoi(argv[6])!=0; + rc.Q_minus_P_res = atoi(argv[7])!=0; + } - run(argv[1], argv[2], scenario, rc); + int scenario = -1; + if (argc>=5 && std::string(argv[3])!=std::string("ALL")) + scenario = atoi(argv[3]); + + run(argv[1], argv[2], scenario, rc); + } return 0; }