FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

surfaceSplitNonManifolds.C

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------------*\
00002   =========                 |
00003   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
00004    \\    /   O peration     |
00005     \\  /    A nd           | Copyright (C) 1991-2010 OpenCFD Ltd.
00006      \\/     M anipulation  |
00007 -------------------------------------------------------------------------------
00008 License
00009     This file is part of OpenFOAM.
00010 
00011     OpenFOAM is free software: you can redistribute it and/or modify it
00012     under the terms of the GNU General Public License as published by
00013     the Free Software Foundation, either version 3 of the License, or
00014     (at your option) any later version.
00015 
00016     OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
00017     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
00018     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00019     for more details.
00020 
00021     You should have received a copy of the GNU General Public License
00022     along with OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.
00023 
00024 Application
00025     surfaceSplitNonManifolds
00026 
00027 Description
00028     Takes multiply connected surface and tries to split surface at
00029     multiply connected edges by duplicating points.
00030 
00031     Introduces concept of
00032     - borderEdge. Edge with 4 faces connected to it.
00033     - borderPoint. Point connected to exactly 2 borderEdges.
00034     - borderLine. Connected list of borderEdges.
00035 
00036     By duplicating borderPoints this will split 'borderLines'. As a
00037     preprocessing step it can detect borderEdges without any borderPoints
00038     and explicitly split these triangles.
00039 
00040     The problems in this algorithm are:
00041     - determining which two (of the four) faces form a surface. Done by walking
00042       face-edge-face while keeping and edge or point on the borderEdge
00043       borderPoint.
00044     - determining the outwards pointing normal to be used to slightly offset the
00045       duplicated point.
00046 
00047     Uses sortedEdgeFaces quite a bit.
00048 
00049     Is tested on simple borderLines resulting from extracting a surface
00050     from a hex mesh. Will quite possibly go wrong on more complicated border
00051     lines (i.e. ones forming a loop).
00052 
00053     Dumps surface every so often since might take a long time to complete.
00054 
00055 Usage
00056 
00057     - surfaceSplitNonManifolds [OPTIONS] <Foam surface file> <surface output file>
00058 
00059     @param <Foam surface file> \n
00060     @todo Detailed description of argument.
00061 
00062     @param <surface output file> \n
00063     @todo Detailed description of argument.
00064 
00065     @param -debug \n
00066     Generate debugging output.
00067 
00068     @param -case <dir>\n
00069     Case directory.
00070 
00071     @param -help \n
00072     Display help message.
00073 
00074     @param -doc \n
00075     Display Doxygen API documentation page for this application.
00076 
00077     @param -srcDoc \n
00078     Display Doxygen source documentation page for this application.
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 // Mark off all border edges. Return number of border edges.
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 // Mark off all border points. Return number of border points. Border points
00235 // marked by setting value to newly introduced point.
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 // Get minumum length of edges connected to pointI
00280 // Serves to get some local length scale.
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 // Find edge among edgeLabels with endpoints v0,v1
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 // Get the other edge connected to pointI on faceI.
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 // Starting from startPoint on startEdge on startFace walk along border
00386 // and insert faces along the way. Walk keeps always one point or one edge
00387 // on the border line.
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,     // is border edge
00396     const label startPointI,    // is border point
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         // Stick to pointI and walk face-edge-face until back on border edge.
00410         //
00411 
00412         do
00413         {
00414             // Cross face to next edge.
00415             edgeI = otherEdge(surf, faceI, edgeI, pointI);
00416 
00417             if (borderEdge[edgeI])
00418             {
00419                 if (!faceToEdge.insert(faceI, edgeI))
00420                 {
00421                     // Was already visited.
00422                     return;
00423                 }
00424                 else
00425                 {
00426                     // First visit to this borderEdge. We're back on borderline.
00427                     break;
00428                 }
00429             }
00430             else if (!faceToPoint.insert(faceI, pointI))
00431             {
00432                 // Was already visited.
00433                 return;
00434             }
00435 
00436             // Cross edge to other face
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         // Back on border edge. Cross to other point on edge.
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 // Find second face which is from same surface i.e. has points on the
00479 // shared edge in reverse order.
00480 label sharedFace
00481 (
00482     const triSurface& surf,
00483     const label firstFaceI,
00484     const label sharedEdgeI
00485 )
00486 {
00487     // Find ordering of face points in edge.
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     // points in face in same order as edge
00496     bool edgeOrder = (f[f.fcIndex(startIndex)] == e.end());
00497 
00498     // Get faces using edge in sorted order. (sorted such that walking
00499     // around them in anti-clockwise order corresponds to edge vector
00500     // acc. to right-hand rule)
00501     const labelList& eFaces = surf.sortedEdgeFaces()[sharedEdgeI];
00502 
00503     // Get position of face in sorted edge faces
00504     label faceIndex = findIndex(eFaces, firstFaceI);
00505 
00506     if (edgeOrder)
00507     {
00508         // Get face before firstFaceI
00509         return eFaces[eFaces.rcIndex(faceIndex)];
00510     }
00511     else
00512     {
00513         // Get face after firstFaceI
00514         return eFaces[eFaces.fcIndex(faceIndex)];
00515     }
00516 }
00517 
00518 
00519 // Calculate (inward pointing) normals on edges shared by faces in faceToEdge and
00520 // averages them to pointNormals.
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             // Get the two connected faces in sorted order
00549             // Note: should have stored this when walking ...
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             // Now we have edge and the two faces in counter-clockwise order
00594             // as seen from edge vector. Calculate normal.
00595             const edge& e = edges[edgeI];
00596             vector eVec = e.vec(points);
00597 
00598             // Determine vector as average of the vectors in the two faces.
00599             // If there is only one face available use only one vector.
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                 // Average to pointVec
00625                 borderPointVec[e.start()] += midVec;
00626                 borderPointVec[e.end()] += midVec;
00627             }
00628         }
00629     }
00630 }
00631 
00632 
00633 // Renumbers vertices (of triangles in faceToEdge) of which the pointMap is
00634 // not -1.
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 // Split all borderEdges that don't have borderPoint. Return true if split
00666 // anything.
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                 // None of the points of the edge is borderPoint. Split edge
00686                 // to introduce border point.
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 // Main program:
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     // Make sure sortedEdgeFaces is calculated correctly
00734     testSortedEdgeFaces(surf);
00735 
00736     // Get all quad connected edges. These are seen as borders when walking.
00737     boolList borderEdge(surf.nEdges(), false);
00738     markBorderEdges(debug, surf, borderEdge);
00739 
00740     // Points on two sides connected to borderEdges are called borderPoints and
00741     // will be duplicated. borderPoint contains label of newly introduced vertex.
00742     labelList borderPoint(surf.nPoints(), -1);
00743     markBorderPoints(debug, surf, borderEdge, borderPoint);
00744 
00745     // Split edges where there would be no borderPoint to duplicate.
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     // Last iteration values.
00755     label nOldBorderEdges = -1;
00756     label nOldBorderPoints = -1;
00757 
00758     label iteration = 0;
00759 
00760     do
00761     {
00762         // Redo borderEdge/borderPoint calculation.
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         // Label of newly introduced duplicate.
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         // Define splitLine as a series of connected borderEdges. Find start
00812         // of one (as edge and point on edge)
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         // Pick any face using edge to start from.
00849         const labelList& eFaces = surf.edgeFaces()[startEdgeI];
00850 
00851         label firstFaceI = eFaces[0];
00852 
00853         // Find second face which is from same surface i.e. has outwards
00854         // pointing normal as well (actually bit more complex than this)
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         // From face on border edge to edge.
00865         Map<label> faceToEdge(2*nBorderEdges);
00866         // From face connected to border point (but not border edge) to point.
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         // Create coordinates for borderPoints by duplicating the existing
00914         // point and then slightly shifting it inwards. To determine the
00915         // inwards direction get the average normal of both connectedFaces on
00916         // the edge and then interpolate this to the (border)point.
00917         //
00918 
00919         vectorField borderPointVec(surf.nPoints(), vector(GREAT, GREAT, GREAT));
00920 
00921         calcPointVecs(surf, faceToEdge, faceToPoint, borderPointVec);
00922 
00923 
00924         // New position. Start off from copy of old points.
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         // Renumber all faces in connectedFaces
00946         //
00947 
00948         // Start off from copy of faces.
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         // Renumber all faces in faceToEdge
00959         renumberFaces(surf, borderPoint, faceToEdge, newTris);
00960         // Renumber all faces in faceToPoint
00961         renumberFaces(surf, borderPoint, faceToPoint, newTris);
00962 
00963 
00964         // Check if faces use unmoved points.
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         // Save prev iteration values.
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 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines