MeshKit
1.0
|
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