PolygonalMesh.cc

Go to the documentation of this file.
00001 #include <esg/Definitions.h>
00002 #include <esg/mesh/PolygonalMesh.h>
00003 #include <assert.h>
00004 #include <iostream>
00005 
00006 using namespace esg;
00007 
00008 #ifndef LONGBITS
00009 #define LONGBITS (sizeof(long int) * 8)
00010 #endif
00011 
00012 const unsigned PolygonalMesh::MAX_LOOP = 50;
00013 
00014 Mesh::Vert* PolygonalMesh::_find_vertex(int index) 
00015 {
00016     return _vertices[index];
00017 }
00018 
00019 void PolygonalMesh::_store_vertex(Vert* v)
00020 {
00021     if (v) _vertices[v->jmeno_vrcholu] = v;
00022 }
00023 
00024 
00025 Vector3 PolygonalMesh::_plane_normal(const unsigned vIndices[],
00026                                    unsigned       i1,
00027                                    unsigned       i2,
00028                                    unsigned       i3) 
00029 {
00030     Vector3 normal;
00031     Mesh::Vert *v;
00032     Vector3 v1, v2, v3;
00033 
00034     v = _find_vertex(vIndices[i1]);
00035     assert(v);
00036     v1.set(v->x, v->y, v->z);
00037     v = _find_vertex(vIndices[i2]);
00038     assert(v);
00039     v2.set(v->x, v->y, v->z);
00040     v = _find_vertex(vIndices[i3]);
00041     assert(v);
00042     v3.set(v->x, v->y, v->z);
00043     normal.cross(v2 - v1, v3 - v1);
00044     normal.normalize();
00045 
00046     return normal;
00047 }
00048 
00049 long int PolygonalMesh::_multiplex(unsigned i1, unsigned i2)
00050 {
00051     if (i1 < i2)
00052         return (i1<<(LONGBITS/2))|i2;
00053     else
00054         return (i2<<(LONGBITS/2))|i1;
00055 }
00056 
00057 Mesh::Edge* PolygonalMesh::_find_edge(unsigned i1, unsigned i2)
00058 {
00059     return _edges[_multiplex(i1,i2)];
00060 }
00061 
00062 void PolygonalMesh::_store_edge(Edge* e)
00063 {
00064     _edges[_multiplex(e->V1->jmeno_vrcholu, e->V2->jmeno_vrcholu)] = e;
00065 }
00066 
00067 void PolygonalMesh::_erase_edge(unsigned i1, unsigned i2)
00068 {
00069     _edges.erase(_edges.find(_multiplex(i1,i2)));
00070 }
00071 
00072 Mesh::Edge* PolygonalMesh::_append_new_edge(Mesh::Vert*  V1p,
00073                                           Mesh::Vert*  V2p,
00074                                           Mesh::Plane* F)
00075 {
00076     Mesh::Edge  *E = new Edge;
00077  
00078     E->V1=V1p; E->V2=V2p; E->jmeno_hrany=++pocet_hran;
00079     E->LeftLoop=F; E->RightLoop=F;
00080     E->LeftIn = E; E->LeftOut = E;
00081     E->RightIn = E; E->RightOut = E;
00082     E->druh_hrany = TELESOVA; // new edge is always "solid's"
00083 
00084     _connect_edge(E,F);
00085 
00086     AppendEdge(pSolid,E);
00087     _store_edge(E); // add edge into the hash
00088     return E;
00089 }
00090 
00091 bool PolygonalMesh::_connect_edge(Mesh::Edge* E, Mesh::Plane* F)
00092 {
00093     if (F->any_edge == NULL) { // first edge of plane
00094         F->any_edge = E;  // LeftLoop and RightLoop are already set
00095         return true;
00096     }
00097     
00098     Mesh::Vert  *Vin, *Vout;
00099     Mesh::Vert  *EVin, *EVout;
00100     Mesh::Edge  *CE = F->any_edge;
00101     Mesh::Vert  *VNin;
00102     Mesh::Vert  *VNout;
00103     Mesh::Edge  *CEN;
00104         
00105     Orient_Edge(E,F,&EVin,&EVout);
00106     Orient_Edge(CE,F,&Vin,&Vout);
00107 
00108     // find edge ending in the new one
00109     register unsigned loops = 0;
00110     while (Vout != EVin) {
00111         if (loops++ > MAX_LOOP) {
00112             std::cerr << "PolygonalMesh::_connect_edge(): Infinite loop detected" << std::endl;
00113             return false;
00114         }
00115         CE = Next_Edge_in_loop(CE,&Vin,&Vout);
00116     }
00117 
00118     // Get next neighbour in loop
00119     VNin  = Vin;
00120     VNout = Vout;
00121     CEN   = Next_Edge_in_loop(CE,&VNin,&VNout);
00122 
00123     // Insert new edge E in to the loop
00124     if (CE->LeftLoop == F) CE->LeftOut = E;
00125     else                   CE->RightOut = E;
00126     if (E->LeftLoop == F) { E->LeftIn   = CE; E->LeftOut = CEN; }
00127     else                  { E->RightIn = CE; E->RightOut = CEN; }
00128     if (CEN->LeftLoop == F) CEN->LeftIn   = E;
00129     else                    CEN->RightIn = E;
00130 
00131     return true;
00132 }
00133 
00134 Mesh::Edge* PolygonalMesh::_split_edge(Mesh::Edge * E, Mesh::Vert * V)
00135 {
00136     Mesh::Edge *NE = new Edge;
00137     
00138     NE = new Edge;
00139     NE->V1=E->V1; NE->V2=V; NE->jmeno_hrany=++pocet_hran;
00140     NE->LeftLoop=E->LeftLoop; NE->RightLoop=E->RightLoop;
00141     NE->druh_hrany = VNITRNI;
00142 
00143     NE->LeftIn  = E->LeftIn;
00144     NE->RightOut = E->RightOut;
00145     if (NE->LeftIn->V2 == NE->V1)  {
00146         NE->LeftIn->LeftOut = NE;
00147         if (NE->LeftIn->RightIn == E) NE->LeftIn->RightIn = NE;
00148     } else {
00149         NE->LeftIn->RightOut = NE;
00150         if (NE->LeftIn->LeftIn == E) NE->LeftIn->LeftIn = NE;
00151     }
00152     if (NE->RightOut->V2 == NE->V1) NE->RightOut->RightIn = NE;
00153     else                            NE->RightOut->LeftIn   = NE;
00154     NE->LeftOut = (NE->RightIn = E);
00155     E->LeftIn   = (E->RightOut = NE);
00156     
00157     _erase_edge(E->V1->jmeno_vrcholu, E->V2->jmeno_vrcholu);
00158     E->V1 = V;
00159     AppendEdge(pSolid,NE);
00160     _store_edge(E);
00161     _store_edge(NE);
00162 
00163     return NE;
00164 }
00165 
00166 Mesh::Plane* PolygonalMesh::_split_plane(Mesh::Plane * F,
00167                                          Mesh::Vert  * V1,
00168                                          Mesh::Vert  * V2)
00169 {
00170     if (_find_edge(V1->jmeno_vrcholu, V2->jmeno_vrcholu)) return NULL;
00171 
00172     Mesh::Plane* NF = NewPlane(pSolid, F->a, F->b, F->c, F->d);
00173     Mesh::Edge*  E  = new Edge;
00174  
00175     E->V1=V1; E->V2=V2; E->jmeno_hrany=++pocet_hran;
00176     E->LeftLoop=F; E->RightLoop=NF;
00177     E->druh_hrany = VNITRNI;
00178 
00179     AppendEdge(pSolid,E);
00180     _store_edge(E); // add edge into the hash
00181 
00182     
00183     Mesh::Vert  *Vin, *Vout;
00184     Mesh::Edge  *CE = F->any_edge;
00185     Mesh::Edge  *CEN;
00186 
00187     // find edge ending in first point and its neighbour
00188     Orient_Edge(CE,F,&Vin,&Vout);
00189     while (Vout != V1) CE = Next_Edge_in_loop(CE,&Vin,&Vout);
00190     CEN   = Next_Edge_in_loop(CE,&Vin,&Vout);
00191 
00192     // Interconnect first part of new edge with its neigbours
00193     if (CE->LeftLoop == F)  CE->LeftOut   = E;
00194     else                    CE->RightOut   = E;
00195     if (CEN->LeftLoop == F) CEN->LeftIn   = E;
00196     else                    CEN->RightIn = E;
00197     E->LeftIn  = CE;
00198     E->RightOut = CEN;
00199 
00200     // Find edge ending in second point and its neighbour.
00201     // During the search re-set
00202     // planes of all edges (all these edges covers new plane)
00203     CE = CEN;
00204     while (Vout != V2) {
00205         if (CE->LeftLoop  == F) CE->LeftLoop  = NF;
00206         if (CE->RightLoop == F) CE->RightLoop = NF;
00207         CE = Next_Edge_in_loop(CE,&Vin,&Vout);
00208     }
00209     if (CE->LeftLoop  == F) CE->LeftLoop  = NF;
00210     if (CE->RightLoop == F) CE->RightLoop = NF;
00211     CEN = Next_Edge_in_loop(CE,&Vin,&Vout);
00212 
00213     // Interconnect second part of new edge with its neigbours
00214     if (CE->LeftLoop == NF)  CE->LeftOut   = E;
00215     else                     CE->RightOut   = E;
00216     if (CEN->LeftLoop == F)  CEN->LeftIn   = E;
00217     else                     CEN->RightIn = E;
00218     E->LeftOut  = CEN;
00219     E->RightIn = CE;
00220 
00221     F->any_edge = (NF->any_edge = E);
00222 
00223     return NF;
00224 }
00225 
00226 bool PolygonalMesh::_get_facet_topology(Vert*          vertices[],
00227                                       Edge*          edges[],
00228                                       unsigned       num,
00229                                       const unsigned vIndices[],
00230                                       const Vector3  normals[])
00231 {
00232     bool duplicate = false;
00233     
00234     for (register unsigned i = 0; i < num; i++) {
00235         vertices[i] = _find_vertex(vIndices[i]);
00236         if (!vertices[i]) {
00237             fprintf(stderr,"PolygonalMesh Error: Index of vertex out of range\n");
00238             return false;
00239         }
00240         
00241         // find an existing vertices with diferent normals => duplicate vertex
00242         if (normals) {
00243             if (vertices[i]->hasValidNormal() &&
00244                 !vertices[i]->normal.equals(normals[i]))
00245                 duplicate = true;
00246             else
00247                 vertices[i]->normal.set(normals[i]);
00248         }
00249     }
00250 
00251     // find edges already shared by two planes => duplicate edge
00252     for (register unsigned i = 0; i < num && !duplicate; i++) {
00253         edges[i] = _find_edge(vertices[i]->jmeno_vrcholu,
00254                               vertices[(i+1)%num]->jmeno_vrcholu);
00255         if (edges[i] && edges[i]->LeftLoop != edges[i]->RightLoop) 
00256                 duplicate = true;
00257     }
00258 
00259     if (duplicate) {
00260         for (register unsigned i = 0; i < num; i++) {
00261             // duplicate only already used vertices - those having
00262             // valid normal, or vertices of already shared edges
00263             if (vertices[i]->hasValidNormal() ||
00264                 (edges[i] && edges[i]->LeftLoop != edges[i]->RightLoop)) {
00265                 Vert* v = NewVertex(pSolid,
00266                                     vertices[i]->x,
00267                                     vertices[i]->y,
00268                                     vertices[i]->z);
00269                 if (normals) v->normal.set(normals[i]);
00270                 else         v->normal.set(vertices[i]->normal);
00271                 vertices[i] = v;
00272                 _store_vertex(vertices[i]);
00273             }
00274             edges[i] = NULL; // all edges will be new
00275         }
00276     }
00277     
00278     return true;
00279 }
00280 
00281 
00282 //-------------------------- public -----------------------
00283 
00284 PolygonalMesh::PolygonalMesh(const Vector3  vertices[],
00285                              unsigned       nvi,
00286                              const unsigned vIndices[])
00287 {
00288     if (! vertices || nvi == 0) {
00289         fprintf(stderr,"PolygonalMesh Error: Surface without vertices\n");
00290         return;
00291     }
00292 
00293     // create solid:
00294     pSolid                 = new Solid;
00295     pSolid->solid_name     = 0;
00296     pSolid->first_vertex   = NULL;
00297     pSolid->first_edge     = NULL;
00298     pSolid->first_plane    = NULL;
00299     pSolid->next_solid     = pSolid;
00300     pSolid->previous_solid = pSolid;
00301 
00302     // create list of vertices:
00303     for (register unsigned i = 0; i < nvi; i++) {
00304         // new_vertex->jmeno_vrcholu = i
00305         if (vIndices) {
00306             Vert* v = NewVertex(pSolid,
00307                                 vertices[vIndices[i]].x,
00308                                 vertices[vIndices[i]].y,
00309                                 vertices[vIndices[i]].z);
00310             _store_vertex(v);
00311         } else {
00312             Vert* v = NewVertex(pSolid,
00313                                 vertices[i].x,
00314                                 vertices[i].y,
00315                                 vertices[i].z);
00316             _store_vertex(v);
00317         }
00318     }
00319 
00320     pActSolid = pSolid;
00321     pActVert  = pSolid->first_vertex;
00322 }
00323 
00324 #define __NEW_FACET_FAILED(r) { \
00325    cerr << "PolygonalMesh::addFacet(): Can't append facet - " << (r) << ":" << endl; \
00326    for (unsigned i = 0; i < nVert; i++) { \
00327        cerr << "    v" << i << ": "; \
00328        cerr << _find_vertex(vIndices[i])->x << " " ; \
00329        cerr << _find_vertex(vIndices[i])->y << " " ; \
00330        cerr << _find_vertex(vIndices[i])->z << endl; \
00331    } \
00332    delete [] fVertices; \
00333    delete [] fEdges; \
00334    return false; \
00335 }
00336 
00337 bool PolygonalMesh::addFacet(const unsigned vIndices[],
00338                            const Vector3  normals[],
00339                            unsigned       nVert,
00340                            const Vector3& normal)
00341 {
00342     Vert** fVertices = new Vert* [nVert];
00343     Edge** fEdges    = new Edge* [nVert];
00344 
00345     for (register unsigned i = 0; i < nVert; i++) {
00346         fVertices[i] = NULL;
00347         fEdges[i]    = NULL;
00348     }
00349     
00350     if (!_get_facet_topology(fVertices, fEdges, nVert, vIndices, normals))
00351         __NEW_FACET_FAILED("Bad topology");
00352 
00353     // init plane
00354     Mesh::Plane* p = NewPlane(pSolid,
00355                               normal.x,normal.y,normal.z,
00356                               -normal.dot(Vector3(fVertices[0]->x,
00357                                                   fVertices[0]->y,
00358                                                   fVertices[0]->z)));
00359 
00360     // append edges to plane and interconnect them
00361     for (unsigned i = 0; i < nVert; i++) {
00362         if (!fEdges[i]) { // edge does not exists yet
00363             fEdges[i]=_append_new_edge(fVertices[i],fVertices[(i+1)%nVert],p);
00364             if (!fEdges[i]) __NEW_FACET_FAILED("Appending new edge");
00365         } else {
00366             fEdges[i]->RightLoop  = p;
00367             fEdges[i]->druh_hrany = VNITRNI;
00368             if (!_connect_edge(fEdges[i], p))
00369                 __NEW_FACET_FAILED("Connecting new edge");
00370         }
00371     }
00372 
00373     delete [] fVertices;
00374     delete [] fEdges;
00375 
00376     return true;
00377 }
00378 
00379 #undef __NEW_FACET_FAILED
00380 
00381 bool PolygonalMesh::addFacet(const unsigned vIndices[],
00382                            const Vector3  normals[],
00383                            unsigned       nVert)
00384 {
00385     return addFacet(vIndices,
00386                     normals,
00387                     nVert,
00388                     _plane_normal(vIndices, 0, 1, nVert-1));
00389 }

Generated on Wed Jun 28 12:24:32 2006 for esg by  doxygen 1.4.6