1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
|
// Copyright (c) 2005 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
// 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.
//
// Licensees holding a valid commercial license may use this file in
// accordance with the commercial license agreement provided with the software.
//
// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
//
// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/next/Envelope_3/include/CGAL/Envelope_3/Envelope_overlay_functor.h $
// $Id: Envelope_overlay_functor.h 67117 2012-01-13 18:14:48Z lrineau $
//
// Author(s) : Michal Meyerovitch <gorgymic@post.tau.ac.il>
// Baruch Zukerman <baruchzu@post.tau.ac.il>
#ifndef CGAL_ENVELOPE_OVERLAY_FUNCTOR_H
#define CGAL_ENVELOPE_OVERLAY_FUNCTOR_H
#include <iostream>
namespace CGAL {
template < class MinimizationDiagram_2>
class Envelope_overlay_functor
{
public:
typedef MinimizationDiagram_2 Minimization_diagram_2;
typedef typename Minimization_diagram_2::Face_const_handle Face_const_handle1;
typedef typename Minimization_diagram_2::Face_const_handle Face_const_handle2;
typedef typename Minimization_diagram_2::Vertex_const_handle Vertex_const_handle1;
typedef typename Minimization_diagram_2::Vertex_const_handle Vertex_const_handle2;
typedef typename Minimization_diagram_2::Halfedge_const_handle Halfedge_const_handle1;
typedef typename Minimization_diagram_2::Halfedge_const_handle Halfedge_const_handle2;
typedef typename Minimization_diagram_2::Face_handle Face_handle;
typedef typename Minimization_diagram_2::Vertex_handle Vertex_handle;
typedef typename Minimization_diagram_2::Halfedge_handle Halfedge_handle;
typedef typename Minimization_diagram_2::Face_handle Res_face_handle;
typedef typename Minimization_diagram_2::Halfedge_handle Res_halfedge_handle;
typedef typename Minimization_diagram_2::Vertex_handle Res_vertex_handle;
protected:
typedef typename Minimization_diagram_2::Dcel::Dcel_data_iterator Envelope_data_iterator;
typedef std::pair<Vertex_handle, Face_handle> 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<Vertex_face_pair, Halfedge_handle,
Less_vertex_face_pair> Boundary_cache;
public:
Envelope_overlay_functor(Minimization_diagram_2& md1,
Minimization_diagram_2& md2,
Minimization_diagram_2& result)
: 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)
{
res_f->set_aux_source(0, m_1.non_const_handle(f1));
res_f->set_aux_source(1, m_2.non_const_handle(f2));
}
void create_vertex(Halfedge_const_handle1 h1,
Halfedge_const_handle2 h2,
Res_vertex_handle res_v)
{
res_v->set_aux_source(0, m_1.non_const_handle(h1));
res_v->set_aux_source(1, m_2.non_const_handle(h2));
//res_v->set_is_intersection(true);
// res_v cannot be isolated
}
void create_vertex(Vertex_const_handle1 v1,
Vertex_const_handle2 v2,
Res_vertex_handle res_v)
{
res_v->set_aux_source(0, m_1.non_const_handle(v1));
res_v->set_aux_source(1, m_2.non_const_handle(v2));
//res_v->set_is_intersection(false);
if (v1->is_isolated() && v2->is_isolated())
{
res_v->set_is_equal_aux_data_in_face(0, v1->get_is_equal_data_in_face());
res_v->set_is_equal_aux_data_in_face(1, v2->get_is_equal_data_in_face());
res_v->set_has_equal_aux_data_in_face(0, v1->get_has_equal_data_in_face());
res_v->set_has_equal_aux_data_in_face(1, v2->get_has_equal_data_in_face());
}
}
void create_vertex(Vertex_const_handle1 v1,
Halfedge_const_handle2 h2,
Res_vertex_handle res_v)
{
res_v->set_aux_source(0, m_1.non_const_handle(v1));
res_v->set_aux_source(1, m_2.non_const_handle(h2));
//res_v->set_is_intersection(true);
// res_v cannot be isolated
}
void create_vertex(Halfedge_const_handle1 h1,
Vertex_const_handle2 v2,
Res_vertex_handle res_v)
{
res_v->set_aux_source(0, m_1.non_const_handle(h1));
res_v->set_aux_source(1, m_2.non_const_handle(v2));
//res_v->set_is_intersection(true);
// res_v cannot be isolated
}
void create_vertex(Face_const_handle1 f1,
Vertex_const_handle2 v2,
Res_vertex_handle res_v)
{
res_v->set_aux_source(0, m_1.non_const_handle(f1));
res_v->set_aux_source(1, m_2.non_const_handle(v2));
//res_v->set_is_intersection(false);
if (v2->is_isolated())
{
// the res_v is also isolated, and we should update the is_equal/has_equal
// data in face information
res_v->set_is_equal_aux_data_in_face(0, true);
res_v->set_is_equal_aux_data_in_face(1, v2->get_is_equal_data_in_face());
res_v->set_has_equal_aux_data_in_face(0, !f1->has_no_data());
res_v->set_has_equal_aux_data_in_face(1, v2->get_has_equal_data_in_face());
}
}
void create_vertex(Vertex_const_handle1 v1,
Face_const_handle2 f2,
Res_vertex_handle res_v)
{
res_v->set_aux_source(0, m_1.non_const_handle(v1));
res_v->set_aux_source(1, m_2.non_const_handle(f2));
//res_v->set_is_intersection(false);
if (v1->is_isolated())
{
// the res_v is also isolated, and we should update the is_equal/has_equal
// data in face information
res_v->set_is_equal_aux_data_in_face(0, v1->get_is_equal_data_in_face());
res_v->set_is_equal_aux_data_in_face(1, true);
res_v->set_has_equal_aux_data_in_face(0, v1->get_has_equal_data_in_face());
res_v->set_has_equal_aux_data_in_face(1, !f2->has_no_data());
}
}
void create_edge(Halfedge_const_handle1 h1,
Halfedge_const_handle2 h2,
Res_halfedge_handle res_h)
{
// update source
res_h->set_aux_source(0, m_1.non_const_handle(h1));
res_h->set_aux_source(1, m_2.non_const_handle(h2));
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(h2->twin()));
// update is_equal/has_equal data in face
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, h2->get_is_equal_data_in_face());
res_h->set_has_equal_aux_data_in_face(0, h1->get_has_equal_data_in_face());
res_h->set_has_equal_aux_data_in_face(1, h2->get_has_equal_data_in_face());
res_h->twin()->set_is_equal_aux_data_in_face(0, h1->twin()->get_is_equal_data_in_face());
res_h->twin()->set_is_equal_aux_data_in_face(1, h2->twin()->get_is_equal_data_in_face());
res_h->twin()->set_has_equal_aux_data_in_face(0, h1->twin()->get_has_equal_data_in_face());
res_h->twin()->set_has_equal_aux_data_in_face(1, h2->twin()->get_has_equal_data_in_face());
// update is_equal/has_equal data in target
update_halfedge_flags_on_edge(res_h, m_1.non_const_handle(h1), 0);
// update aux_data(1)
update_halfedge_flags_on_edge(res_h, m_2.non_const_handle(h2), 1);
// update is_equal/has_equal data in source
// update aux_data(0)
update_halfedge_flags_on_edge(res_h->twin(), m_1.non_const_handle(h1->twin()), 0);
// update aux_data(1)
update_halfedge_flags_on_edge(res_h->twin(), m_2.non_const_handle(h2->twin()), 1);
}
void create_edge(Halfedge_const_handle1 h1,
Face_const_handle2 f2,
Res_halfedge_handle res_h)
{
res_h->set_aux_source(0, m_1.non_const_handle(h1));
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));
// update is_equal/has_equal data in face
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);
res_h->set_has_equal_aux_data_in_face(0, h1->get_has_equal_data_in_face());
res_h->set_has_equal_aux_data_in_face(1, !f2->has_no_data());
res_h->twin()->set_is_equal_aux_data_in_face(0, h1->twin()->get_is_equal_data_in_face());
res_h->twin()->set_is_equal_aux_data_in_face(1, true);
res_h->twin()->set_has_equal_aux_data_in_face(0, h1->twin()->get_has_equal_data_in_face());
res_h->twin()->set_has_equal_aux_data_in_face(1, !f2->has_no_data());
// update is_equal/has_equal data in target for the first source map
update_halfedge_flags_on_edge(res_h, m_1.non_const_handle(h1), 0);
// update source
update_halfedge_flags_on_edge(res_h->twin(), m_1.non_const_handle(h1->twin()), 0);
// update is_equal/has_equal data in target for the second source map
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);
}
void create_edge(Face_const_handle1 f1,
Halfedge_const_handle2 h2,
Res_halfedge_handle res_h)
{
res_h->set_aux_source(0, m_1.non_const_handle(f1));
res_h->set_aux_source(1, m_2.non_const_handle(h2));
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());
res_h->set_has_equal_aux_data_in_face(1, h2->get_has_equal_data_in_face());
res_h->twin()->set_is_equal_aux_data_in_face(0, true);
res_h->twin()->set_is_equal_aux_data_in_face(1, h2->twin()->get_is_equal_data_in_face());
res_h->twin()->set_has_equal_aux_data_in_face(0, !f1->has_no_data());
res_h->twin()->set_has_equal_aux_data_in_face(1, h2->twin()->get_has_equal_data_in_face());
// update is_equal/has_equal data in target for the second source map
update_halfedge_flags_on_edge(res_h, m_2.non_const_handle(h2), 1);
// update source
update_halfedge_flags_on_edge(res_h->twin(), m_2.non_const_handle(h2->twin()), 1);
// update is_equal/has_equal data in target for the first source map
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:
template <class Halfedge_handle_t>
void copy_halfedge_target_info(Halfedge_handle_t from, Res_halfedge_handle to, unsigned int id)
{
to->set_is_equal_aux_data_in_target(id, from->get_is_equal_data_in_target());
to->set_has_equal_aux_data_in_target(id, from->get_has_equal_data_in_target());
}
void set_halfedge_target_info(Res_halfedge_handle to, unsigned int id, bool info)
{
to->set_is_equal_aux_data_in_target(id, info);
to->set_has_equal_aux_data_in_target(id, info);
}
template <class Halfedge_handle_t>
void copy_halfedge_target_info_from_halfedge_face_info(Halfedge_handle_t from,
Res_halfedge_handle to,
unsigned int id)
{
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());
to->set_has_equal_aux_data_in_target_and_face(id, from->get_has_equal_data_in_face());
}
template <class Vertex_handle_t>
void copy_halfedge_target_info_from_vertex_face_info(Vertex_handle_t from,
Res_halfedge_handle to,
unsigned int id)
{
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 on edge on_edge
// and target-face flags
// id is the source diagram where on_edge comes from
// (i.e. the id of the aux information to update)
void update_halfedge_flags_on_edge(Halfedge_handle new_h, Halfedge_handle on_edge, unsigned int id)
{
if(new_h->target()->is_at_open_boundary())
return;
Vertex_handle vh;
Halfedge_handle hh;
const Object& trg_src = new_h->target()->get_aux_source(id);
if (assign(vh, trg_src))
{
// vh is the target of on_edge, and we can copy the halfedge-target information
// from on_edge
copy_halfedge_target_info(on_edge, new_h, id);
new_h->set_has_equal_aux_data_in_target_and_face
(id, on_edge->get_has_equal_data_in_target_and_face());
}
else if (assign(hh, trg_src))
{
// hh is the "HEMSHECH" of on_edge, so we need to set halfedge_target
// information to true
set_halfedge_target_info(new_h, id, true);
// and target-face information using the original halfedge-face information
new_h->set_has_equal_aux_data_in_target_and_face
(id, on_edge->get_has_equal_data_in_face());
}
else
// this cannot happen, since we need to touch an edge
CGAL_assertion(false);
}
// update halfedge-target flags of new_h that is created inside face in_face
// and target-face information
// 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)
{
if(new_h->target()->is_at_open_boundary())
return;
Vertex_handle vh;
Halfedge_handle hh;
Face_handle fh;
// update target
const Object& trg_src = new_h->target()->get_aux_source(id);
if (assign(vh, trg_src))
{
if (vh->is_isolated())
{
copy_halfedge_target_info_from_vertex_face_info(vh, new_h, id);
// the target-face information is taken from vertex-face information too
new_h->set_has_equal_aux_data_in_target_and_face
(id, vh->get_has_equal_data_in_face());
}
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 =
h_of_vh_and_in_face->get_has_equal_data_in_target_and_face();
/*CGAL_assertion(has_equal == calc_has_equal);
if(has_equal != calc_has_equal)
return;*/
// update halfedge-target flags
new_h->set_is_equal_aux_data_in_target(id, is_equal);
new_h->set_has_equal_aux_data_in_target(id, has_equal);
// update target-face flag
new_h->set_has_equal_aux_data_in_target_and_face(id, 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());
new_h->set_has_equal_aux_data_in_target_and_face(id, !fh->has_no_data());
}
}
Minimization_diagram_2& m_1;
Minimization_diagram_2& m_2;
Minimization_diagram_2& m_result;
Boundary_cache traversed_vertices;
};
} //namespace CGAL
#endif
|