diff --git a/Packages/Envelope_3/include/CGAL/Envelope_overlay_functor.h b/Packages/Envelope_3/include/CGAL/Envelope_overlay_functor.h index feec8b01a71..556ac46351e 100644 --- a/Packages/Envelope_3/include/CGAL/Envelope_overlay_functor.h +++ b/Packages/Envelope_3/include/CGAL/Envelope_overlay_functor.h @@ -50,6 +50,21 @@ public: protected: typedef typename Minimization_diagram_2::Dcel::Dcel_data_iterator Envelope_data_iterator; + typedef std::pair Vertex_face_pair; + struct Less_vertex_face_pair + { + bool operator() (const Vertex_face_pair& vf1, + const Vertex_face_pair& vf2) const + { + Vertex_handle v1 = vf1.first, v2 = vf2.first; + Face_handle f1 = vf1.second, f2= vf2.second; + return (&*v1 < &*v2 || + (&*v1 == &*v2 && &*f1 < &*f2)); + } + }; + typedef std::map Boundary_cache; + public: Envelope_overlay_functor(Minimization_diagram_2& md1, @@ -58,6 +73,11 @@ public: : m_1(md1), m_2(md2), m_result(result) { } + + ~Envelope_overlay_functor() + { + traversed_vertices.clear(); + } void create_face (Face_const_handle1 f1, Face_const_handle2 f2, Res_face_handle res_f) { @@ -244,7 +264,7 @@ public: res_h->set_aux_source(1, m_2.non_const_handle(f2)); res_h->twin()->set_aux_source(0, m_1.non_const_handle(h1->twin())); - res_h->twin()->set_aux_source(1, m_2.non_const_handle(f2)); + res_h->twin()->set_aux_source(1, m_2.non_const_handle(f2)); res_h->set_is_equal_aux_data_in_face(0, h1->get_is_equal_data_in_face()); res_h->set_is_equal_aux_data_in_face(1, true); @@ -288,92 +308,10 @@ public: CGAL_assertion(false); // update is_equal/has_equal data in target for the second source map - Vertex_handle vh2; - Halfedge_handle hh2; - Face_handle fh2; - // update target - Object trg_src2 = res_h->target()->get_aux_source(1); - if (assign(vh2, trg_src2)) - // todo - { - if (vh2->is_isolated()) - copy_halfedge_target_info_from_vertex_face_info(vh2, res_h, 1); - else - { - // we have a vertex vh2 on the boundary of the face f2 - bool is_equal = vh2->is_equal_data(f2->begin_data(), f2->end_data()); - bool has_equal = vh2->has_equal_data(f2->begin_data(), f2->end_data()); - - res_h->set_is_equal_aux_data_in_target(1, is_equal); - res_h->set_has_equal_aux_data_in_target(1, has_equal); - } - } - else if (assign(hh2, trg_src2)) - // we should find the halfedge (hh2 or hh2->twin()) that points to face - // f2, and check the in_face flags there - { - CGAL_assertion(hh2->face() == m_2.non_const_handle(f2) || - hh2->twin()->face() == m_2.non_const_handle(f2)); - Face_handle f = m_2.non_const_handle(f2); - if (hh2->face() == f) - copy_halfedge_target_info_from_halfedge_face_info(hh2, res_h, 1); - else - copy_halfedge_target_info_from_halfedge_face_info(hh2->twin(), res_h, 1); - } - else - { - CGAL_assertion(assign(fh2, trg_src2)); - assign(fh2, trg_src2); - // the edge and target are in the same face, so we set halfedge-target - // equal information to true, and has equal acoording to face data - res_h->set_is_equal_aux_data_in_target(1, true); - res_h->set_has_equal_aux_data_in_target(1, !fh2->has_no_data()); -// set_halfedge_target_info(res_h, 1, true); - } - - // update source - Object src_src2 = res_h->source()->get_aux_source(1); - if (assign(vh2, src_src2)) - // todo - { - // we have a vertex vh2 on the boundary of the face f2 - // or an isolated vertex - if (vh2->is_isolated()) - copy_halfedge_target_info_from_vertex_face_info(vh2, res_h->twin(), 1); - else - { - bool is_equal = vh2->is_equal_data(f2->begin_data(), f2->end_data()); - bool has_equal = vh2->has_equal_data(f2->begin_data(), f2->end_data()); - - res_h->twin()->set_is_equal_aux_data_in_target(1, is_equal); - res_h->twin()->set_has_equal_aux_data_in_target(1, has_equal); - } - } - else if (assign(hh2, src_src2)) - // we should find the halfedge (hh2 or hh2->twin()) that points to face - // f2, and check the in_face flags there - { - CGAL_assertion(hh2->face() == m_2.non_const_handle(f2) || - hh2->twin()->face() == m_2.non_const_handle(f2)); - Face_handle f = m_2.non_const_handle(f2); - if (hh2->face() == f) - copy_halfedge_target_info_from_halfedge_face_info(hh2, res_h->twin(), 1); - else - copy_halfedge_target_info_from_halfedge_face_info(hh2->twin(), res_h->twin(), 1); - } - - else - { - CGAL_assertion(assign(fh2, src_src2)); - assign(fh2, src_src2); - // the edge and soucre are in the same face, so we set halfedge-target - // information to true - res_h->twin()->set_is_equal_aux_data_in_target(1, true); - res_h->twin()->set_has_equal_aux_data_in_target(1, !fh2->has_no_data()); - -// set_halfedge_target_info(res_h->twin(), 1, true); - } - + update_halfedge_flags_in_face(res_h, m_2.non_const_handle(f2), 1); + + // update is_equal/has_equal data in source for the second source map + update_halfedge_flags_in_face(res_h->twin(), m_2.non_const_handle(f2), 1); } @@ -387,6 +325,7 @@ public: res_h->twin()->set_aux_source(0, m_1.non_const_handle(f1)); res_h->twin()->set_aux_source(1, m_2.non_const_handle(h2->twin())); + // update halfedge-face flags of the new halfedge res_h->set_is_equal_aux_data_in_face(0, true); res_h->set_is_equal_aux_data_in_face(1, h2->get_is_equal_data_in_face()); res_h->set_has_equal_aux_data_in_face(0, !f1->has_no_data()); @@ -429,90 +368,9 @@ public: CGAL_assertion(false); // update is_equal/has_equal data in target for the first source map - Vertex_handle vh1; - Halfedge_handle hh1; - Face_handle fh1; - // update target - Object trg_src1 = res_h->target()->get_aux_source(0); - if (assign(vh1, trg_src1)) - // todo - { - if (vh1->is_isolated()) - copy_halfedge_target_info_from_vertex_face_info(vh1, res_h, 0); - else - { - // we have a vertex vh1 on the boundary of the face f1 - bool is_equal = vh1->is_equal_data(f1->begin_data(), f1->end_data()); - bool has_equal = vh1->has_equal_data(f1->begin_data(), f1->end_data()); - - res_h->set_is_equal_aux_data_in_target(0, is_equal); - res_h->set_has_equal_aux_data_in_target(0, has_equal); - } - } - else if (assign(hh1, trg_src1)) - // we should find the halfedge (hh1 or hh1>twin()) that points to face - // f1, and check the in_face flags there - { - CGAL_assertion(hh1->face() == m_1.non_const_handle(f1) || - hh1->twin()->face() == m_1.non_const_handle(f1)); - Face_handle f = m_1.non_const_handle(f1); - if (hh1->face() == f) - copy_halfedge_target_info_from_halfedge_face_info(hh1, res_h, 0); - else - copy_halfedge_target_info_from_halfedge_face_info(hh1->twin(), res_h, 0); - } - else - { - CGAL_assertion(assign(fh1, trg_src1)); - assign(fh1, trg_src1); - // the edge and target are in the same face, so we set halfedge-target - // information to true - res_h->set_is_equal_aux_data_in_target(0, true); - res_h->set_has_equal_aux_data_in_target(0, !fh1->has_no_data()); -// set_halfedge_target_info(res_h, 0, true); - } - - // update source - Object src_src1 = res_h->source()->get_aux_source(0); - if (assign(vh1, src_src1)) - // todo - { - if (vh1->is_isolated()) - copy_halfedge_target_info_from_vertex_face_info(vh1, res_h->twin(), 0); - else - { - // we have a vertex vh1 on the boundary of the face f1 - bool is_equal = vh1->is_equal_data(f1->begin_data(), f1->end_data()); - bool has_equal = vh1->has_equal_data(f1->begin_data(), f1->end_data()); - - res_h->twin()->set_is_equal_aux_data_in_target(0, is_equal); - res_h->twin()->set_has_equal_aux_data_in_target(0, has_equal); - } - } - else if (assign(hh1, src_src1)) - // we should find the halfedge (hh1 or hh1->twin()) that points to face - // f1, and check the in_face flags there - { - CGAL_assertion(hh1->face() == m_1.non_const_handle(f1) || - hh1->twin()->face() == m_1.non_const_handle(f1)); - Face_handle f = m_1.non_const_handle(f1); - if (hh1->face() == f) - copy_halfedge_target_info_from_halfedge_face_info(hh1, res_h->twin(), 0); - else - copy_halfedge_target_info_from_halfedge_face_info(hh1->twin(), res_h->twin(), 0); - } - - else - { - CGAL_assertion(assign(fh1, src_src1)); - assign(fh1, src_src1); - // the edge and soucre are in the same face, so we set halfedge-target - // information to true - res_h->twin()->set_is_equal_aux_data_in_target(0, true); - res_h->twin()->set_has_equal_aux_data_in_target(0, !fh1->has_no_data()); - -// set_halfedge_target_info(res_h->twin(), 0, true); - } + update_halfedge_flags_in_face(res_h, m_1.non_const_handle(f1), 0); + // update is_equal/has_equal data in source for the first source map + update_halfedge_flags_in_face(res_h->twin(), m_1.non_const_handle(f1), 0); } protected: @@ -545,10 +403,125 @@ protected: to->set_is_equal_aux_data_in_target(id, from->get_is_equal_data_in_face()); to->set_has_equal_aux_data_in_target(id, from->get_has_equal_data_in_face()); } + + // find a halfedge that v is its target and f is its face + Halfedge_handle find_halfedge_by_vertex_and_face(Vertex_handle v, Face_handle f) + { + // should always invoke this method when v is on the boundary of f + + // for the complexity of the total algorithm, we only loop over + // the halfedges of each vertex once and cache the triples of + // vertex-face-halfedge for future such questions + Vertex_face_pair query(v, f); + typename Boundary_cache::iterator iter = traversed_vertices.find(query); + Halfedge_handle result; + if (iter == traversed_vertices.end()) + { + // first time to check this vertex - traverse all its halfedges + // and update the map + typename Minimization_diagram_2::Halfedge_around_vertex_circulator vc = + v->incident_halfedges(), + vc_begin = vc; + do { + Halfedge_handle hh = vc; + // update the map + traversed_vertices[Vertex_face_pair(v, hh->face())] = hh; + // check for reult + if (hh->face() == f) + result = hh; + ++vc; + } while (vc != vc_begin); + } + else + { + // take it from the map + result = iter->second; + } + CGAL_assertion(result != Halfedge_handle()); + return result; + } + + // update halfedge-target flags of new_h that is created inside face in_face + // id is the source diagram where in_face comes from + // (i.e. the id of the aux information to update) + void update_halfedge_flags_in_face(Halfedge_handle new_h, Face_handle in_face, unsigned int id) + { + // update is_equal/has_equal data in target for the first source map + Vertex_handle vh; + Halfedge_handle hh; + Face_handle fh; + // update target + Object trg_src = new_h->target()->get_aux_source(id); + if (assign(vh, trg_src)) + // todo + { + if (vh->is_isolated()) + copy_halfedge_target_info_from_vertex_face_info(vh, new_h, id); + else + { + // we have a vertex vh on the boundary of the face in_face + // todo: get rid of this calculations: (using unknown value for has_equal flag) + CGAL_assertion_code( + bool calc_is_equal = vh->is_equal_data(in_face->begin_data(), in_face->end_data()); + ) + bool calc_has_equal = vh->has_equal_data(in_face->begin_data(), in_face->end_data()); + + // find the halfedge with target vh on the boundary of in_face + Halfedge_handle h_of_vh_and_in_face = + find_halfedge_by_vertex_and_face(vh, in_face); + // is_equal relationship is easy: + bool is_equal = h_of_vh_and_in_face->get_is_equal_data_in_face() && + h_of_vh_and_in_face->get_is_equal_data_in_target(); + CGAL_assertion(is_equal == calc_is_equal); + + // has_equal relationship is problematic in one case: + bool has_equal; + if (h_of_vh_and_in_face->get_has_equal_data_in_face() == true) + has_equal = h_of_vh_and_in_face->get_has_equal_data_in_target(); + else + if (h_of_vh_and_in_face->get_has_equal_data_in_target() == false) + has_equal = false; + else if (h_of_vh_and_in_face->get_is_equal_data_in_target() == true) + has_equal = false; + else + { + CGAL_assertion_code(std::cout << "happen" << std::endl;) + has_equal = calc_has_equal; + } + CGAL_assertion(has_equal == calc_has_equal); + + new_h->set_is_equal_aux_data_in_target(id, is_equal); + new_h->set_has_equal_aux_data_in_target(id, calc_has_equal); + } + } + else if (assign(hh, trg_src)) + // we should find the halfedge (hh or hh>twin()) that points to face + // in_face, and check the halfedge-face flags there + { + CGAL_assertion(hh->face() == in_face || hh->twin()->face() == in_face); + if (hh->face() == in_face) + copy_halfedge_target_info_from_halfedge_face_info(hh, new_h, id); + else + copy_halfedge_target_info_from_halfedge_face_info(hh->twin(), new_h, id); + } + else + { + CGAL_assertion_code(bool b =) + assign(fh, trg_src); + CGAL_assertion(b); + // the edge and target are in the same face, so we set halfedge-target + // is_equal information to true, and has_equal information according to + // the face data + CGAL_assertion(fh == in_face); + new_h->set_is_equal_aux_data_in_target(id, true); + new_h->set_has_equal_aux_data_in_target(id, !fh->has_no_data()); + } + } Minimization_diagram_2& m_1; Minimization_diagram_2& m_2; - Minimization_diagram_2& m_result; + Minimization_diagram_2& m_result; + Boundary_cache traversed_vertices; }; CGAL_END_NAMESPACE