MechSys  1.0
Computing library for simulations in continuum and discrete mechanics
/home/dorival/mechsys/lib/mesh/unstructured.h
Go to the documentation of this file.
00001 /************************************************************************
00002  * MechSys - Open Library for Mechanical Systems                        *
00003  * Copyright (C) 2005 Dorival M. Pedroso, Raul Durand                   *
00004  * Copyright (C) 2009 Sergio Galindo                                    *
00005  *                                                                      *
00006  * This program is free software: you can redistribute it and/or modify *
00007  * it under the terms of the GNU General Public License as published by *
00008  * the Free Software Foundation, either version 3 of the License, or    *
00009  * any later version.                                                   *
00010  *                                                                      *
00011  * This program is distributed in the hope that it will be useful,      *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the         *
00014  * GNU General Public License for more details.                         *
00015  *                                                                      *
00016  * You should have received a copy of the GNU General Public License    *
00017  * along with this program. If not, see <http://www.gnu.org/licenses/>  *
00018  ************************************************************************/
00019 
00020 #ifndef MECHSYS_MESH_UNSTRUCTURED_H
00021 #define MECHSYS_MESH_UNSTRUCTURED_H
00022 
00023 /* LOCAL indexes of Vertices, Edges, and Faces
00024 
00025   2D:
00026              Nodes                 Edges
00027 
00028    y           2
00029    |           @                     @
00030    +--x       / \                   / \
00031            5 /   \ 4               /   \
00032             @     @             2 /     \ 1
00033            /       \             /       \
00034           /         \           /         \
00035          @-----@-----@         @-----------@
00036         0      3      1              0
00037 */
00038 
00039 // STL
00040 #include <iostream> // for cout, endl, ostream
00041 #include <sstream>  // for ostringstream
00042 #include <fstream>  // for ofstream
00043 #include <cfloat>   // for DBL_EPSILON
00044 #include <map>
00045 
00046 // Jonathan R Shewchuk' Triangle
00047 extern "C"
00048 {
00049     #define REAL double
00050     #define ANSI_DECLARATORS
00051     #define VOID int
00052       #include "triangle.h"
00053     #undef REAL
00054     #undef ANSI_DECLARATORS
00055     #undef VOID
00056 }
00057 
00058 // Hang Si' Tetgen
00059 #define TETLIBRARY
00060 #include "tetgen.h"
00061 #undef REAL
00062 #undef TETLIBRARY
00063 
00064 // MechSys
00065 #include <mechsys/util/array.h>
00066 #include <mechsys/util/fatal.h>
00067 #include <mechsys/util/stopwatch.h>
00068 #include <mechsys/mesh/mesh.h>
00069 #include <mechsys/draw.h>
00070 
00071 namespace Mesh
00072 {
00073 
00074 
00076 
00077 
00079 typedef triangulateio TriIO;
00080 
00082 typedef tetgenio TetIO;
00083 
00084 inline void TriAllocate (int NPoints, int NSegments, int NRegions, int NHoles, TriIO & Tio)
00085 {
00086     // check
00087     if (NPoints<3)   throw new Fatal("Mesh::TriAllocate: At least 3 points are required. (%d is invalid)",NPoints);
00088     if (NSegments<3) throw new Fatal("Mesh::TriAllocate: At least 3 segments are required. (%d is invalid)",NSegments);
00089 
00090     // points
00091     Tio.pointlist       = (double*)malloc(NPoints*2*sizeof(double));
00092     Tio.numberofpoints  = NPoints;
00093     Tio.pointmarkerlist = (int*)malloc(NPoints*sizeof(int));
00094 
00095     // segments
00096     Tio.segmentlist       = (int*)malloc(NSegments*2*sizeof(int));
00097     Tio.segmentmarkerlist = (int*)malloc(NSegments * sizeof(int));
00098     Tio.numberofsegments  = NSegments;
00099     for (int i=0; i<NSegments; ++i) Tio.segmentmarkerlist[i]=0;
00100 
00101     // regions
00102     if (NRegions>0)
00103     {
00104         Tio.regionlist      = (double*)malloc(NRegions*4*sizeof(double));
00105         Tio.numberofregions = NRegions;
00106     }
00107 
00108     // holes
00109     if (NHoles>0)
00110     {
00111         Tio.holelist      = (double*)malloc(NHoles*2*sizeof(double));
00112         Tio.numberofholes = NHoles;
00113     }
00114 }
00115 
00116 inline void TriSetAllToNull (TriIO & Tio)
00117 {
00118     // points
00119     Tio.pointlist               = NULL;
00120     Tio.pointattributelist      = NULL;
00121     Tio.pointmarkerlist         = NULL;
00122     Tio.numberofpoints          = 0;
00123     Tio.numberofpointattributes = 0;
00124 
00125     // triangles
00126     Tio.trianglelist               = NULL;
00127     Tio.triangleattributelist      = NULL;
00128     Tio.trianglearealist           = NULL;
00129     Tio.neighborlist               = NULL;
00130     Tio.numberoftriangles          = 0;
00131     Tio.numberofcorners            = 0;
00132     Tio.numberoftriangleattributes = 0;
00133     Tio.triedgemarks               = NULL;
00134 
00135     // segments
00136     Tio.segmentlist       = NULL;
00137     Tio.segmentmarkerlist = NULL;
00138     Tio.numberofsegments  = 0;
00139 
00140     // holes
00141     Tio.holelist      = NULL;
00142     Tio.numberofholes = 0;
00143 
00144     // regions
00145     Tio.regionlist      = NULL;
00146     Tio.numberofregions = 0;
00147 
00148     // edges
00149     Tio.edgelist       = NULL;
00150     Tio.edgemarkerlist = NULL;
00151     Tio.normlist       = NULL;
00152     Tio.numberofedges  = 0;
00153 }
00154 
00155 inline void TriDeallocateAll (TriIO & Tio)
00156 {
00157     // Points
00158     if (Tio.pointlist          != NULL) free(Tio.pointlist);
00159     if (Tio.pointattributelist != NULL) free(Tio.pointattributelist);
00160     if (Tio.pointmarkerlist    != NULL) free(Tio.pointmarkerlist);
00161 
00162     // Triangles
00163     if (Tio.trianglelist          != NULL) free(Tio.trianglelist);
00164     if (Tio.triangleattributelist != NULL) free(Tio.triangleattributelist);
00165     if (Tio.trianglearealist      != NULL) free(Tio.trianglearealist);
00166     if (Tio.neighborlist          != NULL) free(Tio.neighborlist);
00167     if (Tio.triedgemarks          != NULL) free(Tio.triedgemarks);
00168 
00169     // Segments
00170     if (Tio.segmentlist       != NULL) free(Tio.segmentlist);
00171     if (Tio.segmentmarkerlist != NULL) free(Tio.segmentmarkerlist);
00172 
00173     // Holes
00174     if (Tio.holelist != NULL) free(Tio.holelist);
00175 
00176     // Regions
00177     if (Tio.regionlist != NULL) free(Tio.regionlist);
00178 
00179     // Edges
00180     if (Tio.edgelist       != NULL) free(Tio.edgelist);
00181     if (Tio.edgemarkerlist != NULL) free(Tio.edgemarkerlist);
00182     if (Tio.normlist       != NULL) free(Tio.normlist);
00183 
00184     // Clear all
00185     TriSetAllToNull (Tio);
00186 }
00187 
00188 
00190 
00191 
00192 class Unstructured : public virtual Mesh::Generic
00193 {
00194 public:
00195     // Constants
00196     static size_t FEM2TriPoint[]; 
00197     static size_t FEM2TriEdge []; 
00198     static size_t FEM2TetPoint[]; 
00199     static size_t FEM2TetFace []; 
00200 
00201     // Constructor
00202     Unstructured (int NDim);
00203 
00204     // Destructor
00205     ~Unstructured () { TriDeallocateAll(Tin); }
00206 
00210     void Set    (size_t NPoints, size_t NSegmentsOrFacets, size_t NRegions, size_t NHoles);
00211     void SetReg (size_t iReg, int RTag, double MaxAreaOrVolume, double X, double Y, double Z=0.0);
00212     void SetHol (size_t iHol, double X, double Y, double Z=0.0);
00213     void SetPnt (size_t iPnt, int PTag, double X, double Y, double Z=0.0);
00214     void SetSeg (size_t iSeg, int ETag, int L, int R);
00215     void SetFac (size_t iFac, int FTag, Array<int> const & VertsOnFace);
00216     void SetFac (size_t iFac, int FTag, Array<int> const & Polygon1, Array<int> const & Polygon2);
00217 
00218     // Methods
00219     void Generate (bool O2=false, double GlobalMaxArea=-1, bool Quiet=true, double MinAngle=-1);       
00220     void WritePLY (char const * FileKey, bool Blender=true);                                           
00221     void GenBox   (bool O2=false, double MaxVolume=-1.0, double Lx=1.0, double Ly=1.0, double Lz=1.0); 
00222     bool IsSet    () const;                                                                            
00223 
00224     // Alternative methods
00225     void Delaunay (Array<double> const & X, Array<double> const & Y, int Tag=-1); 
00226 
00227     // Data
00228     TriIO Tin; 
00229     TetIO Pin; 
00230 
00231 #ifdef USE_BOOST_PYTHON
00232     void PySet (BPy::dict const & Dat);
00233 #endif
00234 
00235 private:
00236     // Data
00237     bool _lst_reg_set; 
00238     bool _lst_hol_set; 
00239     bool _lst_pnt_set; 
00240     bool _lst_seg_set; 
00241     bool _lst_fac_set; 
00242 };
00243 
00244 size_t Unstructured::FEM2TriPoint[] = {0,1,2,5,3,4};
00245 size_t Unstructured::FEM2TriEdge [] = {0,1,2};
00246 size_t Unstructured::FEM2TetPoint[] = {0,1,2,3,4,5,6,7,8,9};
00247 size_t Unstructured::FEM2TetFace [] = {3,1,0,2};
00248 
00249 
00251 
00252 inline Unstructured::Unstructured (int NDim)
00253     : Mesh::Generic (NDim),
00254       _lst_reg_set  (false),
00255       _lst_hol_set  (false),
00256       _lst_pnt_set  (false),
00257       _lst_seg_set  (false),
00258       _lst_fac_set  (false)
00259 {
00260     TriSetAllToNull  (Tin);
00261     Pin.deinitialize (); 
00262 }
00263 
00264 inline void Unstructured::Set (size_t NPoints, size_t NSegmentsOrFacets, size_t NRegions, size_t NHoles)
00265 {
00266 
00267     //std::cout << "NRegions = " << NRegions << std::endl;
00268     //std::cout << "NPoints = " << NPoints << std::endl;
00269     //std::cout << "NFacets = " << NSegmentsOrFacets << std::endl;
00270     //std::cout << "NHoles = " << NHoles << std::endl;
00271 
00272     // check
00273     if (NPoints<3)           throw new Fatal("Mesh::Unstructured::Set: The number of points must be greater than 2. (%d is invalid)",NPoints);
00274     if (NSegmentsOrFacets<3) throw new Fatal("Mesh::Unstructured::Set: The number of segments or faces must be greater than 2. (%d is invalid)",NSegmentsOrFacets);
00275     if (NRegions<1)          throw new Fatal("Mesh::Unstructured::Set: The number of regions must be greater than 1. (%d is invalid)",NRegions);
00276 
00277     // flags
00278     _lst_reg_set = false;
00279     _lst_hol_set = false;
00280     _lst_pnt_set = false;
00281     _lst_seg_set = false;
00282     _lst_fac_set = false;
00283 
00284     if (NDim==2)
00285     {
00286         // erase previous PSLG
00287         TriDeallocateAll (Tin);
00288 
00289         // allocate PSLG
00290         TriAllocate (NPoints, NSegmentsOrFacets, NRegions, NHoles, Tin);
00291     }
00292     else if (NDim==3)
00293     {
00294         // erase previous PLC
00295         Pin.deinitialize ();
00296 
00297         // allocate PLC
00298         Pin.initialize ();
00299         
00300         // points
00301         Pin.firstnumber     = 0;
00302         Pin.numberofpoints  = NPoints;
00303         Pin.pointlist       = new double [NPoints*3];
00304         Pin.pointmarkerlist = new int [NPoints];
00305 
00306         // facets
00307         Pin.numberoffacets  = NSegmentsOrFacets;
00308         Pin.facetlist       = new TetIO::facet [NSegmentsOrFacets];
00309         Pin.facetmarkerlist = new int [NSegmentsOrFacets];
00310 
00311         // regions
00312         Pin.numberofregions = NRegions;
00313         Pin.regionlist      = new double [NRegions*5];
00314 
00315         // holes
00316         Pin.numberofholes = NHoles;
00317         Pin.holelist      = new double [NHoles*3];
00318     }
00319     else throw new Fatal("Unstructured::Set: NDim must be either 2 or 3. NDim==%d is invalid",NDim);
00320 }
00321 
00322 inline void Unstructured::SetReg (size_t iReg, int RTag, double MaxAreaOrVolume, double X, double Y, double Z)
00323 {
00324     if (NDim==2)
00325     {
00326         Tin.regionlist[iReg*4  ] = X;
00327         Tin.regionlist[iReg*4+1] = Y;
00328         Tin.regionlist[iReg*4+2] = RTag;
00329         Tin.regionlist[iReg*4+3] = MaxAreaOrVolume;
00330         if ((int)iReg==Tin.numberofregions-1) _lst_reg_set = true;
00331     }
00332     else if (NDim==3)
00333     {
00334         Pin.regionlist[iReg*5  ] = X;
00335         Pin.regionlist[iReg*5+1] = Y;
00336         Pin.regionlist[iReg*5+2] = Z;
00337         Pin.regionlist[iReg*5+3] = RTag;
00338         Pin.regionlist[iReg*5+4] = MaxAreaOrVolume;
00339         if ((int)iReg==Pin.numberofregions-1) _lst_reg_set = true;
00340     }
00341 }
00342 
00343 inline void Unstructured::SetHol (size_t iHol, double X, double Y, double Z)
00344 {
00345     if (NDim==2)
00346     {
00347         Tin.holelist[iHol*2  ] = X;
00348         Tin.holelist[iHol*2+1] = Y;
00349         if ((int)iHol==Tin.numberofholes-1) _lst_hol_set = true;
00350     }
00351     else if (NDim==3)
00352     {
00353         Pin.holelist[iHol*3  ] = X;
00354         Pin.holelist[iHol*3+1] = Y;
00355         Pin.holelist[iHol*3+2] = Z;
00356         if ((int)iHol==Pin.numberofholes-1) _lst_hol_set = true;
00357     }
00358 }
00359 
00360 inline void Unstructured::SetPnt (size_t iPnt, int PTag, double X, double Y, double Z)
00361 {
00362     if (NDim==2)
00363     {
00364         Tin.pointlist[iPnt*2  ]   = X;
00365         Tin.pointlist[iPnt*2+1]   = Y;
00366         Tin.pointmarkerlist[iPnt] = PTag;
00367         if ((int)iPnt==Tin.numberofpoints-1) _lst_pnt_set = true;
00368     }
00369     else if (NDim==3)
00370     {
00371         Pin.pointlist[iPnt*3  ]   = X;
00372         Pin.pointlist[iPnt*3+1]   = Y;
00373         Pin.pointlist[iPnt*3+2]   = Z;
00374         Pin.pointmarkerlist[iPnt] = PTag;
00375         if ((int)iPnt==Pin.numberofpoints-1) _lst_pnt_set = true;
00376     }
00377 }
00378 
00379 inline void Unstructured::SetSeg (size_t iSeg, int ETag, int L, int R)
00380 {
00381     if (NDim==3) throw new Fatal("Unstructured::SetSeg: This method must be called for 2D meshes only");
00382     Tin.segmentlist[iSeg*2  ]   = L;
00383     Tin.segmentlist[iSeg*2+1]   = R;
00384     Tin.segmentmarkerlist[iSeg] = ETag;
00385     if ((int)iSeg==Tin.numberofsegments-1) _lst_seg_set = true;
00386 }
00387 
00388 inline void Unstructured::SetFac (size_t iFac, int FTag, Array<int> const & VertsOnFace)
00389 {
00390     if (NDim==2) throw new Fatal("Unstructured::SetSeg: This method must be called for 3D meshes only");
00391 
00392     Pin.facetmarkerlist[iFac] = FTag;
00393     TetIO::facet * f    = &Pin.facetlist[iFac];
00394     f->numberofpolygons = 1;
00395     f->polygonlist      = new TetIO::polygon [f->numberofpolygons];
00396     f->numberofholes    = 0;
00397     f->holelist         = NULL;
00398 
00399     // read vertices
00400     TetIO::polygon * p  = &f->polygonlist[0];
00401     int npoints         = static_cast<int>(VertsOnFace.Size());
00402     p->numberofvertices = npoints;
00403     p->vertexlist       = new int [npoints];
00404     for (int j=0; j<npoints; ++j) p->vertexlist[j] = VertsOnFace[j];
00405 
00406     if ((int)iFac==Pin.numberoffacets-1) _lst_fac_set = true;
00407 }
00408 
00409 inline void Unstructured::SetFac (size_t iFac, int FTag, Array<int> const & Polygon1, Array<int> const & Polygon2)
00410 {
00411     if (NDim==2) throw new Fatal("Unstructured::SetSeg: This method must be called for 3D meshes only");
00412 
00413     Pin.facetmarkerlist[iFac] = FTag;
00414     TetIO::facet * f    = &Pin.facetlist[iFac];
00415     f->numberofpolygons = 2;
00416     f->polygonlist      = new TetIO::polygon [f->numberofpolygons];
00417     f->numberofholes    = 0;
00418     f->holelist         = NULL;
00419 
00420     // read vertices of polygon 1
00421     TetIO::polygon * p1  = &f->polygonlist[0];
00422     int np1              = static_cast<int>(Polygon1.Size());
00423     p1->numberofvertices = np1;
00424     p1->vertexlist       = new int [np1];
00425     for (int j=0; j<np1; ++j) p1->vertexlist[j] = Polygon1[j];
00426 
00427     // read vertices of polygon 2
00428     TetIO::polygon * p2  = &f->polygonlist[1];
00429     int np2              = static_cast<int>(Polygon2.Size());
00430     p2->numberofvertices = np2;
00431     p2->vertexlist       = new int [np2];
00432     for (int j=0; j<np2; ++j) p2->vertexlist[j] = Polygon2[j];
00433 
00434     if ((int)iFac==Pin.numberoffacets-1) _lst_fac_set = true;
00435 }
00436 
00437 inline void Unstructured::Generate (bool O2, double GlobalMaxArea, bool Quiet, double MinAngle)
00438 {
00439     // check
00440     if (!IsSet()) throw new Fatal("Unstructured::Generate: Please, set the input data (regions,points,segments/facets) first.");
00441 
00442     // info
00443     Util::Stopwatch stopwatch(/*activated*/WithInfo);
00444 
00445     // parameters
00446     String prms("pzA"); // Q=quiet, p=poly, q=quality, z=zero
00447     if (Quiet)           prms.Printf("Q%s",   prms.CStr());
00448     if (GlobalMaxArea>0) prms.Printf("%sa%f", prms.CStr(), GlobalMaxArea);
00449     if (MinAngle>0)      prms.Printf("%sq%f", prms.CStr(), MinAngle);
00450     else                 prms.Printf("%sq",   prms.CStr());
00451     if (O2)              prms.Printf("%so2",  prms.CStr());
00452     prms.Printf("%sa", prms.CStr());
00453 
00454     if (NDim==2)
00455     {
00456         // generate
00457         TriIO tou;
00458         TriSetAllToNull (tou);
00459         triangulate (prms.CStr(), &Tin, &tou, NULL);
00460 
00461         // verts
00462         Verts.Resize (tou.numberofpoints);
00463         for (size_t i=0; i<Verts.Size(); ++i)
00464         {
00465             Verts[i]      = new Vertex;
00466             Verts[i]->ID  = i;
00467             Verts[i]->Tag = 0;
00468             Verts[i]->C   = tou.pointlist[i*2], tou.pointlist[i*2+1], 0.0;
00469 
00470             /* tou.pointmarkerlist[ipoint] will be equal to:
00471              * == edgeTag (<0) => on edge with tag <<<<<<<<<<<<<<<<<< REMOVED
00472              * == 0            => internal vertex (not on boundary)
00473              * == 1            => on boundary                   */
00474             int mark = tou.pointmarkerlist[i];
00475             if (mark<0)
00476             {
00477                 Verts[i]->Tag = mark;
00478                 TgdVerts.Push (Verts[i]);
00479             }
00480         }
00481 
00482         // cells
00483         Cells.Resize (tou.numberoftriangles);
00484         for (size_t i=0; i<Cells.Size(); ++i)
00485         {
00486             Cells[i]      = new Cell;
00487             Cells[i]->ID  = i;
00488             Cells[i]->Tag = tou.triangleattributelist[i*tou.numberoftriangleattributes];
00489             Cells[i]->PartID = 0; // partition id (domain decomposition)
00490             Cells[i]->V.Resize (tou.numberofcorners);
00491             for (size_t j=0; j<Cells[i]->V.Size(); ++j)
00492             {
00493                 Share sha = {Cells[i],j};
00494                 Cells[i]->V[j] = Verts[tou.trianglelist[i*tou.numberofcorners+FEM2TriPoint[j]]];
00495                 Cells[i]->V[j]->Shares.Push (sha);
00496             }
00497             bool has_bry_tag = false;
00498             for (size_t j=0; j<3; ++j)
00499             {
00500                 int edge_tag = tou.triedgemarks[i*3+FEM2TriEdge[j]];
00501                 if (edge_tag<0)
00502                 {
00503                     Cells[i]->BryTags[j] = edge_tag;
00504                     has_bry_tag          = true;
00505                 }
00506             }
00507             if (has_bry_tag) TgdCells.Push (Cells[i]);
00508         }
00509 
00510         // clean up
00511         /* After triangulate (with -p switch), tou.regionlist gets the content of Tin.regionlist and
00512          * tou.holelist gets the content of Tin.holelist. Thus, these output variables must be set
00513          * to NULL in order to tell TriDeallocateAll to ignore them and do not double-free memory. */
00514         tou.regionlist      = NULL;
00515         tou.numberofregions = 0;
00516         tou.holelist        = NULL;
00517         tou.numberofholes   = 0;
00518         TriDeallocateAll (tou);
00519     }
00520     else
00521     {
00522         //for (size_t i=0; i<Pin.numberofpoints; ++i) std::cout << Util::_20_15 << Pin.pointlist[i*3] << " " << Util::_20_15 << Pin.pointlist[i*3+1] << " " << Util::_20_15 << Pin.pointlist[i*3+2] << std::endl;
00523 
00524         //prms = "CpJVVV"; // debug
00525 
00526         // generate
00527         prms.append("f");
00528         char sw[prms.size()+1];
00529         strcpy (sw, prms.CStr());
00530         TetIO pou;
00531         tetrahedralize (sw, &Pin, &pou);
00532 
00533         // verts
00534         Verts.Resize (pou.numberofpoints);
00535         for (size_t i=0; i<Verts.Size(); ++i)
00536         {
00537             Verts[i]      = new Vertex;
00538             Verts[i]->ID  = i;
00539             Verts[i]->Tag = 0;
00540             Verts[i]->C   = pou.pointlist[i*3], pou.pointlist[i*3+1], pou.pointlist[i*3+2];
00541 
00542             /* pou.pointmarkerlist[ipoint] will be equal to:
00543              * == faceTag (<0) => on face with tag <<<<<<<<<<<<<<<<<< REMOVED
00544              * == 0            => internal vertex (not on boundary)
00545              * == 1            => on boundary                   */
00546             int mark = pou.pointmarkerlist[i];
00547             if (mark<0)
00548             {
00549                 Verts[i]->Tag = mark;
00550                 TgdVerts.Push (Verts[i]);
00551             }
00552         }
00553 
00554         // cells
00555         Cells.Resize (pou.numberoftetrahedra);
00556         for (size_t i=0; i<Cells.Size(); ++i)
00557         {
00558             Cells[i]      = new Cell;
00559             Cells[i]->ID  = i;
00560             Cells[i]->Tag = pou.tetrahedronattributelist[i*pou.numberoftetrahedronattributes];
00561             Cells[i]->V.Resize (pou.numberofcorners);
00562             for (size_t j=0; j<Cells[i]->V.Size(); ++j)
00563             {
00564                 Share sha = {Cells[i],j};
00565                 Cells[i]->V[j] = Verts[pou.tetrahedronlist[i*pou.numberofcorners+FEM2TetPoint[j]]];
00566                 Cells[i]->V[j]->Shares.Push (sha);
00567             }
00568         }
00569 
00570         // face tags
00571         for (std::map<int,tetgenio::facemarkers>::const_iterator p=pou.tetfacemarkers.begin(); p!=pou.tetfacemarkers.end(); ++p)
00572         {
00573             int  icell       = p->first;
00574             bool has_bry_tag = false;
00575             for (size_t j=0; j<4; ++j)
00576             {
00577                 int face_tag = p->second.m[FEM2TetFace[j]];
00578                 //std::cout << icell << " " << j << " " << face_tag << "\n";
00579                 if (face_tag<0)
00580                 {
00581                     Cells[icell]->BryTags[j] = face_tag;
00582                     has_bry_tag              = true;
00583                 }
00584             }
00585             if (has_bry_tag) TgdCells.Push (Cells[icell]);
00586         }
00587     }
00588 
00589     // check
00590     if (Verts.Size()<1) throw new Fatal("Unstructured::Generate: Failed with %d vertices and %d cells", Verts.Size(), Cells.Size());
00591     if (Cells.Size()<1) throw new Fatal("Unstructured::Generate: Failed with %d vertices and %d cells", Verts.Size(), Cells.Size());
00592 
00593     // info
00594     if (WithInfo)
00595     {
00596         printf("\n%s--- Unstructured Mesh Generation --- %dD --- O%d -------------------------------------%s\n",TERM_CLR1,NDim,(O2?2:1),TERM_RST);
00597         printf("%s  %s    = %s%s\n",TERM_CLR4,(NDim==2?"Triangle command":"Tetgen command "),prms.CStr(),TERM_RST);
00598         printf("%s  Num of cells       = %zd%s\n", TERM_CLR2, Cells.Size(), TERM_RST);
00599         printf("%s  Num of vertices    = %zd%s\n", TERM_CLR2, Verts.Size(), TERM_RST);
00600     }
00601 }
00602 
00603 inline void Unstructured::WritePLY (char const * FileKey, bool Blender)
00604 {
00605     // output string
00606     String fn(FileKey); fn.append(".ply");
00607     std::ostringstream oss;
00608 
00609     if (Blender)
00610     {
00611         // header
00612         oss << "import Blender\n";
00613         oss << "import bpy\n";
00614 
00615         // scene, mesh, and object
00616         oss << "scn = bpy.data.scenes.active\n";
00617         oss << "msh = bpy.data.meshes.new('unstruct_poly')\n";
00618         oss << "obj = scn.objects.new(msh,'unstruct_poly')\n";
00619 
00620         if (NDim==2)
00621         {
00622             // points
00623             oss << "pts = [";
00624             for (int i=0; i<Tin.numberofpoints; ++i)
00625             {
00626                 oss << "[" << Tin.pointlist[i*2];
00627                 oss << "," << Tin.pointlist[i*2+1] << ", 0.0]";
00628                 if (i==Tin.numberofpoints-1) oss << "]\n";
00629                 else                         oss << ",\n       ";
00630             }
00631             oss << "\n";
00632 
00633             // edges
00634             oss << "edg = [";
00635             for (int i=0; i<Tin.numberofsegments; ++i)
00636             {
00637                 oss << "[" << Tin.segmentlist[i*2] << "," << Tin.segmentlist[i*2+1] << "]";
00638                 if (i==Tin.numberofsegments-1) oss << "]\n";
00639                 else                           oss << ",\n       ";
00640             }
00641             oss << "\n";
00642         }
00643         else
00644         {
00645             // points
00646             oss << "pts = [";
00647             for (int i=0; i<Pin.numberofpoints; ++i)
00648             {
00649                 oss << "[" << Pin.pointlist[i*3];
00650                 oss << "," << Pin.pointlist[i*3+1];
00651                 oss << "," << Pin.pointlist[i*3+2] << "]";
00652                 if (i==Pin.numberofpoints-1) oss << "]\n";
00653                 else                         oss << ",\n       ";
00654             }
00655             oss << "\n";
00656 
00657             // edges
00658             oss << "edg = [";
00659             for (int i=0; i<Pin.numberoffacets; ++i)
00660             {
00661                 TetIO::facet * f = &Pin.facetlist[i];
00662                 for (int j=0; j<f->numberofpolygons; ++j)
00663                 {
00664                     TetIO::polygon * p  = &f->polygonlist[j];
00665                     for (int k=1; k<p->numberofvertices; ++k)
00666                     {
00667                         oss << "[" << p->vertexlist[k-1] << "," << p->vertexlist[k] << "]";
00668                         if (k==p->numberofvertices-1) oss << ",[" << p->vertexlist[k] << "," << p->vertexlist[0] << "]";
00669                         if ((i==Pin.numberoffacets-1) && (j==f->numberofpolygons-1) && (k==p->numberofvertices-1)) oss << "]\n";
00670                         else oss << ",\n       ";
00671                     }
00672                 }
00673             }
00674             oss << "\n";
00675         }
00676 
00677         // extend mesh
00678         oss << "msh.verts.extend(pts)\n";
00679         oss << "msh.edges.extend(edg)\n";
00680     }
00681     else // matplotlib
00682     {
00683         if (NDim==3) throw new Fatal("Unstructured::WritePLY: Method not available for 3D and MatPlotLib");
00684 
00685         // header
00686         MPL::Header (oss);
00687 
00688         // vertices and commands
00689         oss << "# vertices and commands\n";
00690         oss << "dat = []\n";
00691         for (int i=0; i<Tin.numberofsegments; ++i)
00692         {
00693             int I = Tin.segmentlist[i*2];
00694             int J = Tin.segmentlist[i*2+1];
00695             oss << "dat.append((PH.MOVETO, (" << Tin.pointlist[I*2] << "," << Tin.pointlist[I*2+1] << ")))\n";
00696             oss << "dat.append((PH.LINETO, (" << Tin.pointlist[J*2] << "," << Tin.pointlist[J*2+1] << ")))\n";
00697         }
00698         oss << "\n";
00699 
00700         // draw edges
00701         MPL::AddPatch (oss);
00702 
00703         // draw tags
00704         oss << "# draw tags\n";
00705         for (int i=0; i<Tin.numberofpoints; ++i)
00706         {
00707             int pt_tag = Tin.pointmarkerlist[i];
00708             if (pt_tag<0) oss << "ax.text(" << Tin.pointlist[i*2] << "," << Tin.pointlist[i*2+1] << ", " << pt_tag << ", ha='center', va='center', fontsize=14, backgroundcolor=lyellow)\n";
00709         }
00710         for (int i=0; i<Tin.numberofsegments; ++i)
00711         {
00712             int edge_tag = Tin.segmentmarkerlist[i];
00713             if (edge_tag<0)
00714             {
00715                 int    I  = Tin.segmentlist[i*2];
00716                 int    J  = Tin.segmentlist[i*2+1];
00717                 double x0 = Tin.pointlist[I*2];
00718                 double y0 = Tin.pointlist[I*2+1];
00719                 double x1 = Tin.pointlist[J*2];
00720                 double y1 = Tin.pointlist[J*2+1];
00721                 double xm = (x0+x1)/2.0;
00722                 double ym = (y0+y1)/2.0;
00723                 oss << "ax.text(" << xm << "," << ym << ", " << edge_tag << ", ha='center', va='center', fontsize=14, backgroundcolor=pink)\n";
00724             }
00725         }
00726         oss << "\n";
00727 
00728         // show
00729         oss << "# show\n";
00730         oss << "axis ('scaled')\n";
00731         oss << "show ()\n";
00732     }
00733 
00734     // create file
00735     std::ofstream of(fn.CStr(), std::ios::out);
00736     of << oss.str();
00737     of.close();
00738 }
00739 
00740 inline void Unstructured::GenBox (bool O2, double MaxVolume, double Lx, double Ly, double Lz)
00741 {
00742     Set    (8, 6, 1, 0);               // nverts, nfaces, nregs, nholes
00743     SetPnt (0, -1,   0.0,  0.0,  0.0); // id, vtag, x, y, z
00744     SetPnt (1, -2,    Lx,  0.0,  0.0);
00745     SetPnt (2, -3,    Lx,   Ly,  0.0);
00746     SetPnt (3, -4,   0.0,   Ly,  0.0);
00747     SetPnt (4, -5,   0.0,  0.0,   Lz);
00748     SetPnt (5, -6,    Lx,  0.0,   Lz);
00749     SetPnt (6, -7,    Lx,   Ly,   Lz);
00750     SetPnt (7, -8,   0.0,   Ly,   Lz);
00751     SetReg (0, -1, MaxVolume,  Lx/2., Ly/2., Lz/2.); // id, tag, max_vol, reg_x, reg_y, reg_z
00752     SetFac (0, -10, Array<int>(0,3,7,4));            // id, ftag, npolys, nverts, v0,v1,v2,v3
00753     SetFac (1, -20, Array<int>(1,2,6,5));
00754     SetFac (2, -30, Array<int>(0,1,5,4));
00755     SetFac (3, -40, Array<int>(2,3,7,6));
00756     SetFac (4, -50, Array<int>(0,1,2,3));
00757     SetFac (5, -60, Array<int>(4,5,6,7));
00758     Generate (O2);
00759 }
00760 
00761 inline bool Unstructured::IsSet () const
00762 {
00763     if (NDim==2)
00764     {
00765         bool hol_ok = (Tin.numberofholes>0 ? _lst_hol_set : true);
00766         return (_lst_reg_set && hol_ok && _lst_pnt_set && _lst_seg_set);
00767     }
00768     if (NDim==3)
00769     {
00770         bool hol_ok = (Pin.numberofholes>0 ? _lst_hol_set : true);
00771         return (_lst_reg_set && hol_ok && _lst_pnt_set && _lst_fac_set);
00772     }
00773     return false;
00774 }
00775 
00776 inline void Unstructured::Delaunay (Array<double> const & X, Array<double> const & Y, int Tag)
00777 {
00778     // check
00779     if (NDim==3)            throw new Fatal("Unstructured::Delaunay: This method is only available for 2D");
00780     if (X.Size()!=Y.Size()) throw new Fatal("Unstructured::Delaunay: Size of X and Y arrays must be equal (%d!=%d)",X.Size(),Y.Size());
00781 
00782     // erase previous PSLG
00783     TriDeallocateAll (Tin);
00784 
00785     // allocate only the pointlist array inside Triangle's IO structure
00786     size_t npoints = X.Size();
00787     Tin.pointlist      = (double*)malloc(npoints*2*sizeof(double));
00788     Tin.numberofpoints = npoints;
00789 
00790     // set points
00791     for (size_t i=0; i<npoints; ++i)
00792     {
00793         Tin.pointlist[0+i*2] = X[i];
00794         Tin.pointlist[1+i*2] = Y[i];
00795     }
00796 
00797     // triangulate
00798     TriIO tou;
00799     TriSetAllToNull (tou);
00800     triangulate ("Qz", &Tin, &tou, NULL); // Quiet, zero-based
00801 
00802     // verts
00803     Verts.Resize (tou.numberofpoints);
00804     for (size_t i=0; i<Verts.Size(); ++i)
00805     {
00806         Verts[i]      = new Vertex;
00807         Verts[i]->ID  = i;
00808         Verts[i]->Tag = 0;
00809         Verts[i]->C   = tou.pointlist[i*2], tou.pointlist[i*2+1], 0.0;
00810     }
00811 
00812     // cells
00813     Cells.Resize (tou.numberoftriangles);
00814     for (size_t i=0; i<Cells.Size(); ++i)
00815     {
00816         Cells[i]      = new Cell;
00817         Cells[i]->ID  = i;
00818         Cells[i]->Tag = Tag;
00819         Cells[i]->V.Resize (tou.numberofcorners);
00820         for (size_t j=0; j<Cells[i]->V.Size(); ++j)
00821         {
00822             Share sha = {Cells[i],j};
00823             Cells[i]->V[j] = Verts[tou.trianglelist[i*tou.numberofcorners+FEM2TriPoint[j]]];
00824             Cells[i]->V[j]->Shares.Push (sha);
00825         }
00826     }
00827 
00828     // clean up
00829     /* After triangulate (with -p switch), tou.regionlist gets the content of Tin.regionlist and
00830      * tou.holelist gets the content of Tin.holelist. Thus, these output variables must be set
00831      * to NULL in order to tell TriDeallocateAll to ignore them and do not double-free memory. */
00832     //tou.regionlist      = NULL;
00833     //tou.numberofregions = 0;
00834     //tou.holelist        = NULL;
00835     //tou.numberofholes   = 0;
00836     TriDeallocateAll (tou);
00837 }
00838 
00839 #ifdef USE_BOOST_PYTHON
00840 
00841 inline void Unstructured::PySet (BPy::dict const & Dat)
00842 {
00843     BPy::list const & pts = BPy::extract<BPy::list>(Dat["pts"])(); // points
00844     BPy::list const & rgs = BPy::extract<BPy::list>(Dat["rgs"])(); // regions
00845     BPy::list const & hls = BPy::extract<BPy::list>(Dat["hls"])(); // holes
00846     BPy::list const & con = BPy::extract<BPy::list>(Dat["con"])(); 
00847 
00848     size_t NPoints           = BPy::len(pts);
00849     size_t NSegmentsOrFacets = BPy::len(con);
00850     size_t NRegions          = BPy::len(rgs);
00851     size_t NHoles            = BPy::len(hls);
00852 
00853     // allocate memory
00854     Set (NPoints, NSegmentsOrFacets, NRegions, NHoles);
00855 
00856     // read regions
00857     for (size_t i=0; i<NRegions; ++i) SetReg (i, BPy::extract<int   >(rgs[i][0])(),         // tag
00858                                                  BPy::extract<double>(rgs[i][1])(),         // MaxArea/MaxVolume
00859                                                  BPy::extract<double>(rgs[i][2])(),         // x
00860                                                  BPy::extract<double>(rgs[i][3])(),         // y
00861                                       (NDim==3 ? BPy::extract<double>(rgs[i][4])() : 0.0)); // z
00862 
00863     // read holes
00864     for (size_t i=0; i<NHoles; ++i) SetHol (i, BPy::extract<double>(hls[i][0])(),         // x
00865                                                BPy::extract<double>(hls[i][1])(),         // y
00866                                     (NDim==3 ? BPy::extract<double>(hls[i][2])() : 0.0)); // z
00867 
00868     // read points
00869     for (size_t i=0; i<NPoints; ++i) SetPnt (i, BPy::extract<int   >(pts[i][0])(),         // tag
00870                                                 BPy::extract<double>(pts[i][1])(),         // x
00871                                                 BPy::extract<double>(pts[i][2])(),         // y
00872                                      (NDim==3 ? BPy::extract<double>(pts[i][3])() : 0.0)); // y
00873 
00874     // read segments
00875     if (NDim==2)
00876     {
00877         for (size_t i=0; i<NSegmentsOrFacets; ++i) SetSeg (i, BPy::extract<int>(con[i][0])(),  // tag
00878                                                               BPy::extract<int>(con[i][1])(),  // L
00879                                                               BPy::extract<int>(con[i][2])()); // R
00880     }
00881 
00882     // read facets
00883     else
00884     {
00885         for (size_t i=0; i<NSegmentsOrFacets; ++i) SetFac (i,            BPy::extract<int      >(con[i][0])(),   // tag
00886                                                               Array<int>(BPy::extract<BPy::list>(con[i][1])())); // verts
00887     }
00888 }
00889 
00890 #endif
00891 
00892 }; // namespace Mesh
00893 
00894 #endif // MECHSYS_MESH_UNSTRUCTURED_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines