$treeview $search $mathjax
|
Palabos
Version 1.1
$projectbrief
|
$projectbrief
|
$searchbox |
00001 /* This file is part of the Palabos library. 00002 * 00003 * Copyright (C) 2011 FlowKit Sarl 00004 * Avenue de Chailly 23 00005 * 1012 Lausanne, Switzerland 00006 * E-mail contact: contact@flowkit.com 00007 * 00008 * The most recent release of Palabos can be downloaded at 00009 * <http://www.palabos.org/> 00010 * 00011 * The library Palabos is free software: you can redistribute it and/or 00012 * modify it under the terms of the GNU Affero General Public License as 00013 * published by the Free Software Foundation, either version 3 of the 00014 * License, or (at your option) any later version. 00015 * 00016 * The library is distributed in the hope that it will be useful, 00017 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00018 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00019 * GNU Affero General Public License for more details. 00020 * 00021 * You should have received a copy of the GNU Affero General Public License 00022 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00023 */ 00024 00025 /* Main author: Dimitrios Kontaxakis */ 00026 00027 #ifndef TRIANGLE_SET_GENERATOR_HH 00028 #define TRIANGLE_SET_GENERATOR_HH 00029 00030 #include "core/globalDefs.h" 00031 #include "offLattice/triangleSetGenerator.h" 00032 00033 namespace plb { 00034 00035 template<typename T> 00036 TriangleSet<T> constructSphere(Array<T,3> const& center, T radius, plint minNumOfTriangles) 00037 { 00038 static const T eps = std::numeric_limits<T>::epsilon(); 00039 std::vector<typename TriangleSet<T>::Triangle> triangles; 00040 PLB_ASSERT(radius > 0.0 && !util::fpequal(radius, (T) 0.0, eps) && 00041 minNumOfTriangles >= 8); 00042 00043 // Create a triangularized unit sphere 00044 00045 // Initial 6 vertices 00046 00047 Array<T,3> va; 00048 va[0] = 1.0; 00049 va[1] = 0.0; 00050 va[2] = 0.0; 00051 00052 Array<T,3> vb; 00053 vb[0] = 0.0; 00054 vb[1] = 1.0; 00055 vb[2] = 0.0; 00056 00057 Array<T,3> vc; 00058 vc[0] = -1.0; 00059 vc[1] = 0.0; 00060 vc[2] = 0.0; 00061 00062 Array<T,3> vd; 00063 vd[0] = 0.0; 00064 vd[1] = -1.0; 00065 vd[2] = 0.0; 00066 00067 Array<T,3> ve; 00068 ve[0] = 0.0; 00069 ve[1] = 0.0; 00070 ve[2] = 1.0; 00071 00072 Array<T,3> vf; 00073 vf[0] = 0.0; 00074 vf[1] = 0.0; 00075 vf[2] = -1.0; 00076 00077 // Initial 8 triangles 00078 00079 typename TriangleSet<T>::Triangle tmp; 00080 00081 tmp[0] = ve; 00082 tmp[1] = va; 00083 tmp[2] = vb; 00084 triangles.push_back(tmp); 00085 00086 tmp[0] = ve; 00087 tmp[1] = vb; 00088 tmp[2] = vc; 00089 triangles.push_back(tmp); 00090 00091 tmp[0] = ve; 00092 tmp[1] = vc; 00093 tmp[2] = vd; 00094 triangles.push_back(tmp); 00095 00096 tmp[0] = ve; 00097 tmp[1] = vd; 00098 tmp[2] = va; 00099 triangles.push_back(tmp); 00100 00101 tmp[0] = vf; 00102 tmp[1] = vb; 00103 tmp[2] = va; 00104 triangles.push_back(tmp); 00105 00106 tmp[0] = vf; 00107 tmp[1] = vc; 00108 tmp[2] = vb; 00109 triangles.push_back(tmp); 00110 00111 tmp[0] = vf; 00112 tmp[1] = vd; 00113 tmp[2] = vc; 00114 triangles.push_back(tmp); 00115 00116 tmp[0] = vf; 00117 tmp[1] = va; 00118 tmp[2] = vd; 00119 triangles.push_back(tmp); 00120 00121 // Perform refinement iterations 00122 00123 plint size; 00124 while ((size = triangles.size()) < minNumOfTriangles) { 00125 for (plint i = 0; i < size; i++) { 00126 va = triangles[i][0]; 00127 vb = triangles[i][1]; 00128 vc = triangles[i][2]; 00129 00130 vd = 0.5 * (va + vb); 00131 ve = 0.5 * (vb + vc); 00132 vf = 0.5 * (vc + va); 00133 00134 vd /= norm(vd); 00135 ve /= norm(ve); 00136 vf /= norm(vf); 00137 00138 triangles[i][0] = vd; 00139 triangles[i][1] = ve; 00140 triangles[i][2] = vf; 00141 00142 tmp[0] = va; 00143 tmp[1] = vd; 00144 tmp[2] = vf; 00145 triangles.push_back(tmp); 00146 00147 tmp[0] = vd; 00148 tmp[1] = vb; 00149 tmp[2] = ve; 00150 triangles.push_back(tmp); 00151 00152 tmp[0] = vf; 00153 tmp[1] = ve; 00154 tmp[2] = vc; 00155 triangles.push_back(tmp); 00156 } 00157 } 00158 00159 // Scale and translate the mesh 00160 00161 TriangleSet<T> triangleSet(triangles); 00162 00163 triangleSet.scale(radius); 00164 triangleSet.translate(center); 00165 00166 return triangleSet; 00167 } 00168 00169 template<typename T> 00170 TriangleSet<T> constructCylinder( Array<T,3> const& inletCenter, T inletRadius, T outletRadius, 00171 T length, plint nAxial, plint nCirc, 00172 std::vector<Array<T,3> >& inletPoints ) 00173 { 00174 static const T eps = std::numeric_limits<T>::epsilon(); 00175 std::vector<typename TriangleSet<T>::Triangle> triangles; 00176 PLB_ASSERT( inletRadius > 0.0 && !util::fpequal( inletRadius, (T) 0.0, eps) && 00177 outletRadius > 0.0 && !util::fpequal(outletRadius, (T) 0.0, eps) && 00178 length > 0.0 && !util::fpequal( length, (T) 0.0, eps) && 00179 nAxial >= 2 && nCirc >= 2); 00180 00181 inletPoints.resize(0); 00182 triangles.resize(0); 00183 00184 // Construction of the cylindrical grid and triangulation 00185 00186 T pi = (T) acos(-1.0); 00187 00188 T dtheta = 2.0*pi / nCirc; 00189 T dx = length / (nAxial-1.0); 00190 T dr = (outletRadius-inletRadius) / length * dx; 00191 00192 T x0 = inletCenter[0]; 00193 T y0 = inletCenter[1]; 00194 T z0 = inletCenter[2]; 00195 00196 for (plint i = 0; i < nAxial-1; i++) { 00197 T x = x0 + i*dx; 00198 T r = (outletRadius-inletRadius) * (x-x0) / length + inletRadius; 00199 for (plint j = 0; j < nCirc; j++) { 00200 T theta = j * dtheta; 00201 00202 Array<Array<T,3>, 4> v; 00203 00204 v[0][0] = x; 00205 v[0][1] = y0 + r * cos(theta); 00206 v[0][2] = z0 + r * sin(theta); 00207 00208 v[1][0] = x; 00209 v[1][1] = y0 + r * cos(theta + dtheta); 00210 v[1][2] = z0 + r * sin(theta + dtheta); 00211 00212 v[2][0] = x + dx; 00213 v[2][1] = y0 + (r + dr) * cos(theta + dtheta); 00214 v[2][2] = z0 + (r + dr) * sin(theta + dtheta); 00215 00216 v[3][0] = x + dx; 00217 v[3][1] = y0 + (r + dr) * cos(theta); 00218 v[3][2] = z0 + (r + dr) * sin(theta); 00219 00220 Array<T,3> vc; 00221 00222 vc[0] = x + 0.5 * dx; 00223 vc[1] = y0 + (r + 0.5 * dr) * cos(theta + 0.5 * dtheta); 00224 vc[2] = z0 + (r + 0.5 * dr) * sin(theta + 0.5 * dtheta); 00225 00226 Array<Array<T,3>, 4> vce; 00227 00228 00229 vce[0][0] = x; 00230 vce[0][1] = y0 + r * cos(theta + 0.5 * dtheta); 00231 vce[0][2] = z0 + r * sin(theta + 0.5 * dtheta); 00232 00233 if (i==0) { 00234 inletPoints.push_back(v[0]); 00235 inletPoints.push_back(vce[0]); 00236 } 00237 00238 vce[1][0] = x + 0.5 * dx; 00239 vce[1][1] = y0 + (r + 0.5 * dr) * cos(theta + dtheta); 00240 vce[1][2] = z0 + (r + 0.5 * dr) * sin(theta + dtheta); 00241 00242 vce[2][0] = x + dx; 00243 vce[2][1] = y0 + (r + dr) * cos(theta + 0.5 * dtheta); 00244 vce[2][2] = z0 + (r + dr) * sin(theta + 0.5 * dtheta); 00245 00246 vce[3][0] = x + 0.5 * dx; 00247 vce[3][1] = y0 + (r + 0.5 * dr) * cos(theta); 00248 vce[3][2] = z0 + (r + 0.5 * dr) * sin(theta); 00249 00250 typename TriangleSet<T>::Triangle tmp; 00251 00252 tmp[0] = vc; 00253 tmp[1] = v[0]; 00254 tmp[2] = vce[0]; 00255 triangles.push_back(tmp); 00256 00257 tmp[0] = vc; 00258 tmp[1] = vce[0]; 00259 tmp[2] = v[1]; 00260 triangles.push_back(tmp); 00261 00262 tmp[0] = vc; 00263 tmp[1] = v[1]; 00264 tmp[2] = vce[1]; 00265 triangles.push_back(tmp); 00266 00267 tmp[0] = vc; 00268 tmp[1] = vce[1]; 00269 tmp[2] = v[2]; 00270 triangles.push_back(tmp); 00271 00272 tmp[0] = vc; 00273 tmp[1] = v[2]; 00274 tmp[2] = vce[2]; 00275 triangles.push_back(tmp); 00276 00277 tmp[0] = vc; 00278 tmp[1] = vce[2]; 00279 tmp[2] = v[3]; 00280 triangles.push_back(tmp); 00281 00282 tmp[0] = vc; 00283 tmp[1] = v[3]; 00284 tmp[2] = vce[3]; 00285 triangles.push_back(tmp); 00286 00287 tmp[0] = vc; 00288 tmp[1] = vce[3]; 00289 tmp[2] = v[0]; 00290 triangles.push_back(tmp); 00291 } 00292 } 00293 return TriangleSet<T>(triangles); 00294 } 00295 template<typename T> 00296 TriangleSet<T> constructCylinder(Array<T,3> const& inletCenter, T inletRadius, T outletRadius, 00297 T length, plint nAxial, plint nCirc) 00298 { 00299 static const T eps = std::numeric_limits<T>::epsilon(); 00300 std::vector<typename TriangleSet<T>::Triangle> triangles; 00301 PLB_ASSERT( inletRadius > 0.0 && !util::fpequal( inletRadius, (T) 0.0, eps) && 00302 outletRadius > 0.0 && !util::fpequal(outletRadius, (T) 0.0, eps) && 00303 length > 0.0 && !util::fpequal( length, (T) 0.0, eps) && 00304 nAxial >= 2 && nCirc >= 2); 00305 00306 triangles.resize(0); 00307 00308 // Construction of the cylindrical grid and triangulation 00309 00310 T pi = (T) acos(-1.0); 00311 00312 T dtheta = 2.0*pi / nCirc; 00313 T dx = length / (nAxial-1.0); 00314 T dr = (outletRadius-inletRadius) / length * dx; 00315 00316 T x0 = inletCenter[0]; 00317 T y0 = inletCenter[1]; 00318 T z0 = inletCenter[2]; 00319 00320 for (plint i = 0; i < nAxial-1; i++) { 00321 T x = x0 + i*dx; 00322 T r = (outletRadius-inletRadius) * (x-x0) / length + inletRadius; 00323 for (plint j = 0; j < nCirc; j++) { 00324 T theta = j * dtheta; 00325 00326 Array<Array<T,3>, 4> v; 00327 00328 v[0][0] = x; 00329 v[0][1] = y0 + r * cos(theta); 00330 v[0][2] = z0 + r * sin(theta); 00331 00332 v[1][0] = x; 00333 v[1][1] = y0 + r * cos(theta + dtheta); 00334 v[1][2] = z0 + r * sin(theta + dtheta); 00335 00336 v[2][0] = x + dx; 00337 v[2][1] = y0 + (r + dr) * cos(theta + dtheta); 00338 v[2][2] = z0 + (r + dr) * sin(theta + dtheta); 00339 00340 v[3][0] = x + dx; 00341 v[3][1] = y0 + (r + dr) * cos(theta); 00342 v[3][2] = z0 + (r + dr) * sin(theta); 00343 00344 Array<T,3> vc; 00345 00346 vc[0] = x + 0.5 * dx; 00347 vc[1] = y0 + (r + 0.5 * dr) * cos(theta + 0.5 * dtheta); 00348 vc[2] = z0 + (r + 0.5 * dr) * sin(theta + 0.5 * dtheta); 00349 00350 Array<Array<T,3>, 4> vce; 00351 00352 vce[0][0] = x; 00353 vce[0][1] = y0 + r * cos(theta + 0.5 * dtheta); 00354 vce[0][2] = z0 + r * sin(theta + 0.5 * dtheta); 00355 00356 vce[1][0] = x + 0.5 * dx; 00357 vce[1][1] = y0 + (r + 0.5 * dr) * cos(theta + dtheta); 00358 vce[1][2] = z0 + (r + 0.5 * dr) * sin(theta + dtheta); 00359 00360 vce[2][0] = x + dx; 00361 vce[2][1] = y0 + (r + dr) * cos(theta + 0.5 * dtheta); 00362 vce[2][2] = z0 + (r + dr) * sin(theta + 0.5 * dtheta); 00363 00364 vce[3][0] = x + 0.5 * dx; 00365 vce[3][1] = y0 + (r + 0.5 * dr) * cos(theta); 00366 vce[3][2] = z0 + (r + 0.5 * dr) * sin(theta); 00367 00368 typename TriangleSet<T>::Triangle tmp; 00369 00370 tmp[0] = vc; 00371 tmp[1] = v[0]; 00372 tmp[2] = vce[0]; 00373 triangles.push_back(tmp); 00374 00375 tmp[0] = vc; 00376 tmp[1] = vce[0]; 00377 tmp[2] = v[1]; 00378 triangles.push_back(tmp); 00379 00380 tmp[0] = vc; 00381 tmp[1] = v[1]; 00382 tmp[2] = vce[1]; 00383 triangles.push_back(tmp); 00384 00385 tmp[0] = vc; 00386 tmp[1] = vce[1]; 00387 tmp[2] = v[2]; 00388 triangles.push_back(tmp); 00389 00390 tmp[0] = vc; 00391 tmp[1] = v[2]; 00392 tmp[2] = vce[2]; 00393 triangles.push_back(tmp); 00394 00395 tmp[0] = vc; 00396 tmp[1] = vce[2]; 00397 tmp[2] = v[3]; 00398 triangles.push_back(tmp); 00399 00400 tmp[0] = vc; 00401 tmp[1] = v[3]; 00402 tmp[2] = vce[3]; 00403 triangles.push_back(tmp); 00404 00405 tmp[0] = vc; 00406 tmp[1] = vce[3]; 00407 tmp[2] = v[0]; 00408 triangles.push_back(tmp); 00409 } 00410 } 00411 return TriangleSet<T>(triangles); 00412 } 00413 00414 template<typename T> 00415 void addSurface ( 00416 Array<T,3> const& lowerCorner, 00417 Array<T,3> const& delta1, plint n1, Array<T,3> const& delta2, plint n2, 00418 std::vector<typename TriangleSet<T>::Triangle>& triangles ) 00419 { 00420 Array<T,3> pos1(lowerCorner); 00421 for(plint i1=0; i1<n1; ++i1, pos1+=delta1) { 00422 Array<T,3> pos2(pos1); 00423 for(plint i2=0; i2<n2; ++i2, pos2+=delta2) { 00424 typename TriangleSet<T>::Triangle triangle; 00425 triangle[0] = pos2; 00426 triangle[1] = pos2+delta1; 00427 triangle[2] = pos2+delta2; 00428 triangles.push_back(triangle); 00429 triangle[0] += delta1+delta2; 00430 std::swap(triangle[1], triangle[2]); 00431 triangles.push_back(triangle); 00432 } 00433 } 00434 } 00435 00436 template<typename T> 00437 TriangleSet<T> constructCuboid ( 00438 Array<T,3> const& lowerCorner, Array<T,3> const& upperCorner, 00439 Array<plint,3> const& nSegments ) 00440 { 00441 std::vector<typename TriangleSet<T>::Triangle> triangles; 00442 T lx = upperCorner[0]-lowerCorner[0]; 00443 T ly = upperCorner[1]-lowerCorner[1]; 00444 T lz = upperCorner[2]-lowerCorner[2]; 00445 Array<T,3> deltaX(lx/(T)nSegments[0], T(), T()); 00446 Array<T,3> deltaY(T(), ly/(T)nSegments[1], T()); 00447 Array<T,3> deltaZ(T(), T(), lz/(T)nSegments[2]); 00448 00449 addSurface(lowerCorner, 00450 deltaZ, nSegments[2], deltaY, nSegments[1], triangles); 00451 addSurface(lowerCorner+Array<T,3>(lx,T(),T()), 00452 deltaY, nSegments[1], deltaZ, nSegments[2], triangles); 00453 00454 addSurface(lowerCorner, 00455 deltaX, nSegments[0], deltaZ, nSegments[2], triangles); 00456 addSurface(lowerCorner+Array<T,3>(T(),ly,T()), 00457 deltaZ, nSegments[2], deltaX, nSegments[0], triangles); 00458 00459 addSurface(lowerCorner, 00460 deltaY, nSegments[1], deltaX, nSegments[0], triangles); 00461 addSurface(lowerCorner+Array<T,3>(T(),T(),lz), 00462 deltaX, nSegments[0], deltaY, nSegments[1], triangles); 00463 00464 return TriangleSet<T>(triangles); 00465 } 00466 00467 00468 template<typename T> 00469 TriangleSet<T> constructCylinder( Array<T,3> const& inletCenter, Array<T,3> const& axis, 00470 T inletRadius, T outletRadius, 00471 T length, plint nAxial, plint nCirc, 00472 std::vector<Array<T,3> >& inletPoints ) 00473 { 00474 TriangleSet<T> cylinder ( 00475 constructCylinder(Array<T,3>(T(),T(),T()), inletRadius, outletRadius, 00476 length, nAxial, nCirc, inletPoints) ); 00477 Array<T,3> xAxis((T)1,T(),T()); 00478 Array<T,3> rotAxis; 00479 T alignment = dot(xAxis, axis); 00480 T eps = (T)100.*std::numeric_limits<T>::epsilon(); 00481 if (!util::fpequal(alignment, (T)1., eps)) { 00482 crossProduct<T>(xAxis, axis, rotAxis); 00483 rotAxis /= norm(rotAxis); 00484 T angle = angleBetweenVectors(xAxis, axis); 00485 cylinder.rotateAtOrigin(rotAxis, angle); 00486 for (pluint i=0; i<inletPoints.size(); ++i) { 00487 inletPoints[i] = rotateAtOrigin(inletPoints[i], rotAxis, angle); 00488 } 00489 } 00490 cylinder.translate(inletCenter); 00491 for (pluint i=0; i<inletPoints.size(); ++i) { 00492 inletPoints[i] += inletCenter; 00493 } 00494 return cylinder; 00495 } 00496 00497 00498 template<typename T> 00499 TriangleSet<T> patchTubes(TriangleSet<T> const& geometryWithOpenings, plint sortDirection, std::vector<T> patchLengths) 00500 { 00501 typedef typename TriangleSet<T>::Triangle Triangle; 00502 typedef typename TriangularSurfaceMesh<T>::Lid Lid; 00503 00504 std::vector<Triangle> fullGeometry( geometryWithOpenings.getTriangles() ); 00505 00506 DEFscaledMesh<T>* defMesh = new DEFscaledMesh<T>(geometryWithOpenings); 00507 TriangularSurfaceMesh<T>& mesh = defMesh->getMesh(); 00508 00509 std::vector<Lid> holes = mesh.closeHoles(); 00510 std::sort(holes.begin(), holes.end(), LidLessThan<T>(sortDirection, mesh)); 00511 00512 PLB_ASSERT( holes.size() == patchLengths.size() ); 00513 00514 for (pluint iHole=0; iHole<holes.size(); ++iHole) { 00515 Array<T,3> baryCenter = computeGeometricCenter(mesh,holes[iHole]); 00516 plint numHoleVertices = (plint) holes[iHole].boundaryVertices.size(); 00517 00518 Array<T,3> normal = computeNormal(mesh, holes[iHole]); 00519 T aveRadius = computeGeometricRadius(mesh,holes[iHole]); 00520 00521 Array<T,3> nextCenter = baryCenter + normal*aveRadius*10./(T)numHoleVertices; 00522 00523 plint numInletPoints = numHoleVertices; 00524 bool oddNumber = numHoleVertices%2==1; 00525 if (oddNumber) numInletPoints--; // Must be even for cylinder construction algorithm. 00526 std::vector<Array<T,3> > inletPoints; 00527 plint numPointsOnLength = numInletPoints*patchLengths[iHole]/aveRadius/8; 00528 if (numPointsOnLength<3) numPointsOnLength = 3; 00529 TriangleSet<T> piece = constructCylinder(nextCenter, normal, aveRadius, aveRadius, patchLengths[iHole], 00530 numPointsOnLength, numInletPoints/2, inletPoints); 00531 std::vector<Triangle> pieceTriangles = piece.getTriangles(); 00532 00533 plint newId = 0; 00534 T minDistance = std::numeric_limits<T>::max(); 00535 plint minDistanceId = -1; 00536 for (plint i=0; i<numHoleVertices; ++i) { 00537 plint iVertex = holes[iHole].boundaryVertices[i]; 00538 Array<T,3> p1 = mesh.getVertex(iVertex); 00539 T nextDistance = norm(inletPoints[newId]-p1); 00540 if (nextDistance<minDistance) { 00541 minDistance = nextDistance; 00542 minDistanceId = i; 00543 } 00544 } 00545 plint oldId = minDistanceId; 00546 plint newId_p1 = 0; 00547 for (plint i=0; i<numInletPoints; ++i) { 00548 plint newId_p1 = (newId+1) % numInletPoints; 00549 plint oldId_p1 = oldId-1; 00550 if (oldId_p1<0) oldId_p1 = numHoleVertices-1; 00551 00552 plint oldVertex1 = holes[iHole].boundaryVertices[oldId]; 00553 plint oldVertex2 = holes[iHole].boundaryVertices[oldId_p1]; 00554 Array<T,3> p1 = mesh.getVertex(oldVertex1); 00555 Array<T,3> p2 = inletPoints[newId]; 00556 Array<T,3> p3 = mesh.getVertex(oldVertex2); 00557 Array<T,3> p4 = inletPoints[newId_p1]; 00558 00559 pieceTriangles.push_back(Triangle(p1,p3,p2)); 00560 pieceTriangles.push_back(Triangle(p2,p3,p4)); 00561 00562 std::swap(newId, newId_p1); 00563 std::swap(oldId, oldId_p1); 00564 } 00565 00566 if (oddNumber) { 00567 plint id_a = holes[iHole].boundaryVertices[oldId]; 00568 plint oldId_p2 = oldId-1; 00569 if (oldId_p2<0) oldId_p2 = numHoleVertices-1; 00570 plint id_b = holes[iHole].boundaryVertices[oldId_p2]; 00571 plint id_c = newId_p1; 00572 Array<T,3> a = mesh.getVertex(id_a); 00573 Array<T,3> b = mesh.getVertex(id_b); 00574 Array<T,3> c = inletPoints[id_c]; 00575 pieceTriangles.push_back(Triangle(a,b,c)); 00576 } 00577 00578 00579 fullGeometry.insert(fullGeometry.end(), pieceTriangles.begin(), pieceTriangles.end()); 00580 } 00581 00582 return TriangleSet<T>(fullGeometry, geometryWithOpenings.getPrecision()); 00583 } 00584 00585 } // namespace plb 00586 00587 #endif // TRIANGLE_SET_GENERATOR_HH
1.6.3
1.6.3