$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_HH 00028 #define TRIANGLE_SET_HH 00029 00030 #include "triangleSet.h" 00031 #include "core/util.h" 00032 #include <algorithm> 00033 #include <limits> 00034 #include <cstdio> 00035 #include <cmath> 00036 00037 namespace plb { 00038 00039 template<typename T> 00040 TriangleSet<T>::TriangleSet(Precision precision_) 00041 : minEdgeLength(std::numeric_limits<T>::max()), 00042 maxEdgeLength(std::numeric_limits<T>::min()) 00043 { 00044 PLB_ASSERT(precision_ == FLT || precision_ == DBL || precision_ == LDBL); 00045 precision = precision_; 00046 00047 boundingCuboid.lowerLeftCorner = Array<T,3>(0.0, 0.0, 0.0); 00048 boundingCuboid.upperRightCorner = Array<T,3>(0.0, 0.0, 0.0); 00049 } 00050 00051 template<typename T> 00052 TriangleSet<T>::TriangleSet(std::vector<Triangle> const& triangles_, Precision precision_) 00053 : triangles(triangles_), 00054 minEdgeLength(std::numeric_limits<T>::max()), 00055 maxEdgeLength(std::numeric_limits<T>::min()) 00056 { 00057 PLB_ASSERT(precision_ == FLT || precision_ == DBL || precision_ == LDBL); 00058 precision = precision_; 00059 00060 computeMinMaxEdges(); 00061 computeBoundingCuboid(); 00062 } 00063 00064 template<typename T> 00065 TriangleSet<T>::TriangleSet(std::string fname, Precision precision_, SurfaceGeometryFileFormat fformat) 00066 : minEdgeLength(std::numeric_limits<T>::max()), 00067 maxEdgeLength(std::numeric_limits<T>::min()) 00068 { 00069 PLB_ASSERT(precision_ == FLT || precision_ == DBL || precision_ == LDBL); 00070 PLB_ASSERT(fformat == STL); 00071 precision = precision_; 00072 00073 switch (fformat) { 00074 case STL: default: 00075 readSTL(fname); 00076 break; 00077 } 00078 00079 // TODO: Check if the next call is actually needed, since the min and max edges are 00080 // computed in the readAsciiSTL and readBinarySTL functions as well. 00081 computeMinMaxEdges(); 00082 00083 computeBoundingCuboid(); 00084 } 00085 00086 template<typename T> 00087 std::vector<typename TriangleSet<T>::Triangle> const& 00088 TriangleSet<T>::getTriangles() const 00089 { 00090 return triangles; 00091 } 00092 00093 template<typename T> 00094 void TriangleSet<T>::setPrecision(Precision precision_) 00095 { 00096 PLB_ASSERT(precision_ == FLT || precision_ == DBL || precision_ == LDBL); 00097 precision = precision_; 00098 } 00099 00100 template<typename T> 00101 void TriangleSet<T>::readSTL(std::string fname) 00102 { 00103 char buf[256]; 00104 FILE *fp = fopen(fname.c_str(), "r"); 00105 PLB_ASSERT(fp != NULL); // The input file cannot be read. 00106 00107 char *sp = fgets(buf, 256, fp); 00108 PLB_ASSERT(sp != NULL); // The input file cannot be read. 00109 rewind(fp); 00110 00111 if (strstr(buf, "solid") != NULL) { 00112 readAsciiSTL(fp); 00113 } 00114 else { 00115 readBinarySTL(fp); 00116 } 00117 } 00118 00119 template<typename T> 00120 void TriangleSet<T>::readAsciiSTL(FILE* fp) { 00121 char buf[256]; 00122 char *cp, *sp; 00123 00124 sp = fgets(buf, 256, fp); 00125 PLB_ASSERT(sp != NULL); // The input file is badly structured. 00126 00127 char fmt[32]; 00128 bool failed = false; 00129 if (sizeof(T) == sizeof(float)) 00130 strcpy(fmt, "%f%f%f"); 00131 else if (sizeof(T) == sizeof(double)) 00132 strcpy(fmt, "%lf%lf%lf"); 00133 else if (sizeof(T) == sizeof(long double)) 00134 strcpy(fmt, "%Lf%Lf%Lf"); 00135 else 00136 failed = true; 00137 00138 PLB_ASSERT(!failed); // The input file cannot be read. 00139 00140 cp = strstr(buf, "solid"); 00141 PLB_ASSERT(cp != NULL); // The input file is badly structured. 00142 00143 while (cp != NULL && !failed) { 00144 if (fgets(buf, 256, fp) == NULL) { 00145 failed = true; 00146 } 00147 00148 do { 00149 if ((cp = strstr(buf, "facet normal")) == NULL) { 00150 failed = true; 00151 } 00152 cp += 12; 00153 Array<T,3> n; 00154 if (sscanf(cp, fmt, &n[0], &n[1], &n[2]) != 3) { 00155 failed = true; 00156 } 00157 00158 if (fgets(buf, 256, fp) == NULL || strstr(buf, "outer loop") == NULL) 00159 { 00160 failed = true; 00161 } 00162 00163 Triangle triangle; 00164 T nextMin, nextMax; 00165 for (int i = 0; i < 3; i++) { 00166 if ( fgets(buf, 256, fp) == NULL || 00167 (cp = strstr(buf, "vertex")) == NULL ) 00168 { 00169 failed = true; 00170 } 00171 cp += 6; 00172 triangle[i][0] = T(); 00173 triangle[i][1] = T(); 00174 triangle[i][2] = T(); 00175 if (sscanf( cp, fmt, 00176 &triangle[i][0], 00177 &triangle[i][1], 00178 &triangle[i][2] ) != 3) 00179 { 00180 failed = true; 00181 } 00182 } 00183 00184 if (fgets(buf, 256, fp) == NULL || strstr(buf, "endloop") == NULL) { 00185 failed = true; 00186 } 00187 00188 if (fgets(buf, 256, fp) == NULL || strstr(buf, "endfacet") == NULL) { 00189 failed = true; 00190 } 00191 00192 check(triangle, n); 00193 triangles.push_back(triangle); 00194 00195 computeMinMaxEdge(triangles.size()-1, nextMin, nextMax); 00196 minEdgeLength = std::min(minEdgeLength, nextMin); 00197 maxEdgeLength = std::max(maxEdgeLength, nextMax); 00198 00199 if (fgets(buf, 256, fp) == NULL) { 00200 failed = true; 00201 } 00202 cp = strstr(buf, "endsolid"); 00203 } 00204 while (cp == NULL && !failed); 00205 00206 if (fgets(buf, 256, fp) == NULL) 00207 break; 00208 00209 cp = strstr(buf, "solid"); 00210 } 00211 PLB_ASSERT(!failed); // The input file is badly structured. 00212 } 00213 00214 template<typename T> 00215 void TriangleSet<T>::readBinarySTL(FILE* fp) 00216 { 00217 char buf[256]; 00218 unsigned int nt; 00219 float array[3]; 00220 unsigned short abc; 00221 bool failed = false; 00222 00223 int count = 0; 00224 while (fread(buf, sizeof(char), 80, fp) == 80 && 00225 fread(&nt, sizeof(unsigned int), 1, fp) == 1 && !failed) { 00226 count++; 00227 T nextMin, nextMax; 00228 for (unsigned it = 0; it < nt && !failed; it++) { 00229 if (fread(array, sizeof(float), 3, fp) != 3) { 00230 failed = true; 00231 } 00232 Array<T,3> n; 00233 n[0] = array[0]; 00234 n[1] = array[1]; 00235 n[2] = array[2]; 00236 00237 Triangle triangle; 00238 for (int i = 0; i < 3 && !failed; i++) { 00239 if (fread(array, sizeof(float), 3, fp) != 3) { 00240 failed = true; 00241 } 00242 triangle[i][0] = T(); 00243 triangle[i][1] = T(); 00244 triangle[i][2] = T(); 00245 triangle[i][0] = array[0]; 00246 triangle[i][1] = array[1]; 00247 triangle[i][2] = array[2]; 00248 } 00249 00250 if (fread(&abc, sizeof(unsigned short), 1, fp) != 1) { 00251 failed = true; 00252 } 00253 00254 check(triangle, n); 00255 triangles.push_back(triangle); 00256 00257 computeMinMaxEdge(triangles.size()-1, nextMin, nextMax); 00258 minEdgeLength = std::min(minEdgeLength, nextMin); 00259 maxEdgeLength = std::max(maxEdgeLength, nextMax); 00260 } 00261 } 00262 00263 if (count == 0) 00264 failed = true; 00265 00266 PLB_ASSERT(!failed); // The input file is badly structured. 00267 } 00268 00270 template<typename T> 00271 void TriangleSet<T>::check(Triangle& triangle, Array<T,3> const& n) 00272 { 00273 T eps = getEpsilon<T>(precision); 00274 00275 Array<T,3> v01 = triangle[1] - triangle[0]; 00276 Array<T,3> v02 = triangle[2] - triangle[0]; 00277 Array<T,3> v12 = triangle[2] - triangle[1]; 00278 00279 T norm01 = sqrt(VectorTemplateImpl<T,3>::normSqr(v01)); 00280 T norm02 = sqrt(VectorTemplateImpl<T,3>::normSqr(v02)); 00281 T norm12 = sqrt(VectorTemplateImpl<T,3>::normSqr(v12)); 00282 00283 if (util::fpequal(norm01, (T) 0.0, eps) || util::fpequal(norm02, (T) 0.0, eps) || 00284 util::fpequal(norm12, (T) 0.0, eps)) 00285 { 00286 PLB_ASSERT(false); // One of the triangles is degenerate. 00287 } 00288 00289 Array<T,3> cn; 00290 crossProduct(v01, v02, cn); 00291 00292 T norm_cn = sqrt(VectorTemplateImpl<T,3>::normSqr(cn)); 00293 00294 if (util::fpequal(norm_cn, (T) 0.0, eps)) 00295 { 00296 PLB_ASSERT(false); // One of the triangles has zero area. 00297 } 00298 00299 T dot = VectorTemplateImpl<T,3>::scalarProduct(cn,n); 00300 00301 if (dot < 0.0) { 00302 std::swap(triangle[1],triangle[2]); 00303 } 00304 } 00305 00306 template<typename T> 00307 void TriangleSet<T>::translate(Array<T,3> const& vector) 00308 { 00309 T eps = std::numeric_limits<T>::epsilon(); 00310 if (util::fpequal((T) sqrt(VectorTemplateImpl<T,3>::normSqr(vector)), (T) 0.0, eps)) 00311 return; 00312 00313 plint size = triangles.size(); 00314 if (size == 0) 00315 return; 00316 00317 for (plint i = 0; i < size; i++) { 00318 for (int j = 0; j < 3; j++) { 00319 triangles[i][j] += vector; 00320 } 00321 } 00322 00323 boundingCuboid.lowerLeftCorner += vector; 00324 boundingCuboid.upperRightCorner += vector; 00325 } 00326 00327 template<typename T> 00328 void TriangleSet<T>::scale(T alpha) 00329 { 00330 T eps = std::numeric_limits<T>::epsilon(); 00331 if (util::fpequal(alpha, (T) 1.0, eps)) 00332 return; 00333 00334 plint size = triangles.size(); 00335 if (size == 0) 00336 return; 00337 00338 for (plint i = 0; i < size; i++) { 00339 for (int j = 0; j < 3; j++) { 00340 triangles[i][j] *= alpha; 00341 } 00342 } 00343 minEdgeLength *= alpha; 00344 maxEdgeLength *= alpha; 00345 00346 boundingCuboid.lowerLeftCorner *= alpha; 00347 boundingCuboid.upperRightCorner *= alpha; 00348 } 00349 00350 template<typename T> 00351 void TriangleSet<T>::rotateAtOrigin(Array<T,3> const& normedAxis, T theta) { 00352 plint size = (plint)triangles.size(); 00353 for (plint iTriangle = 0; iTriangle < size; iTriangle++) { 00354 for (int iVertex = 0; iVertex < 3; iVertex++) { 00355 triangles[iTriangle][iVertex] = 00356 plb::rotateAtOrigin ( 00357 triangles[iTriangle][iVertex], normedAxis, theta ); 00358 } 00359 } 00360 00361 computeBoundingCuboid(); 00362 } 00363 00364 template<typename T> 00365 void TriangleSet<T>::rotate(T phi, T theta, T psi) 00366 { 00367 T eps = std::numeric_limits<T>::epsilon(); 00368 T pi = acos(-1.0); 00369 00370 PLB_ASSERT((theta > 0.0 || util::fpequal(theta, (T) 0.0, eps)) && 00371 (theta < pi || util::fpequal(theta, pi, eps))); 00372 00373 plint size = triangles.size(); 00374 if (size == 0) 00375 return; 00376 00377 T a[3][3]; 00378 a[0][0] = 1.0; 00379 a[0][1] = 0.0; 00380 a[0][2] = 0.0; 00381 a[1][0] = 0.0; 00382 a[1][1] = cos(theta); 00383 a[1][2] = sin(theta); 00384 a[2][0] = 0.0; 00385 a[2][1] = -sin(theta); 00386 a[2][2] = cos(theta); 00387 00388 T b[3][3]; 00389 b[0][0] = cos(phi); 00390 b[0][1] = sin(phi); 00391 b[0][2] = 0.0; 00392 b[1][0] = -sin(phi); 00393 b[1][1] = cos(phi); 00394 b[1][2] = 0.0; 00395 b[2][0] = 0.0; 00396 b[2][1] = 0.0; 00397 b[2][2] = 1.0; 00398 00399 T c[3][3]; 00400 for (int i = 0; i < 3; i++) { 00401 for (int j = 0; j < 3; j++) { 00402 c[i][j] = 0.0; 00403 for (int k = 0; k < 3; k++) { 00404 c[i][j] += a[i][k]*b[k][j]; 00405 } 00406 } 00407 } 00408 00409 b[0][0] = cos(psi); 00410 b[0][1] = sin(psi); 00411 b[0][2] = 0.0; 00412 b[1][0] = -sin(psi); 00413 b[1][1] = cos(psi); 00414 b[1][2] = 0.0; 00415 b[2][0] = 0.0; 00416 b[2][1] = 0.0; 00417 b[2][2] = 1.0; 00418 00419 for (int i = 0; i < 3; i++) { 00420 for (int j = 0; j < 3; j++) { 00421 a[i][j] = 0.0; 00422 for (int k = 0; k < 3; k++) { 00423 a[i][j] += b[i][k]*c[k][j]; 00424 } 00425 } 00426 } 00427 00428 for (plint iTriangle = 0; iTriangle < size; iTriangle++) { 00429 for (int iVertex = 0; iVertex < 3; iVertex++) { 00430 Array<T,3> x = triangles[iTriangle][iVertex]; 00431 for (int i = 0; i < 3; i++) { 00432 triangles[iTriangle][iVertex][i] = 0.0; 00433 for (int j = 0; j < 3; j++) { 00434 triangles[iTriangle][iVertex][i] += a[i][j]*x[j]; 00435 } 00436 } 00437 } 00438 } 00439 00440 computeBoundingCuboid(); 00441 } 00442 00443 template<typename T> 00444 void TriangleSet<T>::merge(std::vector<TriangleSet<T> > meshes) 00445 { 00446 PLB_ASSERT(meshes.size() != 0); 00447 00448 triangles.assign(meshes[0].getTriangles().begin(), meshes[0].getTriangles().end()); 00449 minEdgeLength = meshes[0].getMinEdgeLength(); 00450 maxEdgeLength = meshes[0].getMaxEdgeLength(); 00451 boundingCuboid = meshes[0].getBoundingCuboid(); 00452 for (plint i = 1; i < meshes.size(); i++) { 00453 triangles.insert(triangles.end(), meshes[i].getTriangles().begin(), meshes[i].getTriangles().end()); 00454 minEdgeLength = std::min(minEdgeLength, meshes[i].getMinEdgeLength()); 00455 maxEdgeLength = std::max(maxEdgeLength, meshes[i].getMaxEdgeLength()); 00456 00457 Cuboid<T> bcuboid = meshes[i].getBoundingCuboid(); 00458 for (plint j = 0; j < 3; j++) { 00459 boundingCuboid.lowerLeftCorner[j] = std::min(boundingCuboid.lowerLeftCorner[j], 00460 bcuboid.lowerLeftCorner[j]); 00461 boundingCuboid.upperRightCorner[j] = std::max(boundingCuboid.upperRightCorner[j], 00462 bcuboid.upperRightCorner[j]); 00463 } 00464 } 00465 } 00466 00467 template<typename T> 00468 void TriangleSet<T>::reverseOrientation() 00469 { 00470 plint size = triangles.size(); 00471 for (plint i = 0; i < size; i++) 00472 std::swap(triangles[i][1],triangles[i][2]); 00473 } 00474 00475 template<typename T> 00476 void TriangleSet<T>::writeAsciiSTL(std::string fname) const 00477 { 00478 if (global::mpi().isMainProcessor()) { 00479 FILE *fp = fopen(fname.c_str(), "w"); 00480 PLB_ASSERT(fp != NULL); 00481 00482 plint size = triangles.size(); 00483 fprintf(fp, "solid plb\n"); 00484 for (plint i = 0; i < size; i++) { 00485 Array<T,3> v0 = triangles[i][0]; 00486 Array<T,3> v1 = triangles[i][1]; 00487 Array<T,3> v2 = triangles[i][2]; 00488 00489 Array<T,3> e01 = v1 - v0; 00490 Array<T,3> e02 = v2 - v0; 00491 00492 Array<T,3> n; 00493 crossProduct(e01, e02, n); 00494 n /= sqrt(VectorTemplateImpl<T,3>::normSqr(n)); 00495 fprintf(fp, " facet normal % e % e % e\n", (double) n[0], (double) n[1], (double) n[2]); 00496 fprintf(fp, " outer loop\n"); 00497 fprintf(fp, " vertex % e % e % e\n", (double) v0[0], (double) v0[1], (double) v0[2]); 00498 fprintf(fp, " vertex % e % e % e\n", (double) v1[0], (double) v1[1], (double) v1[2]); 00499 fprintf(fp, " vertex % e % e % e\n", (double) v2[0], (double) v2[1], (double) v2[2]); 00500 fprintf(fp, " endloop\n"); 00501 fprintf(fp, " endfacet\n"); 00502 } 00503 fprintf(fp, "endsolid plb\n"); 00504 fclose(fp); 00505 } 00506 } 00507 00508 template<typename T> 00509 void TriangleSet<T>::writeBinarySTL(std::string fname) const 00510 { 00511 if (global::mpi().isMainProcessor()) { 00512 FILE *fp = fopen(fname.c_str(), "wb"); 00513 PLB_ASSERT(fp != NULL); 00514 00515 unsigned int nt = triangles.size(); 00516 unsigned short abc = 0; 00517 char buf[80]; 00518 00519 for (int i = 0; i < 80; i++) 00520 buf[i] = '\0'; 00521 00522 fwrite(buf, sizeof(char), 80, fp); 00523 fwrite(&nt, sizeof(unsigned int), 1, fp); 00524 for (plint i = 0; i < nt; i++) { 00525 Array<T,3> v0 = triangles[i][0]; 00526 Array<T,3> v1 = triangles[i][1]; 00527 Array<T,3> v2 = triangles[i][2]; 00528 00529 Array<T,3> e01 = v1 - v0; 00530 Array<T,3> e02 = v2 - v0; 00531 00532 Array<T,3> nrml; 00533 crossProduct(e01, e02, nrml); 00534 nrml /= sqrt(VectorTemplateImpl<T,3>::normSqr(nrml)); 00535 00536 float n[3]; 00537 n[0] = nrml[0]; 00538 n[1] = nrml[1]; 00539 n[2] = nrml[2]; 00540 fwrite((void *) n, sizeof(float), 3, fp); 00541 float v[3]; 00542 v[0] = v0[0]; 00543 v[1] = v0[1]; 00544 v[2] = v0[2]; 00545 fwrite((void *) v, sizeof(float), 3, fp); 00546 v[0] = v1[0]; 00547 v[1] = v1[1]; 00548 v[2] = v1[2]; 00549 fwrite((void *) v, sizeof(float), 3, fp); 00550 v[0] = v2[0]; 00551 v[1] = v2[1]; 00552 v[2] = v2[2]; 00553 fwrite((void *) v, sizeof(float), 3, fp); 00554 fwrite(&abc, sizeof(unsigned short), 1, fp); 00555 } 00556 00557 fclose(fp); 00558 } 00559 } 00560 00561 template<typename T> 00562 int TriangleSet<T>::cutTriangleWithPlane(Plane<T> const& plane, Triangle const& triangle, 00563 TriangleSet<T>& newTriangleSet) const 00564 { 00565 T epsilon = getEpsilon<T>(precision); 00566 00567 int vertexTags[3]; 00568 00569 // Tag the triangle vertices. 00570 for (int iVertex = 0; iVertex < 3; iVertex++) { 00571 Array<T,3> tmp = triangle[iVertex] - plane.point; 00572 T norm_tmp = norm(tmp); 00573 if (norm_tmp > epsilon) { 00574 tmp /= norm_tmp; 00575 } else { 00576 tmp[0] = tmp[1] = tmp[2] = 0.0; 00577 } 00578 T dotp = dot(tmp, plane.normal); 00579 if (fabs(dotp) <= epsilon) { 00580 vertexTags[iVertex] = 0; 00581 } else if (dotp > 0.0 && fabs(dotp) > epsilon) { 00582 vertexTags[iVertex] = -1; 00583 } else if (dotp < 0.0 && fabs(dotp) > epsilon) { 00584 vertexTags[iVertex] = 1; 00585 } else { 00586 return -1; 00587 } 00588 } 00589 00590 // All three vertices belong to one side of the cut plane. 00591 if (vertexTags[0] == 1 && vertexTags[1] == 1 && vertexTags[2] == 1) { 00592 newTriangleSet.triangles.push_back(triangle); 00593 return 1; 00594 } else if (vertexTags[0] == -1 && vertexTags[1] == -1 && vertexTags[2] == -1) { 00595 return 0; 00596 } 00597 00598 // One vertex belongs to one side of the cut plane and the other two vertices 00599 // belong to the other side. 00600 for (int i = 0; i < 3; i++) { 00601 int j = (i + 1) != 3 ? (i + 1) : 0; 00602 int k = (j + 1) != 3 ? (j + 1) : 0; 00603 00604 if (vertexTags[i] == 1 && vertexTags[j] == -1 && vertexTags[k] == -1) { 00605 Array<T,3> intersection_ij(0.0, 0.0, 0.0), intersection_ik(0.0, 0.0, 0.0); 00606 int rv = 0; 00607 rv = lineIntersectionWithPlane<T>(plane, triangle[i], triangle[j], precision, intersection_ij); 00608 if (rv != 1) { 00609 return -1; 00610 } 00611 rv = lineIntersectionWithPlane<T>(plane, triangle[i], triangle[k], precision, intersection_ik); 00612 if (rv != 1) { 00613 return -1; 00614 } 00615 Triangle newTriangle(triangle[i], intersection_ij, intersection_ik); 00616 newTriangleSet.triangles.push_back(newTriangle); 00617 return 1; 00618 } else if (vertexTags[i] == -1 && vertexTags[j] == 1 && vertexTags[k] == 1) { 00619 Array<T,3> intersection_ij(0.0, 0.0, 0.0), intersection_ik(0.0, 0.0, 0.0); 00620 int rv = 0; 00621 rv = lineIntersectionWithPlane<T>(plane, triangle[i], triangle[j], precision, intersection_ij); 00622 if (rv != 1) { 00623 return -1; 00624 } 00625 rv = lineIntersectionWithPlane<T>(plane, triangle[i], triangle[k], precision, intersection_ik); 00626 if (rv != 1) { 00627 return -1; 00628 } 00629 Triangle newTriangle_0(triangle[k], intersection_ij, triangle[j]); 00630 Triangle newTriangle_1(triangle[k], intersection_ik, intersection_ij); 00631 newTriangleSet.triangles.push_back(newTriangle_0); 00632 newTriangleSet.triangles.push_back(newTriangle_1); 00633 return 1; 00634 } 00635 } 00636 00637 // Only one vertex belongs to the cut plane. 00638 for (int i = 0; i < 3; i++) { 00639 int j = (i + 1) != 3 ? (i + 1) : 0; 00640 int k = (j + 1) != 3 ? (j + 1) : 0; 00641 00642 if (vertexTags[i] == 0) { 00643 if (vertexTags[j] == 1 && vertexTags[k] == 1) { 00644 newTriangleSet.triangles.push_back(triangle); 00645 return 1; 00646 } else if (vertexTags[j] == -1 && vertexTags[k] == -1) { 00647 return 0; 00648 } else if (vertexTags[j] == 1 && vertexTags[k] == -1) { 00649 Array<T,3> intersection(0.0, 0.0, 0.0); 00650 int rv = 0; 00651 rv = lineIntersectionWithPlane<T>(plane, triangle[j], triangle[k], precision, intersection); 00652 if (rv != 1) { 00653 return -1; 00654 } 00655 Triangle newTriangle(triangle[i], triangle[j], intersection); 00656 newTriangleSet.triangles.push_back(newTriangle); 00657 return 1; 00658 } else if (vertexTags[j] == -1 && vertexTags[k] == 1) { 00659 Array<T,3> intersection(0.0, 0.0, 0.0); 00660 int rv = 0; 00661 rv = lineIntersectionWithPlane<T>(plane, triangle[j], triangle[k], precision, intersection); 00662 if (rv != 1) { 00663 return -1; 00664 } 00665 Triangle newTriangle(triangle[i], intersection, triangle[k]); 00666 newTriangleSet.triangles.push_back(newTriangle); 00667 return 1; 00668 } 00669 } 00670 } 00671 00672 // Only two of the three vertices belong to the cut plane. 00673 for (int i = 0; i < 3; i++) { 00674 int j = (i + 1) != 3 ? (i + 1) : 0; 00675 int k = (j + 1) != 3 ? (j + 1) : 0; 00676 00677 if (vertexTags[i] == 0 && vertexTags[j] == 0) { 00678 if (vertexTags[k] == 1) { 00679 newTriangleSet.triangles.push_back(triangle); 00680 return 1; 00681 } else if (vertexTags[k] == -1) { 00682 return 0; 00683 } 00684 } 00685 } 00686 00687 // All 3 vertices belong to the cut plane. 00688 if (vertexTags[0] == 0 && vertexTags[1] == 0 && vertexTags[2] == 0) { 00689 newTriangleSet.triangles.push_back(triangle); 00690 return 1; 00691 } 00692 00693 return -1; 00694 } 00695 00696 template<typename T> 00697 int TriangleSet<T>::cutWithPlane(Plane<T> const& plane, TriangleSet<T>& newTriangleSet) const 00698 { 00699 T epsilon = getEpsilon<T>(precision); 00700 00701 T norm_normal = norm(plane.normal); 00702 PLB_ASSERT(norm_normal > epsilon); // The cut plane normal vector cannot have zero magnitude. 00703 Plane<T> newPlane; 00704 newPlane.point = plane.point; 00705 newPlane.normal = plane.normal / norm_normal; 00706 00707 newTriangleSet.triangles.resize(0); 00708 00709 newTriangleSet.precision = precision; 00710 00711 for (pluint iTriangle = 0; iTriangle < triangles.size(); iTriangle++) { 00712 if (cutTriangleWithPlane(newPlane, triangles[iTriangle], newTriangleSet) == -1) { 00713 return -1; 00714 } 00715 } 00716 00717 if (newTriangleSet.triangles.size() != 0) { 00718 newTriangleSet.computeMinMaxEdges(); 00719 newTriangleSet.computeBoundingCuboid(); 00720 } 00721 00722 if (newTriangleSet.triangles.size() == 0 || newTriangleSet.triangles.size() == triangles.size()) { 00723 return 0; 00724 } 00725 00726 return 1; 00727 } 00728 00729 template<typename T> 00730 int TriangleSet<T>::cutWithPlane ( 00731 Plane<T> const& plane, Cuboid<T> const& cuboid, TriangleSet<T>& newTriangleSet ) const 00732 { 00733 T epsilon = getEpsilon<T>(precision); 00734 00735 T norm_normal = norm(plane.normal); 00736 PLB_ASSERT(norm_normal > epsilon); // The cut plane normal vector cannot have zero magnitude. 00737 Plane<T> newPlane; 00738 newPlane.point = plane.point; 00739 newPlane.normal = plane.normal / norm_normal; 00740 00741 T norm_diagonal = norm(cuboid.upperRightCorner - cuboid.lowerLeftCorner); 00742 PLB_ASSERT(norm_diagonal > epsilon); // The diagonal of the cuboid cannot have zero length. 00743 00744 newTriangleSet.triangles.resize(0); 00745 00746 newTriangleSet.precision = precision; 00747 00748 for (pluint iTriangle = 0; iTriangle < triangles.size(); iTriangle++) { 00749 Triangle const& triangle = triangles[iTriangle]; 00750 00751 Array<T,3> vertices[3]; 00752 vertices[0] = triangle[0]; 00753 vertices[1] = triangle[1]; 00754 vertices[2] = triangle[2]; 00755 00756 // Check if the triangle is fully contained in the cuboid. 00757 int isNotFullyContained = 0; 00758 for (int iVertex = 0; iVertex < 3; iVertex++) { 00759 Array<T,3> diff_l; 00760 diff_l = vertices[iVertex] - cuboid.lowerLeftCorner; 00761 00762 Array<T,3> diff_u; 00763 diff_u = vertices[iVertex] - cuboid.upperRightCorner; 00764 00765 if ((diff_l[0] < 0.0 && fabs(diff_l[0]) > epsilon) || 00766 (diff_l[1] < 0.0 && fabs(diff_l[1]) > epsilon) || 00767 (diff_l[2] < 0.0 && fabs(diff_l[2]) > epsilon) || 00768 (diff_u[0] > 0.0 && fabs(diff_u[0]) > epsilon) || 00769 (diff_u[1] > 0.0 && fabs(diff_u[1]) > epsilon) || 00770 (diff_u[2] > 0.0 && fabs(diff_u[2]) > epsilon)) { 00771 isNotFullyContained = 1; 00772 break; 00773 } 00774 } 00775 00776 if (isNotFullyContained) { 00777 newTriangleSet.triangles.push_back(triangle); 00778 continue; 00779 } 00780 00781 if (cutTriangleWithPlane(newPlane, triangle, newTriangleSet) == -1) 00782 return -1; 00783 } 00784 00785 if (newTriangleSet.triangles.size() != 0) { 00786 newTriangleSet.computeMinMaxEdges(); 00787 newTriangleSet.computeBoundingCuboid(); 00788 } 00789 00790 if (newTriangleSet.triangles.size() == 0 || newTriangleSet.triangles.size() == triangles.size()) { 00791 return 0; 00792 } 00793 00794 return 1; 00795 } 00796 00797 template<typename T> 00798 void TriangleSet<T>::computeMinMaxEdges() { 00799 T nextMin, nextMax; 00800 for (pluint i=0; i<triangles.size(); ++i) { 00801 computeMinMaxEdge(i, nextMin, nextMax); 00802 minEdgeLength = std::min(minEdgeLength, nextMin); 00803 maxEdgeLength = std::max(maxEdgeLength, nextMax); 00804 } 00805 } 00806 00807 template<typename T> 00808 void TriangleSet<T>::computeMinMaxEdge(pluint iTriangle, T& minEdge, T& maxEdge) const { 00809 PLB_ASSERT( iTriangle<triangles.size() ); 00810 Triangle const& triangle = triangles[iTriangle]; 00811 T edge1 = norm(triangle[1]-triangle[0]); 00812 T edge2 = norm(triangle[2]-triangle[1]); 00813 T edge3 = norm(triangle[0]-triangle[2]); 00814 minEdge = std::min(edge1, std::min(edge2, edge3)); 00815 maxEdge = std::max(edge1, std::max(edge2, edge3)); 00816 } 00817 00818 template<typename T> 00819 void TriangleSet<T>::computeBoundingCuboid() { 00820 T xMin, yMin, zMin; 00821 T xMax, yMax, zMax; 00822 00823 xMin = yMin = zMin = std::numeric_limits<T>::max(); 00824 xMax = yMax = zMax = -std::numeric_limits<T>::max(); 00825 for (pluint i=0; i<triangles.size(); ++i) { 00826 Triangle const& triangle = triangles[i]; 00827 00828 xMin = std::min(xMin, std::min(triangle[0][0], std::min(triangle[1][0], triangle[2][0]))); 00829 yMin = std::min(yMin, std::min(triangle[0][1], std::min(triangle[1][1], triangle[2][1]))); 00830 zMin = std::min(zMin, std::min(triangle[0][2], std::min(triangle[1][2], triangle[2][2]))); 00831 00832 xMax = std::max(xMax, std::max(triangle[0][0], std::max(triangle[1][0], triangle[2][0]))); 00833 yMax = std::max(yMax, std::max(triangle[0][1], std::max(triangle[1][1], triangle[2][1]))); 00834 zMax = std::max(zMax, std::max(triangle[0][2], std::max(triangle[1][2], triangle[2][2]))); 00835 } 00836 boundingCuboid.lowerLeftCorner = Array<T,3>(xMin, yMin, zMin); 00837 boundingCuboid.upperRightCorner = Array<T,3>(xMax, yMax, zMax); 00838 } 00839 00840 } // namespace plb 00841 00842 #endif // TRIANGLE_SET_HH
1.6.3
1.6.3