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
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082 #include <OpenFOAM/argList.H>
00083 #include <triSurface/triSurface.H>
00084 #include <OpenFOAM/OFstream.H>
00085 #include <OpenFOAM/ListOps.H>
00086 #include <meshTools/triSurfaceTools.H>
00087
00088 using namespace Foam;
00089
00090
00091
00092 void writeOBJ(Ostream& os, const pointField& pts)
00093 {
00094 forAll(pts, i)
00095 {
00096 const point& pt = pts[i];
00097
00098 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
00099 }
00100 }
00101
00102
00103 void dumpPoints(const triSurface& surf, const labelList& borderPoint)
00104 {
00105 fileName fName("borderPoints.obj");
00106
00107 Info<< "Dumping borderPoints as Lightwave .obj file to " << fName
00108 << "\nThis can be visualized with e.g. javaview (www.javaview.de)\n\n";
00109
00110 OFstream os(fName);
00111
00112 forAll(borderPoint, pointI)
00113 {
00114 if (borderPoint[pointI] != -1)
00115 {
00116 const point& pt = surf.localPoints()[pointI];
00117
00118 os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
00119 }
00120 }
00121 }
00122
00123
00124 void dumpEdges(const triSurface& surf, const boolList& borderEdge)
00125 {
00126 fileName fName("borderEdges.obj");
00127
00128 Info<< "Dumping borderEdges as Lightwave .obj file to " << fName
00129 << "\nThis can be visualized with e.g. javaview (www.javaview.de)\n\n";
00130
00131 OFstream os(fName);
00132
00133 writeOBJ(os, surf.localPoints());
00134
00135 forAll(borderEdge, edgeI)
00136 {
00137 if (borderEdge[edgeI])
00138 {
00139 const edge& e = surf.edges()[edgeI];
00140
00141 os << "l " << e.start()+1 << ' ' << e.end()+1 << endl;
00142 }
00143 }
00144 }
00145
00146
00147 void dumpFaces
00148 (
00149 const fileName& fName,
00150 const triSurface& surf,
00151 const Map<label>& connectedFaces
00152 )
00153 {
00154 Info<< "Dumping connectedFaces as Lightwave .obj file to " << fName
00155 << "\nThis can be visualized with e.g. javaview (www.javaview.de)\n\n";
00156
00157 OFstream os(fName);
00158
00159 for
00160 (
00161 Map<label>::const_iterator iter = connectedFaces.begin();
00162 iter != connectedFaces.end();
00163 ++iter
00164 )
00165 {
00166 const labelledTri& f = surf.localFaces()[iter.key()];
00167
00168 point ctr(f.centre(surf.localPoints()));
00169
00170 os << "v " << ctr.x() << ' ' << ctr.y() << ' ' << ctr.z() << endl;
00171 }
00172 }
00173
00174
00175 void testSortedEdgeFaces(const triSurface& surf)
00176 {
00177 const labelListList& edgeFaces = surf.edgeFaces();
00178 const labelListList& sortedEdgeFaces = surf.sortedEdgeFaces();
00179
00180 forAll(edgeFaces, edgeI)
00181 {
00182 const labelList& myFaces = edgeFaces[edgeI];
00183 const labelList& sortMyFaces = sortedEdgeFaces[edgeI];
00184
00185 forAll(myFaces, i)
00186 {
00187 if (findIndex(sortMyFaces, myFaces[i]) == -1)
00188 {
00189 FatalErrorIn("testSortedEdgeFaces(..)") << abort(FatalError);
00190 }
00191 }
00192 forAll(sortMyFaces, i)
00193 {
00194 if (findIndex(myFaces, sortMyFaces[i]) == -1)
00195 {
00196 FatalErrorIn("testSortedEdgeFaces(..)") << abort(FatalError);
00197 }
00198 }
00199 }
00200 }
00201
00202
00203
00204 label markBorderEdges
00205 (
00206 const bool debug,
00207 const triSurface& surf,
00208 boolList& borderEdge
00209 )
00210 {
00211 label nBorderEdges = 0;
00212
00213 const labelListList& edgeFaces = surf.edgeFaces();
00214
00215 forAll(edgeFaces, edgeI)
00216 {
00217 if (edgeFaces[edgeI].size() == 4)
00218 {
00219 borderEdge[edgeI] = true;
00220
00221 nBorderEdges++;
00222 }
00223 }
00224
00225 if (debug)
00226 {
00227 dumpEdges(surf, borderEdge);
00228 }
00229
00230 return nBorderEdges;
00231 }
00232
00233
00234
00235
00236 label markBorderPoints
00237 (
00238 const bool debug,
00239 const triSurface& surf,
00240 const boolList& borderEdge,
00241 labelList& borderPoint
00242 )
00243 {
00244 label nPoints = surf.nPoints();
00245
00246 const labelListList& pointEdges = surf.pointEdges();
00247
00248 forAll(pointEdges, pointI)
00249 {
00250 const labelList& pEdges = pointEdges[pointI];
00251
00252 label nBorderEdges = 0;
00253
00254 forAll(pEdges, i)
00255 {
00256 if (borderEdge[pEdges[i]])
00257 {
00258 nBorderEdges++;
00259 }
00260 }
00261
00262 if (nBorderEdges == 2 && borderPoint[pointI] == -1)
00263 {
00264 borderPoint[pointI] = nPoints++;
00265 }
00266 }
00267
00268 label nBorderPoints = nPoints - surf.nPoints();
00269
00270 if (debug)
00271 {
00272 dumpPoints(surf, borderPoint);
00273 }
00274
00275 return nBorderPoints;
00276 }
00277
00278
00279
00280
00281 scalar minEdgeLen(const triSurface& surf, const label pointI)
00282 {
00283 const pointField& points = surf.localPoints();
00284
00285 const labelList& pEdges = surf.pointEdges()[pointI];
00286
00287 scalar minLen = GREAT;
00288
00289 forAll(pEdges, i)
00290 {
00291 label edgeI = pEdges[i];
00292
00293 scalar len = surf.edges()[edgeI].mag(points);
00294
00295 if (len < minLen)
00296 {
00297 minLen = len;
00298 }
00299 }
00300 return minLen;
00301 }
00302
00303
00304
00305 label findEdge
00306 (
00307 const triSurface& surf,
00308 const labelList& edgeLabels,
00309 const label v0,
00310 const label v1
00311 )
00312 {
00313 forAll(edgeLabels, i)
00314 {
00315 label edgeI = edgeLabels[i];
00316
00317 const edge& e = surf.edges()[edgeI];
00318
00319 if
00320 (
00321 (
00322 e.start() == v0
00323 && e.end() == v1
00324 )
00325 || (
00326 e.start() == v1
00327 && e.end() == v0
00328 )
00329 )
00330 {
00331 return edgeI;
00332 }
00333 }
00334
00335
00336 FatalErrorIn("findEdge(..)") << "Cannot find edge with labels " << v0
00337 << ' ' << v1 << " in candidates " << edgeLabels
00338 << " with vertices:" << UIndirectList<edge>(surf.edges(), edgeLabels)()
00339 << abort(FatalError);
00340
00341 return -1;
00342 }
00343
00344
00345
00346 label otherEdge
00347 (
00348 const triSurface& surf,
00349 const label faceI,
00350 const label otherEdgeI,
00351 const label pointI
00352 )
00353 {
00354 const labelList& fEdges = surf.faceEdges()[faceI];
00355
00356 forAll(fEdges, i)
00357 {
00358 label edgeI = fEdges[i];
00359
00360 const edge& e = surf.edges()[edgeI];
00361
00362 if
00363 (
00364 edgeI != otherEdgeI
00365 && (
00366 e.start() == pointI
00367 || e.end() == pointI
00368 )
00369 )
00370 {
00371 return edgeI;
00372 }
00373 }
00374
00375 FatalErrorIn("otherEdge(..)") << "Cannot find other edge on face " << faceI
00376 << " verts:" << surf.localPoints()[faceI]
00377 << " connected to point " << pointI
00378 << " faceEdges:" << UIndirectList<edge>(surf.edges(), fEdges)()
00379 << abort(FatalError);
00380
00381 return -1;
00382 }
00383
00384
00385
00386
00387
00388 void walkSplitLine
00389 (
00390 const triSurface& surf,
00391 const boolList& borderEdge,
00392 const labelList& borderPoint,
00393
00394 const label startFaceI,
00395 const label startEdgeI,
00396 const label startPointI,
00397
00398 Map<label>& faceToEdge,
00399 Map<label>& faceToPoint
00400 )
00401 {
00402 label faceI = startFaceI;
00403 label edgeI = startEdgeI;
00404 label pointI = startPointI;
00405
00406 do
00407 {
00408
00409
00410
00411
00412 do
00413 {
00414
00415 edgeI = otherEdge(surf, faceI, edgeI, pointI);
00416
00417 if (borderEdge[edgeI])
00418 {
00419 if (!faceToEdge.insert(faceI, edgeI))
00420 {
00421
00422 return;
00423 }
00424 else
00425 {
00426
00427 break;
00428 }
00429 }
00430 else if (!faceToPoint.insert(faceI, pointI))
00431 {
00432
00433 return;
00434 }
00435
00436
00437 const labelList& eFaces = surf.edgeFaces()[edgeI];
00438
00439 if (eFaces.size() != 2)
00440 {
00441 FatalErrorIn("walkSplitPoint(..)")
00442 << "Can only handle edges with 2 or 4 edges for now."
00443 << abort(FatalError);
00444 }
00445
00446 if (eFaces[0] == faceI)
00447 {
00448 faceI = eFaces[1];
00449 }
00450 else if (eFaces[1] == faceI)
00451 {
00452 faceI = eFaces[0];
00453 }
00454 else
00455 {
00456 FatalErrorIn("walkSplitPoint(..)") << abort(FatalError);
00457 }
00458 }
00459 while (true);
00460
00461
00462
00463
00464
00465
00466 pointI = surf.edges()[edgeI].otherVertex(pointI);
00467
00468 if (borderPoint[pointI] == -1)
00469 {
00470 return;
00471 }
00472
00473 }
00474 while (true);
00475 }
00476
00477
00478
00479
00480 label sharedFace
00481 (
00482 const triSurface& surf,
00483 const label firstFaceI,
00484 const label sharedEdgeI
00485 )
00486 {
00487
00488
00489 const edge& e = surf.edges()[sharedEdgeI];
00490
00491 const labelledTri& f = surf.localFaces()[firstFaceI];
00492
00493 label startIndex = findIndex(f, e.start());
00494
00495
00496 bool edgeOrder = (f[f.fcIndex(startIndex)] == e.end());
00497
00498
00499
00500
00501 const labelList& eFaces = surf.sortedEdgeFaces()[sharedEdgeI];
00502
00503
00504 label faceIndex = findIndex(eFaces, firstFaceI);
00505
00506 if (edgeOrder)
00507 {
00508
00509 return eFaces[eFaces.rcIndex(faceIndex)];
00510 }
00511 else
00512 {
00513
00514 return eFaces[eFaces.fcIndex(faceIndex)];
00515 }
00516 }
00517
00518
00519
00520
00521 void calcPointVecs
00522 (
00523 const triSurface& surf,
00524 const Map<label>& faceToEdge,
00525 const Map<label>& faceToPoint,
00526 vectorField& borderPointVec
00527 )
00528 {
00529 const labelListList& sortedEdgeFaces = surf.sortedEdgeFaces();
00530 const edgeList& edges = surf.edges();
00531 const pointField& points = surf.localPoints();
00532
00533 boolList edgeDone(surf.nEdges(), false);
00534
00535 for
00536 (
00537 Map<label>::const_iterator iter = faceToEdge.begin();
00538 iter != faceToEdge.end();
00539 ++iter
00540 )
00541 {
00542 label edgeI = iter();
00543
00544 if (!edgeDone[edgeI])
00545 {
00546 edgeDone[edgeI] = true;
00547
00548
00549
00550
00551 label face0I = -1;
00552 label face1I = -1;
00553
00554 const labelList& eFaces = sortedEdgeFaces[edgeI];
00555
00556 forAll(eFaces, i)
00557 {
00558 label faceI = eFaces[i];
00559
00560 if (faceToEdge.found(faceI))
00561 {
00562 if (face0I == -1)
00563 {
00564 face0I = faceI;
00565 }
00566 else if (face1I == -1)
00567 {
00568 face1I = faceI;
00569
00570 break;
00571 }
00572 }
00573 }
00574
00575 if (face0I == -1 && face1I == -1)
00576 {
00577 Info<< "Writing surface to errorSurf.ftr" << endl;
00578
00579 surf.write("errorSurf.ftr");
00580
00581 FatalErrorIn("calcPointVecs(..)")
00582 << "Cannot find two faces using border edge " << edgeI
00583 << " verts:" << edges[edgeI]
00584 << " eFaces:" << eFaces << endl
00585 << "face0I:" << face0I
00586 << " face1I:" << face1I << nl
00587 << "faceToEdge:" << faceToEdge << nl
00588 << "faceToPoint:" << faceToPoint
00589 << "Written surface to errorSurf.ftr"
00590 << abort(FatalError);
00591 }
00592
00593
00594
00595 const edge& e = edges[edgeI];
00596 vector eVec = e.vec(points);
00597
00598
00599
00600 vector midVec(vector::zero);
00601
00602 if (face0I != -1)
00603 {
00604 label v0 = triSurfaceTools::oppositeVertex(surf, face0I, edgeI);
00605 vector e0 = (points[v0] - points[e.start()]) ^ eVec;
00606 e0 /= mag(e0);
00607 midVec = e0;
00608 }
00609
00610 if (face1I != -1)
00611 {
00612 label v1 = triSurfaceTools::oppositeVertex(surf, face1I, edgeI);
00613 vector e1 = (points[e.start()] - points[v1]) ^ eVec;
00614 e1 /= mag(e1);
00615 midVec += e1;
00616 }
00617
00618 scalar magMidVec = mag(midVec);
00619
00620 if (magMidVec > SMALL)
00621 {
00622 midVec /= magMidVec;
00623
00624
00625 borderPointVec[e.start()] += midVec;
00626 borderPointVec[e.end()] += midVec;
00627 }
00628 }
00629 }
00630 }
00631
00632
00633
00634
00635 void renumberFaces
00636 (
00637 const triSurface& surf,
00638 const labelList& pointMap,
00639 const Map<label>& faceToEdge,
00640 List<labelledTri>& newTris
00641 )
00642 {
00643 for
00644 (
00645 Map<label>::const_iterator iter = faceToEdge.begin();
00646 iter != faceToEdge.end();
00647 ++iter
00648 )
00649 {
00650 label faceI = iter.key();
00651
00652 const labelledTri& f = surf.localFaces()[faceI];
00653
00654 forAll(f, fp)
00655 {
00656 if (pointMap[f[fp]] != -1)
00657 {
00658 newTris[faceI][fp] = pointMap[f[fp]];
00659 }
00660 }
00661 }
00662 }
00663
00664
00665
00666
00667 bool splitBorderEdges
00668 (
00669 triSurface& surf,
00670 const boolList& borderEdge,
00671 const labelList& borderPoint
00672 )
00673 {
00674 labelList edgesToBeSplit(surf.nEdges());
00675 label nSplit = 0;
00676
00677 forAll(borderEdge, edgeI)
00678 {
00679 if (borderEdge[edgeI])
00680 {
00681 const edge& e = surf.edges()[edgeI];
00682
00683 if (borderPoint[e.start()] == -1 && borderPoint[e.end()] == -1)
00684 {
00685
00686
00687 edgesToBeSplit[nSplit++] = edgeI;
00688 }
00689 }
00690 }
00691 edgesToBeSplit.setSize(nSplit);
00692
00693 if (nSplit > 0)
00694 {
00695 Info<< "Splitting surface along " << nSplit << " borderEdges that don't"
00696 << " neighbour other borderEdges" << nl << endl;
00697
00698 surf = triSurfaceTools::greenRefine(surf, edgesToBeSplit);
00699
00700 return true;
00701 }
00702 else
00703 {
00704 Info<< "No edges to be split" <<nl << endl;
00705
00706 return false;
00707 }
00708 }
00709
00710
00711
00712
00713 int main(int argc, char *argv[])
00714 {
00715 argList::noParallel();
00716 argList::validArgs.clear();
00717
00718 argList::validArgs.append("surface file");
00719 argList::validArgs.append("output surface file");
00720 argList::validOptions.insert("debug", "");
00721
00722 argList args(argc, argv);
00723
00724 fileName inSurfName(args.additionalArgs()[0]);
00725 fileName outSurfName(args.additionalArgs()[1]);
00726 bool debug = args.optionFound("debug");
00727
00728
00729 Info<< "Reading surface from " << inSurfName << endl;
00730
00731 triSurface surf(inSurfName);
00732
00733
00734 testSortedEdgeFaces(surf);
00735
00736
00737 boolList borderEdge(surf.nEdges(), false);
00738 markBorderEdges(debug, surf, borderEdge);
00739
00740
00741
00742 labelList borderPoint(surf.nPoints(), -1);
00743 markBorderPoints(debug, surf, borderEdge, borderPoint);
00744
00745
00746 splitBorderEdges(surf, borderEdge, borderPoint);
00747
00748
00749 Info<< "Writing split surface to " << outSurfName << nl << endl;
00750 surf.write(outSurfName);
00751 Info<< "Finished writing surface to " << outSurfName << nl << endl;
00752
00753
00754
00755 label nOldBorderEdges = -1;
00756 label nOldBorderPoints = -1;
00757
00758 label iteration = 0;
00759
00760 do
00761 {
00762
00763 boolList borderEdge(surf.nEdges(), false);
00764
00765 label nBorderEdges = markBorderEdges(debug, surf, borderEdge);
00766
00767 if (nBorderEdges == 0)
00768 {
00769 Info<< "Found no border edges. Exiting." << nl << nl;
00770
00771 break;
00772 }
00773
00774
00775 labelList borderPoint(surf.nPoints(), -1);
00776
00777 label nBorderPoints =
00778 markBorderPoints
00779 (
00780 debug,
00781 surf,
00782 borderEdge,
00783 borderPoint
00784 );
00785
00786 if (nBorderPoints == 0)
00787 {
00788 Info<< "Found no border points. Exiting." << nl << nl;
00789
00790 break;
00791 }
00792
00793 Info<< "Found:\n"
00794 << " border edges :" << nBorderEdges << nl
00795 << " border points:" << nBorderPoints << nl
00796 << endl;
00797
00798 if
00799 (
00800 nBorderPoints == nOldBorderPoints
00801 && nBorderEdges == nOldBorderEdges
00802 )
00803 {
00804 Info<< "Stopping since number of border edges and point is same"
00805 << " as in previous iteration" << nl << endl;
00806
00807 break;
00808 }
00809
00810
00811
00812
00813
00814
00815 label startEdgeI = -1;
00816 label startPointI = -1;
00817
00818 forAll(borderEdge, edgeI)
00819 {
00820 if (borderEdge[edgeI])
00821 {
00822 const edge& e = surf.edges()[edgeI];
00823
00824 if ((borderPoint[e[0]] != -1) && (borderPoint[e[1]] == -1))
00825 {
00826 startEdgeI = edgeI;
00827 startPointI = e[0];
00828
00829 break;
00830 }
00831 else if ((borderPoint[e[0]] == -1) && (borderPoint[e[1]] != -1))
00832 {
00833 startEdgeI = edgeI;
00834 startPointI = e[1];
00835
00836 break;
00837 }
00838 }
00839 }
00840
00841 if (startEdgeI == -1)
00842 {
00843 Info<< "Cannot find starting point of splitLine\n" << endl;
00844
00845 break;
00846 }
00847
00848
00849 const labelList& eFaces = surf.edgeFaces()[startEdgeI];
00850
00851 label firstFaceI = eFaces[0];
00852
00853
00854
00855 label secondFaceI = sharedFace(surf, firstFaceI, startEdgeI);
00856
00857 Info<< "Starting local walk from:" << endl
00858 << " edge :" << startEdgeI << endl
00859 << " point:" << startPointI << endl
00860 << " face0:" << firstFaceI << endl
00861 << " face1:" << secondFaceI << endl
00862 << endl;
00863
00864
00865 Map<label> faceToEdge(2*nBorderEdges);
00866
00867 Map<label> faceToPoint(2*nBorderPoints);
00868
00869 faceToEdge.insert(firstFaceI, startEdgeI);
00870
00871 walkSplitLine
00872 (
00873 surf,
00874 borderEdge,
00875 borderPoint,
00876
00877 firstFaceI,
00878 startEdgeI,
00879 startPointI,
00880
00881 faceToEdge,
00882 faceToPoint
00883 );
00884
00885 faceToEdge.insert(secondFaceI, startEdgeI);
00886
00887 walkSplitLine
00888 (
00889 surf,
00890 borderEdge,
00891 borderPoint,
00892
00893 secondFaceI,
00894 startEdgeI,
00895 startPointI,
00896
00897 faceToEdge,
00898 faceToPoint
00899 );
00900
00901 Info<< "Finished local walk and visited" << nl
00902 << " border edges :" << faceToEdge.size() << nl
00903 << " border points(but not edges):" << faceToPoint.size() << nl
00904 << endl;
00905
00906 if (debug)
00907 {
00908 dumpFaces("faceToEdge.obj", surf, faceToEdge);
00909 dumpFaces("faceToPoint.obj", surf, faceToPoint);
00910 }
00911
00912
00913
00914
00915
00916
00917
00918
00919 vectorField borderPointVec(surf.nPoints(), vector(GREAT, GREAT, GREAT));
00920
00921 calcPointVecs(surf, faceToEdge, faceToPoint, borderPointVec);
00922
00923
00924
00925 pointField newPoints(surf.localPoints());
00926 newPoints.setSize(newPoints.size() + nBorderPoints);
00927
00928 forAll(borderPoint, pointI)
00929 {
00930 label newPointI = borderPoint[pointI];
00931
00932 if (newPointI != -1)
00933 {
00934 scalar minLen = minEdgeLen(surf, pointI);
00935
00936 vector n = borderPointVec[pointI];
00937 n /= mag(n);
00938
00939 newPoints[newPointI] = newPoints[pointI] + 0.1 * minLen * n;
00940 }
00941 }
00942
00943
00944
00945
00946
00947
00948
00949 List<labelledTri> newTris(surf.size());
00950
00951 forAll(surf, faceI)
00952 {
00953 newTris[faceI] = surf.localFaces()[faceI];
00954
00955 newTris[faceI].region() = surf[faceI].region();
00956 }
00957
00958
00959 renumberFaces(surf, borderPoint, faceToEdge, newTris);
00960
00961 renumberFaces(surf, borderPoint, faceToPoint, newTris);
00962
00963
00964
00965 forAll(newTris, faceI)
00966 {
00967 const labelledTri& f = newTris[faceI];
00968
00969 forAll(f, fp)
00970 {
00971 const point& pt = newPoints[f[fp]];
00972
00973 if (mag(pt) >= GREAT/2)
00974 {
00975 Info<< "newTri:" << faceI << " verts:" << f
00976 << " vert:" << f[fp] << " point:" << pt << endl;
00977 }
00978 }
00979 }
00980
00981
00982 surf = triSurface(newTris, surf.patches(), newPoints);
00983
00984 if (debug || (iteration != 0 && (iteration % 20) == 0))
00985 {
00986 Info<< "Writing surface to " << outSurfName << nl << endl;
00987
00988 surf.write(outSurfName);
00989
00990 Info<< "Finished writing surface to " << outSurfName << nl << endl;
00991 }
00992
00993
00994 nOldBorderEdges = nBorderEdges;
00995 nOldBorderPoints = nBorderPoints;
00996
00997 iteration++;
00998 }
00999 while (true);
01000
01001 Info<< "Writing final surface to " << outSurfName << nl << endl;
01002
01003 surf.write(outSurfName);
01004
01005 Info << "End\n" << endl;
01006
01007 return 0;
01008 }
01009
01010
01011