00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "faceCollapser.H"
00029 #include <OpenFOAM/polyMesh.H>
00030 #include "polyTopoChange.H"
00031 #include <dynamicMesh/polyModifyPoint.H>
00032 #include <dynamicMesh/polyModifyFace.H>
00033 #include <dynamicMesh/polyRemoveFace.H>
00034 #include <OpenFOAM/SortableList.H>
00035 #include <meshTools/meshTools.H>
00036 #include <OpenFOAM/OFstream.H>
00037
00038
00039
00040
00041
00042 void Foam::faceCollapser::insert
00043 (
00044 const labelList& elems,
00045 const label excludeElem,
00046 labelHashSet& set
00047 )
00048 {
00049 forAll(elems, i)
00050 {
00051 if (elems[i] != excludeElem)
00052 {
00053 set.insert(elems[i]);
00054 }
00055 }
00056 }
00057
00058
00059
00060 Foam::label Foam::faceCollapser::findEdge
00061 (
00062 const edgeList& edges,
00063 const labelList& edgeLabels,
00064 const label v0,
00065 const label v1
00066 )
00067 {
00068 forAll(edgeLabels, i)
00069 {
00070 label edgeI = edgeLabels[i];
00071
00072 const edge& e = edges[edgeI];
00073
00074 if
00075 (
00076 (e[0] == v0 && e[1] == v1)
00077 || (e[0] == v1 && e[1] == v0)
00078 )
00079 {
00080 return edgeI;
00081 }
00082 }
00083
00084 FatalErrorIn("findEdge") << "Cannot find edge between vertices " << v0
00085 << " and " << v1 << " in edge labels " << edgeLabels
00086 << abort(FatalError);
00087
00088 return -1;
00089 }
00090
00091
00092
00093
00094
00095 void Foam::faceCollapser::filterFace
00096 (
00097 const Map<labelList>& splitEdges,
00098 const label faceI,
00099 polyTopoChange& meshMod
00100 ) const
00101 {
00102 const face& f = mesh_.faces()[faceI];
00103 const labelList& fEdges = mesh_.faceEdges()[faceI];
00104
00105
00106 DynamicList<label> newFace(10 * f.size());
00107
00108 forAll(f, fp)
00109 {
00110 label v0 = f[fp];
00111
00112 newFace.append(v0);
00113
00114
00115 label fp1 = f.fcIndex(fp);
00116
00117 label v1 = f[fp1];
00118
00119
00120 label edgeI = findEdge(mesh_.edges(), fEdges, v0, v1);
00121
00122 Map<labelList>::const_iterator edgeFnd =
00123 splitEdges.find(edgeI);
00124
00125 if (edgeFnd != splitEdges.end())
00126 {
00127
00128
00129
00130
00131 const labelList& extraVerts = edgeFnd();
00132
00133 if (v0 == mesh_.edges()[edgeI].start())
00134 {
00135 forAll(extraVerts, i)
00136 {
00137 newFace.append(extraVerts[i]);
00138 }
00139 }
00140 else
00141 {
00142 forAllReverse(extraVerts, i)
00143 {
00144 newFace.append(extraVerts[i]);
00145 }
00146 }
00147 }
00148 }
00149 face newF(newFace.shrink());
00150
00151
00152
00153
00154 if (newF != f)
00155 {
00156 label nei = -1;
00157
00158 label patchI = -1;
00159
00160 if (mesh_.isInternalFace(faceI))
00161 {
00162 nei = mesh_.faceNeighbour()[faceI];
00163 }
00164 else
00165 {
00166 patchI = mesh_.boundaryMesh().whichPatch(faceI);
00167 }
00168
00169
00170 label zoneID = mesh_.faceZones().whichZone(faceI);
00171
00172 bool zoneFlip = false;
00173
00174 if (zoneID >= 0)
00175 {
00176 const faceZone& fZone = mesh_.faceZones()[zoneID];
00177
00178 zoneFlip = fZone.flipMap()[fZone.whichFace(faceI)];
00179 }
00180
00181 meshMod.setAction
00182 (
00183 polyModifyFace
00184 (
00185 newF,
00186 faceI,
00187 mesh_.faceOwner()[faceI],
00188 nei,
00189 false,
00190 patchI,
00191 false,
00192 zoneID,
00193 zoneFlip
00194 )
00195 );
00196 }
00197 }
00198
00199
00200
00201
00202
00203 Foam::faceCollapser::faceCollapser(const polyMesh& mesh)
00204 :
00205 mesh_(mesh)
00206 {}
00207
00208
00209
00210
00211 void Foam::faceCollapser::setRefinement
00212 (
00213 const labelList& faceLabels,
00214 const labelList& fpStart,
00215 const labelList& fpEnd,
00216 polyTopoChange& meshMod
00217 ) const
00218 {
00219 const pointField& points = mesh_.points();
00220 const edgeList& edges = mesh_.edges();
00221 const faceList& faces = mesh_.faces();
00222 const labelListList& edgeFaces = mesh_.edgeFaces();
00223
00224
00225
00226
00227 Map<labelList> splitEdges(faceLabels.size());
00228
00229
00230
00231 labelHashSet affectedFaces(4*faceLabels.size());
00232
00233
00234
00235
00236
00237
00238 forAll(faceLabels, i)
00239 {
00240 const label faceI = faceLabels[i];
00241
00242 const face& f = faces[faceI];
00243
00244 const label fpA = fpStart[i];
00245 const label fpB = fpEnd[i];
00246
00247 const point& pA = points[f[fpA]];
00248 const point& pB = points[f[fpB]];
00249
00250 Pout<< "Face:" << f << " collapsed to fp:" << fpA << ' ' << fpB
00251 << " with points:" << pA << ' ' << pB
00252 << endl;
00253
00254
00255 linePointRef lineAB(pA, pB);
00256
00257
00258
00259
00260 SortableList<scalar> dist(f.size());
00261
00262 dist[fpA] = 0;
00263 dist[fpB] = magSqr(pB - pA);
00264
00265
00266
00267
00268
00269 label fpMin1 = fpA;
00270 label fp = f.fcIndex(fpMin1);
00271
00272 while (fp != fpB)
00273 {
00274
00275 pointHit near = lineAB.nearestDist(points[f[fp]]);
00276
00277 scalar w = magSqr(near.rawPoint() - pA);
00278
00279 if (w <= dist[fpMin1])
00280 {
00281
00282 w = dist[fpMin1] + 1E-6*(dist[fpB] - dist[fpA]);
00283
00284 point newPoint
00285 (
00286 pA + Foam::sqrt(w / (dist[fpB] - dist[fpA]))*(pB - pA)
00287 );
00288
00289 Pout<< "Adapting position of vertex " << f[fp] << " on face "
00290 << f << " from " << near.rawPoint() << " to " << newPoint
00291 << endl;
00292
00293 near.setPoint(newPoint);
00294 }
00295
00296
00297
00298
00299 meshMod.setAction
00300 (
00301 polyModifyPoint
00302 (
00303 f[fp],
00304 near.rawPoint(),
00305 false,
00306 -1,
00307 true
00308 )
00309 );
00310
00311 dist[fp] = w;
00312
00313
00314 fpMin1 = fp;
00315 fp = f.fcIndex(fpMin1);
00316 }
00317
00318
00319
00320
00321
00322 fpMin1 = fpA;
00323 fp = f.rcIndex(fpMin1);
00324
00325 while (fp != fpB)
00326 {
00327
00328 pointHit near = lineAB.nearestDist(points[f[fp]]);
00329
00330 scalar w = magSqr(near.rawPoint() - pA);
00331
00332 if (w <= dist[fpMin1])
00333 {
00334
00335 w = dist[fpMin1] + 1E-6*(dist[fpB] - dist[fpA]);
00336
00337 point newPoint
00338 (
00339 pA + Foam::sqrt(w / (dist[fpB] - dist[fpA]))*(pB - pA)
00340 );
00341
00342 Pout<< "Adapting position of vertex " << f[fp] << " on face "
00343 << f << " from " << near.rawPoint() << " to " << newPoint
00344 << endl;
00345
00346 near.setPoint(newPoint);
00347 }
00348
00349
00350
00351
00352 meshMod.setAction
00353 (
00354 polyModifyPoint
00355 (
00356 f[fp],
00357 near.rawPoint(),
00358 false,
00359 -1,
00360 true
00361 )
00362 );
00363
00364 dist[fp] = w;
00365
00366
00367 fpMin1 = fp;
00368 fp = f.rcIndex(fpMin1);
00369 }
00370
00371 dist.sort();
00372
00373
00374 if (dist.indices()[dist.size()-1] != fpB)
00375 {
00376 OFstream str("conflictingFace.obj");
00377 meshTools::writeOBJ(str, faceList(1, f), points);
00378
00379 FatalErrorIn("faceCollapser::setRefinement")
00380 << "Trying to collapse face:" << faceI << " vertices:" << f
00381 << " to edges between vertices " << f[fpA] << " and "
00382 << f[fpB] << " but " << f[fpB] << " does not seem to be the"
00383 << " vertex furthest away from " << f[fpA] << endl
00384 << "Dumped conflicting face to obj file conflictingFace.obj"
00385 << abort(FatalError);
00386 }
00387
00388
00389
00390 Pout<< "Face:" << f << " fpA:" << fpA << " fpB:" << fpB << nl;
00391
00392 labelList sortedFp(f.size());
00393 forAll(dist.indices(), i)
00394 {
00395 label fp = dist.indices()[i];
00396
00397 Pout<< " fp:" << fp << " distance:" << dist[i] << nl;
00398
00399 sortedFp[fp] = i;
00400 }
00401
00402 const labelList& fEdges = mesh_.faceEdges()[faceI];
00403
00404
00405
00406
00407
00408
00409
00410 forAll(f, fp)
00411 {
00412 label fp1 = f.fcIndex(fp);
00413
00414
00415 label sorted0 = sortedFp[fp];
00416 label sorted1 = sortedFp[fp1];
00417
00418
00419 DynamicList<label> edgePoints(f.size());
00420
00421
00422 bool fpToFp1;
00423
00424 if (sorted0 < sorted1)
00425 {
00426 fpToFp1 = true;
00427
00428 for (label j = sorted0+1; j < sorted1; j++)
00429 {
00430 edgePoints.append(f[dist.indices()[j]]);
00431 }
00432 }
00433 else
00434 {
00435 fpToFp1 = false;
00436
00437 for (label j = sorted1+1; j < sorted0; j++)
00438 {
00439 edgePoints.append(f[dist.indices()[j]]);
00440 }
00441 }
00442
00443 if (edgePoints.size())
00444 {
00445 edgePoints.shrink();
00446
00447 label edgeI = findEdge(edges, fEdges, f[fp], f[fp1]);
00448
00449 const edge& e = edges[edgeI];
00450
00451 if (fpToFp1 == (f[fp] == e.start()))
00452 {
00453 splitEdges.insert(edgeI, edgePoints);
00454 }
00455 else
00456 {
00457 reverse(edgePoints);
00458 splitEdges.insert(edgeI, edgePoints);
00459 }
00460
00461
00462 insert(edgeFaces[edgeI], faceI, affectedFaces);
00463 }
00464 }
00465 }
00466
00467 for
00468 (
00469 Map<labelList>::const_iterator iter = splitEdges.begin();
00470 iter != splitEdges.end();
00471 ++iter
00472 )
00473 {
00474 Pout<< "Split edge:" << iter.key()
00475 << " verts:" << mesh_.edges()[iter.key()]
00476 << " in:" << nl;
00477 const labelList& edgePoints = iter();
00478
00479 forAll(edgePoints, i)
00480 {
00481 Pout<< " " << edgePoints[i] << nl;
00482 }
00483 }
00484
00485
00486
00487
00488
00489
00490 forAll(faceLabels, i)
00491 {
00492 const label faceI = faceLabels[i];
00493
00494 meshMod.setAction(polyRemoveFace(faceI));
00495
00496
00497 affectedFaces.erase(faceI);
00498 }
00499
00500
00501
00502
00503
00504
00505 for
00506 (
00507 labelHashSet::const_iterator iter = affectedFaces.begin();
00508 iter != affectedFaces.end();
00509 ++iter
00510 )
00511 {
00512 filterFace(splitEdges, iter.key(), meshMod);
00513 }
00514 }
00515
00516
00517