Main Page | Namespace List | Class List | File List | Namespace Members | Class Members

DelaunayMeshGenerator.cpp

00001 // 00002 // file : DelaunayMeshGenerator.cpp 00003 // author : jh 00004 // date : 15 jul 2002 00005 // changed : 29 jul 2002 00006 // 00007 00008 #include <stdlib.h> 00009 00010 #include "DelaunayMeshGenerator.h" 00011 #include "geometry.h" 00012 00013 #include <qdatetime.h> 00014 00015 00016 extern char* __delaunay_lib_version; 00017 00018 00019 00020 DelaunayMeshGenerator::DelaunayMeshGenerator(const QString& filename, bool verbose) 00021 : QXmlDefaultHandler(), _verbose(verbose) 00022 { 00023 #ifdef _DEBUG_ 00024 fprintf(stderr, "<DelaunayMeshGenerator::DelaunayMeshGenerator()>\n"); 00025 #endif 00026 00027 reset(); 00028 QFile xmlfile(filename); 00029 open(xmlfile); 00030 00031 00032 #ifdef _DEBUG_ 00033 fprintf(stderr, "numer of vertices : %d \n", _vertices.count() ); 00034 fprintf(stderr, "</DelaunayMeshGenerator::DelaunayMeshGenerator()>\n"); 00035 #endif 00036 00037 } 00038 00039 00040 00041 DelaunayMeshGenerator::DelaunayMeshGenerator(QIODevice& iodevice, bool verbose) 00042 : QXmlDefaultHandler(), _verbose(verbose) 00043 { 00044 reset(); 00045 open(iodevice); 00046 } 00047 00048 00049 00050 00051 void 00052 DelaunayMeshGenerator::reset() 00053 { 00054 _mesh = 0; 00055 _count_ID = 1; 00056 } 00057 00058 00059 00060 DelaunayMeshGenerator::~DelaunayMeshGenerator() 00061 { 00062 // _vertices.setAutoDelete(true); 00063 // _active_vertices.setAutoDelete(true); 00064 00065 _edges.setAutoDelete(true); 00066 _active_edges.setAutoDelete(true); 00067 00068 // _triangles.setAutoDelete(true); 00069 00070 if(_mesh != 0) 00071 delete _mesh; 00072 } 00073 00074 00075 00076 void 00077 DelaunayMeshGenerator::add_vertex(Vertex* v) 00078 { 00079 #ifdef _DEBUG_ 00080 fprintf(stderr, "<DelaunayMeshGenerator::addVertex()>\n"); 00081 #endif 00082 00083 _vertices.append(v); 00084 00085 #ifdef _DEBUG_ 00086 fprintf(stderr, "</DelaunayMeshGenerator::addVertex()>\n"); 00087 #endif 00088 00089 } 00090 00091 00092 00093 void 00094 DelaunayMeshGenerator::generate() 00095 { 00096 #ifdef _DEBUG_ 00097 fprintf(stderr, "<DelaunayMeshGenerator::generate()>\n"); 00098 #endif 00099 00100 init(); 00101 00102 #ifdef _DEBUG_ 00103 fprintf(stderr, "[DelaunayMeshGenerator::generate()] bbox (%f/%f)-(%f/%f) \n", 00104 minX, minY, maxX, maxY ); 00105 #endif 00106 00107 _active_edges = _edges; 00108 _active_vertices = _vertices; 00109 00110 Vertex* new_vertex = 0; 00111 00112 00113 int count = 0; 00114 00115 00116 while(!_active_edges.isEmpty()) { 00117 00118 Edge* edge = _active_edges.take(0); 00119 00120 /* 00121 fprintf(stderr, "<DelaunayMeshGenerator::generate()> [%d] next active edge [%s]-[%s] ... \n", 00122 count++, 00123 edge->get_vertex(0)->get_ID().latin1(), 00124 edge->get_vertex(1)->get_ID().latin1() ); 00125 */ 00126 00127 if(_verbose) { 00128 count++; 00129 if(count % 100 == 0) { 00130 fprintf(stderr, "number of active vertices = %d \n", _active_vertices.count() ); 00131 } 00132 } 00133 00134 ((Vertex*) edge->vertex(0))->grad -= 1; 00135 ((Vertex*) edge->vertex(1))->grad -= 1; 00136 00137 box_minX = minX; 00138 box_maxX = maxX; 00139 box_minY = minY; 00140 box_maxY = maxY; 00141 00142 new_vertex = 0; 00143 u_alt = 1e15; 00144 00145 00146 QPtrListIterator<Vertex> it(_active_vertices); 00147 00148 Vertex* vertex; 00149 00150 while( (vertex = it.current()) != 0 ) { 00151 00152 ++it; 00153 00154 #ifdef _DEBUG_ 00155 fprintf(stderr, "check vertex [%s] (%d active vertices) \n", 00156 vertex->get_ID().latin1(), _active_vertices.count() ); 00157 #endif 00158 00159 00160 if(vertex == edge->vertex(0) || vertex == edge->vertex(1) ) { 00161 #ifdef _DEBUG_ 00162 fprintf(stderr, "continue [%s] (1) \n", vertex->get_ID().latin1() ); 00163 #endif 00164 continue; 00165 } 00166 00167 00168 if(vertex->x() < box_minX || vertex->x() > box_maxX || 00169 vertex->y() < box_minY || vertex->y() > box_maxY ) { 00170 00171 #ifdef _DEBUG_ 00172 fprintf(stderr, "continue [%s] (2) \n", vertex->ID().latin1() ); 00173 #endif 00174 00175 continue; 00176 00177 } 00178 00179 00180 if( geometry::area(edge->vertex(0), 00181 edge->vertex(1), 00182 vertex ) <= CEps ) { 00183 #ifdef _DEBUG_ 00184 fprintf(stderr, "continue [%s] (3) \n", vertex->ID().latin1() ); 00185 #endif 00186 continue; 00187 } 00188 00189 00190 00191 if( test_intersection(vertex, edge->vertex(0)) ) { 00192 #ifdef _DEBUG_ 00193 fprintf(stderr, "continue [%s] (4) \n", vertex->ID().latin1() ); 00194 #endif 00195 continue; 00196 } 00197 00198 00199 00200 if( test_intersection(edge->vertex(1), vertex) ) { 00201 00202 #ifdef _DEBUG_ 00203 fprintf(stderr, "continue [%s] (5) \n", vertex->ID().latin1() ); 00204 #endif 00205 continue; 00206 00207 } 00208 00209 00210 if( is_voronoi_triangle(edge, vertex) ) 00211 new_vertex = vertex; 00212 00213 00214 } 00215 00216 if(new_vertex != 0) { 00217 create_triangle(edge, new_vertex); 00218 } else { 00219 fprintf(stderr, "ERROR : newpoint = null! \n"); 00220 exit(1); 00221 } 00222 00223 } 00224 00225 /* 00226 const QDict<Vertex>& v_list = _mesh->get_vertices(); 00227 fprintf(stderr, "</generate()> numer of vertices (mesh) : %d \n", v_list.count() ); 00228 */ 00229 00230 #ifdef _DEBUG_ 00231 fprintf(stderr, "</DelaunayMeshGenerator::generate()>\n"); 00232 #endif 00233 00234 } 00235 00236 00237 00238 void 00239 DelaunayMeshGenerator::create_triangle(Edge* basisedge, Vertex* vertex) 00240 { 00241 #ifdef _DEBUG_ 00242 fprintf(stderr, "</DelaunayMeshGenerator::createTriangle()>\n"); 00243 fprintf(stderr, "[/DelaunayMeshGenerator::createTriangle()] basisedge [%s]-[%s], vertex [%s]\n", 00244 basisedge->vertex(0)->ID().latin1(), 00245 basisedge->vertex(1)->ID().latin1(), 00246 vertex->ID().latin1() ); 00247 #endif 00248 00249 00250 Triangle* tri; 00251 Edge* edge; 00252 Edge* e[2]; 00253 00254 tri = new Triangle(createID(), 00255 basisedge->vertex(0), 00256 basisedge->vertex(1), 00257 vertex); 00258 00259 vertex->used = true; 00260 00261 00262 // check if new edge already exists 00263 00264 e[0] = e[1] = 0; 00265 00266 00267 QPtrListIterator<Edge> it(_active_edges); 00268 00269 while( (edge = it.current()) != 0 ) { 00270 00271 ++it; 00272 00273 for(int i=0; i<2; i++) { 00274 00275 if(vertex == edge->vertex(i) && 00276 basisedge->vertex(i) == edge->vertex((i+1)%2)) { 00277 00278 e[i] = edge; 00279 00280 ((Vertex*) edge->vertex(0))->grad -= 1; 00281 ((Vertex*) edge->vertex(1))->grad -= 1; 00282 00283 if(((Vertex*) edge->vertex(0))->grad == 0 && 00284 ((Vertex*) edge->vertex(0))->used == true ) 00285 _active_vertices.removeRef( ((Vertex*) edge->vertex(0)) ); 00286 00287 if(((Vertex*) edge->vertex(1))->grad == 0 && 00288 ((Vertex*) edge->vertex(1))->used == true ) 00289 _active_vertices.removeRef( ((Vertex*) edge->vertex(1)) ); 00290 00291 } 00292 00293 if(e[0] != 0 && e[1] != 0) 00294 break; 00295 00296 } 00297 00298 } // while(iter.hasNext()) 00299 00300 00301 if(e[0] == 0) { 00302 00303 #ifdef _DEBUG_ 00304 fprintf(stderr, "[DelaunayMeshGenerator::createTriangle()] create new edge \n"); 00305 fprintf(stderr, " new edge [%s][%s] \n", 00306 basisedge->vertex(0)->ID().latin1(), 00307 vertex->ID().latin1() ); 00308 #endif 00309 00310 e[0] = new Edge(basisedge->vertex(0), vertex); 00311 00312 vertex->grad += 1; 00313 ((Vertex*) basisedge->vertex(0))->grad += 1; 00314 00315 _active_edges.append( e[0] ); 00316 00317 } else { 00318 _active_edges.removeRef( e[0] ); 00319 } 00320 00321 00322 if(e[1] == 0) { 00323 00324 #ifdef _DEBUG_ 00325 fprintf(stderr, "[DelaunayMeshGenerator::createTriangle()] create new edge \n"); 00326 fprintf(stderr, " new edge [%s][%s] \n", 00327 vertex->ID().latin1(), 00328 basisedge->vertex(1)->ID().latin1() ); 00329 #endif 00330 00331 e[1] = new Edge(vertex, basisedge->vertex(1)); 00332 00333 vertex->grad += 1; 00334 ((Vertex*) basisedge->vertex(1))->grad += 1; 00335 00336 _active_edges.append( e[1] ); 00337 00338 } else { 00339 _active_edges.removeRef( e[1] ); 00340 } 00341 00342 00343 /* 00344 * finally add new triangle to array 00345 */ 00346 _mesh->add_triangle(tri); 00347 00348 #ifdef _DEBUG_ 00349 fprintf(stderr, "</DelaunayMeshGenerator::createTriangle(): triangle added.\n"); 00350 #endif 00351 00352 00353 } 00354 00355 00356 00357 bool 00358 DelaunayMeshGenerator::test_intersection(Vertex* v1, Vertex* v2) 00359 { 00360 #ifdef _DEBUG_ 00361 fprintf(stderr, "<DelaunayMeshGenerator::testIntersection(%s - %s)\n", 00362 v1->ID().latin1(), v2->ID().latin1() ); 00363 fprintf(stderr, " (%f/%f)-(%f/%f))>\n", 00364 v1->x(), v1->y(), v2->x(), v2->y() ); 00365 #endif 00366 00367 /* 00368 QPtrListIterator<Edge> it(_active_edges ); 00369 */ 00370 00371 Edge* edge; 00372 00373 geometry::line l1, l2; 00374 00375 l1.p1.x = v1->x(); 00376 l1.p1.y = v1->y(); 00377 00378 l1.p2.x = v2->x(); 00379 l1.p2.y = v2->y(); 00380 00381 00382 // while( (edge = it.current()) != 0 ) { 00383 00384 int size = _active_edges.count(); 00385 00386 #ifdef _DEBUG_ 00387 fprintf(stderr, "[DelaunayMeshGenerator::testIntersection()] %d active edges\n", 00388 size ); 00389 #endif 00390 00391 for(int i=0; i<size; i++) { 00392 00393 edge = _active_edges.at(i); 00394 00395 #ifdef _DEBUG_ 00396 fprintf(stderr, "[DelaunayMeshGenerator::testIntersection()] test [%d/%d] active edge [%s]-[%s]\n", 00397 i, size, 00398 edge->vertex(0)->ID().latin1(), 00399 edge->vertex(1)->ID().latin1() ); 00400 fprintf(stderr, " edge [%s - %s] \n", 00401 edge->vertex(0)->ID().latin1(), 00402 edge->vertex(1)->ID().latin1() ); 00403 #endif 00404 00405 if( edge->vertex(0) == v1 || edge->vertex(1) == v1 ) { 00406 continue; 00407 } 00408 00409 if( edge->vertex(0) == v2 || edge->vertex(1) == v2 ) { 00410 continue; 00411 } 00412 00413 l2.p1.x = edge->vertex(0)->x(); 00414 l2.p1.y = edge->vertex(0)->y(); 00415 l2.p2.x = edge->vertex(1)->x(); 00416 l2.p2.y = edge->vertex(1)->y(); 00417 00418 if(geometry::intersect(l1,l2)) { 00419 00420 #ifdef _DEBUG_ 00421 fprintf(stderr, "<DelaunayMeshGenerator::testIntersection()> return <true>\n"); 00422 #endif 00423 00424 return true; 00425 00426 } 00427 00428 } 00429 00430 #ifdef _DEBUG_ 00431 fprintf(stderr, "<DelaunayMeshGenerator::testIntersection()> return <false>\n"); 00432 #endif 00433 00434 return false; 00435 00436 } 00437 00438 00439 00440 bool 00441 DelaunayMeshGenerator::is_voronoi_triangle(Edge* edge, Vertex* v) 00442 { 00443 double u; 00444 00445 double e2[2]; 00446 00447 double xm,ym; 00448 double dx,dy; 00449 double radius; 00450 00451 00452 double x1 = edge->vertex(0)->x(); 00453 double y1 = edge->vertex(0)->y(); 00454 00455 double x2 = edge->vertex(1)->x(); 00456 double y2 = edge->vertex(1)->y(); 00457 00458 double x3 = v->x(); 00459 double y3 = v->y(); 00460 00461 00462 e2[0] = -(y2 - y1) / sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)); 00463 e2[1] = (x2 - x1) / sqrt((x2 - x1)*(x2 - x1) + (y2 - y1)*(y2 - y1)); 00464 00465 00466 u = ((x3 - x2)*(x3 - x1) + (y3 - y2)*(y3 - y1)) / 00467 (2.0 * (e2[0] * (x3 - x1) + e2[1] * (y3 - y1))); 00468 00469 00470 if(u_alt > u) { 00471 00472 u_alt = u; 00473 00474 xm = 0.5 * (x1 + x2) + u_alt * e2[0]; 00475 ym = 0.5 * (y1 + y2) + u_alt * e2[1]; 00476 dx = xm - x1; 00477 dy = ym - y1; 00478 radius = sqrt(dx*dx+dy*dy); 00479 00480 box_minX = xm - radius; 00481 box_minY = ym - radius; 00482 box_maxX = xm + radius; 00483 box_maxY = ym + radius; 00484 00485 return true; 00486 00487 } 00488 00489 return false; 00490 00491 } 00492 00493 00494 00495 void 00496 DelaunayMeshGenerator::init() 00497 { 00498 _mesh = new Mesh(); 00499 00500 minX = minY = 1e15; 00501 maxX = maxY = -1e15; 00502 00503 for(Vertex* v = _vertices.first(); v; v = _vertices.next()) { 00504 00505 _mesh->add_vertex(v); 00506 00507 v->grad = 0; 00508 v->used = false; 00509 00510 if(minX > v->x()) minX = v->x(); 00511 if(maxX < v->x()) maxX = v->x(); 00512 if(minY > v->y()) minY = v->y(); 00513 if(maxY < v->y()) maxY = v->y(); 00514 00515 } 00516 00517 00518 /* 00519 const QDict<Vertex>& v_list = _mesh->get_vertices(); 00520 fprintf(stderr, "numer of vertices (mesh) : %d \n", v_list.count() ); 00521 */ 00522 00523 00524 // set state of all edges to contour 00525 00526 for(Edge* e = _edges.first(); e; e = _edges.next()) { 00527 00528 for(int i=0; i<2; i++) { 00529 Vertex* v = (Vertex*) e->vertex(i); 00530 v->grad += 1; 00531 v->used = true; 00532 } 00533 00534 } 00535 00536 } 00537 00538 00539 00540 void 00541 DelaunayMeshGenerator::write_XML(QTextStream& cout) 00542 { 00543 cout << "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"; 00544 cout << "<!-- created by delaunay mesh generator \n"; 00545 cout << " " << __delaunay_lib_version << endl; 00546 cout << " " << QTime::currentTime().toString() << " -->\n"; 00547 00548 cout << "<objects>\n"; 00549 00550 for(Vertex* v = _vertices.first(); v; v = _vertices.next()) { 00551 v->write_XML(cout); 00552 } 00553 00554 for(Edge* e = _edges.first(); e; e = _edges.next()) { 00555 e->write_XML(cout); 00556 } 00557 00558 cout << "</objects>\n"; 00559 } 00560 00561 00562 00563 bool 00564 DelaunayMeshGenerator::startElement(const QString&, const QString&, 00565 const QString& qName, 00566 const QXmlAttributes& xmlattr) 00567 { 00568 00569 QString qNameL = qName.stripWhiteSpace().lower(); 00570 00571 #ifdef _DEBUG_ 00572 fprintf(stderr, "<DelaunayMeshGenerator::startElement()> elem = %s \n", 00573 qNameL.latin1() ); 00574 #endif 00575 00576 if(qNameL == "point") { 00577 00578 QString id = xmlattr.value("id"); 00579 QString x = xmlattr.value("x"); 00580 QString y = xmlattr.value("y"); 00581 00582 Vertex* v = new Vertex(id, x.toDouble(), y.toDouble()); 00583 00584 // fprintf(stderr, "created vertex : [%s] \n", v->ID().latin1() ); 00585 00586 add_vertex(v); 00587 00588 return true; 00589 00590 } 00591 00592 if(qNameL == "edge") { 00593 00594 QString from = xmlattr.value("from"); 00595 QString to = xmlattr.value("to"); 00596 00597 Vertex* v1 = vertex(from); 00598 Vertex* v2 = vertex(to); 00599 00600 if(v1 == 0) { 00601 fprintf(stderr, "<DelaunayMeshGenerator::startElement()> : ERROR = \n"); 00602 fprintf(stderr, " could not find point [%s] !!\n", from.latin1()); 00603 exit(1); 00604 } 00605 00606 if(v2 == 0) { 00607 fprintf(stderr, "<DelaunayMeshGenerator::startElement()> : ERROR = \n"); 00608 fprintf(stderr, " could not find point [%s] !!\n", to.latin1()); 00609 exit(1); 00610 } 00611 00612 Edge* e = new Edge(v1,v2); 00613 00614 add_edge(e); 00615 00616 return true; 00617 00618 } 00619 00620 return true; 00621 00622 }

Generated on Sun Sep 12 12:59:33 2004 for DelaunayMeshGenerator by doxygen 1.3.7