MeshKit  1.0
DiskQuadMesher.hpp
Go to the documentation of this file.
00001 #include <stdio.h>
00002 #include <stdlib.h>
00003 #include <math.h>
00004 #include <assert.h>
00005 #include <iostream>
00006 #include <fstream>
00007 
00008 #include <vector>
00009 #include <map>
00010 #include <algorithm>
00011 
00012 #include "meshkit/tfiblend.hpp"
00013 
00014 using namespace std;
00015 
00016 struct DiskQuadMesher {
00017      void setBoundary(const vector<double> &p) {
00018           boundCoords = p;
00019      }
00020 
00021      int getQuadMesh( int nr, vector<double> &points, vector<int> &quads) {
00022           nR = nr;
00023           return execute();
00024      }
00025 
00026      int saveAs( const string &s);
00027 
00028 private:
00029 //   Input:
00030      int   nR, nT;  // Number of nodes along radial and tangential directions.
00031      int   nBounds;
00032      vector<double>  boundCoords;  // Coordinates along the circumfernce in CCW dir.
00033 
00034      struct Edge {
00035           int connect[2];
00036           bool isSame(int n0, int n1) const {
00037                if( connect[0] == n0 && connect[1] == n1 ) return  1;
00038                if( connect[0] == n1 && connect[1] == n0 ) return -1;
00039                return 0;
00040           }
00041           vector<int>  inserted_nodes;
00042      };
00043 
00044      vector<Edge> edges;
00045      int global_id;
00046 
00047      vector<double>  quadCoords; // Coordinate of quadmesh. (Boundary included);
00048      vector<int>     quadConnect;// Connectivity of quadmesh.
00049 
00050      int  landmarks[17]; // There are 17 landmark nodes in the full circle.
00051      int  execute();
00052      void getCentroid();// Centroid of the boundary nodes.
00053 
00054      void mid_point( int n0, int n1, int &nw, double r = 0.0);
00055      void split_boundary( int n0, int n1);
00056      int  linear_interpolation( int n0, int n1, int np, int edgeid );
00057      int  quad_template( int n0, int n1, int n2, int n3 );
00058 };
00059 
00061 
00062 inline
00063 void DiskQuadMesher :: mid_point( int n0, int n1, int &nw, double r)
00064 {
00065 
00066      double xm = TFI::linear_interpolation(r, quadCoords[2*n0 + 0], quadCoords[2*n1+0] );
00067      double ym = TFI::linear_interpolation(r, quadCoords[2*n0 + 1], quadCoords[2*n1+1] );
00068 
00069      nw = quadCoords.size()/2;
00070 
00071      quadCoords.push_back( xm );
00072      quadCoords.push_back( ym );
00073 }
00074 
00076 
00077 inline
00078 int DiskQuadMesher :: linear_interpolation( int n0, int n1, int np, int edgeid )
00079 {
00080      assert( np >= 1 );
00081      vector<int>  edgenodes(np);
00082 
00083      double dt =  2.0/(double)(np-1);
00084 
00085      edgenodes[0] = landmarks[n0];
00086      for( int i = 1; i < np-1; i++) {
00087           double r = -1.0 + i*dt;
00088           mid_point( landmarks[n0], landmarks[n1], edgenodes[i], r);
00089      }
00090      edgenodes[np-1] = landmarks[n1];
00091 
00092      Edge edge;
00093      edge.connect[0] = n0;
00094      edge.connect[1] = n1;
00095      edge.inserted_nodes =  edgenodes;
00096      edges[edgeid] = edge;
00097      return 0;
00098 }
00099 
00101 
00102 inline
00103 void DiskQuadMesher::split_boundary(int n0, int n1)
00104 {
00105      vector<int> edgenodes;
00106      assert( nT > 0);
00107 
00108      int dr = nT - 1;
00109      edgenodes.resize(nT);
00110      for(int i = 0; i < nT; i++) {
00111           edgenodes[i] = (n0*dr  + i)%nBounds;
00112      }
00113 
00114      Edge edge;
00115      edge.connect[0] = n0;
00116      edge.connect[1] = n1;
00117      edge.inserted_nodes =  edgenodes;
00118      edges[n0] = edge;
00119 }
00120 
00122 
00123 inline
00124 int DiskQuadMesher :: saveAs( const string &s)
00125 {
00126      ofstream ofile( s.c_str(), ios::out);
00127 
00128      ofile << "OFF" << endl;
00129 
00130      int numNodes = quadCoords.size()/2;
00131      int numFaces = quadConnect.size()/4;
00132 
00133      ofile <<  numNodes << " " << numFaces << "  0 " << endl;
00134 
00135      for( int i = 0; i < numNodes; i++)
00136           ofile << quadCoords[2*i] << " " << quadCoords[2*i+1] <<  " 0.0 " << endl;
00137 
00138      for( int i = 0; i < numFaces; i++)
00139           ofile << " 4 " << quadConnect[4*i+0] << " "
00140           << quadConnect[4*i+1] << " "
00141           << quadConnect[4*i+2] << " "
00142           << quadConnect[4*i+3] << endl;
00143 }
00144 
00146 
00147 inline
00148 int DiskQuadMesher :: quad_template( int n0, int n1, int n2, int n3 )
00149 {
00150      int err, vid;
00151 
00152      vector<int> ab = edges[n0].inserted_nodes;
00153      vector<int> bc = edges[n1].inserted_nodes;
00154      vector<int> dc = edges[n2].inserted_nodes;
00155      vector<int> ad = edges[n3].inserted_nodes;
00156 
00157      if( ab.size() != dc.size() ) return 2;
00158      if( ad.size() != bc.size() ) return 2;
00159 
00160      if( bc.back()  == ab.back()  ) std::reverse( bc.begin(), bc.end() );
00161      if( bc.back()  == dc.front() ) std::reverse( dc.begin(), dc.end() );
00162      if( dc.front() == ad.front() ) std::reverse( ad.begin(), ad.end() );
00163 
00164      int nx = ab.size();
00165      int ny = ad.size();
00166 
00167      assert( ab.front() == ad.front() );
00168      assert( ab.back()  == bc.front() );
00169      assert( bc.back()  == dc.back() );
00170      assert( ad.back()  == dc.front() );
00171 
00172      vector<double> x(nx*ny), y(nx*ny);
00173      vector<int> facenodes(nx*ny);
00174 
00175      for( int j = 0; j < ny; j++) {
00176           for( int i = 0; i < nx; i++) {
00177                vid = j*nx + i;
00178                x[vid] =  0.0;
00179                y[vid] =  0.0;
00180           }
00181      }
00182 
00183      for( int i = 0; i < nx; i++) {
00184           vid = i;
00185           facenodes[vid] =  ab[i];
00186 
00187           x[vid] =  quadCoords[2*ab[i] + 0];
00188           y[vid] =  quadCoords[2*ab[i] + 1];
00189 
00190           vid = (ny-1)*nx + i;
00191           facenodes[vid] =  dc[i];
00192           x[vid] =  quadCoords[2*dc[i] + 0];
00193           y[vid] =  quadCoords[2*dc[i] + 1];
00194      }
00195 
00196      for( int j = 1; j < ny-1; j++) {
00197           vid = j*nx;
00198           facenodes[vid] =  ad[j];
00199           x[vid] =  quadCoords[2*ad[j] + 0];
00200           y[vid] =  quadCoords[2*ad[j] + 1];
00201 
00202           vid = j*nx + (nx-1);
00203           facenodes[vid] =  bc[j];
00204           x[vid] =  quadCoords[2*bc[j] + 0];
00205           y[vid] =  quadCoords[2*bc[j] + 1];
00206      }
00207 
00208      TFI::blend_from_edges( &x[0], nx, ny);
00209      TFI::blend_from_edges( &y[0], nx, ny);
00210 
00211      global_id = quadCoords.size()/2;
00212      for( int j = 1; j < ny-1; j++) {
00213           for( int i = 1; i < nx-1; i++) {
00214                vid = j*nx + i;
00215                facenodes[vid] = global_id++;
00216                quadCoords.push_back( x[vid] );
00217                quadCoords.push_back( y[vid] );
00218           }
00219      }
00220 
00221      for( int j = 0; j < ny-1; j++) {
00222           for( int i = 0; i < nx-1; i++) {
00223                vid = j*nx + i;
00224                quadConnect.push_back( facenodes[vid] );
00225 
00226                vid = j*nx + i+1;
00227                quadConnect.push_back( facenodes[vid] );
00228 
00229                vid = (j+1)*nx + i+1;
00230                quadConnect.push_back( facenodes[vid] );
00231 
00232                vid = (j+1)*nx + i;
00233                quadConnect.push_back( facenodes[vid] );
00234 
00235           }
00236      }
00237 }
00238 
00240 inline
00241 int  DiskQuadMesher:: execute()
00242 {
00243      int vid;
00244      quadCoords.clear();
00245      quadConnect.clear();
00246 
00247      edges.resize(28);
00248 
00249      nBounds = boundCoords.size()/2;
00250 
00251      if( nBounds  < 8 ) return 1;
00252      if( nBounds%8 )    return 2;
00253 
00254      int dr = nBounds/8;
00255      for( int i = 0; i < 8; i++) {
00256           vid = i*dr;
00257           landmarks[i] = vid;
00258      }
00259      nT = dr + 1;
00260 
00261      for( int i = 0; i < nBounds; i++) {
00262           quadCoords.push_back( boundCoords[2*i + 0] );
00263           quadCoords.push_back( boundCoords[2*i + 1] );
00264      }
00265 
00266      double centroid[] = { 0.0, 0.0};
00267 
00268      for( size_t i = 0; i < nBounds; i++)  {
00269           centroid[0] += boundCoords[2*i + 0];
00270           centroid[1] += boundCoords[2*i + 1];
00271      }
00272 
00273      centroid[0] /= ( double) nBounds;
00274      centroid[1] /= ( double) nBounds;
00275 
00276      landmarks[8] = nBounds;
00277      quadCoords.push_back( centroid[0] );
00278      quadCoords.push_back( centroid[1] );
00279 
00280      global_id = nBounds + 1;
00281      mid_point( landmarks[8], landmarks[0], landmarks[9]  );
00282      mid_point( landmarks[8], landmarks[1], landmarks[10] );
00283      mid_point( landmarks[8], landmarks[2], landmarks[11] );
00284      mid_point( landmarks[8], landmarks[3], landmarks[12] );
00285      mid_point( landmarks[8], landmarks[4], landmarks[13] );
00286      mid_point( landmarks[8], landmarks[5], landmarks[14] );
00287      mid_point( landmarks[8], landmarks[6], landmarks[15] );
00288      mid_point( landmarks[8], landmarks[7], landmarks[16] );
00289 
00290      for( int i = 0; i < 8; i++)
00291           split_boundary( i, (i+1)%8 );
00292 
00293      assert( nT >= 1 );
00294 
00295      linear_interpolation( 9,  10, nT, 16 );
00296      linear_interpolation( 10, 11, nT, 17 );
00297      linear_interpolation( 11, 12, nT, 18 );
00298      linear_interpolation( 12, 13, nT, 19 );
00299      linear_interpolation( 13, 14, nT, 20 );
00300      linear_interpolation( 14, 15, nT, 21 );
00301      linear_interpolation( 15, 16, nT, 22 );
00302      linear_interpolation( 16,  9, nT, 23 );
00303 
00304      assert( nR > 1 );
00305      linear_interpolation( 9,   0, nR,  8 );
00306      linear_interpolation( 10,  1, nR,  9 );
00307      linear_interpolation( 11,  2, nR, 10 );
00308      linear_interpolation( 12,  3, nR, 11 );
00309      linear_interpolation( 13,  4, nR, 12 );
00310      linear_interpolation( 14,  5, nR, 13 );
00311      linear_interpolation( 15,  6, nR, 14 );
00312      linear_interpolation( 16,  7, nR, 15 );
00313 
00314      linear_interpolation( 8,  9,  nT, 24 );
00315      linear_interpolation( 8,  11, nT, 25 );
00316      linear_interpolation( 8,  13, nT, 26 );
00317      linear_interpolation( 8,  15, nT, 27 );
00318 
00319      // First quarter circle
00320      quad_template(0, 9, 16, 8  );
00321      quad_template(1, 10, 17, 9 );
00322      quad_template(16, 17, 25, 24);
00323 
00324      // Second quarter circle
00325      quad_template(2, 11, 18, 10 );
00326      quad_template(3, 12, 19, 11 );
00327      quad_template(18, 19, 26, 25 );
00328 
00329      // Third quarter circle
00330      quad_template(4, 13, 20, 12 );
00331      quad_template(5, 14, 21, 13 );
00332      quad_template(20, 21, 27, 26 );
00333 
00334      // Forth quarter circle
00335      quad_template(6, 15, 22, 14 );
00336      quad_template(7, 8,  23, 15 );
00337      quad_template(22, 23, 24, 27);
00338 }
00340 
00341 #ifdef DEF_MAIN
00342 int main()
00343 {
00344      vector<double> points;
00345 
00346      int nr = 8*3;
00347      double dt = 2.0*M_PI/(double)nr;
00348 
00349      points.resize( 2*nr );
00350      for( int i = 0; i < nr; i++) {
00351           points[2*i]   = cos( i*dt );
00352           points[2*i+1] = sin( i*dt );
00353      }
00354 
00355      DiskQuadMesher dqm;
00356      dqm.setBoundary( points );
00357 
00358      vector<double>  qPoints;
00359      vector<int>     quads;
00360 
00361      dqm.getQuadMesh(5, qPoints, quads);
00362 
00363      dqm.saveAs("tmp.off");
00364 }
00365 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines