Creation of OpenFOAM-dev repository 15/04/2008

This commit is contained in:
OpenFOAM-admin
2008-04-15 18:56:58 +01:00
commit 3170c7c0c9
9896 changed files with 4016171 additions and 0 deletions

View File

@ -0,0 +1,740 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Description
\*---------------------------------------------------------------------------*/
#include "edgeIntersections.H"
#include "triSurfaceSearch.H"
#include "labelPairLookup.H"
#include "OFstream.H"
#include "HashSet.H"
#include "labelHashSet.H"
#include "triSurface.H"
#include "pointIndexHit.H"
#include "octreeDataTriSurface.H"
#include "octree.H"
#include "meshTools.H"
#include "plane.H"
#include "Random.H"
#include "mathematicalConstants.H"
#include "treeBoundBox.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
defineTypeNameAndDebug(Foam::edgeIntersections, 0);
Foam::scalar Foam::edgeIntersections::alignedCos_ =
Foam::cos(89.0 * Foam::mathematicalConstant::pi/180.0);
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::edgeIntersections::checkEdges(const triSurface& surf)
{
const pointField& localPoints = surf.localPoints();
const edgeList& edges = surf.edges();
const labelListList& edgeFaces = surf.edgeFaces();
treeBoundBox bb(localPoints);
scalar minSize = SMALL*bb.minDim();
forAll(edges, edgeI)
{
const edge& e = edges[edgeI];
scalar eMag = e.mag(localPoints);
if (eMag < minSize)
{
WarningIn
(
"Foam::edgeIntersections::checkEdges(const triSurface& surf)"
) << "Edge " << edgeI << " vertices " << e
<< " coords:" << localPoints[e[0]] << ' '
<< localPoints[e[1]] << " is very small compared to bounding"
<< " box dimensions " << bb << endl
<< "This might lead to problems in intersection"
<< endl;
}
if (edgeFaces[edgeI].size() == 1)
{
WarningIn
(
"Foam::edgeIntersections::checkEdges(const triSurface& surf)"
) << "Edge " << edgeI << " vertices " << e
<< " coords:" << localPoints[e[0]] << ' '
<< localPoints[e[1]] << " has only one face connected to it:"
<< edgeFaces[edgeI] << endl
<< "This might lead to problems in intersection"
<< endl;
}
}
}
// Update intersections for selected edges.
void Foam::edgeIntersections::intersectEdges
(
const triSurface& surf1,
const pointField& points1, // surf1 meshPoints (not localPoints!)
const triSurfaceSearch& querySurf2,
const scalarField& surf1PointTol, // surf1 tolerance per point
const labelList& edgeLabels
)
{
const triSurface& surf2 = querySurf2.surface();
const vectorField& normals2 = surf2.faceNormals();
const labelList& meshPoints = surf1.meshPoints();
if (debug)
{
Pout<< "Calculating intersection of " << edgeLabels.size() << " edges"
<< " out of " << surf1.nEdges() << " with " << surf2.size()
<< " triangles ..." << endl;
}
// Construct octree.
const octree<octreeDataTriSurface>& tree = querySurf2.tree();
label nHits = 0;
// Go through all edges, calculate intersections
forAll(edgeLabels, i)
{
label edgeI = edgeLabels[i];
if (debug && (i % 1000 == 0))
{
Pout<< "Intersecting edge " << edgeI << " with surface" << endl;
}
const edge& e = surf1.edges()[edgeI];
const point& pStart = points1[meshPoints[e.start()]];
const point& pEnd = points1[meshPoints[e.end()]];
const vector eVec(pEnd - pStart);
const scalar eMag = mag(eVec);
const vector n(eVec/(eMag + VSMALL));
// Smallish length for intersection calculation errors.
const point tolVec = 1e-6*eVec;
// Start tracking somewhat before pStart and upto somewhat after p1.
// Note that tolerances here are smaller than those used to classify
// hit below.
// This will cause this hit to be marked as degenerate and resolved
// later on.
point p0 = pStart - 0.5*surf1PointTol[e[0]]*n;
const point p1 = pEnd + 0.5*surf1PointTol[e[1]]*n;
const scalar maxS = mag(p1 - pStart);
// Get all intersections of the edge with the surface
DynamicList<pointIndexHit> currentIntersections(100);
DynamicList<label> currentIntersectionTypes(100);
while (true)
{
pointIndexHit pHit = tree.findLine(p0, p1);
if (pHit.hit())
{
nHits++;
currentIntersections.append(pHit);
// Classify point on surface1 edge.
label edgeEnd = -1;
if (mag(pHit.hitPoint() - pStart) < surf1PointTol[e[0]])
{
edgeEnd = 0;
}
else if (mag(pHit.hitPoint() - pEnd) < surf1PointTol[e[1]])
{
edgeEnd = 1;
}
else if (mag(n & normals2[pHit.index()]) < alignedCos_)
{
Pout<< "Flat angle edge:" << edgeI
<< " face:" << pHit.index()
<< " cos:" << mag(n & normals2[pHit.index()])
<< endl;
edgeEnd = 2;
}
currentIntersectionTypes.append(edgeEnd);
if (edgeEnd == 1)
{
// Close to end
break;
}
else
{
// Continue tracking. Shift by a small amount.
p0 = pHit.hitPoint() + tolVec;
if (((p0-pStart) & n) >= maxS)
{
break;
}
}
}
else
{
// No hit.
break;
}
}
// Done current edge. Transfer all data into *this
currentIntersections.shrink();
currentIntersectionTypes.shrink();
operator[](edgeI).transfer(currentIntersections);
classification_[edgeI].transfer(currentIntersectionTypes);
currentIntersections.clear();
currentIntersectionTypes.clear();
}
if (debug)
{
Pout<< "Found " << nHits << " intersections of edges with surface ..."
<< endl;
}
}
// If edgeI intersections are close to endpoint of edge shift endpoints
// slightly along edge
// Updates
// - points1 with new endpoint position
// - affectedEdges with all edges affected by moving the point
// Returns true if changed anything.
bool Foam::edgeIntersections::inlinePerturb
(
const triSurface& surf1,
const scalarField& surf1PointTol, // surf1 tolerance per point
const label edgeI,
Random& rndGen,
pointField& points1,
boolList& affectedEdges
) const
{
bool hasPerturbed = false;
// Check if edge close to endpoint. Note that we only have to check
// the intersection closest to the edge endpoints (i.e. first and last in
// edgeEdgs)
const labelList& edgeEnds = classification_[edgeI];
if (edgeEnds.size() > 0)
{
bool perturbStart = false;
bool perturbEnd = false;
// Check first intersection.
if (edgeEnds[0] == 0)
{
perturbStart = true;
}
if (edgeEnds[edgeEnds.size()-1] == 1)
{
perturbEnd = true;
}
if (perturbStart || perturbEnd)
{
const edge& e = surf1.edges()[edgeI];
label v0 = surf1.meshPoints()[e[0]];
label v1 = surf1.meshPoints()[e[1]];
vector eVec(points1[v1] - points1[v0]);
vector n = eVec/mag(eVec);
if (perturbStart)
{
// Perturb with something (hopefully) larger than tolerance.
scalar t = 4.0*(rndGen.scalar01() - 0.5);
points1[v0] += t*surf1PointTol[e[0]]*n;
const labelList& pEdges = surf1.pointEdges()[e[0]];
forAll(pEdges, i)
{
affectedEdges[pEdges[i]] = true;
}
}
if (perturbEnd)
{
// Perturb with something larger than tolerance.
scalar t = 4.0*(rndGen.scalar01() - 0.5);
points1[v1] += t*surf1PointTol[e[1]]*n;
const labelList& pEdges = surf1.pointEdges()[e[1]];
forAll(pEdges, i)
{
affectedEdges[pEdges[i]] = true;
}
}
hasPerturbed = true;
}
}
return hasPerturbed;
}
// Perturb single edge endpoint when perpendicular to face
bool Foam::edgeIntersections::rotatePerturb
(
const triSurface& surf1,
const scalarField& surf1PointTol, // surf1 tolerance per point
const label edgeI,
Random& rndGen,
pointField& points1,
boolList& affectedEdges
) const
{
const labelList& meshPoints = surf1.meshPoints();
const labelList& edgeEnds = classification_[edgeI];
bool hasPerturbed = false;
forAll(edgeEnds, i)
{
if (edgeEnds[i] == 2)
{
const edge& e = surf1.edges()[edgeI];
// Endpoint to modify. Choose either start or end.
label pointI = e[rndGen.bit()];
//label pointI = e[0];
// Generate random vector slightly larger than tolerance.
vector rndVec = rndGen.vector01() - vector(0.5, 0.5, 0.5);
// Make sure rndVec only perp to edge
vector n(points1[meshPoints[e[1]]] - points1[meshPoints[e[0]]]);
scalar magN = mag(n) + VSMALL;
n /= magN;
rndVec -= n*(n & rndVec);
// Normalize
rndVec /= mag(rndVec) + VSMALL;
// Scale to be moved by tolerance.
rndVec *= 0.01*magN;
Pout<< "rotating: shifting endpoint " << meshPoints[pointI]
<< " of edge:" << edgeI << " verts:"
<< points1[meshPoints[e[0]]] << ' '
<< points1[meshPoints[e[1]]]
<< " by " << rndVec
<< " tol:" << surf1PointTol[pointI] << endl;
points1[meshPoints[pointI]] += rndVec;
// Mark edges affected by change to point
const labelList& pEdges = surf1.pointEdges()[pointI];
forAll(pEdges, i)
{
affectedEdges[pEdges[i]] = true;
}
hasPerturbed = true;
// Enough done for current edge; no need to test other intersections
// of this edge.
break;
}
}
return hasPerturbed;
}
// Perturb edge when close to face
bool Foam::edgeIntersections::offsetPerturb
(
const triSurface& surf1,
const triSurface& surf2,
const label edgeI,
Random& rndGen,
pointField& points1,
boolList& affectedEdges
) const
{
const labelList& meshPoints = surf1.meshPoints();
const edge& e = surf1.edges()[edgeI];
const List<pointIndexHit>& hits = operator[](edgeI);
bool hasPerturbed = false;
// For all hits on edge
forAll(hits, i)
{
const pointIndexHit& pHit = hits[i];
// Classify point on face of surface2
label surf2FaceI = pHit.index();
const labelledTri& f2 = surf2.localFaces()[surf2FaceI];
const pointField& surf2Pts = surf2.localPoints();
label nearType;
label nearLabel;
triPointRef tri
(
surf2Pts[f2[0]],
surf2Pts[f2[1]],
surf2Pts[f2[2]]
);
point ctr = tri.centre();
// Get measure for tolerance.
scalar tolDim = 0.001*mag(tri.a() - ctr);
tri.classify(pHit.hitPoint(), tolDim, nearType, nearLabel);
if (nearType == triPointRef::POINT || nearType == triPointRef::EDGE)
{
// Shift edge towards tri centre
vector offset = 0.01*rndGen.scalar01()*(ctr - pHit.hitPoint());
// shift e[0]
points1[meshPoints[e[0]]] += offset;
// Mark edges affected by change to e0
const labelList& pEdges0 = surf1.pointEdges()[e[0]];
forAll(pEdges0, i)
{
affectedEdges[pEdges0[i]] = true;
}
// shift e[1]
points1[meshPoints[e[1]]] += offset;
// Mark edges affected by change to e1
const labelList& pEdges1 = surf1.pointEdges()[e[1]];
forAll(pEdges1, i)
{
affectedEdges[pEdges1[i]] = true;
}
hasPerturbed = true;
// No need to test any other hits on this edge
break;
}
}
return hasPerturbed;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
// Construct null
Foam::edgeIntersections::edgeIntersections()
:
List<List<pointIndexHit> >(),
classification_()
{}
// Construct from surface and tolerance
Foam::edgeIntersections::edgeIntersections
(
const triSurface& surf1,
const triSurfaceSearch& query2,
const scalarField& surf1PointTol
)
:
List<List<pointIndexHit> >(surf1.nEdges()),
classification_(surf1.nEdges())
{
checkEdges(surf1);
checkEdges(query2.surface());
// Current set of edges to test
labelList edgesToTest(surf1.nEdges());
// Start off with all edges
forAll(edgesToTest, i)
{
edgesToTest[i] = i;
}
// Determine intersections for edgesToTest
intersectEdges
(
surf1,
surf1.points(), // surf1 meshPoints (not localPoints!)
query2,
surf1PointTol,
edgesToTest
);
}
// Construct from components
Foam::edgeIntersections::edgeIntersections
(
const List<List<pointIndexHit> >& intersections,
const labelListList& classification
)
:
List<List<pointIndexHit> >(intersections),
classification_(classification)
{}
// * * * * * * * * * * * * * * * Static Functions * * * * * * * * * * * * * //
Foam::scalarField Foam::edgeIntersections::minEdgeLength(const triSurface& surf)
{
const pointField& localPoints = surf.localPoints();
const labelListList& pointEdges = surf.pointEdges();
const edgeList& edges = surf.edges();
scalarField minLen(localPoints.size());
forAll(minLen, pointI)
{
const labelList& pEdges = pointEdges[pointI];
scalar minDist = GREAT;
forAll(pEdges, i)
{
minDist = min(minDist, edges[pEdges[i]].mag(localPoints));
}
minLen[pointI] = minDist;
}
return minLen;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::edgeIntersections::removeDegenerates
(
const label nIters,
const triSurface& surf1,
const triSurfaceSearch& query2,
const scalarField& surf1PointTol,
pointField& points1
)
{
const triSurface& surf2 = query2.surface();
Random rndGen(356574);
// Current set of edges to (re)test
labelList edgesToTest(surf1.nEdges());
// Start off with all edges
forAll(edgesToTest, i)
{
edgesToTest[i] = i;
}
label iter = 0;
for (; iter < nIters; iter++)
{
// Go through all edges to (re)test and perturb points if they are
// degenerate hits. Mark off edges that need to be recalculated.
boolList affectedEdges(surf1.nEdges(), false);
label nShifted = 0;
label nRotated = 0;
label nOffset = 0;
forAll(edgesToTest, i)
{
label edgeI = edgesToTest[i];
// If edge not already marked for retesting
if (!affectedEdges[edgeI])
{
// 1. Check edges close to endpoint and perturb if nessecary.
bool shiftedEdgeEndPoints =
inlinePerturb
(
surf1,
surf1PointTol,
edgeI,
rndGen,
points1,
affectedEdges
);
nShifted += (shiftedEdgeEndPoints ? 1 : 0);
if (!shiftedEdgeEndPoints)
{
bool rotatedEdge =
rotatePerturb
(
surf1,
surf1PointTol,
edgeI,
rndGen,
points1,
affectedEdges
);
nRotated += (rotatedEdge ? 1 : 0);
if (!rotatedEdge)
{
// 2. we're sure now that the edge actually pierces the
// face. Now check the face for intersections close its
// points/edges
bool offsetEdgePoints =
offsetPerturb
(
surf1,
surf2,
edgeI,
rndGen,
points1,
affectedEdges
);
nOffset += (offsetEdgePoints ? 1 : 0);
}
}
}
}
if (debug)
{
Pout<< "Edges to test : " << nl
<< " total:" << edgesToTest.size() << nl
<< " resolved by:" << nl
<< " shifting : " << nShifted << nl
<< " rotating : " << nRotated << nl
<< " offsetting : " << nOffset << nl
<< endl;
}
if (nShifted == 0 && nRotated == 0 && nOffset == 0)
{
// Nothing changed in current iteration. Current hit pattern is
// without any degenerates.
break;
}
// Repack affected edges
labelList newEdgesToTest(surf1.nEdges());
label newEdgeI = 0;
forAll(affectedEdges, edgeI)
{
if (affectedEdges[edgeI])
{
newEdgesToTest[newEdgeI++] = edgeI;
}
}
newEdgesToTest.setSize(newEdgeI);
if (debug)
{
Pout<< "Edges to test:" << nl
<< " was : " << edgesToTest.size() << nl
<< " is : " << newEdgesToTest.size() << nl
<< endl;
}
// Transfer and test.
edgesToTest.transfer(newEdgesToTest);
if (edgesToTest.size() == 0)
{
FatalErrorIn("perturb") << "oops" << abort(FatalError);
}
// Re intersect moved edges.
intersectEdges
(
surf1,
points1, // surf1 meshPoints (not localPoints!)
query2,
surf1PointTol,
edgesToTest
);
}
return iter;
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// ************************************************************************* //

View File

@ -0,0 +1,211 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::edgeIntersections
Description
Holder of intersections of edges of a surface with another surface.
Optionally shuffles around points on surface to resolve any 'conflicts'
(edge hitting triangle edge, edge hitting point etc.).
SourceFiles
edgeIntersections.C
\*---------------------------------------------------------------------------*/
#ifndef edgeIntersections_H
#define edgeIntersections_H
#include "pointIndexHit.H"
#include "scalarField.H"
#include "pointField.H"
#include "typeInfo.H"
#include "boolList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class triSurface;
class triSurfaceSearch;
class Random;
class edge;
/*---------------------------------------------------------------------------*\
Class edgeIntersections Declaration
\*---------------------------------------------------------------------------*/
class edgeIntersections
:
public List<List<pointIndexHit> >
{
// Private data
//- For every entry in *this gives the edge classification result.
// -1 : intersection not close to edge
// 0 : intersection close to e[0]
// 1 : intersection close to e[1]
// 2 : edge aligned with intersection face
labelListList classification_;
// Private Member Functions
//- Check for too small edges
static void checkEdges(const triSurface& surf);
//- Intersect selected surface edges (edgeLabels) with surface2.
// Updates *this with pointHits and classification_ with status
// of hitPoint compared to edge end points.
void intersectEdges
(
const triSurface& surf1,
const pointField& points1, // surf1 meshPoints
const triSurfaceSearch& querySurf2,
const scalarField& surf1PointTol, // surf1 tolerance per point
const labelList& edgeLabels
);
//- Perturb endpoints of edge if they are close to the intersection.
// Move point (in points1) by factor*surf1PointTol in direction of
// edge. Mark pointEdges of moved point in affectedEdges.
// Return true if anything changed.
bool inlinePerturb
(
const triSurface& surf1,
const scalarField& surf1PointTol,
const label edgeI,
Random& rndGen,
pointField& points1,
boolList& affectedEdges
) const;
//- Perturb single endpoint of edge if edge is algigned with face.
// See inlinePerturb. Return true if anything changed.
bool rotatePerturb
(
const triSurface& surf1,
const scalarField& surf1PointTol,
const label edgeI,
Random& rndGen,
pointField& points1,
boolList& affectedEdges
) const;
//- Perturb edge by shifting in direction trianglecentre - intersection
// when hits close to face. Update points, mark affected edges and
// return true if anything changed.
bool offsetPerturb
(
const triSurface& surf1,
const triSurface& surf2,
const label edgeI,
Random& rndGen,
pointField& points1,
boolList& affectedEdges
) const;
public:
ClassName("edgeIntersections");
// Static data members
//- cosine between edge and face normal when considered parallel
// (note: should be private and make access- and set- function)
static scalar alignedCos_;
// Static Functions
//- Calculate min edge length for every surface point
static scalarField minEdgeLength(const triSurface& surf);
// Constructors
//- Construct null
edgeIntersections();
//- Construct from surface and tolerance
edgeIntersections
(
const triSurface& surf1,
const triSurfaceSearch& query2,
const scalarField& surf1PointTol
);
//- Construct from components
edgeIntersections
(
const List<List<pointIndexHit> >&,
const labelListList&
);
// Member Functions
// Access
//- For every intersection the classification status.
const labelListList& classification() const
{
return classification_;
}
// Edit
//- Resolve ties. Shuffles points so all edge - face intersections
// will be on the face interior.
// Points will be the new surface points.
// Returns number of iterations needed. (= nIters if still
// has degenerate cuts)
label removeDegenerates
(
const label nIters,
const triSurface& surf1,
const triSurfaceSearch& query2,
const scalarField& surf1PointTol,
pointField& points1
);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,309 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Class
Foam::surfaceIntersection
Description
Basic surface-surface intersection description. Constructed from two
surfaces it creates a description of the intersection.
The intersection information consists of the intersection line(s)
with new points, new edges between points (note that these edges and
points are on both surfaces) and various addressing from original
surface faces/edges to intersection and vice versa.
Gets either precalculated intersection information or calculates it
itself.
Algorithm works by intersecting all edges of one surface with the other
surface and storing a reference from both faces (one on surface1, one on
surface 2) to the vertex. If the reference re-occurs we have the second
hit of both faces and an edge is created between the retrieved vertex and
the new one.
Note: when doing intersecting itself uses intersection::planarTol() as a
fraction of
current edge length to determine if intersection is a point-touching one
instead of an edge-piercing action.
SourceFiles
surfaceIntersection.C
surfaceIntersectionFuncs.C
surfaceIntersectionTemplates.C
\*---------------------------------------------------------------------------*/
#ifndef surfaceIntersection_H
#define surfaceIntersection_H
#include "DynamicList.H"
#include "point.H"
#include "edge.H"
#include "labelPairLookup.H"
#include "typeInfo.H"
#include "edgeList.H"
#include "pointIndexHit.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declaration of classes
class triSurfaceSearch;
class triSurface;
class edgeIntersections;
/*---------------------------------------------------------------------------*\
Class surfaceIntersection Declaration
\*---------------------------------------------------------------------------*/
class surfaceIntersection
{
// Private data
//- Newly introduced points.
pointField cutPoints_;
//- Newly introduced edges (are on both surfaces). Reference into
// cutPoints.
edgeList cutEdges_;
//- From face on surf1 and face on surf2 to intersection point
// (label in cutPoints)
labelPairLookup facePairToVertex_;
//- From face on surf1 and face on surf2 to intersection edge
// (label in cutEdges)
labelPairLookup facePairToEdge_;
//- Edges on surf1 that are cut. From edge on surf1 to label in cutPoint
// If multiple cuts:sorted from edge.start to edge.end
labelListList surf1EdgeCuts_;
//- Edges on surf2 that are cut. From edge on surf2 to label in cutPoint
// If multiple cuts:sorted from edge.start to edge.end
labelListList surf2EdgeCuts_;
// Private Member Functions
//- Write point in obj format.
static void writeOBJ(const point& pt, Ostream& os);
//- Write points and edges in obj format
static void writeOBJ
(
const List<point>&,
const List<edge>&,
Ostream&
);
//- Transfer contents of DynamicList to straight List
template<class T>
static void transfer(DynamicList<T>&, List<T>&);
//- Transfer contents of List<DynamicList<..> > to List<List<..>>
template<class T>
static void transfer(List<DynamicList<T> >&, List<List<T> >&);
//- Get minimum length of all edges connected to point
static scalar minEdgeLen(const triSurface& surf, const label pointI);
//- Get edge label of edge between face vertices fp and fp+1
static label getEdge
(
const triSurface& surf,
const label faceI,
const label fp
);
//- Remove duplicates from ordered dynamic list. Returns map from old
// to new (-1 if element removed)
static void removeDuplicates(const labelList& map, labelList& labels);
//- Apply map to elements of a labelList
static void inlineRemap(const labelList& map, labelList& elems);
// Remove all duplicate and degenerate elements. Return unique elements
// and map from old to new.
static edgeList filterEdges(const edgeList&, labelList& map);
//- Remove all duplicate elements.
static labelList filterLabels(const labelList& elems, labelList& map);
//- Do some checks if edge and face (resulting from hit)
// should not be considered. Returns true if can be discarded.
static bool excludeEdgeHit
(
const triSurface& surf,
const label edgeI,
const label faceI,
const scalar tol
);
////- Given edge (eStart - eEnd) and normal direction construct plane
//// and intersect all edges of hitFace with it.
//// Return the edge and coordinate of hit.
//static pointIndexHit faceEdgeIntersection
//(
// const triSurface&,
// const label hitFaceI,
//
// const vector& n,
// const point& eStart,
// const point& eEnd
//);
//- Debugging: Dump intersected edges to stream
void writeIntersectedEdges
(
const triSurface& surf,
const labelListList& edgeCutVerts,
Ostream& os
) const;
//- Detect if point close to edge of end. Returns -1: not close.
// 0:close (within startTol) to start, 1:close (within endTol) to end
static label classify
(
const scalar startTol,
const scalar endTol,
const point& p,
const edge& e,
const pointField& points
);
//- Update reference between faceA and faceB. Updates facePairToVertex_
// (first occurrence of face pair) and facePairToEdge_ (second occ.)
void storeIntersection
(
const bool isFirstSurf,
const labelList& facesA,
const label faceB,
DynamicList<edge>&,
DynamicList<point>&
);
//- Investigate pHit to whether is case of point hits point,
// point hits edge, point hits face or edge hits face.
void classifyHit
(
const triSurface& surf1,
const scalarField& surf1PointTol,
const triSurface& surf2,
const bool isFirstSurf,
const label edgeI,
const scalar tolDim,
const pointIndexHit& pHit,
DynamicList<edge>& allCutEdges,
DynamicList<point>& allCutPoints,
List<DynamicList<label> >& surfEdgeCuts
);
//- Cut edges of surf1 with surface 2.
void doCutEdges
(
const triSurface& surf1,
const triSurfaceSearch& querySurf2,
const bool isFirstSurf,
const bool isSelfIntersection,
DynamicList<edge>& allCutEdges,
DynamicList<point>& allCutPoints,
List<DynamicList<label> >& surfEdgeCuts
);
public:
ClassName("surfaceIntersection");
// Constructors
//- Construct null
surfaceIntersection();
//- Construct from precalculated intersection information.
// Advantage: intersection information is guaranteed to have no
// degenerate cuts.
surfaceIntersection
(
const triSurface& surf1,
const edgeIntersections& intersections1,
const triSurface& surf2,
const edgeIntersections& intersections2
);
//- Construct from two surfaces. Does all its own cutting.
// Has problems with degenerate cuts
surfaceIntersection
(
const triSurfaceSearch& querySurf1,
const triSurfaceSearch& querySurf2
);
//- Special: intersect surface with itself. Used to check for
// self-intersection.
surfaceIntersection(const triSurfaceSearch& querySurf1);
// Member Functions
const pointField& cutPoints() const;
const edgeList& cutEdges() const;
//const labelPairLookup& facePairToVertex() const;
const labelPairLookup& facePairToEdge() const;
//- Access either surf1EdgeCuts (isFirstSurface = true) or
// surf2EdgeCuts
const labelListList& edgeCuts(const bool) const;
const labelListList& surf1EdgeCuts() const;
const labelListList& surf2EdgeCuts() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "surfaceIntersectionTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,341 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Description
\*---------------------------------------------------------------------------*/
#include "surfaceIntersection.H"
#include "triSurfaceSearch.H"
#include "labelPairLookup.H"
#include "OFstream.H"
#include "HashSet.H"
#include "labelHashSet.H"
#include "triSurface.H"
#include "pointIndexHit.H"
#include "octreeDataTriSurface.H"
#include "octree.H"
#include "meshTools.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::surfaceIntersection::writeOBJ(const point& pt, Ostream& os)
{
os << "v " << pt.x() << ' ' << pt.y() << ' ' << pt.z() << endl;
}
void Foam::surfaceIntersection::writeOBJ
(
const List<point>& pts,
const List<edge>& edges,
Ostream& os
)
{
forAll(pts, i)
{
writeOBJ(pts[i], os);
}
forAll(edges, i)
{
const edge& e = edges[i];
os << "l " << e.start()+1 << ' ' << e.end()+1 << endl;
}
}
// Get minimum length of all edges connected to point
Foam::scalar Foam::surfaceIntersection::minEdgeLen
(
const triSurface& surf,
const label pointI
)
{
const labelList& pEdges = surf.pointEdges()[pointI];
scalar minLen = GREAT;
forAll(pEdges, pEdgeI)
{
const edge& e = surf.edges()[pEdges[pEdgeI]];
minLen = min(minLen, e.mag(surf.localPoints()));
}
return minLen;
}
// Get edge between fp and fp+1 on faceI.
Foam::label Foam::surfaceIntersection::getEdge
(
const triSurface& surf,
const label faceI,
const label fp
)
{
const labelledTri& f = surf.localFaces()[faceI];
edge faceEdge(f[fp], f[(fp+1) % 3]);
const labelList& eLabels = surf.faceEdges()[faceI];
forAll(eLabels, eI)
{
const label edgeI = eLabels[eI];
if (surf.edges()[edgeI] == faceEdge)
{
return edgeI;
}
}
FatalErrorIn
(
"surfaceIntersection::getEdge(const triSurface&"
", const label, const label"
) << "Problem:: Cannot find edge with vertices " << faceEdge
<< " in face " << faceI
<< abort(FatalError);
return -1;
}
// Given a map remove all consecutive duplicate elements.
void Foam::surfaceIntersection::removeDuplicates
(
const labelList& map,
labelList& elems
)
{
bool hasDuplicate = false;
label prevVertI = -1;
forAll(elems, elemI)
{
label newVertI = map[elems[elemI]];
if (newVertI == prevVertI)
{
hasDuplicate = true;
break;
}
prevVertI = newVertI;
}
if (hasDuplicate)
{
// Create copy
labelList oldElems(elems);
label elemI = 0;
// Insert first
elems[elemI++] = map[oldElems[0]];
for(label vertI = 1; vertI < oldElems.size(); vertI++)
{
// Insert others only if they differ from one before
label newVertI = map[oldElems[vertI]];
if (newVertI != elems[elems.size()-1])
{
elems[elemI++] = newVertI;
}
}
elems.setSize(elemI);
}
}
// Remap.
void Foam::surfaceIntersection::inlineRemap
(
const labelList& map,
labelList& elems
)
{
forAll(elems, elemI)
{
elems[elemI] = map[elems[elemI]];
}
}
// Remove all duplicate and degenerate elements. Return unique elements and
// map from old to new.
Foam::edgeList Foam::surfaceIntersection::filterEdges
(
const edgeList& edges,
labelList& map
)
{
HashSet<edge, Hash<edge> > uniqueEdges(10*edges.size());
edgeList newEdges(edges.size());
map.setSize(edges.size());
map = -1;
label newEdgeI = 0;
forAll(edges, edgeI)
{
const edge& e = edges[edgeI];
if
(
(e.start() != e.end())
&& (uniqueEdges.find(e) == uniqueEdges.end())
)
{
// Edge is -non degenerate and -not yet seen.
uniqueEdges.insert(e);
map[edgeI] = newEdgeI;
newEdges[newEdgeI++] = e;
}
}
newEdges.setSize(newEdgeI);
return newEdges;
}
// Remove all duplicate elements.
Foam::labelList Foam::surfaceIntersection::filterLabels
(
const labelList& elems,
labelList& map
)
{
labelHashSet uniqueElems(10*elems.size());
labelList newElems(elems.size());
map.setSize(elems.size());
map = -1;
label newElemI = 0;
forAll(elems, elemI)
{
label elem = elems[elemI];
if (uniqueElems.find(elem) == uniqueElems.end())
{
// First time elem is seen
uniqueElems.insert(elem);
map[elemI] = newElemI;
newElems[newElemI++] = elem;
}
}
newElems.setSize(newElemI);
return newElems;
}
void Foam::surfaceIntersection::writeIntersectedEdges
(
const triSurface& surf,
const labelListList& edgeCutVerts,
Ostream& os
) const
{
// Dump all points (surface followed by cutPoints)
const pointField& pts = surf.localPoints();
forAll(pts, pointI)
{
writeOBJ(pts[pointI], os);
}
forAll(cutPoints(), cutPointI)
{
writeOBJ(cutPoints()[cutPointI], os);
}
forAll(edgeCutVerts, edgeI)
{
const labelList& extraVerts = edgeCutVerts[edgeI];
if (extraVerts.size() != 0)
{
const edge& e = surf.edges()[edgeI];
// Start of original edge to first extra point
os << "l " << e.start()+1 << ' '
<< extraVerts[0] + surf.nPoints() + 1 << endl;
for(label i = 1; i < extraVerts.size(); i++)
{
os << "l " << extraVerts[i-1] + surf.nPoints() + 1 << ' '
<< extraVerts[i] + surf.nPoints() + 1 << endl;
}
os << "l " << extraVerts[extraVerts.size()-1] + surf.nPoints() + 1
<< ' ' << e.end()+1 << endl;
}
}
}
// Return 0 (p close to start), 1(close to end) or -1.
Foam::label Foam::surfaceIntersection::classify
(
const scalar startTol,
const scalar endTol,
const point& p,
const edge& e,
const pointField& points
)
{
if (mag(p - points[e.start()]) < startTol)
{
return 0;
}
else if (mag(p - points[e.end()]) < endTol)
{
return 1;
}
else
{
return -1;
}
}
// ************************************************************************* //

View File

@ -0,0 +1,64 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 1991-2007 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2 of the License, or (at your
option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
Description
\*---------------------------------------------------------------------------*/
#include "surfaceIntersection.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
// Transfer contents of DynamicList to List
template<class T>
void Foam::surfaceIntersection::transfer
(
DynamicList<T>& dList,
List<T>& lList
)
{
dList.shrink();
lList.transfer(dList);
dList.clear();
}
// Transfer contents of DynamicList to List
template<class T>
void Foam::surfaceIntersection::transfer
(
List<DynamicList<T> >& dList,
List<List<T> >& lList
)
{
lList.setSize(dList.size());
forAll(dList, elemI)
{
transfer(dList[elemI], lList[elemI]);
}
}
// ************************************************************************* //