mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
Reintroducing CV meshers after removal by a commit in master, originating in the dsmc branch.
This commit is contained in:
@ -0,0 +1,84 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
Typedefs
|
||||
CGALTriangulation2Ddefs
|
||||
|
||||
Description
|
||||
CGAL data structures used for 2D Delaunay meshing.
|
||||
|
||||
Define CGAL_INEXACT to use Exact_predicates_inexact_constructions kernel
|
||||
otherwise the more robust but much less efficient
|
||||
Exact_predicates_exact_constructions will be used.
|
||||
|
||||
Define CGAL_HIERARCHY to use hierarchical Delaunay triangulation which is
|
||||
faster but uses more memory than the standard Delaunay triangulation.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CGALTriangulation2Ddefs_H
|
||||
#define CGALTriangulation2Ddefs_H
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "CGAL/Delaunay_triangulation_2.h"
|
||||
|
||||
#include "indexedVertex.H"
|
||||
#include "indexedFace.H"
|
||||
|
||||
#ifdef CGAL_INEXACT
|
||||
// Fast kernel using a double as the storage type but the triangulation
|
||||
// may fail
|
||||
#include "CGAL/Exact_predicates_inexact_constructions_kernel.h"
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
#else
|
||||
// Very robust but expensive kernel
|
||||
#include "CGAL/Exact_predicates_exact_constructions_kernel.h"
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel K;
|
||||
#endif
|
||||
|
||||
typedef CGAL::indexedVertex<K> Vb;
|
||||
typedef CGAL::indexedFace<K> Fb;
|
||||
|
||||
#ifdef CGAL_HIERARCHY
|
||||
// Data structures for hierarchical Delaunay triangulation which is more
|
||||
// efficient but also uses more storage
|
||||
#include "CGAL/Triangulation_hierarchy_2.h"
|
||||
typedef CGAL::Triangulation_hierarchy_vertex_base_2<Vb> Vbh;
|
||||
typedef CGAL::Triangulation_data_structure_2<Vbh, Fb> Tds;
|
||||
typedef CGAL::Delaunay_triangulation_2<K, Tds> Triangulation;
|
||||
typedef CGAL::Triangulation_hierarchy_2<Triangulation> HTriangulation;
|
||||
#else
|
||||
// Data structures for standard Delaunay triangulation
|
||||
typedef CGAL::Triangulation_data_structure_2<Vb, Fb> Tds;
|
||||
typedef CGAL::Delaunay_triangulation_2<K, Tds> Triangulation;
|
||||
typedef Triangulation HTriangulation;
|
||||
#endif
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
567
applications/utilities/mesh/generation/CV2DMesher/CV2D.C
Normal file
567
applications/utilities/mesh/generation/CV2DMesher/CV2D.C
Normal file
@ -0,0 +1,567 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV2D.H"
|
||||
#include "Random.H"
|
||||
#include "transform.H"
|
||||
#include "IFstream.H"
|
||||
#include "uint.H"
|
||||
#include "ulong.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::CV2D::insertBoundingBox()
|
||||
{
|
||||
Info<< "insertBoundingBox: creating bounding mesh" << endl;
|
||||
scalar bigSpan = 10*tols_.span;
|
||||
insertPoint(point2D(-bigSpan, -bigSpan), Vb::FAR_POINT);
|
||||
insertPoint(point2D(-bigSpan, bigSpan), Vb::FAR_POINT);
|
||||
insertPoint(point2D(bigSpan, -bigSpan), Vb::FAR_POINT);
|
||||
insertPoint(point2D(bigSpan, bigSpan), Vb::FAR_POINT);
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::fast_restore_Delaunay(Vertex_handle vh)
|
||||
{
|
||||
int i;
|
||||
Face_handle f = vh->face(), next, start(f);
|
||||
|
||||
do
|
||||
{
|
||||
i=f->index(vh);
|
||||
if (!is_infinite(f))
|
||||
{
|
||||
if (!internal_flip(f, cw(i))) external_flip(f, i);
|
||||
if (f->neighbor(i) == start) start = f;
|
||||
}
|
||||
f = f->neighbor(cw(i));
|
||||
} while (f != start);
|
||||
}
|
||||
|
||||
void Foam::CV2D::external_flip(Face_handle& f, int i)
|
||||
{
|
||||
Face_handle n = f->neighbor(i);
|
||||
|
||||
if
|
||||
(
|
||||
CGAL::ON_POSITIVE_SIDE
|
||||
!= side_of_oriented_circle(n, f->vertex(i)->point())
|
||||
) return;
|
||||
|
||||
flip(f, i);
|
||||
i = n->index(f->vertex(i));
|
||||
external_flip(n, i);
|
||||
}
|
||||
|
||||
bool Foam::CV2D::internal_flip(Face_handle& f, int i)
|
||||
{
|
||||
Face_handle n = f->neighbor(i);
|
||||
|
||||
if
|
||||
(
|
||||
CGAL::ON_POSITIVE_SIDE
|
||||
!= side_of_oriented_circle(n, f->vertex(i)->point())
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
flip(f, i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::CV2D::CV2D
|
||||
(
|
||||
const dictionary& controlDict,
|
||||
const querySurface& qSurf
|
||||
)
|
||||
:
|
||||
HTriangulation(),
|
||||
qSurf_(qSurf),
|
||||
controls_(controlDict),
|
||||
tols_(controlDict, controls_.minCellSize, qSurf.bb()),
|
||||
z_((1.0/3.0)*(qSurf_.bb().min().z() + qSurf_.bb().max().z())),
|
||||
startOfInternalPoints_(0),
|
||||
startOfSurfacePointPairs_(0),
|
||||
startOfBoundaryConformPointPairs_(0)
|
||||
{
|
||||
insertBoundingBox();
|
||||
insertFeaturePoints();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::CV2D::~CV2D()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::CV2D::insertPoints
|
||||
(
|
||||
const point2DField& points,
|
||||
const scalar nearness
|
||||
)
|
||||
{
|
||||
Info<< "insertInitialPoints(const point2DField& points): ";
|
||||
|
||||
startOfInternalPoints_ = number_of_vertices();
|
||||
label nVert = startOfInternalPoints_;
|
||||
|
||||
// Add the points and index them
|
||||
forAll(points, i)
|
||||
{
|
||||
const point2D& p = points[i];
|
||||
|
||||
if (qSurf_.wellInside(toPoint3D(p), nearness))
|
||||
{
|
||||
insert(toPoint(p))->index() = nVert++;
|
||||
}
|
||||
else
|
||||
{
|
||||
Warning
|
||||
<< "Rejecting point " << p << " outside surface" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
Info<< nVert << " vertices inserted" << endl;
|
||||
|
||||
if (controls_.writeInitialTriangulation)
|
||||
{
|
||||
// Checking validity of triangulation
|
||||
assert(is_valid());
|
||||
|
||||
writeTriangles("initial_triangles.obj", true);
|
||||
writeFaces("initial_faces.obj", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::insertPoints(const fileName& pointFileName)
|
||||
{
|
||||
IFstream pointsFile(pointFileName);
|
||||
|
||||
if (pointsFile.good())
|
||||
{
|
||||
insertPoints(point2DField(pointsFile), 0.5*controls_.minCellSize2);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorIn("insertInitialPoints")
|
||||
<< "Could not open pointsFile " << pointFileName
|
||||
<< exit(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::insertGrid()
|
||||
{
|
||||
Info<< "insertInitialGrid: ";
|
||||
|
||||
startOfInternalPoints_ = number_of_vertices();
|
||||
label nVert = startOfInternalPoints_;
|
||||
|
||||
scalar x0 = qSurf_.bb().min().x();
|
||||
scalar xR = qSurf_.bb().max().x() - x0;
|
||||
int ni = int(xR/controls_.minCellSize) + 1;
|
||||
scalar deltax = xR/ni;
|
||||
|
||||
scalar y0 = qSurf_.bb().min().y();
|
||||
scalar yR = qSurf_.bb().max().y() - y0;
|
||||
int nj = int(yR/controls_.minCellSize) + 1;
|
||||
scalar deltay = yR/nj;
|
||||
|
||||
Random rndGen(1321);
|
||||
scalar pert = controls_.randomPurturbation*min(deltax, deltay);
|
||||
|
||||
for (int i=0; i<ni; i++)
|
||||
{
|
||||
for (int j=0; j<nj; j++)
|
||||
{
|
||||
point p(x0 + i*deltax, y0 + j*deltay, 0);
|
||||
|
||||
if (controls_.randomiseInitialGrid)
|
||||
{
|
||||
p.x() += pert*(rndGen.scalar01() - 0.5);
|
||||
p.y() += pert*(rndGen.scalar01() - 0.5);
|
||||
}
|
||||
|
||||
if (qSurf_.wellInside(p, 0.5*controls_.minCellSize2))
|
||||
{
|
||||
insert(Point(p.x(), p.y()))->index() = nVert++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< nVert << " vertices inserted" << endl;
|
||||
|
||||
if (controls_.writeInitialTriangulation)
|
||||
{
|
||||
// Checking validity of triangulation
|
||||
assert(is_valid());
|
||||
|
||||
writeTriangles("initial_triangles.obj", true);
|
||||
writeFaces("initial_faces.obj", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::insertSurfacePointPairs()
|
||||
{
|
||||
startOfSurfacePointPairs_ = number_of_vertices();
|
||||
|
||||
if (controls_.insertSurfaceNearestPointPairs)
|
||||
{
|
||||
insertSurfaceNearestPointPairs();
|
||||
}
|
||||
|
||||
if (controls_.writeNearestTriangulation)
|
||||
{
|
||||
writeFaces("near_allFaces.obj", false);
|
||||
writeFaces("near_faces.obj", true);
|
||||
writeTriangles("near_triangles.obj", true);
|
||||
}
|
||||
|
||||
// Insertion of point-pais for near-points may cause protrusions
|
||||
// so insertBoundaryConformPointPairs must be executed last
|
||||
if (controls_.insertSurfaceNearPointPairs)
|
||||
{
|
||||
insertSurfaceNearPointPairs();
|
||||
}
|
||||
|
||||
startOfBoundaryConformPointPairs_ = number_of_vertices();
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::boundaryConform()
|
||||
{
|
||||
if (!controls_.insertSurfaceNearestPointPairs)
|
||||
{
|
||||
markNearBoundaryPoints();
|
||||
}
|
||||
|
||||
// Mark all the faces as SAVE_CHANGED
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_faces_iterator fit = finite_faces_begin();
|
||||
fit != finite_faces_end();
|
||||
fit++
|
||||
)
|
||||
{
|
||||
fit->faceIndex() = Fb::SAVE_CHANGED;
|
||||
}
|
||||
|
||||
for (label iter=1; iter<=controls_.maxBoundaryConformingIter; iter++)
|
||||
{
|
||||
label nIntersections = insertBoundaryConformPointPairs
|
||||
(
|
||||
"surfaceIntersections_" + Foam::name(iter) + ".obj"
|
||||
);
|
||||
|
||||
if (nIntersections == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "BC iteration " << iter << ": "
|
||||
<< nIntersections << " point-pairs inserted" << endl;
|
||||
}
|
||||
|
||||
// Any faces changed by insertBoundaryConformPointPairs will now
|
||||
// be marked CHANGED, mark those as SAVE_CHANGED and those that
|
||||
// remained SAVE_CHANGED as UNCHANGED
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_faces_iterator fit = finite_faces_begin();
|
||||
fit != finite_faces_end();
|
||||
fit++
|
||||
)
|
||||
{
|
||||
if (fit->faceIndex() == Fb::SAVE_CHANGED)
|
||||
{
|
||||
fit->faceIndex() = Fb::UNCHANGED;
|
||||
}
|
||||
else if (fit->faceIndex() == Fb::CHANGED)
|
||||
{
|
||||
fit->faceIndex() = Fb::SAVE_CHANGED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< nl;
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::removeSurfacePointPairs()
|
||||
{
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
++vit
|
||||
)
|
||||
{
|
||||
if (vit->index() >= startOfSurfacePointPairs_)
|
||||
{
|
||||
remove(vit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::newPoints(const scalar relaxation)
|
||||
{
|
||||
Info<< "newPointsFromVertices: ";
|
||||
|
||||
const vectorField& faceNormals = qSurf_.faceNormals();
|
||||
|
||||
// Initialise the total displacement and its distance for writing out
|
||||
vector2D totalDisp = vector2D::zero;
|
||||
scalar totalDist = 0;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
++vit
|
||||
)
|
||||
{
|
||||
if (vit->internalPoint())
|
||||
{
|
||||
// Current dual-cell defining vertex ("centre")
|
||||
point2DFromPoint defVert0 = toPoint2D(vit->point());
|
||||
|
||||
Triangulation::Edge_circulator ec = incident_edges(vit);
|
||||
Triangulation::Edge_circulator ecStart = ec;
|
||||
|
||||
// Circulate around the edges to find the first which is not
|
||||
// infinite
|
||||
do
|
||||
{
|
||||
if (!is_infinite(ec)) break;
|
||||
} while (++ec != ecStart);
|
||||
|
||||
// Store the start-end of the first non-infinte edge
|
||||
point2D de0 = toPoint2D(circumcenter(ec->first));
|
||||
|
||||
// Keep track of the maximum edge length^2
|
||||
scalar maxEdgeLen2 = 0.0;
|
||||
|
||||
// Keep track of the index of the longest edge
|
||||
label edgecd0i = -1;
|
||||
|
||||
// Edge counter
|
||||
label edgei = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (!is_infinite(ec))
|
||||
{
|
||||
// Get the end of the current edge
|
||||
point2D de1 = toPoint2D
|
||||
(
|
||||
circumcenter(ec->first->neighbor(ec->second))
|
||||
);
|
||||
|
||||
// Store the current edge vector
|
||||
edges[edgei] = de1 - de0;
|
||||
|
||||
// Store the edge mid-point in the vertices array
|
||||
vertices[edgei] = 0.5*(de1 + de0);
|
||||
|
||||
// Move the current edge end into the edge start for the
|
||||
// next iteration
|
||||
de0 = de1;
|
||||
|
||||
// Keep track of the longest edge
|
||||
|
||||
scalar edgeLen2 = magSqr(edges[edgei]);
|
||||
|
||||
if (edgeLen2 > maxEdgeLen2)
|
||||
{
|
||||
maxEdgeLen2 = edgeLen2;
|
||||
edgecd0i = edgei;
|
||||
}
|
||||
|
||||
edgei++;
|
||||
}
|
||||
} while (++ec != ecStart);
|
||||
|
||||
// Initialise cd0 such that the mesh will align
|
||||
// in in the x-y directions
|
||||
vector2D cd0(1, 0);
|
||||
|
||||
if (controls_.relaxOrientation)
|
||||
{
|
||||
// Get the longest edge from the array and use as the primary
|
||||
// direction of the coordinate system of the "square" cell
|
||||
cd0 = edges[edgecd0i];
|
||||
}
|
||||
|
||||
if (controls_.nearWallAlignedDist > 0)
|
||||
{
|
||||
pointIndexHit pHit = qSurf_.tree().findNearest
|
||||
(
|
||||
toPoint3D(defVert0),
|
||||
controls_.nearWallAlignedDist2
|
||||
);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
cd0 = toPoint2D(faceNormals[pHit.index()]);
|
||||
}
|
||||
}
|
||||
|
||||
// Rotate by 45deg needed to create an averaging procedure which
|
||||
// encourages the cells to be square
|
||||
cd0 = vector2D(cd0.x() + cd0.y(), cd0.y() - cd0.x());
|
||||
|
||||
// Normalise the primary coordinate direction
|
||||
cd0 /= mag(cd0);
|
||||
|
||||
// Calculate the orthogonal coordinate direction
|
||||
vector2D cd1(-cd0.y(), cd0.x());
|
||||
|
||||
|
||||
// Restart the circulator
|
||||
ec = ecStart;
|
||||
|
||||
// ... and the counter
|
||||
edgei = 0;
|
||||
|
||||
// Initialise the displacement for the centre and sum-weights
|
||||
vector2D disp = vector2D::zero;
|
||||
scalar sumw = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (!is_infinite(ec))
|
||||
{
|
||||
// Pick up the current edge
|
||||
const vector2D& ei = edges[edgei];
|
||||
|
||||
// Calculate the centre to edge-centre vector
|
||||
vector2D deltai = vertices[edgei] - defVert0;
|
||||
|
||||
// Set the weight for this edge contribution
|
||||
scalar w = 1;
|
||||
|
||||
if (controls_.squares)
|
||||
{
|
||||
w = magSqr(deltai.x()*ei.y() - deltai.y()*ei.x());
|
||||
// alternative weights
|
||||
//w = mag(deltai.x()*ei.y() - deltai.y()*ei.x());
|
||||
//w = magSqr(ei)*mag(deltai);
|
||||
|
||||
// Use the following for an ~square mesh
|
||||
// Find the coordinate contributions for this edge delta
|
||||
scalar cd0deltai = cd0 & deltai;
|
||||
scalar cd1deltai = cd1 & deltai;
|
||||
|
||||
// Create a "square" displacement
|
||||
if (mag(cd0deltai) > mag(cd1deltai))
|
||||
{
|
||||
disp += (w*cd0deltai)*cd0;
|
||||
}
|
||||
else
|
||||
{
|
||||
disp += (w*cd1deltai)*cd1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use this for a hexagon/pentagon mesh
|
||||
disp += w*deltai;
|
||||
}
|
||||
|
||||
// Sum the weights
|
||||
sumw += w;
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalErrorIn("CV2D::newPoints() const")
|
||||
<< "Infinite triangle found in internal mesh"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
edgei++;
|
||||
|
||||
} while (++ec != ecStart);
|
||||
|
||||
// Calculate the average displacement
|
||||
disp /= sumw;
|
||||
totalDisp += disp;
|
||||
totalDist += mag(disp);
|
||||
|
||||
// Move the point by a fraction of the average displacement
|
||||
movePoint(vit, defVert0 + relaxation*disp);
|
||||
}
|
||||
}
|
||||
|
||||
Info << "\nTotal displacement = " << totalDisp
|
||||
<< " total distance = " << totalDist << endl;
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::moveInternalPoints(const point2DField& newPoints)
|
||||
{
|
||||
label pointI = 0;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
++vit
|
||||
)
|
||||
{
|
||||
if (vit->internalPoint())
|
||||
{
|
||||
movePoint(vit, newPoints[pointI++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::write() const
|
||||
{
|
||||
if (controls_.writeFinalTriangulation)
|
||||
{
|
||||
writeFaces("allFaces.obj", false);
|
||||
writeFaces("faces.obj", true);
|
||||
writeTriangles("allTriangles.obj", false);
|
||||
writeTriangles("triangles.obj", true);
|
||||
writePatch("patch.pch");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
514
applications/utilities/mesh/generation/CV2DMesher/CV2D.H
Normal file
514
applications/utilities/mesh/generation/CV2DMesher/CV2D.H
Normal file
@ -0,0 +1,514 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
CV2D
|
||||
|
||||
Description
|
||||
Conformal-Voronoi 2D automatic mesher with grid or read initial points
|
||||
and point position relaxation with optional "squarification".
|
||||
|
||||
There are a substantial number of options to this mesher read from
|
||||
CV2DMesherDict file e.g.:
|
||||
|
||||
// Min cell size used in tolerances when inserting points for
|
||||
// boundary conforming.
|
||||
// Also used to as the grid spacing usind in insertGrid.
|
||||
minCellSize 0.05;
|
||||
|
||||
// Feature angle used to inser feature points
|
||||
// 0 = all features, 180 = no features
|
||||
featureAngle 45;
|
||||
|
||||
// Maximum quadrant angle allowed at a concave corner before
|
||||
// additional "mitering" lines are added
|
||||
maxQuadAngle 110;
|
||||
|
||||
// Should the mesh be square-dominated or of unbiased hexagons
|
||||
squares yes;
|
||||
|
||||
// Near-wall region where cells are aligned with the wall specified as a
|
||||
// number of cell layers
|
||||
nearWallAlignedDist 3;
|
||||
|
||||
// Chose if the cell orientation should relax during the iterations
|
||||
// or remain fixed to the x-y directions
|
||||
relaxOrientation no;
|
||||
|
||||
// Insert near-boundary point mirror or point-pairs
|
||||
insertSurfaceNearestPointPairs yes;
|
||||
|
||||
// Mirror near-boundary points rather than insert point-pairs
|
||||
mirrorPoints no;
|
||||
|
||||
// Insert point-pairs vor dual-cell vertices very near the surface
|
||||
insertSurfaceNearPointPairs yes;
|
||||
|
||||
// Choose if to randomise the initial grid created by insertGrid.
|
||||
randomiseInitialGrid yes;
|
||||
|
||||
// Perturbation fraction, 1 = cell-size.
|
||||
randomPurturbation 0.1;
|
||||
|
||||
// Number of relaxation iterations.
|
||||
nIterations 5;
|
||||
|
||||
// Relaxation factor at the start of the iteration sequence.
|
||||
// 0.5 is a sensible maximum and < 0.2 converges better.
|
||||
relaxationFactorStart 0.8;
|
||||
|
||||
// Relaxation factor at the end of the iteration sequence.
|
||||
// Should be <= relaxationFactorStart
|
||||
relaxationFactorEnd 0;
|
||||
|
||||
writeInitialTriangulation no;
|
||||
writeFeatureTriangulation no;
|
||||
writeNearestTriangulation no;
|
||||
writeInsertedPointPairs no;
|
||||
writeFinalTriangulation yes;
|
||||
|
||||
// Maximum number of iterations used in boundaryConform.
|
||||
maxBoundaryConformingIter 5;
|
||||
|
||||
minEdgeLenCoeff 0.5;
|
||||
maxNotchLenCoeff 0.3;
|
||||
minNearPointDistCoeff 0.25;
|
||||
ppDistCoeff 0.05;
|
||||
|
||||
SourceFiles
|
||||
CGALTriangulation2Ddefs.H
|
||||
indexedVertex.H
|
||||
indexedFace.H
|
||||
CV2DI.H
|
||||
CV2D.C
|
||||
CV2DIO.C
|
||||
tolerances.C
|
||||
controls.C
|
||||
insertFeaturePoints.C
|
||||
insertSurfaceNearestPointPairs.C
|
||||
insertSurfaceNearPointPairs.C
|
||||
insertBoundaryConformPointPairs.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CV2D_H
|
||||
#define CV2D_H
|
||||
|
||||
#define CGAL_INEXACT
|
||||
#define CGAL_HIERARCHY
|
||||
|
||||
#include "CGALTriangulation2Ddefs.H"
|
||||
|
||||
#include "querySurface.H"
|
||||
#include "point2DFieldFwd.H"
|
||||
#include "dictionary.H"
|
||||
#include "Switch.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class CV2D Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class CV2D
|
||||
:
|
||||
public HTriangulation
|
||||
{
|
||||
public:
|
||||
|
||||
class controls
|
||||
{
|
||||
public:
|
||||
|
||||
//- Minimum cell size below which protusions through the surface are
|
||||
// not split
|
||||
scalar minCellSize;
|
||||
|
||||
//- Square of minCellSize
|
||||
scalar minCellSize2;
|
||||
|
||||
//- The feature angle used to select corners to be
|
||||
// explicitly represented in the mesh.
|
||||
// 0 = all features, 180 = no features
|
||||
scalar featAngle;
|
||||
|
||||
//- Maximum quadrant angle allowed at a concave corner before
|
||||
// additional "mitering" lines are added
|
||||
scalar maxQuadAngle;
|
||||
|
||||
//- Should the mesh be square-dominated or of unbiased hexagons
|
||||
Switch squares;
|
||||
|
||||
//- Near-wall region where cells are aligned with the wall
|
||||
scalar nearWallAlignedDist;
|
||||
|
||||
//- Square of nearWallAlignedDist
|
||||
scalar nearWallAlignedDist2;
|
||||
|
||||
//- Chose if the cell orientation should relax during the iterations
|
||||
// or remain fixed to the x-y directions
|
||||
Switch relaxOrientation;
|
||||
|
||||
//- Insert near-boundary point mirror or point-pairs
|
||||
Switch insertSurfaceNearestPointPairs;
|
||||
|
||||
//- Mirror near-boundary points rather than insert point-pairs
|
||||
Switch mirrorPoints;
|
||||
|
||||
//- Insert point-pairs vor dual-cell vertices very near the surface
|
||||
Switch insertSurfaceNearPointPairs;
|
||||
|
||||
Switch writeInitialTriangulation;
|
||||
Switch writeFeatureTriangulation;
|
||||
Switch writeNearestTriangulation;
|
||||
Switch writeInsertedPointPairs;
|
||||
Switch writeFinalTriangulation;
|
||||
|
||||
Switch randomiseInitialGrid;
|
||||
scalar randomPurturbation;
|
||||
|
||||
label maxBoundaryConformingIter;
|
||||
|
||||
//- Relaxation factor at the start of the iteration
|
||||
scalar relaxationFactorStart;
|
||||
|
||||
//- Relaxation factor at the end of the iteration
|
||||
scalar relaxationFactorEnd;
|
||||
|
||||
controls(const dictionary& controlDict);
|
||||
};
|
||||
|
||||
|
||||
class tolerances
|
||||
{
|
||||
public:
|
||||
|
||||
//- Maximum cartesian span of the geometry
|
||||
scalar span;
|
||||
|
||||
//- Square of span
|
||||
scalar span2;
|
||||
|
||||
//- Minumum edge-length of the cell size below which protusions
|
||||
// through the surface are not split
|
||||
scalar minEdgeLen;
|
||||
|
||||
//- Square of minEdgeLen
|
||||
scalar minEdgeLen2;
|
||||
|
||||
//- Maximum notch size below which protusions into the surface are
|
||||
// not filled
|
||||
scalar maxNotchLen;
|
||||
|
||||
//- Square of maxNotchLen
|
||||
scalar maxNotchLen2;
|
||||
|
||||
//- The minimum distance alowed between a dual-cell vertex
|
||||
// and the surface before a point-pair is introduced
|
||||
scalar minNearPointDist;
|
||||
|
||||
//- Square of minNearPoint
|
||||
scalar minNearPointDist2;
|
||||
|
||||
//- Distance between boundary conforming point-pairs
|
||||
scalar ppDist;
|
||||
|
||||
//- Square of ppDist
|
||||
scalar ppDist2;
|
||||
|
||||
tolerances
|
||||
(
|
||||
const dictionary& controlDict,
|
||||
scalar minCellSize,
|
||||
const boundBox&
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- The surface to mesh
|
||||
const querySurface& qSurf_;
|
||||
|
||||
//- Meshing controls
|
||||
controls controls_;
|
||||
|
||||
//- Meshing tolerances
|
||||
tolerances tols_;
|
||||
|
||||
//- z-level
|
||||
scalar z_;
|
||||
|
||||
//- Keep track of the start of the internal points
|
||||
label startOfInternalPoints_;
|
||||
|
||||
//- Keep track of the start of the surface point-pairs
|
||||
label startOfSurfacePointPairs_;
|
||||
|
||||
//- Keep track of the boundary conform point-pairs
|
||||
// stored after the insertion of the surface point-pairs in case
|
||||
// the boundary conform function is called more than once without
|
||||
// removing and insertin the surface point-pairs
|
||||
label startOfBoundaryConformPointPairs_;
|
||||
|
||||
//- Temporary storage for a dual-cell
|
||||
static const label maxNvert = 20;
|
||||
mutable point2D vertices[maxNvert+1];
|
||||
mutable vector2D edges[maxNvert+1];
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
CV2D(const CV2D&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const CV2D&);
|
||||
|
||||
|
||||
//- Insert point and return it's index
|
||||
inline label insertPoint
|
||||
(
|
||||
const point2D& pt,
|
||||
const label type
|
||||
);
|
||||
|
||||
inline bool insertMirrorPoint
|
||||
(
|
||||
const point2D& nearSurfPt,
|
||||
const point2D& surfPt
|
||||
);
|
||||
|
||||
//- Insert a point-pair at a distance ppDist either side of
|
||||
// surface point point surfPt in the direction n
|
||||
inline void insertPointPair
|
||||
(
|
||||
const scalar mirrorDist,
|
||||
const point2D& surfPt,
|
||||
const vector2D& n
|
||||
);
|
||||
|
||||
//- Create the initial mesh from the bounding-box
|
||||
void insertBoundingBox();
|
||||
|
||||
//- Insert point groups at the feature points.
|
||||
void insertFeaturePoints();
|
||||
|
||||
//- Insert point-pairs at the given set of points using the surface
|
||||
// normals corresponding to the given set of surface triangles
|
||||
// and write the inserted point locations to the given file.
|
||||
void insertPointPairs
|
||||
(
|
||||
const DynamicList<point2D>& nearSurfacePoints,
|
||||
const DynamicList<point2D>& surfacePoints,
|
||||
const DynamicList<label>& surfaceTris,
|
||||
const fileName fName
|
||||
);
|
||||
|
||||
//- Check to see if dual cell specified by given vertex iterator
|
||||
// intersects the boundary and hence reqires a point-pair.
|
||||
bool dualCellSurfaceIntersection
|
||||
(
|
||||
const Triangulation::Finite_vertices_iterator& vit
|
||||
) const;
|
||||
|
||||
//- Insert point-pairs at the nearest points on the surface to the
|
||||
// control vertex of dual-cells which intersect the boundary in order
|
||||
// to provide a boundary-layer mesh.
|
||||
// NB: This is not guaranteed to close the boundary
|
||||
void insertSurfaceNearestPointPairs();
|
||||
|
||||
//- Insert point-pairs at small duak-cell edges on the surface in order
|
||||
// to improve the boundary-layer mesh generated by
|
||||
// insertSurfaceNearestPointPairs.
|
||||
void insertSurfaceNearPointPairs();
|
||||
|
||||
//- Insert point-pair and correcting the Finite_vertices_iterator
|
||||
// to account for the additional vertices
|
||||
void insertPointPair
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator& vit,
|
||||
const point2D& p,
|
||||
const label trii
|
||||
);
|
||||
|
||||
//- Insert point-pair at the best intersection point between the lines
|
||||
// from the dual-cell real centroid and it's vertices and the surface.
|
||||
bool insertPointPairAtIntersection
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator& vit,
|
||||
const point2D& defVert,
|
||||
const point2D vertices[],
|
||||
const scalar maxProtSize
|
||||
);
|
||||
|
||||
//- Insert point-pairs corresponding to dual-cells which intersect
|
||||
// the boundary surface
|
||||
label insertBoundaryConformPointPairs(const fileName& fName);
|
||||
|
||||
void markNearBoundaryPoints();
|
||||
|
||||
//- Restore the Delaunay contraint
|
||||
void fast_restore_Delaunay(Vertex_handle vh);
|
||||
|
||||
// Flip operations used by fast_restore_Delaunay
|
||||
void external_flip(Face_handle& f, int i);
|
||||
bool internal_flip(Face_handle& f, int i);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct for given surface
|
||||
CV2D(const dictionary& controlDict, const querySurface& qSurf);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
~CV2D();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
const controls& meshingControls() const
|
||||
{
|
||||
return controls_;
|
||||
}
|
||||
|
||||
|
||||
// Conversion functions between point2D, point and Point
|
||||
|
||||
inline const point2D& toPoint2D(const point&) const;
|
||||
inline point toPoint3D(const point2D&) const;
|
||||
|
||||
# ifdef CGAL_INEXACT
|
||||
typedef const point2D& point2DFromPoint;
|
||||
typedef const Point& PointFromPoint2D;
|
||||
# else
|
||||
typedef point2D point2DFromPoint;
|
||||
typedef Point PointFromPoint2D;
|
||||
# endif
|
||||
|
||||
inline point2DFromPoint toPoint2D(const Point&) const;
|
||||
inline PointFromPoint2D toPoint(const point2D&) const;
|
||||
inline point toPoint3D(const Point&) const;
|
||||
|
||||
|
||||
// Point insertion
|
||||
|
||||
//- Create the initial mesh from the given internal points.
|
||||
// Points must be inside the boundary by at least nearness
|
||||
// otherwise they are ignored.
|
||||
void insertPoints
|
||||
(
|
||||
const point2DField& points,
|
||||
const scalar nearness
|
||||
);
|
||||
|
||||
//- Create the initial mesh from the internal points in the given
|
||||
// file. Points outside the geometry are ignored.
|
||||
void insertPoints(const fileName& pointFileName);
|
||||
|
||||
//- Create the initial mesh as a regular grid of points.
|
||||
// Points outside the geometry are ignored.
|
||||
void insertGrid();
|
||||
|
||||
//- Insert all surface point-pairs from
|
||||
// insertSurfaceNearestPointPairs and
|
||||
// findIntersectionForOutsideCentroid
|
||||
void insertSurfacePointPairs();
|
||||
|
||||
//- Insert point-pairs where there are protrusions into
|
||||
// or out of the surface
|
||||
void boundaryConform();
|
||||
|
||||
|
||||
// Point removal
|
||||
|
||||
//- Remove the point-pairs introduced by insertSurfacePointPairs
|
||||
// and boundaryConform
|
||||
void removeSurfacePointPairs();
|
||||
|
||||
|
||||
// Point motion
|
||||
|
||||
inline void movePoint(const Vertex_handle& vh, const point2D& p);
|
||||
|
||||
//- Move the internal points to the given new locations and update
|
||||
// the triangulation to ensure it is Delaunay
|
||||
void moveInternalPoints(const point2DField& newPoints);
|
||||
|
||||
//- Calculate the displacements to create the new points
|
||||
void newPoints(const scalar relaxation);
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
//- Write internal points to .obj file
|
||||
void writePoints(const fileName& fName, bool internalOnly) const;
|
||||
|
||||
//- Write triangles as .obj file
|
||||
void writeTriangles(const fileName& fName, bool internalOnly) const;
|
||||
|
||||
//- Write dual faces as .obj file
|
||||
void writeFaces(const fileName& fName, bool internalOnly) const;
|
||||
|
||||
//- Calculates dual points (circumcentres of tets) and faces
|
||||
// (point-cell walk of tets). Returns
|
||||
// - dualPoints (in triangle ordering)
|
||||
// - dualFaces (compacted)
|
||||
void calcDual(point2DField& dualPoints, faceList& dualFaces) const;
|
||||
|
||||
//- Write patch
|
||||
void writePatch(const fileName& fName) const;
|
||||
|
||||
void write() const;
|
||||
};
|
||||
|
||||
|
||||
inline bool boundaryTriangle(const CV2D::Face_handle fc);
|
||||
inline bool outsideTriangle(const CV2D::Face_handle fc);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "CV2DI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
169
applications/utilities/mesh/generation/CV2DMesher/CV2DI.H
Normal file
169
applications/utilities/mesh/generation/CV2DMesher/CV2DI.H
Normal file
@ -0,0 +1,169 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
inline Foam::label Foam::CV2D::insertPoint
|
||||
(
|
||||
const point2D& p,
|
||||
const label type
|
||||
)
|
||||
{
|
||||
uint nVert = number_of_vertices();
|
||||
|
||||
Vertex_handle vh = insert(toPoint(p));
|
||||
|
||||
if (nVert == number_of_vertices())
|
||||
{
|
||||
WarningIn("Foam::CV2D::insertPoint")
|
||||
<< "Failed to insert point " << p << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
vh->index() = nVert;
|
||||
vh->type() = type;
|
||||
}
|
||||
|
||||
return vh->index();
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::CV2D::insertMirrorPoint
|
||||
(
|
||||
const point2D& nearSurfPt,
|
||||
const point2D& surfPt
|
||||
)
|
||||
{
|
||||
point2D mirrorPoint(2*surfPt - nearSurfPt);
|
||||
|
||||
if (qSurf_.outside(toPoint3D(mirrorPoint)))
|
||||
{
|
||||
insertPoint(mirrorPoint, Vb::MIRROR_POINT);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::CV2D::insertPointPair
|
||||
(
|
||||
const scalar ppDist,
|
||||
const point2D& surfPt,
|
||||
const vector2D& n
|
||||
)
|
||||
{
|
||||
vector2D ppDistn = ppDist*n;
|
||||
|
||||
label master = insertPoint
|
||||
(
|
||||
surfPt - ppDistn,
|
||||
number_of_vertices() + 1
|
||||
);
|
||||
|
||||
insertPoint(surfPt + ppDistn, master);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline const Foam::point2D& Foam::CV2D::toPoint2D(const point& p) const
|
||||
{
|
||||
return reinterpret_cast<const point2D&>(p);
|
||||
}
|
||||
|
||||
inline Foam::point Foam::CV2D::toPoint3D(const point2D& p) const
|
||||
{
|
||||
return point(p.x(), p.y(), z_);
|
||||
}
|
||||
|
||||
|
||||
#ifdef CGAL_INEXACT
|
||||
|
||||
inline Foam::CV2D::point2DFromPoint Foam::CV2D::toPoint2D(const Point& P) const
|
||||
{
|
||||
return reinterpret_cast<point2DFromPoint>(P);
|
||||
}
|
||||
|
||||
inline Foam::CV2D::PointFromPoint2D Foam::CV2D::toPoint(const point2D& p) const
|
||||
{
|
||||
return reinterpret_cast<PointFromPoint2D>(p);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline Foam::CV2D::point2DFromPoint Foam::CV2D::toPoint2D(const Point& P) const
|
||||
{
|
||||
return point2D(CGAL::to_double(P.x()), CGAL::to_double(P.y()));
|
||||
}
|
||||
|
||||
inline Foam::CV2D::PointFromPoint2D Foam::CV2D::toPoint(const point2D& p) const
|
||||
{
|
||||
return Point(p.x(), p.y());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
inline Foam::point Foam::CV2D::toPoint3D(const Point& P) const
|
||||
{
|
||||
return point(CGAL::to_double(P.x()), CGAL::to_double(P.y()), z_);
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::CV2D::movePoint(const Vertex_handle& vh, const point2D& p)
|
||||
{
|
||||
vh->set_point(toPoint(p));
|
||||
fast_restore_Delaunay(vh);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Friend Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::boundaryTriangle(const CV2D::Face_handle fc)
|
||||
{
|
||||
return boundaryTriangle
|
||||
(
|
||||
*fc->vertex(0),
|
||||
*fc->vertex(1),
|
||||
*fc->vertex(2)
|
||||
);
|
||||
}
|
||||
|
||||
inline bool Foam::outsideTriangle(const CV2D::Face_handle fc)
|
||||
{
|
||||
return outsideTriangle
|
||||
(
|
||||
*fc->vertex(0),
|
||||
*fc->vertex(1),
|
||||
*fc->vertex(2)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
285
applications/utilities/mesh/generation/CV2DMesher/CV2DIO.C
Normal file
285
applications/utilities/mesh/generation/CV2DMesher/CV2DIO.C
Normal file
@ -0,0 +1,285 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV2D.H"
|
||||
#include "OFstream.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::CV2D::writePoints(const fileName& fName, bool internalOnly) const
|
||||
{
|
||||
Info<< "Writing points to " << fName << nl << endl;
|
||||
OFstream str(fName);
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
++vit
|
||||
)
|
||||
{
|
||||
if (!internalOnly || vit->internalOrBoundaryPoint())
|
||||
{
|
||||
meshTools::writeOBJ(str, toPoint3D(vit->point()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::writeTriangles(const fileName& fName, bool internalOnly) const
|
||||
{
|
||||
Info<< "Writing triangles to " << fName << nl << endl;
|
||||
OFstream str(fName);
|
||||
|
||||
labelList vertexMap(number_of_vertices());
|
||||
label verti = 0;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
++vit
|
||||
)
|
||||
{
|
||||
if (!internalOnly || !vit->farPoint())
|
||||
{
|
||||
vertexMap[vit->index()] = verti++;
|
||||
meshTools::writeOBJ(str, toPoint3D(vit->point()));
|
||||
}
|
||||
}
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_faces_iterator fit = finite_faces_begin();
|
||||
fit != finite_faces_end();
|
||||
++fit
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
!internalOnly
|
||||
|| (
|
||||
fit->vertex(0)->internalOrBoundaryPoint()
|
||||
|| fit->vertex(1)->internalOrBoundaryPoint()
|
||||
|| fit->vertex(2)->internalOrBoundaryPoint()
|
||||
)
|
||||
)
|
||||
{
|
||||
str << "f " << vertexMap[fit->vertex(0)->index()] + 1
|
||||
<< ' ' << vertexMap[fit->vertex(1)->index()] + 1
|
||||
<< ' ' << vertexMap[fit->vertex(2)->index()] + 1
|
||||
<< nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::writeFaces(const fileName& fName, bool internalOnly) const
|
||||
{
|
||||
Info<< "Writing dual faces to " << fName << nl << endl;
|
||||
OFstream str(fName);
|
||||
|
||||
label dualVerti = 0;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_faces_iterator fit = finite_faces_begin();
|
||||
fit != finite_faces_end();
|
||||
++fit
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
!internalOnly
|
||||
|| (
|
||||
fit->vertex(0)->internalOrBoundaryPoint()
|
||||
|| fit->vertex(1)->internalOrBoundaryPoint()
|
||||
|| fit->vertex(2)->internalOrBoundaryPoint()
|
||||
)
|
||||
)
|
||||
{
|
||||
fit->faceIndex() = dualVerti++;
|
||||
meshTools::writeOBJ(str, toPoint3D(circumcenter(fit)));
|
||||
}
|
||||
else
|
||||
{
|
||||
fit->faceIndex() = -1;
|
||||
}
|
||||
}
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
++vit
|
||||
)
|
||||
{
|
||||
if (!internalOnly || vit->internalOrBoundaryPoint())
|
||||
{
|
||||
Face_circulator fcStart = incident_faces(vit);
|
||||
Face_circulator fc = fcStart;
|
||||
|
||||
str<< 'f';
|
||||
|
||||
do
|
||||
{
|
||||
if (!is_infinite(fc))
|
||||
{
|
||||
if (fc->faceIndex() < 0)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"Foam::CV2D::writeFaces"
|
||||
"(const fileName& fName, bool internalOnly)"
|
||||
)<< "Dual face uses vertex defined by a triangle"
|
||||
" defined by an external point"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
str<< ' ' << fc->faceIndex() + 1;
|
||||
}
|
||||
} while (++fc != fcStart);
|
||||
|
||||
str<< nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::calcDual(point2DField& dualPoints, faceList& dualFaces) const
|
||||
{
|
||||
// Dual points stored in triangle order.
|
||||
dualPoints.setSize(number_of_faces());
|
||||
label dualVerti = 0;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_faces_iterator fit = finite_faces_begin();
|
||||
fit != finite_faces_end();
|
||||
++fit
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
fit->vertex(0)->internalOrBoundaryPoint()
|
||||
|| fit->vertex(1)->internalOrBoundaryPoint()
|
||||
|| fit->vertex(2)->internalOrBoundaryPoint()
|
||||
)
|
||||
{
|
||||
fit->faceIndex() = dualVerti;
|
||||
dualPoints[dualVerti++] = toPoint2D(circumcenter(fit));
|
||||
}
|
||||
else
|
||||
{
|
||||
fit->faceIndex() = -1;
|
||||
}
|
||||
}
|
||||
|
||||
dualPoints.setSize(dualVerti);
|
||||
|
||||
|
||||
// Create dual faces
|
||||
// ~~~~~~~~~~~~~~~~~
|
||||
|
||||
dualFaces.setSize(number_of_vertices());
|
||||
label dualFacei = 0;
|
||||
labelList faceVerts(maxNvert);
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
++vit
|
||||
)
|
||||
{
|
||||
if (vit->internalOrBoundaryPoint())
|
||||
{
|
||||
Face_circulator fcStart = incident_faces(vit);
|
||||
Face_circulator fc = fcStart;
|
||||
label verti = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (!is_infinite(fc))
|
||||
{
|
||||
if (fc->faceIndex() < 0)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"Foam::CV2D::calcDual"
|
||||
"(point2DField& dualPoints, faceList& dualFaces)"
|
||||
)<< "Dual face uses vertex defined by a triangle"
|
||||
" defined by an external point"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
// Look up the index of the triangle
|
||||
faceVerts[verti++] = fc->faceIndex();
|
||||
}
|
||||
} while (++fc != fcStart);
|
||||
|
||||
if (faceVerts.size() > 2)
|
||||
{
|
||||
dualFaces[dualFacei++] =
|
||||
face(labelList::subList(faceVerts, verti));
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "From triangle point:" << vit->index()
|
||||
<< " coord:" << toPoint2D(vit->point())
|
||||
<< " generated illegal dualFace:" << faceVerts
|
||||
<< endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dualFaces.setSize(dualFacei);
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::writePatch(const fileName& fName) const
|
||||
{
|
||||
point2DField dual2DPoints;
|
||||
faceList dualFaces;
|
||||
|
||||
calcDual(dual2DPoints, dualFaces);
|
||||
pointField dualPoints(dual2DPoints.size());
|
||||
forAll(dualPoints, ip)
|
||||
{
|
||||
dualPoints[ip] = toPoint3D(dual2DPoints[ip]);
|
||||
}
|
||||
|
||||
// Dump as primitive patch to be read by extrudeMesh.
|
||||
OFstream str(fName);
|
||||
|
||||
Info<< "Writing patch to be used with extrudeMesh to file " << fName
|
||||
<< endl;
|
||||
|
||||
str << dualPoints << nl << dualFaces << nl;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
116
applications/utilities/mesh/generation/CV2DMesher/CV2DMesher.C
Normal file
116
applications/utilities/mesh/generation/CV2DMesher/CV2DMesher.C
Normal file
@ -0,0 +1,116 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
Application
|
||||
CV2DMesher
|
||||
|
||||
Description
|
||||
Conformal-Voronoi 2D automatic mesher with grid or read initial points
|
||||
and point position relaxation with optional "squarification".
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV2D.H"
|
||||
#include "argList.H"
|
||||
#include "IFstream.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::noParallel();
|
||||
argList::validArgs.clear();
|
||||
argList::validArgs.append("surface");
|
||||
argList::validOptions.insert("pointsFile", "<filename>");
|
||||
|
||||
argList args(argc, argv);
|
||||
|
||||
// Read control dictionary
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~
|
||||
dictionary controlDict(IFstream(args.executable() + "Dict")());
|
||||
|
||||
label nIterations(readLabel(controlDict.lookup("nIterations")));
|
||||
|
||||
|
||||
// Read the surface to conform to
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
querySurface surf(args.args()[1]);
|
||||
surf.writeTreeOBJ();
|
||||
|
||||
Info<< nl
|
||||
<< "Read surface with " << surf.size() << " triangles from file "
|
||||
<< args.args()[1] << nl << endl;
|
||||
|
||||
|
||||
// Read and triangulation
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
CV2D mesh(controlDict, surf);
|
||||
if (args.options().found("pointsFile"))
|
||||
{
|
||||
fileName pointFileName(IStringStream(args.options()["pointsFile"])());
|
||||
mesh.insertPoints(pointFileName);
|
||||
mesh.insertSurfacePointPairs();
|
||||
mesh.boundaryConform();
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh.insertGrid();
|
||||
mesh.insertSurfacePointPairs();
|
||||
mesh.boundaryConform();
|
||||
}
|
||||
|
||||
for (int iter=1; iter<=nIterations; iter++)
|
||||
{
|
||||
Info<< nl
|
||||
<< "Relaxation iteration " << iter << nl
|
||||
<< "~~~~~~~~~~~~~~~~~~~~~~~~" << endl;
|
||||
|
||||
scalar relax =
|
||||
mesh.meshingControls().relaxationFactorStart
|
||||
+
|
||||
(
|
||||
mesh.meshingControls().relaxationFactorEnd
|
||||
- mesh.meshingControls().relaxationFactorStart
|
||||
)
|
||||
*scalar(iter)/scalar(nIterations);
|
||||
|
||||
mesh.newPoints(relax);
|
||||
mesh.removeSurfacePointPairs();
|
||||
mesh.insertSurfacePointPairs();
|
||||
mesh.boundaryConform();
|
||||
}
|
||||
|
||||
mesh.write();
|
||||
|
||||
Info<< nl << "End\n" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
14
applications/utilities/mesh/generation/CV2DMesher/Make/files
Executable file
14
applications/utilities/mesh/generation/CV2DMesher/Make/files
Executable file
@ -0,0 +1,14 @@
|
||||
#include CGAL_FILES
|
||||
|
||||
querySurface.C
|
||||
CV2D.C
|
||||
controls.C
|
||||
tolerances.C
|
||||
insertFeaturePoints.C
|
||||
insertSurfaceNearestPointPairs.C
|
||||
insertSurfaceNearPointPairs.C
|
||||
insertBoundaryConformPointPairs.C
|
||||
CV2DIO.C
|
||||
CV2DMesher.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/CV2DMesher
|
||||
16
applications/utilities/mesh/generation/CV2DMesher/Make/options
Executable file
16
applications/utilities/mesh/generation/CV2DMesher/Make/options
Executable file
@ -0,0 +1,16 @@
|
||||
//EXE_DEBUG = -DFULLDEBUG -g -O0
|
||||
EXE_NDEBUG = -DNDEBUG
|
||||
|
||||
include $(GENERAL_RULES)/CGAL
|
||||
FFLAGS = -DCGAL_FILES='"${CGAL_PATH}/CGAL/files"'
|
||||
|
||||
EXE_INC = \
|
||||
${EXE_NDEBUG} \
|
||||
${CGAL_INC} \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/triSurface/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lmeshTools \
|
||||
-ltriSurface
|
||||
|
||||
76
applications/utilities/mesh/generation/CV2DMesher/controls.C
Normal file
76
applications/utilities/mesh/generation/CV2DMesher/controls.C
Normal file
@ -0,0 +1,76 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV2D.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::CV2D::controls::controls(const dictionary& controlDict)
|
||||
:
|
||||
minCellSize(readScalar(controlDict.lookup("minCellSize"))),
|
||||
minCellSize2(Foam::sqr(minCellSize)),
|
||||
|
||||
featAngle(readScalar(controlDict.lookup("featureAngle"))),
|
||||
maxQuadAngle(readScalar(controlDict.lookup("maxQuadAngle"))),
|
||||
squares(controlDict.lookup("squares")),
|
||||
|
||||
nearWallAlignedDist
|
||||
(
|
||||
readScalar(controlDict.lookup("nearWallAlignedDist"))*minCellSize
|
||||
),
|
||||
nearWallAlignedDist2(Foam::sqr(nearWallAlignedDist)),
|
||||
|
||||
relaxOrientation(controlDict.lookup("relaxOrientation")),
|
||||
|
||||
insertSurfaceNearestPointPairs
|
||||
(
|
||||
controlDict.lookup("insertSurfaceNearestPointPairs")
|
||||
),
|
||||
mirrorPoints(controlDict.lookup("mirrorPoints")),
|
||||
insertSurfaceNearPointPairs
|
||||
(
|
||||
controlDict.lookup("insertSurfaceNearPointPairs")
|
||||
),
|
||||
writeInitialTriangulation(controlDict.lookup("writeInitialTriangulation")),
|
||||
writeFeatureTriangulation(controlDict.lookup("writeFeatureTriangulation")),
|
||||
writeNearestTriangulation(controlDict.lookup("writeNearestTriangulation")),
|
||||
writeInsertedPointPairs(controlDict.lookup("writeInsertedPointPairs")),
|
||||
writeFinalTriangulation(controlDict.lookup("writeFinalTriangulation")),
|
||||
randomiseInitialGrid(controlDict.lookup("randomiseInitialGrid")),
|
||||
randomPurturbation(readScalar(controlDict.lookup("randomPurturbation"))),
|
||||
maxBoundaryConformingIter
|
||||
(
|
||||
readLabel(controlDict.lookup("maxBoundaryConformingIter"))
|
||||
),
|
||||
relaxationFactorStart
|
||||
(
|
||||
readScalar(controlDict.lookup("relaxationFactorStart"))
|
||||
),
|
||||
relaxationFactorEnd(readScalar(controlDict.lookup("relaxationFactorEnd")))
|
||||
{}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
148
applications/utilities/mesh/generation/CV2DMesher/indexedFace.H
Normal file
148
applications/utilities/mesh/generation/CV2DMesher/indexedFace.H
Normal file
@ -0,0 +1,148 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
indexedFace
|
||||
|
||||
Description
|
||||
An indexed form of CGAL::Triangulation_face_base_2<K> used to keep
|
||||
track of the vertices in the triangulation.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef indexedFace_H
|
||||
#define indexedFace_H
|
||||
|
||||
#include <CGAL/Triangulation_2.h>
|
||||
#include "indexedVertex.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class indexedFace Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Gt, class Fb=CGAL::Triangulation_face_base_2<Gt> >
|
||||
class indexedFace
|
||||
:
|
||||
public Fb
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- The index for this triangle face
|
||||
// -1: triangle and changed and associated data needs updating
|
||||
// >=0: index of triangles, set by external update algorithm
|
||||
int index_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
enum faceTypes
|
||||
{
|
||||
UNCHANGED = 0,
|
||||
CHANGED = -1,
|
||||
SAVE_CHANGED = -2
|
||||
};
|
||||
|
||||
typedef typename Fb::Vertex_handle Vertex_handle;
|
||||
typedef typename Fb::Face_handle Face_handle;
|
||||
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS
|
||||
{
|
||||
typedef typename Fb::template Rebind_TDS<TDS2>::Other Fb2;
|
||||
typedef indexedFace<Gt, Fb2> Other;
|
||||
};
|
||||
|
||||
|
||||
indexedFace()
|
||||
:
|
||||
Fb(),
|
||||
index_(CHANGED)
|
||||
{}
|
||||
|
||||
indexedFace(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2)
|
||||
:
|
||||
Fb(v0, v1, v2),
|
||||
index_(CHANGED)
|
||||
{}
|
||||
|
||||
indexedFace
|
||||
(
|
||||
Vertex_handle v0,
|
||||
Vertex_handle v1,
|
||||
Vertex_handle v2,
|
||||
Face_handle n0,
|
||||
Face_handle n1,
|
||||
Face_handle n2
|
||||
)
|
||||
:
|
||||
Fb(v0, v1, v2, n0, n1, n2),
|
||||
index_(CHANGED)
|
||||
{}
|
||||
|
||||
|
||||
void set_vertex(int i, Vertex_handle v)
|
||||
{
|
||||
index_ = CHANGED;
|
||||
Fb::set_vertex(i, v);
|
||||
}
|
||||
|
||||
void set_vertices()
|
||||
{
|
||||
index_ = CHANGED;
|
||||
Fb::set_vertices();
|
||||
}
|
||||
|
||||
void set_vertices(Vertex_handle v0, Vertex_handle v1, Vertex_handle v2)
|
||||
{
|
||||
index_ = CHANGED;
|
||||
Fb::set_vertices(v0, v1, v2);
|
||||
}
|
||||
|
||||
|
||||
int& faceIndex()
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
int faceIndex() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace CGAL
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,261 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
indexedVertex
|
||||
|
||||
Description
|
||||
An indexed form of CGAL::Triangulation_vertex_base_2<K> used to keep
|
||||
track of the vertices in the triangulation.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef indexedVertex_H
|
||||
#define indexedVertex_H
|
||||
|
||||
#include <CGAL/Triangulation_2.h>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class indexedVertex Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Gt, class Vb=CGAL::Triangulation_vertex_base_2<Gt> >
|
||||
class indexedVertex
|
||||
:
|
||||
public Vb
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- The index for this triangle vertex
|
||||
int index_;
|
||||
|
||||
//- Index of pair-point :
|
||||
// NEAR_BOUNDARY_POINT : internal near boundary point.
|
||||
// INTERNAL_POINT : internal point.
|
||||
// FAR_POINT : far-point.
|
||||
// >= 0 : part of point-pair. Index of other point.
|
||||
// Lowest numbered is inside one (master).
|
||||
int type_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
enum pointTypes
|
||||
{
|
||||
NEAR_BOUNDARY_POINT = -4,
|
||||
INTERNAL_POINT = -3,
|
||||
MIRROR_POINT = -2,
|
||||
FAR_POINT = -1
|
||||
};
|
||||
|
||||
typedef typename Vb::Vertex_handle Vertex_handle;
|
||||
typedef typename Vb::Face_handle Face_handle;
|
||||
typedef typename Vb::Point Point;
|
||||
|
||||
template<typename TDS2>
|
||||
struct Rebind_TDS
|
||||
{
|
||||
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
|
||||
typedef indexedVertex<Gt,Vb2> Other;
|
||||
};
|
||||
|
||||
|
||||
indexedVertex()
|
||||
:
|
||||
Vb(),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT)
|
||||
{}
|
||||
|
||||
indexedVertex(const Point& p)
|
||||
:
|
||||
Vb(p),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT)
|
||||
{}
|
||||
|
||||
indexedVertex(const Point& p, Face_handle f)
|
||||
:
|
||||
Vb(f, p),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT)
|
||||
{}
|
||||
|
||||
indexedVertex(Face_handle f)
|
||||
:
|
||||
Vb(f),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT)
|
||||
{}
|
||||
|
||||
|
||||
int& index()
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
int index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
|
||||
int& type()
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
int type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
|
||||
//- Is point a far-point
|
||||
inline bool farPoint() const
|
||||
{
|
||||
return type_ == FAR_POINT;
|
||||
}
|
||||
|
||||
//- Is point internal, i.e. not on boundary
|
||||
inline bool internalPoint() const
|
||||
{
|
||||
return type_ <= INTERNAL_POINT;
|
||||
}
|
||||
|
||||
//- Is point internal and near the boundary
|
||||
inline bool nearBoundary() const
|
||||
{
|
||||
return type_ == NEAR_BOUNDARY_POINT;
|
||||
}
|
||||
|
||||
//- Set the point to be near the boundary
|
||||
inline void setNearBoundary()
|
||||
{
|
||||
type_ = NEAR_BOUNDARY_POINT;
|
||||
}
|
||||
|
||||
//- Is point a mirror point
|
||||
inline bool mirrorPoint() const
|
||||
{
|
||||
return type_ == MIRROR_POINT;
|
||||
}
|
||||
|
||||
//- Either master or slave of pointPair.
|
||||
inline bool pairPoint() const
|
||||
{
|
||||
return type_ >= 0;
|
||||
}
|
||||
|
||||
//- Master of a pointPair is the lowest numbered one.
|
||||
inline bool ppMaster() const
|
||||
{
|
||||
if (type_ > index_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//- Slave of a pointPair is the highest numbered one.
|
||||
inline bool ppSlave() const
|
||||
{
|
||||
if (type_ >= 0 && type_ < index_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//- Either original internal point or master of pointPair.
|
||||
inline bool internalOrBoundaryPoint() const
|
||||
{
|
||||
return internalPoint() || ppMaster();
|
||||
}
|
||||
|
||||
//- Is point near the boundary or part of the boundary definition
|
||||
inline bool nearOrOnBoundary() const
|
||||
{
|
||||
return pairPoint() || mirrorPoint() || nearBoundary();
|
||||
}
|
||||
|
||||
//- Do the two given vertices consitute a boundary point-pair
|
||||
inline friend bool pointPair
|
||||
(
|
||||
const indexedVertex& v0,
|
||||
const indexedVertex& v1
|
||||
)
|
||||
{
|
||||
return v0.index_ == v1.type_ || v1.index_ == v0.type_;
|
||||
}
|
||||
|
||||
//- Do the three given vertices consitute a boundary triangle
|
||||
inline friend bool boundaryTriangle
|
||||
(
|
||||
const indexedVertex& v0,
|
||||
const indexedVertex& v1,
|
||||
const indexedVertex& v2
|
||||
)
|
||||
{
|
||||
return (v0.pairPoint() && pointPair(v1, v2))
|
||||
|| (v1.pairPoint() && pointPair(v2, v0))
|
||||
|| (v2.pairPoint() && pointPair(v0, v1));
|
||||
}
|
||||
|
||||
//- Do the three given vertices consitute an outside triangle
|
||||
inline friend bool outsideTriangle
|
||||
(
|
||||
const indexedVertex& v0,
|
||||
const indexedVertex& v1,
|
||||
const indexedVertex& v2
|
||||
)
|
||||
{
|
||||
return (v0.farPoint() || v0.ppSlave())
|
||||
|| (v1.farPoint() || v1.ppSlave())
|
||||
|| (v2.farPoint() || v2.ppSlave());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace CGAL
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,290 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV2D.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::CV2D::insertPointPair
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator& vit,
|
||||
const point2D& p,
|
||||
const label trii
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
!controls_.mirrorPoints
|
||||
|| !insertMirrorPoint(toPoint2D(vit->point()), p)
|
||||
)
|
||||
{
|
||||
insertPointPair
|
||||
(
|
||||
tols_.ppDist,
|
||||
p,
|
||||
toPoint2D(qSurf_.faceNormals()[trii])
|
||||
);
|
||||
}
|
||||
|
||||
vit = Triangulation::Finite_vertices_iterator
|
||||
(
|
||||
CGAL::Filter_iterator
|
||||
<
|
||||
Triangulation::All_vertices_iterator,
|
||||
Triangulation::Infinite_tester
|
||||
>(finite_vertices_end(), vit.predicate(), vit.base())
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::CV2D::insertPointPairAtIntersection
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator& vit,
|
||||
const point2D& defVert,
|
||||
const point2D vertices[],
|
||||
const scalar maxProtSize2
|
||||
)
|
||||
{
|
||||
bool found = false;
|
||||
point2D interPoint;
|
||||
label interTri = -1;
|
||||
scalar interDist2 = 0;
|
||||
|
||||
Face_circulator fcStart = incident_faces(vit);
|
||||
Face_circulator fc = fcStart;
|
||||
label vi = 0;
|
||||
|
||||
do
|
||||
{
|
||||
if (!is_infinite(fc))
|
||||
{
|
||||
pointIndexHit pHit = qSurf_.tree().findLine
|
||||
(
|
||||
toPoint3D(defVert),
|
||||
toPoint3D(vertices[vi])
|
||||
);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
scalar dist2 =
|
||||
magSqr(toPoint2D(pHit.hitPoint()) - vertices[vi]);
|
||||
|
||||
// Check the point is further away than the furthest so far
|
||||
if (dist2 > interDist2)
|
||||
{
|
||||
scalar mps2 = maxProtSize2;
|
||||
|
||||
// If this is a boundary triangle reset the tolerance
|
||||
// to avoid finding a hit point very close to a boundary
|
||||
// vertex
|
||||
if (boundaryTriangle(fc))
|
||||
{
|
||||
mps2 = tols_.maxNotchLen2;
|
||||
}
|
||||
|
||||
if (dist2 > mps2)
|
||||
{
|
||||
found = true;
|
||||
interPoint = toPoint2D(pHit.hitPoint());
|
||||
interTri = pHit.index();
|
||||
interDist2 = dist2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vi++;
|
||||
}
|
||||
} while (++fc != fcStart);
|
||||
|
||||
if (found)
|
||||
{
|
||||
insertPointPair(vit, interPoint, interTri);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::CV2D::insertBoundaryConformPointPairs
|
||||
(
|
||||
const fileName& fName
|
||||
)
|
||||
{
|
||||
label nIntersections = 0;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
vit++
|
||||
)
|
||||
{
|
||||
// Consider only those points part of point-pairs or near boundary
|
||||
if (!vit->nearOrOnBoundary())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Counter-clockwise circulator
|
||||
Face_circulator fcStart = incident_faces(vit);
|
||||
Face_circulator fc = fcStart;
|
||||
|
||||
bool infinite = false;
|
||||
bool changed = false;
|
||||
|
||||
do
|
||||
{
|
||||
if (is_infinite(fc))
|
||||
{
|
||||
infinite = true;
|
||||
break;
|
||||
}
|
||||
else if (fc->faceIndex() < Fb::UNCHANGED)
|
||||
{
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
} while (++fc != fcStart);
|
||||
|
||||
// If the dual-cell is connected to the infinite point or none of the
|
||||
// faces whose circumcentres it uses have changed ignore
|
||||
if (infinite || !changed) continue;
|
||||
|
||||
fc = fcStart;
|
||||
label nVerts = 0;
|
||||
|
||||
do
|
||||
{
|
||||
vertices[nVerts++] = toPoint2D(circumcenter(fc));
|
||||
|
||||
if (nVerts == maxNvert)
|
||||
{
|
||||
break;
|
||||
}
|
||||
} while (++fc != fcStart);
|
||||
|
||||
// Check if dual-cell has a large number of faces in which case
|
||||
// assumed to be in the far-field and reject
|
||||
if (nVerts == maxNvert) continue;
|
||||
|
||||
// Set n+1 vertex to the first vertex for easy circulating
|
||||
vertices[nVerts] = vertices[0];
|
||||
|
||||
// Convert triangle vertex to OpenFOAM point
|
||||
point2DFromPoint defVert = toPoint2D(vit->point());
|
||||
|
||||
scalar maxProtSize2 = tols_.maxNotchLen2;
|
||||
|
||||
if (vit->internalOrBoundaryPoint())
|
||||
{
|
||||
// Calculate metrics of the dual-cell
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
// The perimeter of the dual-cell
|
||||
scalar perimeter = 0;
|
||||
|
||||
// Twice the area of the dual-cell
|
||||
scalar areaT2 = 0;
|
||||
|
||||
for (int vi=0; vi<nVerts; vi++)
|
||||
{
|
||||
vector2D edge(vertices[vi+1] - vertices[vi]);
|
||||
perimeter += mag(edge);
|
||||
vector2D otherEdge = defVert - vertices[vi];
|
||||
areaT2 += mag(edge.x()*otherEdge.y() - edge.y()*otherEdge.x());
|
||||
}
|
||||
|
||||
// If the dual-cell is very small reject refinement
|
||||
if (areaT2 < tols_.minEdgeLen2) continue;
|
||||
|
||||
// Estimate the cell width
|
||||
scalar cellWidth = areaT2/perimeter;
|
||||
|
||||
|
||||
// Check dimensions of dual-cell
|
||||
/*
|
||||
// Quick rejection of dual-cell refinement based on it's perimeter
|
||||
if (perimeter < 2*tols_.minCellSize) continue;
|
||||
|
||||
// Also check the area of the cell and reject refinement
|
||||
// if it is less than that allowed
|
||||
if (areaT2 < tols_.minCellSize2) continue;
|
||||
|
||||
// Estimate the cell width and reject refinement if it is less than
|
||||
// that allowed
|
||||
if (cellWidth < 0.5*tols_.minEdgeLen) continue;
|
||||
*/
|
||||
|
||||
if
|
||||
(
|
||||
perimeter > 2*controls_.minCellSize
|
||||
&& areaT2 > controls_.minCellSize2
|
||||
&& cellWidth > 0.5*tols_.minEdgeLen
|
||||
)
|
||||
{
|
||||
maxProtSize2 = 0.25*tols_.maxNotchLen2;
|
||||
}
|
||||
}
|
||||
|
||||
if (insertPointPairAtIntersection(vit, defVert, vertices, maxProtSize2))
|
||||
{
|
||||
nIntersections++;
|
||||
}
|
||||
}
|
||||
|
||||
return nIntersections;
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::markNearBoundaryPoints()
|
||||
{
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
vit++
|
||||
)
|
||||
{
|
||||
if (vit->internalPoint())
|
||||
{
|
||||
point vert(toPoint3D(vit->point()));
|
||||
|
||||
pointIndexHit pHit =
|
||||
qSurf_.tree().findNearest(vert, 4*controls_.minCellSize2);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
vit->setNearBoundary();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,162 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV2D.H"
|
||||
#include "plane.H"
|
||||
#include "triSurfaceTools.H"
|
||||
#include "mathematicalConstants.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
// Create feature points/edges by creating a triplet in the corner.
|
||||
// (this triplet will have as its circumcentre the feature)
|
||||
void Foam::CV2D::insertFeaturePoints()
|
||||
{
|
||||
labelList featEdges(qSurf_.extractFeatures2D(controls_.featAngle));
|
||||
|
||||
const pointField& localPts = qSurf_.localPoints();
|
||||
|
||||
forAll(featEdges, i)
|
||||
{
|
||||
label edgeI = featEdges[i];
|
||||
const edge& featEdge = qSurf_.edges()[edgeI];
|
||||
|
||||
// Get the feature point as the mid-point of the edge and convert to 2D
|
||||
point2D featPt = toPoint2D(featEdge.centre(qSurf_.localPoints()));
|
||||
|
||||
// Pick up the two faces adjacent to the feature edge
|
||||
const labelList& eFaces = qSurf_.edgeFaces()[edgeI];
|
||||
|
||||
label faceA = eFaces[0];
|
||||
vector2D nA = toPoint2D(qSurf_.faceNormals()[faceA]);
|
||||
|
||||
label faceB = eFaces[1];
|
||||
vector2D nB = toPoint2D(qSurf_.faceNormals()[faceB]);
|
||||
|
||||
// Intersect planes parallel to faceA and faceB offset by ppDist.
|
||||
plane planeA(toPoint3D(featPt - tols_.ppDist*nA), toPoint3D(nA));
|
||||
plane planeB(toPoint3D(featPt - tols_.ppDist*nB), toPoint3D(nB));
|
||||
plane::ray interLine(planeA.planeIntersect(planeB));
|
||||
|
||||
// The reference point is where this line intersects the z_ plane
|
||||
point2D refPt = toPoint2D
|
||||
(
|
||||
interLine.refPoint()
|
||||
+ ((z_ - interLine.refPoint().z())/interLine.dir().z())
|
||||
*interLine.dir()
|
||||
);
|
||||
|
||||
point2D faceAVert = toPoint2D
|
||||
(
|
||||
localPts[triSurfaceTools::oppositeVertex(qSurf_, faceA, edgeI)]
|
||||
);
|
||||
|
||||
// Determine convex or concave angle
|
||||
if (((faceAVert - featPt) & nB) < 0)
|
||||
{
|
||||
// Convex. So refPt will be inside domain and hence a master point
|
||||
|
||||
// Insert the master point refering the the first slave
|
||||
label masterPtIndex = insertPoint(refPt, number_of_vertices() + 1);
|
||||
|
||||
// Insert the slave points by reflecting refPt in both faces.
|
||||
// with each slave refering to the master
|
||||
|
||||
point2D reflectedA = refPt + 2*((featPt - refPt) & nA)*nA;
|
||||
insertPoint(reflectedA, masterPtIndex);
|
||||
|
||||
point2D reflectedB = refPt + 2*((featPt - refPt) & nB)*nB;
|
||||
insertPoint(reflectedB, masterPtIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Concave. master and reflected points inside the domain.
|
||||
// Generate reflected master to be outside.
|
||||
point2D reflMasterPt = refPt + 2*(featPt - refPt);
|
||||
|
||||
// Reflect refPt in both faces.
|
||||
point2D reflectedA =
|
||||
reflMasterPt + 2*((featPt - reflMasterPt) & nA)*nA;
|
||||
|
||||
point2D reflectedB =
|
||||
reflMasterPt + 2*((featPt - reflMasterPt) & nB)*nB;
|
||||
|
||||
// Total angle around the concave feature
|
||||
// scalar totalAngle =
|
||||
// 180*(2.0*mathematicalConstant::pi - acos(mag(nA & nB)))
|
||||
// /mathematicalConstant::pi;
|
||||
|
||||
scalar totalAngle =
|
||||
180*(mathematicalConstant::pi + acos(mag(nA & nB)))
|
||||
/mathematicalConstant::pi;
|
||||
|
||||
// Number of quadrants the angle should be split into
|
||||
int nQuads = int(totalAngle/controls_.maxQuadAngle) + 1;
|
||||
|
||||
// The number of additional master points needed to obtain the
|
||||
// required number of quadrants.
|
||||
int nAddPoints = min(max(nQuads - 2, 0), 2);
|
||||
|
||||
// index of reflMaster
|
||||
label reflectedMaster = number_of_vertices() + 2 + nAddPoints;
|
||||
|
||||
// Master A is inside.
|
||||
label reflectedAI = insertPoint(reflectedA, reflectedMaster);
|
||||
|
||||
// Master B is inside.
|
||||
insertPoint(reflectedB, reflectedMaster);
|
||||
|
||||
if (nAddPoints == 1)
|
||||
{
|
||||
// One additinal point is the reflection of the slave point,
|
||||
// i.e. the original reference point
|
||||
insertPoint(refPt, reflectedMaster);
|
||||
}
|
||||
else if (nAddPoints == 2)
|
||||
{
|
||||
point2D reflectedAa = refPt - ((featPt - reflMasterPt) & nB)*nB;
|
||||
insertPoint(reflectedAa, reflectedMaster);
|
||||
|
||||
point2D reflectedBb = refPt - ((featPt - reflMasterPt) & nA)*nA;
|
||||
insertPoint(reflectedBb, reflectedMaster);
|
||||
}
|
||||
|
||||
// Slave is outside.
|
||||
insertPoint(reflMasterPt, reflectedAI);
|
||||
}
|
||||
}
|
||||
|
||||
if (controls_.writeFeatureTriangulation)
|
||||
{
|
||||
writePoints("feat_allPoints.obj", false);
|
||||
writeFaces("feat_allFaces.obj", false);
|
||||
writeFaces("feat_faces.obj", true);
|
||||
writeTriangles("feat_triangles.obj", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,103 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV2D.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::CV2D::insertSurfaceNearPointPairs()
|
||||
{
|
||||
Info<< "insertSurfaceNearPointPairs: ";
|
||||
|
||||
label nNearPoints = 0;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_edges_iterator eit = finite_edges_begin();
|
||||
eit != finite_edges_end();
|
||||
eit++
|
||||
)
|
||||
{
|
||||
Vertex_handle v0h = eit->first->vertex(cw(eit->second));
|
||||
Vertex_handle v1h = eit->first->vertex(ccw(eit->second));
|
||||
|
||||
if (v0h->ppMaster() && v1h->ppMaster())
|
||||
{
|
||||
point2DFromPoint v0(toPoint2D(v0h->point()));
|
||||
point2DFromPoint v1(toPoint2D(v1h->point()));
|
||||
|
||||
// Check that the two triangle vertices are further apart than the
|
||||
// minimum cell size
|
||||
if (magSqr(v1 - v0) > controls_.minCellSize2)
|
||||
{
|
||||
point2D e0(toPoint2D(circumcenter(eit->first)));
|
||||
|
||||
point2D e1
|
||||
(
|
||||
toPoint2D(circumcenter(eit->first->neighbor(eit->second)))
|
||||
);
|
||||
|
||||
// Calculate the length^2 of the edge normal to the surface
|
||||
scalar edgeLen2 = magSqr(e0 - e1);
|
||||
|
||||
if (edgeLen2 < tols_.minNearPointDist2)
|
||||
{
|
||||
pointIndexHit pHit = qSurf_.tree().findNearest
|
||||
(
|
||||
toPoint3D(e0),
|
||||
tols_.minEdgeLen2
|
||||
);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
insertPointPair
|
||||
(
|
||||
tols_.ppDist,
|
||||
toPoint2D(pHit.hitPoint()),
|
||||
toPoint2D(qSurf_.faceNormals()[pHit.index()])
|
||||
);
|
||||
|
||||
nNearPoints++;
|
||||
|
||||
// Correct the edge iterator for the change in the
|
||||
// number od edges following the point-pair insertion
|
||||
eit = Finite_edges_iterator
|
||||
(
|
||||
finite_edges_end().base(),
|
||||
eit.predicate(),
|
||||
eit.base()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< nNearPoints << " point-pairs inserted" << endl;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,223 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV2D.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
bool Foam::CV2D::dualCellSurfaceIntersection
|
||||
(
|
||||
const Triangulation::Finite_vertices_iterator& vit
|
||||
) const
|
||||
{
|
||||
Triangulation::Edge_circulator ecStart = incident_edges(vit);
|
||||
Triangulation::Edge_circulator ec = ecStart;
|
||||
|
||||
do
|
||||
{
|
||||
if (!is_infinite(ec))
|
||||
{
|
||||
point e0 = toPoint3D(circumcenter(ec->first));
|
||||
|
||||
// If edge end is outside bounding box then edge cuts boundary
|
||||
if (!qSurf_.bb().contains(e0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
point e1 = toPoint3D(circumcenter(ec->first->neighbor(ec->second)));
|
||||
|
||||
// If other edge end is ouside bounding box then edge cuts boundary
|
||||
if (!qSurf_.bb().contains(e1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (magSqr(e1 - e0) > tols_.minEdgeLen2)
|
||||
{
|
||||
pointIndexHit pHit = qSurf_.tree().findLineAny(e0, e1);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} while (++ec != ecStart);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::insertPointPairs
|
||||
(
|
||||
const DynamicList<point2D>& nearSurfacePoints,
|
||||
const DynamicList<point2D>& surfacePoints,
|
||||
const DynamicList<label>& surfaceTris,
|
||||
const fileName fName
|
||||
)
|
||||
{
|
||||
if (controls_.mirrorPoints)
|
||||
{
|
||||
forAll(surfacePoints, ppi)
|
||||
{
|
||||
insertMirrorPoint
|
||||
(
|
||||
nearSurfacePoints[ppi],
|
||||
surfacePoints[ppi]
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(surfacePoints, ppi)
|
||||
{
|
||||
insertPointPair
|
||||
(
|
||||
tols_.ppDist,
|
||||
surfacePoints[ppi],
|
||||
toPoint2D(qSurf_.faceNormals()[surfaceTris[ppi]])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Info<< surfacePoints.size() << " point-pairs inserted" << endl;
|
||||
|
||||
if (controls_.writeInsertedPointPairs)
|
||||
{
|
||||
OFstream str(fName);
|
||||
label vertI = 0;
|
||||
|
||||
forAll(surfacePoints, ppi)
|
||||
{
|
||||
meshTools::writeOBJ(str, toPoint3D(surfacePoints[ppi]));
|
||||
vertI++;
|
||||
}
|
||||
|
||||
Info<< "insertPointPairs: Written " << surfacePoints.size()
|
||||
<< " inserted point-pair locations to file "
|
||||
<< str.name() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV2D::insertSurfaceNearestPointPairs()
|
||||
{
|
||||
Info<< "insertSurfaceNearestPointPairs: ";
|
||||
|
||||
label nSurfacePointsEst = min
|
||||
(
|
||||
number_of_vertices(),
|
||||
size_t(10*sqrt(scalar(number_of_vertices())))
|
||||
);
|
||||
|
||||
DynamicList<point2D> nearSurfacePoints(nSurfacePointsEst);
|
||||
DynamicList<point2D> surfacePoints(nSurfacePointsEst);
|
||||
DynamicList<label> surfaceTris(nSurfacePointsEst);
|
||||
|
||||
// Local references to surface mesh addressing
|
||||
const pointField& localPoints = qSurf_.localPoints();
|
||||
const labelListList& edgeFaces = qSurf_.edgeFaces();
|
||||
const vectorField& faceNormals = qSurf_.faceNormals();
|
||||
const labelListList& faceEdges = qSurf_.faceEdges();
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
vit++
|
||||
)
|
||||
{
|
||||
if (vit->internalPoint())
|
||||
{
|
||||
point2DFromPoint vert(toPoint2D(vit->point()));
|
||||
|
||||
pointIndexHit pHit = qSurf_.tree().findNearest
|
||||
(
|
||||
toPoint3D(vert),
|
||||
4*controls_.minCellSize2
|
||||
);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
vit->setNearBoundary();
|
||||
|
||||
// Reference to the nearest triangle
|
||||
const labelledTri& f = qSurf_[pHit.index()];
|
||||
|
||||
// Find where point is on triangle.
|
||||
// Note tolerance needed is relative one
|
||||
// (used in comparing normalized [0..1] triangle coordinates).
|
||||
label nearType, nearLabel;
|
||||
triPointRef
|
||||
(
|
||||
localPoints[f[0]],
|
||||
localPoints[f[1]],
|
||||
localPoints[f[2]]
|
||||
).classify(pHit.hitPoint(), 1e-6, nearType, nearLabel);
|
||||
|
||||
// If point is on a edge check if it is an internal feature
|
||||
|
||||
bool internalFeatureEdge = false;
|
||||
|
||||
if (nearType == triPointRef::EDGE)
|
||||
{
|
||||
label edgeI = faceEdges[pHit.index()][nearLabel];
|
||||
const labelList& eFaces = edgeFaces[edgeI];
|
||||
|
||||
if
|
||||
(
|
||||
eFaces.size() == 2
|
||||
&& (faceNormals[eFaces[0]] & faceNormals[eFaces[1]])
|
||||
< -0.2
|
||||
)
|
||||
{
|
||||
internalFeatureEdge = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!internalFeatureEdge && dualCellSurfaceIntersection(vit))
|
||||
{
|
||||
nearSurfacePoints.append(vert);
|
||||
surfacePoints.append(toPoint2D(pHit.hitPoint()));
|
||||
surfaceTris.append(pHit.index());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
insertPointPairs
|
||||
(
|
||||
nearSurfacePoints,
|
||||
surfacePoints,
|
||||
surfaceTris,
|
||||
"surfaceNearestIntersections.obj"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
229
applications/utilities/mesh/generation/CV2DMesher/querySurface.C
Normal file
229
applications/utilities/mesh/generation/CV2DMesher/querySurface.C
Normal file
@ -0,0 +1,229 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "querySurface.H"
|
||||
#include "mathematicalConstants.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::querySurface::querySurface(const fileName& surfaceFileName)
|
||||
:
|
||||
triSurface(surfaceFileName),
|
||||
rndGen_(12345),
|
||||
bb_(localPoints()),
|
||||
tree_
|
||||
(
|
||||
treeDataTriSurface(*this),
|
||||
bb_.extend(rndGen_, 1e-3), // slightly randomize bb
|
||||
8, // maxLevel
|
||||
4, //10, // leafsize
|
||||
10.0 //3.0 // duplicity
|
||||
)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::querySurface::~querySurface()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::labelList Foam::querySurface::extractFeatures2D
|
||||
(
|
||||
const scalar featAngle
|
||||
) const
|
||||
{
|
||||
scalar featCos = cos(mathematicalConstant::pi*featAngle/180.0);
|
||||
|
||||
const labelListList& edgeFaces = this->edgeFaces();
|
||||
const pointField& localPoints = this->localPoints();
|
||||
const edgeList& edges = this->edges();
|
||||
const vectorField& faceNormals = this->faceNormals();
|
||||
|
||||
DynamicList<label> featEdges(edges.size());
|
||||
|
||||
forAll(edgeFaces, edgeI)
|
||||
{
|
||||
const edge& e = edges[edgeI];
|
||||
|
||||
if (magSqr(e.vec(localPoints) & vector(1,1,0)) < SMALL)
|
||||
{
|
||||
const labelList& eFaces = edgeFaces[edgeI];
|
||||
|
||||
if
|
||||
(
|
||||
eFaces.size() == 2
|
||||
&& (faceNormals[eFaces[0]] & faceNormals[eFaces[1]]) < featCos
|
||||
)
|
||||
{
|
||||
featEdges.append(edgeI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return featEdges.shrink();
|
||||
}
|
||||
|
||||
Foam::indexedOctree<Foam::treeDataTriSurface>::volumeType
|
||||
Foam::querySurface::insideOutside
|
||||
(
|
||||
const scalar searchSpan2,
|
||||
const point& pt
|
||||
) const
|
||||
{
|
||||
if (!bb_.contains(pt))
|
||||
{
|
||||
return indexedOctree<treeDataTriSurface>::OUTSIDE;
|
||||
}
|
||||
|
||||
pointIndexHit pHit = tree_.findNearest(pt, searchSpan2);
|
||||
|
||||
if (!pHit.hit())
|
||||
{
|
||||
return tree_.getVolumeType(pt);
|
||||
}
|
||||
else
|
||||
{
|
||||
return indexedOctree<treeDataTriSurface>::MIXED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if point is inside surface
|
||||
bool Foam::querySurface::inside(const point& pt) const
|
||||
{
|
||||
if (!bb_.contains(pt))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return
|
||||
(
|
||||
tree_.getVolumeType(pt) == indexedOctree<treeDataTriSurface>::INSIDE
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Check if point is outside surface
|
||||
bool Foam::querySurface::outside(const point& pt) const
|
||||
{
|
||||
if (!bb_.contains(pt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return
|
||||
(
|
||||
tree_.getVolumeType(pt) == indexedOctree<treeDataTriSurface>::OUTSIDE
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Check if point is inside surface by at least dist2
|
||||
bool Foam::querySurface::wellInside(const point& pt, const scalar dist2) const
|
||||
{
|
||||
if (!bb_.contains(pt))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pointIndexHit pHit = tree_.findNearest(pt, dist2);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return
|
||||
tree_.getVolumeType(pt)
|
||||
== indexedOctree<treeDataTriSurface>::INSIDE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if point is outside surface by at least dist2
|
||||
bool Foam::querySurface::wellOutside(const point& pt, const scalar dist2) const
|
||||
{
|
||||
if (!bb_.contains(pt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
pointIndexHit pHit = tree_.findNearest(pt, dist2);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return
|
||||
tree_.getVolumeType(pt)
|
||||
== indexedOctree<treeDataTriSurface>::OUTSIDE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::querySurface::writeTreeOBJ() const
|
||||
{
|
||||
OFstream str("tree.obj");
|
||||
label vertI = 0;
|
||||
|
||||
const List<indexedOctree<treeDataTriSurface>::node>& nodes = tree_.nodes();
|
||||
|
||||
forAll(nodes, nodeI)
|
||||
{
|
||||
const indexedOctree<treeDataTriSurface>::node& nod = nodes[nodeI];
|
||||
|
||||
const treeBoundBox& bb = nod.bb_;
|
||||
|
||||
const pointField points(bb.points());
|
||||
|
||||
label startVertI = vertI;
|
||||
|
||||
forAll(points, i)
|
||||
{
|
||||
meshTools::writeOBJ(str, points[i]);
|
||||
vertI++;
|
||||
}
|
||||
|
||||
const edgeList edges(treeBoundBox::edges);
|
||||
|
||||
forAll(edges, i)
|
||||
{
|
||||
const edge& e = edges[i];
|
||||
|
||||
str << "l " << e[0]+startVertI+1 << ' ' << e[1]+startVertI+1
|
||||
<< nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
149
applications/utilities/mesh/generation/CV2DMesher/querySurface.H
Normal file
149
applications/utilities/mesh/generation/CV2DMesher/querySurface.H
Normal file
@ -0,0 +1,149 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
querySurface
|
||||
|
||||
Description
|
||||
Searchable triSurface using an octree to speed-up queries.
|
||||
|
||||
SourceFiles
|
||||
querySurface.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef querySurface_H
|
||||
#define querySurface_H
|
||||
|
||||
#include "triSurface.H"
|
||||
#include "treeDataTriSurface.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "Random.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class querySurface Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class querySurface
|
||||
:
|
||||
public triSurface
|
||||
{
|
||||
// Private data
|
||||
|
||||
Random rndGen_;
|
||||
|
||||
// Bounding box of surface. Used for relative tolerances.
|
||||
treeBoundBox bb_;
|
||||
|
||||
// Search engine on surface
|
||||
indexedOctree<treeDataTriSurface> tree_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
querySurface(const querySurface&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const querySurface&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given file name of the surface
|
||||
querySurface(const fileName& surfaceFileName);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
~querySurface();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
const treeBoundBox& bb() const
|
||||
{
|
||||
return bb_;
|
||||
}
|
||||
|
||||
const indexedOctree<treeDataTriSurface>& tree() const
|
||||
{
|
||||
return tree_;
|
||||
}
|
||||
|
||||
|
||||
// Query
|
||||
|
||||
//- Extract feature edges/points(2D)
|
||||
// using the given feature angle in deg
|
||||
labelList extractFeatures2D(const scalar featAngle) const;
|
||||
|
||||
//- Returns inside, outside or mixed (= close to surface)
|
||||
indexedOctree<Foam::treeDataTriSurface>::volumeType insideOutside
|
||||
(
|
||||
const scalar searchSpan2,
|
||||
const point& pt
|
||||
) const;
|
||||
|
||||
//- Check if point is inside surface
|
||||
bool inside(const point& pt) const;
|
||||
|
||||
//- Check if point is outside surface
|
||||
bool outside(const point& pt) const;
|
||||
|
||||
//- Check if point is inside surface by at least dist2
|
||||
bool wellInside(const point& pt, const scalar dist2) const;
|
||||
|
||||
//- Check if point is outside surface by at least dist2
|
||||
bool wellOutside(const point& pt, const scalar dist2) const;
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
void writeTreeOBJ() const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
//#include "querySurfaceI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,62 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV2D.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::CV2D::tolerances::tolerances
|
||||
(
|
||||
const dictionary& controlDict,
|
||||
const scalar minCellSize,
|
||||
const boundBox& bb
|
||||
)
|
||||
:
|
||||
span
|
||||
(
|
||||
max(mag(bb.max().x()), mag(bb.min().x()))
|
||||
+ max(mag(bb.max().y()), mag(bb.min().y()))
|
||||
),
|
||||
span2(Foam::sqr(span)),
|
||||
|
||||
minEdgeLen(readScalar(controlDict.lookup("minEdgeLenCoeff"))*minCellSize),
|
||||
minEdgeLen2(Foam::sqr(minEdgeLen)),
|
||||
|
||||
maxNotchLen(readScalar(controlDict.lookup("maxNotchLenCoeff"))*minCellSize),
|
||||
maxNotchLen2(Foam::sqr(maxNotchLen)),
|
||||
|
||||
minNearPointDist
|
||||
(
|
||||
readScalar(controlDict.lookup("minNearPointDistCoeff"))*minCellSize
|
||||
),
|
||||
minNearPointDist2(Foam::sqr(minNearPointDist)),
|
||||
|
||||
ppDist(readScalar(controlDict.lookup("ppDistCoeff"))*minCellSize),
|
||||
ppDist2(Foam::sqr(ppDist))
|
||||
{}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,84 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
Typedefs
|
||||
CGALTriangulation3Ddefs
|
||||
|
||||
Description
|
||||
CGAL data structures used for 3D Delaunay meshing.
|
||||
|
||||
Define CGAL_INEXACT to use Exact_predicates_inexact_constructions kernel
|
||||
otherwise the more robust but much less efficient
|
||||
Exact_predicates_exact_constructions will be used.
|
||||
|
||||
Define CGAL_HIERARCHY to use hierarchical Delaunay triangulation which is
|
||||
faster but uses more memory than the standard Delaunay triangulation.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CGALTriangulation3Ddefs_H
|
||||
#define CGALTriangulation3Ddefs_H
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "CGAL/Delaunay_triangulation_3.h"
|
||||
|
||||
#include "indexedVertex.H"
|
||||
#include "indexedCell.H"
|
||||
|
||||
#ifdef CGAL_INEXACT
|
||||
// Fast kernel using a double as the storage type but the triangulation
|
||||
// may fail
|
||||
#include "CGAL/Exact_predicates_inexact_constructions_kernel.h"
|
||||
typedef CGAL::Exact_predicates_inexact_constructions_kernel K;
|
||||
#else
|
||||
// Very robust but expensive kernel
|
||||
#include "CGAL/Exact_predicates_exact_constructions_kernel.h"
|
||||
typedef CGAL::Exact_predicates_exact_constructions_kernel K;
|
||||
#endif
|
||||
|
||||
typedef CGAL::indexedVertex<K> Vb;
|
||||
typedef CGAL::indexedCell<K> Cb;
|
||||
|
||||
#ifdef CGAL_HIERARCHY
|
||||
// Data structures for hierarchical Delaunay triangulation which is more
|
||||
// efficient but also uses more storage
|
||||
#include "CGAL/Triangulation_hierarchy_3.h"
|
||||
typedef CGAL::Triangulation_hierarchy_vertex_base_3<Vb> Vbh;
|
||||
typedef CGAL::Triangulation_data_structure_3<Vbh, Cb> Tds;
|
||||
typedef CGAL::Delaunay_triangulation_3<K, Tds> Triangulation;
|
||||
typedef CGAL::Triangulation_hierarchy_3<Triangulation> HTriangulation;
|
||||
#else
|
||||
// Data structures for standard Delaunay triangulation
|
||||
typedef CGAL::Triangulation_data_structure_3<Vb, Cb> Tds;
|
||||
typedef CGAL::Delaunay_triangulation_3<K, Tds> Triangulation;
|
||||
typedef Triangulation HTriangulation;
|
||||
#endif
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
1714
applications/utilities/mesh/generation/CV3DMesher/CV3D.C
Normal file
1714
applications/utilities/mesh/generation/CV3DMesher/CV3D.C
Normal file
File diff suppressed because it is too large
Load Diff
460
applications/utilities/mesh/generation/CV3DMesher/CV3D.H
Normal file
460
applications/utilities/mesh/generation/CV3DMesher/CV3D.H
Normal file
@ -0,0 +1,460 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
CV3D
|
||||
|
||||
Description
|
||||
|
||||
SourceFiles
|
||||
CV3DI.H
|
||||
CV3D.C
|
||||
CV3DIO.C
|
||||
controls.C
|
||||
tolerances.C
|
||||
insertFeaturePoints.C
|
||||
insertSurfaceNearestPointPairs.C
|
||||
insertSurfaceNearPointPairs.C
|
||||
insertBoundaryConformPointPairs.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef CV3D_H
|
||||
#define CV3D_H
|
||||
|
||||
//#define CGAL_INEXACT
|
||||
#define CGAL_HIERARCHY
|
||||
|
||||
#include "CGALTriangulation3Ddefs.H"
|
||||
|
||||
#include "querySurface.H"
|
||||
#include "IOdictionary.H"
|
||||
#include "pointIOField.H"
|
||||
#include "argList.H"
|
||||
#include "DynamicList.H"
|
||||
#include "Switch.H"
|
||||
#include "Time.H"
|
||||
#include "polyMesh.H"
|
||||
#include "SortableList.H"
|
||||
#include "plane.H"
|
||||
#include "triSurfaceTools.H"
|
||||
#include "mathematicalConstants.H"
|
||||
#include "transform.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class CV3D Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class CV3D
|
||||
:
|
||||
public HTriangulation
|
||||
{
|
||||
public:
|
||||
|
||||
class controls
|
||||
{
|
||||
public:
|
||||
|
||||
//- Relaxation factor at the start of the iteration
|
||||
scalar relaxationFactorStart;
|
||||
|
||||
//- Relaxation factor at the end of the iteration
|
||||
scalar relaxationFactorEnd;
|
||||
|
||||
//- Minimum cell size below which protusions through the surface are
|
||||
// not split
|
||||
scalar minCellSize;
|
||||
|
||||
//- Square of minCellSize
|
||||
scalar minCellSize2;
|
||||
|
||||
//- The feature angle used to select corners to be
|
||||
// explicitly represented in the mesh.
|
||||
// 0 = no features, 180 = all features
|
||||
scalar includedAngle;
|
||||
|
||||
//- Maximum quadrant angle allowed at a concave corner before
|
||||
// additional "mitering" lines are added
|
||||
scalar maxQuadAngle;
|
||||
|
||||
//- Should the mesh be square-dominated or of unbiased hexagons
|
||||
Switch squares;
|
||||
|
||||
//- Near-wall region where cells are aligned with the wall
|
||||
scalar nearWallAlignedDist;
|
||||
|
||||
//- Square of nearWallAlignedDist
|
||||
scalar nearWallAlignedDist2;
|
||||
|
||||
//- Chose if the cell orientation should relax during the iterations
|
||||
// or remain fixed to the x-y directions
|
||||
Switch relaxOrientation;
|
||||
|
||||
//- Insert near-boundary point mirror or point-pairs
|
||||
Switch insertSurfaceNearestPointPairs;
|
||||
|
||||
//- Mirror near-boundary points rather than insert point-pairs
|
||||
Switch mirrorPoints;
|
||||
|
||||
//- Insert point-pairs for dual-cell vertices very near the surface
|
||||
Switch insertSurfaceNearPointPairs;
|
||||
|
||||
Switch writeInitialTriangulation;
|
||||
Switch writeFeatureTriangulation;
|
||||
Switch writeNearestTriangulation;
|
||||
Switch writeInsertedPointPairs;
|
||||
Switch writeFinalTriangulation;
|
||||
|
||||
Switch randomiseInitialGrid;
|
||||
scalar randomPerturbation;
|
||||
|
||||
controls(const IOdictionary& controlDict);
|
||||
};
|
||||
|
||||
class tolerances
|
||||
{
|
||||
public:
|
||||
|
||||
//- Maximum cartesian span of the geometry
|
||||
scalar span;
|
||||
|
||||
//- Square of span
|
||||
scalar span2;
|
||||
|
||||
//- Minumum edge-length of the cell size below which protusions
|
||||
// through the surface are not split
|
||||
scalar minEdgeLen;
|
||||
|
||||
//- Square of minEdgeLen
|
||||
scalar minEdgeLen2;
|
||||
|
||||
//- Distance between boundary conforming point-pairs
|
||||
scalar ppDist;
|
||||
|
||||
//- Square of ppDist
|
||||
scalar ppDist2;
|
||||
|
||||
//- Maximum distance between adjacent control points on a feature edge
|
||||
//- before they are considered a group
|
||||
scalar edgeGroupSpacing;
|
||||
|
||||
//- Guard distance from a feature point within which an edge control
|
||||
//- point may not be placed
|
||||
scalar featurePointGuard;
|
||||
|
||||
//- Guard distance from a feature edge within which a surface control
|
||||
//- point may not be placed
|
||||
scalar featureEdgeGuard;
|
||||
|
||||
//- minimum and maximum distances along a feature edge allowed between
|
||||
//- pairs of points. Eventually these should be able to adapt to local
|
||||
//- grading requirements.
|
||||
scalar minEdgeSpacing;
|
||||
scalar maxEdgeSpacing;
|
||||
|
||||
tolerances
|
||||
(
|
||||
const IOdictionary& controlDict,
|
||||
scalar minCellSize,
|
||||
const boundBox&
|
||||
);
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
// Private data
|
||||
|
||||
//- The surface to mesh
|
||||
const querySurface& qSurf_;
|
||||
|
||||
//- The time registry of the application
|
||||
const Time& runTime_;
|
||||
|
||||
//- Meshing controls
|
||||
controls controls_;
|
||||
|
||||
//- Meshing tolerances
|
||||
tolerances tols_;
|
||||
|
||||
//- Keep track of the start of the internal points
|
||||
label startOfInternalPoints_;
|
||||
|
||||
//- Keep track of the start of the surface point-pairs
|
||||
label startOfSurfacePointPairs_;
|
||||
|
||||
//- Keep track of the boundary conform point-pairs
|
||||
// stored after the insertion of the surface point-pairs in case
|
||||
// the boundary conform function is called more than once without
|
||||
// removing and insertin the surface point-pairs
|
||||
label startOfBoundaryConformPointPairs_;
|
||||
|
||||
//- Store the feature constraining points to be reinserted after a
|
||||
//- triangulation clear
|
||||
List<Vb> featureConstrainingVertices_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
CV3D(const CV3D&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const CV3D&);
|
||||
|
||||
//- Insert point and return it's index
|
||||
inline label insertPoint
|
||||
(
|
||||
const point& pt,
|
||||
const label type
|
||||
);
|
||||
|
||||
inline bool insertMirrorPoint
|
||||
(
|
||||
const point& nearSurfPt,
|
||||
const point& surfPt
|
||||
);
|
||||
|
||||
//- Insert a point-pair at a distance ppDist either side of
|
||||
// surface point point surfPt in the direction n
|
||||
inline void insertPointPair
|
||||
(
|
||||
const scalar mirrorDist,
|
||||
const point& surfPt,
|
||||
const vector& n
|
||||
);
|
||||
|
||||
inline void insertVb(const Vb& v);
|
||||
|
||||
inline void movePoint(const Vertex_handle& vh, const point& p);
|
||||
|
||||
//- Create the initial mesh from the bounding-box
|
||||
void insertBoundingBox();
|
||||
|
||||
//- Insert point groups at the feature points.
|
||||
void insertFeaturePoints();
|
||||
|
||||
//- Reinsert stored feature point defining points.
|
||||
void reinsertFeaturePoints();
|
||||
|
||||
//- Reinsert points that have been saved to clear the mesh.
|
||||
void reinsertPoints (const pointField& points);
|
||||
|
||||
//- Insert point-pairs at the given set of points using the surface
|
||||
// normals corresponding to the given set of surface triangles
|
||||
// and write the inserted point locations to the given file.
|
||||
void insertPointPairs
|
||||
(
|
||||
const DynamicList<point>& nearSurfacePoints,
|
||||
const DynamicList<point>& surfacePoints,
|
||||
const DynamicList<label>& surfaceTris,
|
||||
const fileName fName
|
||||
);
|
||||
|
||||
//- Insert edge control groups at the given edge points using the
|
||||
// normals of the faces attached to the edge.
|
||||
void insertEdgePointGroups
|
||||
(
|
||||
const DynamicList<point>& edgePoints,
|
||||
const DynamicList<label>& edgeLabels,
|
||||
const fileName fName
|
||||
);
|
||||
|
||||
//- Check to see if dual cell specified by given vertex iterator
|
||||
// intersects the boundary and hence reqires a point-pair.
|
||||
bool dualCellSurfaceIntersection
|
||||
(
|
||||
const Triangulation::Finite_vertices_iterator& vit
|
||||
) const;
|
||||
|
||||
//- Smooths the points positioned along a feature edge by collecting
|
||||
//- bunches together and deleting excess points.
|
||||
void smoothEdgePositions
|
||||
(
|
||||
DynamicList<point>& edgePoints,
|
||||
DynamicList<label>& edgeLabels
|
||||
) const;
|
||||
|
||||
void smoothEdge
|
||||
(
|
||||
List<point>& edgePoints,
|
||||
List<scalar>& edgeDistances,
|
||||
const label edgeI
|
||||
) const;
|
||||
|
||||
//- Insert point-pairs at the nearest points on the surface to the
|
||||
// control vertex of dual-cells which intersect the boundary in order
|
||||
// to provide a boundary-layer mesh.
|
||||
// NB: This is not guaranteed to close the boundary
|
||||
void insertSurfaceNearestPointPairs();
|
||||
|
||||
//- Insert point-pairs at small dual-cell edges on the surface in order
|
||||
// to improve the boundary-layer mesh generated by
|
||||
// insertSurfaceNearestPointPairs.
|
||||
void insertSurfaceNearPointPairs();
|
||||
|
||||
void markNearBoundaryPoints();
|
||||
|
||||
//- Dual calculation
|
||||
void calcDualMesh
|
||||
(
|
||||
pointField& points,
|
||||
faceList& faces,
|
||||
labelList& owner,
|
||||
labelList& neighbour,
|
||||
wordList& patchNames,
|
||||
labelList& patchSizes,
|
||||
labelList& patchStarts
|
||||
);
|
||||
|
||||
void setVertexAlignmentDirections();
|
||||
|
||||
scalar alignmentDistanceWeight(scalar dist) const;
|
||||
|
||||
scalar faceAreaWeight(scalar faceArea) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct for given surface
|
||||
CV3D
|
||||
(
|
||||
const Time& runTime,
|
||||
const querySurface& qSurf
|
||||
);
|
||||
|
||||
// Destructor
|
||||
|
||||
~CV3D();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
const controls& meshingControls() const
|
||||
{
|
||||
return controls_;
|
||||
}
|
||||
|
||||
// Conversion functions between point and Point
|
||||
|
||||
# ifdef CGAL_INEXACT
|
||||
typedef const point& pointFromPoint;
|
||||
typedef const Point& PointFrompoint;
|
||||
# else
|
||||
typedef point pointFromPoint;
|
||||
typedef Point PointFrompoint;
|
||||
# endif
|
||||
|
||||
inline pointFromPoint topoint(const Point&) const;
|
||||
inline PointFrompoint toPoint(const point&) const;
|
||||
|
||||
// Point insertion
|
||||
|
||||
//- Create the initial mesh from the given internal points.
|
||||
// Points must be inside the boundary by at least nearness
|
||||
// otherwise they are ignored.
|
||||
void insertPoints
|
||||
(
|
||||
const pointField& points,
|
||||
const scalar nearness
|
||||
);
|
||||
|
||||
//- Create the initial mesh from the internal points in the given
|
||||
// file. Points outside the geometry are ignored.
|
||||
void insertPoints(const fileName& pointFileName);
|
||||
|
||||
//- Create the initial mesh as a BCC lattice of points.
|
||||
// Points outside the geometry are ignored.
|
||||
void insertGrid();
|
||||
|
||||
|
||||
// Point motion
|
||||
|
||||
//- Calculate the displacements to relax the points
|
||||
void relaxPoints(const scalar relaxation);
|
||||
|
||||
//- Insert all surface point-pairs from
|
||||
// insertSurfaceNearestPointPairs and
|
||||
// findIntersectionForOutsideCentroid
|
||||
void insertSurfacePointPairs();
|
||||
|
||||
//- Insert point-pairs where there are protrusions into
|
||||
// or out of the surface
|
||||
void boundaryConform();
|
||||
|
||||
// Point removal
|
||||
|
||||
//- Remove the point-pairs introduced by insertSurfacePointPairs
|
||||
// and boundaryConform
|
||||
void removeSurfacePointPairs();
|
||||
|
||||
// Check
|
||||
|
||||
// Edit
|
||||
|
||||
// Write
|
||||
|
||||
//- Write Delaunay points to .obj file
|
||||
void writePoints(const fileName& fName, bool internalOnly) const;
|
||||
|
||||
//- Write Delaunay triangles as .obj file
|
||||
void writeTriangles(const fileName& fName, bool internalOnly) const;
|
||||
|
||||
//- Write dual points and faces as .obj file
|
||||
void writeDual
|
||||
(
|
||||
const pointField& points,
|
||||
const faceList& faces,
|
||||
const fileName& fName
|
||||
) const;
|
||||
|
||||
//- Write polyMesh
|
||||
void writeMesh(bool writeToTimestep = false);
|
||||
|
||||
void write();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "CV3DI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
177
applications/utilities/mesh/generation/CV3DMesher/CV3DI.H
Normal file
177
applications/utilities/mesh/generation/CV3DMesher/CV3DI.H
Normal file
@ -0,0 +1,177 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
inline Foam::label Foam::CV3D::insertPoint
|
||||
(
|
||||
const point& p,
|
||||
const label type
|
||||
)
|
||||
{
|
||||
uint nVert = number_of_vertices();
|
||||
|
||||
Vertex_handle vh = insert(toPoint(p));
|
||||
|
||||
if (nVert == number_of_vertices())
|
||||
{
|
||||
WarningIn("Foam::CV3D::insertPoint")
|
||||
<< "Failed to insert point " << p << endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
vh->index() = nVert;
|
||||
vh->type() = type;
|
||||
}
|
||||
|
||||
return vh->index();
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::CV3D::insertMirrorPoint
|
||||
(
|
||||
const point& nearSurfPt,
|
||||
const point& surfPt
|
||||
)
|
||||
{
|
||||
point mirrorPoint(2*surfPt - nearSurfPt);
|
||||
|
||||
if (qSurf_.outside(mirrorPoint))
|
||||
{
|
||||
insertPoint(mirrorPoint, Vb::MIRROR_POINT);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::CV3D::insertPointPair
|
||||
(
|
||||
const scalar ppDist,
|
||||
const point& surfPt,
|
||||
const vector& n
|
||||
)
|
||||
{
|
||||
vector ppDistn = ppDist*n;
|
||||
|
||||
label master = insertPoint
|
||||
(
|
||||
surfPt - ppDistn,
|
||||
number_of_vertices() + 1
|
||||
);
|
||||
|
||||
insertPoint(surfPt + ppDistn, master);
|
||||
}
|
||||
|
||||
|
||||
inline void Foam::CV3D::insertVb(const Vb& v)
|
||||
{
|
||||
const Point& Pt(v.point());
|
||||
|
||||
uint nVert = number_of_vertices();
|
||||
|
||||
Vertex_handle vh = insert(Pt);
|
||||
|
||||
if (nVert == number_of_vertices())
|
||||
{
|
||||
FatalErrorIn("Foam::CV3D::insert(const Vb& v")
|
||||
<< "Failed to reinsert Vb at " << topoint(Pt)
|
||||
<< endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
vh->index() = v.index();
|
||||
vh->type() = v.type();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV3D::movePoint(const Vertex_handle& vh, const point& p)
|
||||
{
|
||||
label vi = vh->index();
|
||||
|
||||
// remove(vh);
|
||||
// insert(toPoint(p))->index() = vi;
|
||||
|
||||
move_point(vh, toPoint(p));
|
||||
vh->index() = vi;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef CGAL_INEXACT
|
||||
|
||||
inline Foam::CV3D::pointFromPoint Foam::CV3D::topoint
|
||||
(
|
||||
const Point& P
|
||||
) const
|
||||
{
|
||||
return reinterpret_cast<pointFromPoint>(P);
|
||||
}
|
||||
|
||||
inline Foam::CV3D::PointFrompoint Foam::CV3D::toPoint
|
||||
(
|
||||
const point& p
|
||||
) const
|
||||
{
|
||||
return reinterpret_cast<PointFrompoint>(p);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
inline Foam::CV3D::pointFromPoint Foam::CV3D::topoint
|
||||
(
|
||||
const Point& P
|
||||
) const
|
||||
{
|
||||
return point
|
||||
(
|
||||
CGAL::to_double(P.x()),
|
||||
CGAL::to_double(P.y()),
|
||||
CGAL::to_double(P.z())
|
||||
);
|
||||
}
|
||||
|
||||
inline Foam::CV3D::PointFrompoint Foam::CV3D::toPoint
|
||||
(
|
||||
const point& p
|
||||
) const
|
||||
{
|
||||
return Point(p.x(), p.y(), p.z());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
244
applications/utilities/mesh/generation/CV3DMesher/CV3DIO.C
Normal file
244
applications/utilities/mesh/generation/CV3DMesher/CV3DIO.C
Normal file
@ -0,0 +1,244 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV3D.H"
|
||||
#include "IOstreams.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::CV3D::writePoints(const fileName& fName, bool internalOnly) const
|
||||
{
|
||||
Info<< nl << "Writing points to " << fName << endl;
|
||||
OFstream str(fName);
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
++vit
|
||||
)
|
||||
{
|
||||
if (!internalOnly || vit->internalOrBoundaryPoint())
|
||||
{
|
||||
meshTools::writeOBJ(str, topoint(vit->point()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV3D::writeDual
|
||||
(
|
||||
const pointField& points,
|
||||
const faceList& faces,
|
||||
const fileName& fName
|
||||
) const
|
||||
{
|
||||
Info<< nl << "Writing dual points and faces to " << fName << endl;
|
||||
|
||||
OFstream str(fName);
|
||||
|
||||
forAll(points, p)
|
||||
{
|
||||
meshTools::writeOBJ(str, points[p]);
|
||||
}
|
||||
|
||||
forAll (faces, f)
|
||||
{
|
||||
str<< 'f';
|
||||
|
||||
const face& fP = faces[f];
|
||||
|
||||
forAll(fP, p)
|
||||
{
|
||||
str<< ' ' << fP[p] + 1;
|
||||
}
|
||||
|
||||
str<< nl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV3D::writeTriangles(const fileName& fName, bool internalOnly) const
|
||||
{
|
||||
Info<< nl << "Writing triangles to " << fName << endl;
|
||||
OFstream str(fName);
|
||||
|
||||
labelList vertexMap(number_of_vertices());
|
||||
label verti = 0;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
++vit
|
||||
)
|
||||
{
|
||||
if (!internalOnly || !vit->farPoint())
|
||||
{
|
||||
vertexMap[vit->index()] = verti++;
|
||||
meshTools::writeOBJ(str, topoint(vit->point()));
|
||||
}
|
||||
}
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_facets_iterator fit = finite_facets_begin();
|
||||
fit != finite_facets_end();
|
||||
++fit
|
||||
)
|
||||
{
|
||||
const Cell_handle& c(fit->first);
|
||||
|
||||
const int& oppositeVertex(fit->second);
|
||||
|
||||
List<label> facetIndices(3,-1);
|
||||
|
||||
bool writeFacet = true;
|
||||
|
||||
for(label i = 0, k = 0;i < 4; i++)
|
||||
{
|
||||
if(i != oppositeVertex)
|
||||
{
|
||||
if(!internalOnly || !c->vertex(i)->farPoint())
|
||||
{
|
||||
facetIndices[k] = i;
|
||||
k++;
|
||||
}
|
||||
else
|
||||
{
|
||||
writeFacet = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(writeFacet)
|
||||
{
|
||||
str << "f "
|
||||
<< vertexMap[c->vertex(facetIndices[0])->index()] + 1
|
||||
<< ' ' << vertexMap[c->vertex(facetIndices[1])->index()] + 1
|
||||
<< ' ' << vertexMap[c->vertex(facetIndices[2])->index()] + 1
|
||||
<< nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Foam::CV3D::writeMesh(bool writeToTimestep)
|
||||
{
|
||||
pointField points(0);
|
||||
faceList faces(0);
|
||||
labelList owner(0);
|
||||
labelList neighbour(0);
|
||||
wordList patchNames(0);
|
||||
labelList patchSizes(0);
|
||||
labelList patchStarts(0);
|
||||
|
||||
calcDualMesh
|
||||
(
|
||||
points,
|
||||
faces,
|
||||
owner,
|
||||
neighbour,
|
||||
patchNames,
|
||||
patchSizes,
|
||||
patchStarts
|
||||
);
|
||||
|
||||
writeDual(points, faces, "dualMesh.obj");
|
||||
|
||||
IOobject io
|
||||
(
|
||||
Foam::polyMesh::defaultRegion,
|
||||
runTime_.constant(),
|
||||
runTime_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
);
|
||||
|
||||
if (writeToTimestep)
|
||||
{
|
||||
Info<< nl << "Writing polyMesh to time directory "
|
||||
<< runTime_.timeName() << endl;
|
||||
|
||||
io = IOobject
|
||||
(
|
||||
Foam::polyMesh::defaultRegion,
|
||||
runTime_.path()/runTime_.timeName(),
|
||||
runTime_,
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< nl << "Writing polyMesh to constant." << endl;
|
||||
}
|
||||
|
||||
polyMesh pMesh
|
||||
(
|
||||
io,
|
||||
xferMove(points),
|
||||
xferMove(faces),
|
||||
xferMove(owner),
|
||||
xferMove(neighbour)
|
||||
);
|
||||
// polyMesh pMesh
|
||||
// (
|
||||
// io,
|
||||
// points,
|
||||
// faces,
|
||||
// owner,
|
||||
// neighbour
|
||||
// );
|
||||
|
||||
List<polyPatch*> patches(patchStarts.size());
|
||||
|
||||
forAll (patches, p)
|
||||
{
|
||||
patches[p] = new polyPatch
|
||||
(
|
||||
patchNames[p],
|
||||
patchSizes[p],
|
||||
patchStarts[p],
|
||||
p,
|
||||
pMesh.boundaryMesh()
|
||||
);
|
||||
}
|
||||
|
||||
pMesh.addPatches(patches);
|
||||
|
||||
if (!pMesh.write())
|
||||
{
|
||||
FatalErrorIn("CV3D::writeMesh()")
|
||||
<< "Failed writing polyMesh."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||
|
||||
// ************************************************************************* //
|
||||
130
applications/utilities/mesh/generation/CV3DMesher/CV3DMesher.C
Normal file
130
applications/utilities/mesh/generation/CV3DMesher/CV3DMesher.C
Normal file
@ -0,0 +1,130 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
Application
|
||||
CV3DMesher
|
||||
|
||||
Description
|
||||
Conformal-Voronoi 3D automatic mesher
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "fvCFD.H"
|
||||
#include "CV3D.H"
|
||||
#include "IFstream.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::noParallel();
|
||||
argList::validArgs.clear();
|
||||
argList::validArgs.append("surface");
|
||||
argList::validOptions.insert("pointsFile", "<filename>");
|
||||
|
||||
# include "setRootCase.H"
|
||||
# include "createTime.H"
|
||||
|
||||
IOdictionary CV3DMesherDict
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"CV3DMesherDict",
|
||||
runTime.system(),
|
||||
runTime,
|
||||
IOobject::MUST_READ,
|
||||
IOobject::NO_WRITE
|
||||
)
|
||||
);
|
||||
|
||||
// Read the surface to conform to
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
querySurface surf
|
||||
(
|
||||
args.args()[1],
|
||||
readScalar(CV3DMesherDict.lookup("includedAngle"))
|
||||
);
|
||||
|
||||
Info<< nl
|
||||
<< "Read surface with " << surf.size() << " triangles from file "
|
||||
<< args.args()[1] << nl << endl;
|
||||
|
||||
// Read and triangulation
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
CV3D mesh(runTime, surf);
|
||||
|
||||
if (args.options().found("pointsFile"))
|
||||
{
|
||||
fileName pointFileName(args.options()["pointsFile"]);
|
||||
mesh.insertPoints(pointFileName);
|
||||
mesh.insertSurfacePointPairs();
|
||||
mesh.boundaryConform();
|
||||
}
|
||||
else
|
||||
{
|
||||
mesh.insertGrid();
|
||||
mesh.insertSurfacePointPairs();
|
||||
mesh.boundaryConform();
|
||||
}
|
||||
|
||||
scalar relaxation = mesh.meshingControls().relaxationFactorStart;
|
||||
|
||||
while (runTime.run())
|
||||
{
|
||||
runTime++;
|
||||
|
||||
Info<< nl << "Time = " << runTime.timeName()
|
||||
<< nl << "relaxation = " << relaxation
|
||||
<< endl;
|
||||
|
||||
mesh.relaxPoints(relaxation);
|
||||
|
||||
mesh.insertSurfacePointPairs();
|
||||
|
||||
relaxation -= (relaxation - mesh.meshingControls().relaxationFactorEnd)
|
||||
/max
|
||||
(
|
||||
(runTime.endTime().value() - runTime.timeOutputValue())
|
||||
/runTime.deltaT().value(),
|
||||
1
|
||||
);
|
||||
|
||||
Info<< "ExecutionTime = " << runTime.elapsedCpuTime() << " s"
|
||||
<< " ClockTime = " << runTime.elapsedClockTime() << " s"
|
||||
<< nl << endl;
|
||||
}
|
||||
|
||||
mesh.write();
|
||||
|
||||
Info << nl << "End\n" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
15
applications/utilities/mesh/generation/CV3DMesher/Make/files
Normal file
15
applications/utilities/mesh/generation/CV3DMesher/Make/files
Normal file
@ -0,0 +1,15 @@
|
||||
#include CGAL_FILES
|
||||
|
||||
querySurface.C
|
||||
CV3D.C
|
||||
controls.C
|
||||
tolerances.C
|
||||
CV3DIO.C
|
||||
CV3DMesher.C
|
||||
calcDualMesh.C
|
||||
insertFeaturePoints.C
|
||||
insertSurfaceNearestPointPairs.C
|
||||
insertSurfaceNearPointPairs.C
|
||||
insertBoundaryConformPointPairs.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/CV3DMesher
|
||||
@ -0,0 +1,21 @@
|
||||
//EXE_DEBUG = -DFULLDEBUG -g -O0
|
||||
EXE_FROUNDING_MATH = -frounding-math
|
||||
EXE_NDEBUG = -DNDEBUG
|
||||
|
||||
include $(GENERAL_RULES)/CGAL
|
||||
FFLAGS = -DCGAL_FILES='"${CGAL_PATH}/CGAL/files"'
|
||||
|
||||
EXE_INC = \
|
||||
${EXE_FROUNDING_MATH} \
|
||||
${EXE_NDEBUG} \
|
||||
${CGAL_INC} \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
||||
-I$(LIB_SRC)/triSurface/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lmeshTools \
|
||||
-ltriSurface \
|
||||
-ldynamicMesh \
|
||||
-lboost_thread-gcc43-mt-1_37
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,96 @@
|
||||
IOobject io
|
||||
(
|
||||
Foam::polyMesh::defaultRegion,
|
||||
runTime.constant(),
|
||||
runTime,
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
);
|
||||
|
||||
polyMesh pMesh(io);
|
||||
|
||||
IOobject io2
|
||||
(
|
||||
Foam::polyMesh::defaultRegion,
|
||||
runTime.timeName(),
|
||||
runTime,
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
);
|
||||
|
||||
polyMesh pMesh2(io2, pointField(0), faceList(0), cellList(0));
|
||||
|
||||
polyTopoChange meshCreator(pMesh.boundaryMesh().size());
|
||||
|
||||
meshCreator.addPoint(point(-1,-1,-1), -1, -1, true);
|
||||
meshCreator.addPoint(point(1,-1,-1), -1, -1, true);
|
||||
meshCreator.addPoint(point(1,1,-1), -1, -1, true);
|
||||
meshCreator.addPoint(point(-1,1,-1), -1, -1, true);
|
||||
meshCreator.addPoint(point(-1,-1,1), -1, -1, true);
|
||||
meshCreator.addPoint(point(1,-1,1), -1, -1, true);
|
||||
meshCreator.addPoint(point(1,1,1), -1, -1, true);
|
||||
meshCreator.addPoint(point(-1,1,1), -1, -1, true);
|
||||
|
||||
meshCreator.addCell(-1, -1, -1, -1, -1);
|
||||
|
||||
labelList faceConstruct(4);
|
||||
|
||||
faceConstruct[0] = 1;
|
||||
faceConstruct[1] = 2;
|
||||
faceConstruct[2] = 6;
|
||||
faceConstruct[3] = 5;
|
||||
|
||||
meshCreator.addFace(face(faceConstruct), 0, -1, -1, -1, -1, false, 0, -1, false);
|
||||
|
||||
faceConstruct[0] = 0;
|
||||
faceConstruct[1] = 4;
|
||||
faceConstruct[2] = 7;
|
||||
faceConstruct[3] = 3;
|
||||
|
||||
meshCreator.addFace(face(faceConstruct), 0, -1, -1, -1, -1, false, 0, -1, false);
|
||||
|
||||
faceConstruct[0] = 2;
|
||||
faceConstruct[1] = 3;
|
||||
faceConstruct[2] = 7;
|
||||
faceConstruct[3] = 6;
|
||||
|
||||
meshCreator.addFace(face(faceConstruct), 0, -1, -1, -1, -1, false, 0, -1, false);
|
||||
|
||||
faceConstruct[0] = 0;
|
||||
faceConstruct[1] = 1;
|
||||
faceConstruct[2] = 5;
|
||||
faceConstruct[3] = 4;
|
||||
|
||||
meshCreator.addFace(face(faceConstruct), 0, -1, -1, -1, -1, false, 0, -1, false);
|
||||
|
||||
faceConstruct[0] = 0;
|
||||
faceConstruct[1] = 3;
|
||||
faceConstruct[2] = 2;
|
||||
faceConstruct[3] = 1;
|
||||
|
||||
meshCreator.addFace(face(faceConstruct), 0, -1, -1, -1, -1, false, 0, -1, false);
|
||||
|
||||
faceConstruct[0] = 4;
|
||||
faceConstruct[1] = 5;
|
||||
faceConstruct[2] = 6;
|
||||
faceConstruct[3] = 7;
|
||||
|
||||
meshCreator.addFace(face(faceConstruct), 0, -1, -1, -1, -1, false, 0, -1, false);
|
||||
|
||||
Info<< meshCreator.points() << endl;
|
||||
Info<< meshCreator.faces() << endl;
|
||||
Info<< meshCreator.faceOwner() << endl;
|
||||
Info<< meshCreator.faceNeighbour() << endl;
|
||||
|
||||
// calcDualMesh(meshCreator);
|
||||
|
||||
autoPtr<mapPolyMesh> map = meshCreator.changeMesh(pMesh, false);
|
||||
|
||||
pMesh.updateMesh(map);
|
||||
|
||||
if (!pMesh.write())
|
||||
{
|
||||
FatalErrorIn("CV3D::writeMesh(const Time& runTime)")
|
||||
<< "Failed writing polyMesh."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
@ -0,0 +1,289 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
indexedVertex
|
||||
|
||||
Description
|
||||
An indexed form of CGAL::Triangulation_vertex_base_3<K> used to keep
|
||||
track of the vertices in the triangulation.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef indexedVertex_H
|
||||
#define indexedVertex_H
|
||||
|
||||
#include <CGAL/Triangulation_3.h>
|
||||
#include "vector.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class indexedVertex Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Gt, class Vb=CGAL::Triangulation_vertex_base_3<Gt> >
|
||||
class indexedVertex
|
||||
:
|
||||
public Vb
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- The index for this triangle vertex
|
||||
int index_;
|
||||
|
||||
//- Index of pair-point :
|
||||
// NEAR_BOUNDARY_POINT : internal near boundary point.
|
||||
// INTERNAL_POINT : internal point.
|
||||
// FAR_POINT : far-point.
|
||||
// >= 0 : part of point-pair. Index of other point.
|
||||
// Lowest numbered is inside one (master).
|
||||
int type_;
|
||||
|
||||
Foam::vector displacementSum_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
enum pointTypes
|
||||
{
|
||||
NEAR_BOUNDARY_POINT = -4,
|
||||
INTERNAL_POINT = -3,
|
||||
MIRROR_POINT = -2,
|
||||
FAR_POINT = -1
|
||||
};
|
||||
|
||||
typedef typename Vb::Vertex_handle Vertex_handle;
|
||||
typedef typename Vb::Cell_handle Cell_handle;
|
||||
typedef typename Vb::Point Point;
|
||||
|
||||
template<typename TDS2>
|
||||
struct Rebind_TDS
|
||||
{
|
||||
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
|
||||
typedef indexedVertex<Gt,Vb2> Other;
|
||||
};
|
||||
|
||||
indexedVertex()
|
||||
:
|
||||
Vb(),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT),
|
||||
displacementSum_(Foam::vector::zero)
|
||||
{}
|
||||
|
||||
indexedVertex(const Point& p)
|
||||
:
|
||||
Vb(p),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT),
|
||||
displacementSum_(Foam::vector::zero)
|
||||
{}
|
||||
|
||||
indexedVertex(const Point& p, Cell_handle f)
|
||||
:
|
||||
Vb(f, p),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT),
|
||||
displacementSum_(Foam::vector::zero)
|
||||
{}
|
||||
|
||||
indexedVertex(Cell_handle f)
|
||||
:
|
||||
Vb(f),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT),
|
||||
displacementSum_(Foam::vector::zero)
|
||||
{}
|
||||
|
||||
|
||||
int& index()
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
int index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
|
||||
int& type()
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
int type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
|
||||
Foam::vector& displacementSum()
|
||||
{
|
||||
return displacementSum_;
|
||||
}
|
||||
|
||||
const Foam::vector& displacementSum() const
|
||||
{
|
||||
return displacementSum_;
|
||||
}
|
||||
|
||||
//- Is point a far-point
|
||||
inline bool farPoint() const
|
||||
{
|
||||
return type_ == FAR_POINT;
|
||||
}
|
||||
|
||||
//- Is point internal, i.e. not on boundary
|
||||
inline bool internalPoint() const
|
||||
{
|
||||
return type_ <= INTERNAL_POINT;
|
||||
}
|
||||
|
||||
//- Is point internal and near the boundary
|
||||
inline bool nearBoundary() const
|
||||
{
|
||||
return type_ == NEAR_BOUNDARY_POINT;
|
||||
}
|
||||
|
||||
//- Set the point to be near the boundary
|
||||
inline void setNearBoundary()
|
||||
{
|
||||
type_ = NEAR_BOUNDARY_POINT;
|
||||
}
|
||||
|
||||
//- Is point a mirror point
|
||||
inline bool mirrorPoint() const
|
||||
{
|
||||
return type_ == MIRROR_POINT;
|
||||
}
|
||||
|
||||
//- Either master or slave of pointPair.
|
||||
inline bool pairPoint() const
|
||||
{
|
||||
return type_ >= 0;
|
||||
}
|
||||
|
||||
//- Master of a pointPair is the lowest numbered one.
|
||||
inline bool ppMaster() const
|
||||
{
|
||||
if (type_ > index_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//- Slave of a pointPair is the highest numbered one.
|
||||
inline bool ppSlave() const
|
||||
{
|
||||
if (type_ >= 0 && type_ < index_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//- Either original internal point or master of pointPair.
|
||||
inline bool internalOrBoundaryPoint() const
|
||||
{
|
||||
return internalPoint() || ppMaster();
|
||||
}
|
||||
|
||||
//- Is point near the boundary or part of the boundary definition
|
||||
inline bool nearOrOnBoundary() const
|
||||
{
|
||||
return pairPoint() || mirrorPoint() || nearBoundary();
|
||||
}
|
||||
|
||||
//- Do the two given vertices consitute a boundary point-pair
|
||||
inline friend bool pointPair
|
||||
(
|
||||
const indexedVertex& v0,
|
||||
const indexedVertex& v1
|
||||
)
|
||||
{
|
||||
return v0.index_ == v1.type_ || v1.index_ == v0.type_;
|
||||
}
|
||||
|
||||
//- Do the three given vertices consitute a boundary triangle
|
||||
inline friend bool boundaryTriangle
|
||||
(
|
||||
const indexedVertex& v0,
|
||||
const indexedVertex& v1,
|
||||
const indexedVertex& v2
|
||||
)
|
||||
{
|
||||
return (v0.pairPoint() && pointPair(v1, v2))
|
||||
|| (v1.pairPoint() && pointPair(v2, v0))
|
||||
|| (v2.pairPoint() && pointPair(v0, v1));
|
||||
}
|
||||
|
||||
//- Do the three given vertices consitute an outside triangle
|
||||
inline friend bool outsideTriangle
|
||||
(
|
||||
const indexedVertex& v0,
|
||||
const indexedVertex& v1,
|
||||
const indexedVertex& v2
|
||||
)
|
||||
{
|
||||
return (v0.farPoint() || v0.ppSlave())
|
||||
|| (v1.farPoint() || v1.ppSlave())
|
||||
|| (v2.farPoint() || v2.ppSlave());
|
||||
}
|
||||
|
||||
|
||||
// inline void operator=(const Triangulation::Finite_vertices_iterator vit)
|
||||
// {
|
||||
// Vb::operator=indexedVertex(vit->point());
|
||||
|
||||
// this->index_ = vit->index();
|
||||
|
||||
// this->type_ = vit->type();
|
||||
|
||||
// this->displacementSum_ = vit->displacementSum();
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace CGAL
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
642
applications/utilities/mesh/generation/CV3DMesher/calcDualMesh.C
Normal file
642
applications/utilities/mesh/generation/CV3DMesher/calcDualMesh.C
Normal file
@ -0,0 +1,642 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV3D.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::CV3D::calcDualMesh
|
||||
(
|
||||
pointField& points,
|
||||
faceList& faces,
|
||||
labelList& owner,
|
||||
labelList& neighbour,
|
||||
wordList& patchNames,
|
||||
labelList& patchSizes,
|
||||
labelList& patchStarts
|
||||
)
|
||||
{
|
||||
// ~~~~~~~~~~~ removing short edges by indexing dual vertices ~~~~~~~~~~~~~~
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_cells_iterator cit = finite_cells_begin();
|
||||
cit != finite_cells_end();
|
||||
++cit
|
||||
)
|
||||
{
|
||||
cit->cellIndex() = -1;
|
||||
}
|
||||
|
||||
points.setSize(number_of_cells());
|
||||
|
||||
label dualVerti = 0;
|
||||
|
||||
// Scanning by number of short (dual) edges (nSE) attached to the
|
||||
// circumcentre of each Delaunay tet. A Delaunay tet may only have four
|
||||
// dual edges emanating from its circumcentre, assigning positions and
|
||||
// indices to those with 4 short edges attached first, then >= 3, then >= 2
|
||||
// etc.
|
||||
for (label nSE = 4; nSE >= 0; nSE--)
|
||||
{
|
||||
Info<< nl << "Scanning for dual vertices with >= "
|
||||
<< nSE
|
||||
<< " short edges attached." << endl;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_cells_iterator cit = finite_cells_begin();
|
||||
cit != finite_cells_end();
|
||||
++cit
|
||||
)
|
||||
{
|
||||
// If the Delaunay tet has an index already then it has either
|
||||
// evaluated itself and taken action or has had its index dictated
|
||||
// by a neighbouring tet with more short edges attached.
|
||||
|
||||
if (cit->cellIndex() == -1)
|
||||
{
|
||||
point dualVertex = topoint(dual(cit));
|
||||
|
||||
label shortEdges = 0;
|
||||
|
||||
List<bool> edgeIsShort(4, false);
|
||||
|
||||
List<bool> neighbourAlreadyIndexed(4, false);
|
||||
|
||||
// Loop over the four facets of the Delaunay tet
|
||||
for (label f = 0; f < 4; f++)
|
||||
{
|
||||
// Check that at least one of the vertices of the facet is
|
||||
// an internal or boundary point
|
||||
if
|
||||
(
|
||||
cit->vertex(vertex_triple_index(f, 0))->
|
||||
internalOrBoundaryPoint()
|
||||
|| cit->vertex(vertex_triple_index(f, 1))->
|
||||
internalOrBoundaryPoint()
|
||||
|| cit->vertex(vertex_triple_index(f, 2))->
|
||||
internalOrBoundaryPoint()
|
||||
)
|
||||
{
|
||||
point neighDualVertex;
|
||||
|
||||
label cNI = cit->neighbor(f)->cellIndex();
|
||||
|
||||
if (cNI == -1)
|
||||
{
|
||||
neighDualVertex = topoint(dual(cit->neighbor(f)));
|
||||
}
|
||||
else
|
||||
{
|
||||
neighDualVertex = points[cNI];
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
magSqr(dualVertex - neighDualVertex)
|
||||
< tols_.minEdgeLen2
|
||||
)
|
||||
{
|
||||
edgeIsShort[f] = true;
|
||||
|
||||
if (cNI > -1)
|
||||
{
|
||||
neighbourAlreadyIndexed[f] = true;
|
||||
}
|
||||
|
||||
shortEdges++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (nSE == 0 && shortEdges == 0)
|
||||
{
|
||||
// Final iteration and no short edges are found, index
|
||||
// remaining dual vertices.
|
||||
|
||||
if
|
||||
(
|
||||
cit->vertex(0)->internalOrBoundaryPoint()
|
||||
|| cit->vertex(1)->internalOrBoundaryPoint()
|
||||
|| cit->vertex(2)->internalOrBoundaryPoint()
|
||||
|| cit->vertex(3)->internalOrBoundaryPoint()
|
||||
)
|
||||
{
|
||||
cit->cellIndex() = dualVerti;
|
||||
points[dualVerti] = dualVertex;
|
||||
dualVerti++;
|
||||
}
|
||||
}
|
||||
else if
|
||||
(
|
||||
shortEdges >= nSE
|
||||
)
|
||||
{
|
||||
// Info<< neighbourAlreadyIndexed << ' '
|
||||
// << edgeIsShort << endl;
|
||||
|
||||
label numUnindexedNeighbours = 1;
|
||||
|
||||
for (label f = 0; f < 4; f++)
|
||||
{
|
||||
if (edgeIsShort[f] && !neighbourAlreadyIndexed[f])
|
||||
{
|
||||
dualVertex += topoint(dual(cit->neighbor(f)));
|
||||
|
||||
numUnindexedNeighbours++;
|
||||
}
|
||||
}
|
||||
|
||||
dualVertex /= numUnindexedNeighbours;
|
||||
|
||||
label nearestExistingIndex = -1;
|
||||
|
||||
point nearestIndexedNeighbourPos = vector::zero;
|
||||
|
||||
scalar minDistSqrToNearestIndexedNeighbour = VGREAT;
|
||||
|
||||
for (label f = 0; f < 4; f++)
|
||||
{
|
||||
if (edgeIsShort[f] && neighbourAlreadyIndexed[f])
|
||||
{
|
||||
label cNI = cit->neighbor(f)->cellIndex();
|
||||
|
||||
point indexedNeighbourPos = points[cNI];
|
||||
|
||||
if
|
||||
(
|
||||
magSqr(indexedNeighbourPos - dualVertex)
|
||||
< minDistSqrToNearestIndexedNeighbour
|
||||
)
|
||||
{
|
||||
nearestExistingIndex = cNI;
|
||||
|
||||
nearestIndexedNeighbourPos =
|
||||
indexedNeighbourPos;
|
||||
|
||||
minDistSqrToNearestIndexedNeighbour =
|
||||
magSqr(indexedNeighbourPos - dualVertex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if
|
||||
(
|
||||
nearestExistingIndex > -1
|
||||
&& minDistSqrToNearestIndexedNeighbour < tols_.minEdgeLen2
|
||||
)
|
||||
{
|
||||
points[nearestExistingIndex] =
|
||||
0.5*(dualVertex + nearestIndexedNeighbourPos);
|
||||
|
||||
for (label f = 0; f < 4; f++)
|
||||
{
|
||||
if (edgeIsShort[f] && !neighbourAlreadyIndexed[f])
|
||||
{
|
||||
cit->neighbor(f)->cellIndex() =
|
||||
nearestExistingIndex;
|
||||
}
|
||||
}
|
||||
|
||||
cit->cellIndex() = nearestExistingIndex;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (label f = 0; f < 4; f++)
|
||||
{
|
||||
if (edgeIsShort[f] && !neighbourAlreadyIndexed[f])
|
||||
{
|
||||
cit->neighbor(f)->cellIndex() = dualVerti;
|
||||
}
|
||||
}
|
||||
|
||||
cit->cellIndex() = dualVerti;
|
||||
|
||||
points[dualVerti] = dualVertex;
|
||||
|
||||
dualVerti++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
points.setSize(dualVerti);
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~ dual cell indexing ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// assigns an index to the Delaunay vertices which will be the dual cell
|
||||
// index used for owner neighbour assignment.
|
||||
|
||||
// The indices of the points are reset which destroys the point-pair
|
||||
// matching, so the type of each vertex are reset to avoid any ambiguity.
|
||||
|
||||
label dualCelli = 0;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
++vit
|
||||
)
|
||||
{
|
||||
if (vit->internalOrBoundaryPoint())
|
||||
{
|
||||
vit->type() = Vb::INTERNAL_POINT;
|
||||
vit->index() = dualCelli;
|
||||
dualCelli++;
|
||||
}
|
||||
else
|
||||
{
|
||||
vit->type() = Vb::FAR_POINT;
|
||||
vit->index() = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// ~~~~~~~~~~~~ dual face and owner neighbour construction ~~~~~~~~~~~~~~~~~
|
||||
|
||||
label nPatches = qSurf_.patches().size() + 1;
|
||||
|
||||
label defaultPatchIndex = qSurf_.patches().size();
|
||||
|
||||
patchNames.setSize(nPatches);
|
||||
|
||||
const geometricSurfacePatchList& surfacePatches = qSurf_.patches();
|
||||
|
||||
forAll(surfacePatches, sP)
|
||||
{
|
||||
patchNames[sP] = surfacePatches[sP].name();
|
||||
}
|
||||
|
||||
patchNames[defaultPatchIndex] = "CV3D_default_patch";
|
||||
|
||||
patchSizes.setSize(nPatches);
|
||||
|
||||
patchStarts.setSize(nPatches);
|
||||
|
||||
List<DynamicList<face> > patchFaces(nPatches, DynamicList<face>(0));
|
||||
|
||||
List<DynamicList<label> > patchOwners(nPatches, DynamicList<label>(0));
|
||||
|
||||
faces.setSize(number_of_edges());
|
||||
|
||||
owner.setSize(number_of_edges());
|
||||
|
||||
neighbour.setSize(number_of_edges());
|
||||
|
||||
label dualFacei = 0;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_edges_iterator eit = finite_edges_begin();
|
||||
eit != finite_edges_end();
|
||||
++eit
|
||||
)
|
||||
{
|
||||
Cell_handle c = eit->first;
|
||||
Vertex_handle vA = c->vertex(eit->second);
|
||||
Vertex_handle vB = c->vertex(eit->third);
|
||||
|
||||
if
|
||||
(
|
||||
vA->internalOrBoundaryPoint()
|
||||
|| vB->internalOrBoundaryPoint()
|
||||
)
|
||||
{
|
||||
Cell_circulator ccStart = incident_cells(*eit);
|
||||
Cell_circulator cc1 = ccStart;
|
||||
Cell_circulator cc2 = cc1;
|
||||
|
||||
// Advance the second circulator so that it always stays on the next
|
||||
// cell around the edge;
|
||||
cc2++;
|
||||
|
||||
DynamicList<label> verticesOnFace;
|
||||
|
||||
do
|
||||
{
|
||||
label cc1I = cc1->cellIndex();
|
||||
|
||||
label cc2I = cc2->cellIndex();
|
||||
|
||||
|
||||
if (cc1I < 0 || cc2I < 0)
|
||||
{
|
||||
FatalErrorIn("Foam::CV3D::calcDualMesh")
|
||||
<< "Dual face uses circumcenter defined by a "
|
||||
<< "Delaunay tetrahedron with no internal "
|
||||
<< "or boundary points."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
if (cc1I != cc2I)
|
||||
{
|
||||
verticesOnFace.append(cc1I);
|
||||
}
|
||||
|
||||
cc1++;
|
||||
|
||||
cc2++;
|
||||
} while (cc1 != ccStart);
|
||||
|
||||
verticesOnFace.shrink();
|
||||
|
||||
if (verticesOnFace.size() >= 3)
|
||||
{
|
||||
face newDualFace(verticesOnFace);
|
||||
|
||||
label dcA = vA->index();
|
||||
|
||||
if (!vA->internalOrBoundaryPoint())
|
||||
{
|
||||
dcA = -1;
|
||||
}
|
||||
|
||||
label dcB = vB->index();
|
||||
|
||||
if (!vB->internalOrBoundaryPoint())
|
||||
{
|
||||
dcB = -1;
|
||||
}
|
||||
|
||||
label dcOwn = -1;
|
||||
label dcNei = -1;
|
||||
|
||||
if (dcA == -1 && dcB == -1)
|
||||
{
|
||||
FatalErrorIn("calcDualMesh")
|
||||
<< "Attempting to create a face joining "
|
||||
<< "two external dual cells "
|
||||
<< exit(FatalError);
|
||||
}
|
||||
else if (dcA == -1 || dcB == -1)
|
||||
{
|
||||
// boundary face, find which is the owner
|
||||
|
||||
if (dcA == -1)
|
||||
{
|
||||
dcOwn = dcB;
|
||||
|
||||
// reverse face order to correctly orientate normal
|
||||
reverse(newDualFace);
|
||||
}
|
||||
else
|
||||
{
|
||||
dcOwn = dcA;
|
||||
}
|
||||
|
||||
// Find which patch this face is on by finding the
|
||||
// intersection with the surface of the Delaunay edge
|
||||
// generating the face and identify the region of the
|
||||
// intersection.
|
||||
|
||||
point ptA = topoint(vA->point());
|
||||
|
||||
point ptB = topoint(vB->point());
|
||||
|
||||
pointIndexHit pHit = qSurf_.tree().findLineAny(ptA, ptB);
|
||||
|
||||
label patchIndex = qSurf_[pHit.index()].region();
|
||||
|
||||
if (patchIndex == -1)
|
||||
{
|
||||
patchIndex = defaultPatchIndex;
|
||||
|
||||
WarningIn("Foam::CV3D::calcDualMesh.C")
|
||||
<< "Dual face found that is not on a surface "
|
||||
<< "patch. Adding to CV3D_default_patch."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
patchFaces[patchIndex].append(newDualFace);
|
||||
patchOwners[patchIndex].append(dcOwn);
|
||||
}
|
||||
else
|
||||
{
|
||||
// internal face, find the lower cell to be the owner
|
||||
|
||||
if (dcB > dcA)
|
||||
{
|
||||
dcOwn = dcA;
|
||||
dcNei = dcB;
|
||||
}
|
||||
else
|
||||
{
|
||||
dcOwn = dcB;
|
||||
dcNei = dcA;
|
||||
|
||||
// reverse face order to correctly orientate normal
|
||||
reverse(newDualFace);
|
||||
}
|
||||
|
||||
faces[dualFacei] = newDualFace;
|
||||
|
||||
owner[dualFacei] = dcOwn;
|
||||
|
||||
neighbour[dualFacei] = dcNei;
|
||||
|
||||
dualFacei++;
|
||||
}
|
||||
}
|
||||
// else
|
||||
// {
|
||||
// Info<< verticesOnFace.size()
|
||||
// << " size face not created." << endl;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
label nInternalFaces = dualFacei;
|
||||
|
||||
faces.setSize(nInternalFaces);
|
||||
|
||||
owner.setSize(nInternalFaces);
|
||||
|
||||
neighbour.setSize(nInternalFaces);
|
||||
|
||||
// ~~~~~~~~ sort owner, reordinging neighbour and faces to match ~~~~~~~~~~~
|
||||
// two stage sort for upper triangular order: sort by owner first, then for
|
||||
// each block of owners sort by neighbour
|
||||
|
||||
labelList sortingIndices;
|
||||
|
||||
// Stage 1
|
||||
|
||||
{
|
||||
SortableList<label> sortedOwner(owner);
|
||||
|
||||
sortingIndices = sortedOwner.indices();
|
||||
}
|
||||
|
||||
{
|
||||
labelList copyOwner(owner.size());
|
||||
|
||||
forAll(sortingIndices, sI)
|
||||
{
|
||||
copyOwner[sI] = owner[sortingIndices[sI]];
|
||||
}
|
||||
|
||||
owner = copyOwner;
|
||||
}
|
||||
|
||||
{
|
||||
labelList copyNeighbour(neighbour.size());
|
||||
|
||||
forAll(sortingIndices, sI)
|
||||
{
|
||||
copyNeighbour[sI] = neighbour[sortingIndices[sI]];
|
||||
}
|
||||
|
||||
neighbour = copyNeighbour;
|
||||
}
|
||||
|
||||
{
|
||||
faceList copyFaces(faces.size());
|
||||
|
||||
forAll(sortingIndices, sI)
|
||||
{
|
||||
copyFaces[sI] = faces[sortingIndices[sI]];
|
||||
}
|
||||
|
||||
faces = copyFaces;
|
||||
}
|
||||
|
||||
// Stage 2
|
||||
|
||||
sortingIndices = -1;
|
||||
|
||||
DynamicList<label> ownerCellJumps;
|
||||
|
||||
// Force first owner entry to be a jump
|
||||
ownerCellJumps.append(0);
|
||||
|
||||
for (label o = 1; o < owner.size(); o++)
|
||||
{
|
||||
if (owner[o] > owner[o-1])
|
||||
{
|
||||
ownerCellJumps.append(o);
|
||||
}
|
||||
}
|
||||
|
||||
ownerCellJumps.shrink();
|
||||
|
||||
forAll(ownerCellJumps, oCJ)
|
||||
{
|
||||
label start = ownerCellJumps[oCJ];
|
||||
|
||||
label length;
|
||||
|
||||
if (oCJ == ownerCellJumps.size() - 1)
|
||||
{
|
||||
length = owner.size() - start;
|
||||
}
|
||||
else
|
||||
{
|
||||
length = ownerCellJumps[oCJ + 1] - start;
|
||||
}
|
||||
|
||||
SubList<label> neighbourBlock(neighbour, length, start);
|
||||
|
||||
SortableList<label> sortedNeighbourBlock(neighbourBlock);
|
||||
|
||||
forAll(sortedNeighbourBlock, sNB)
|
||||
{
|
||||
sortingIndices[start + sNB] =
|
||||
sortedNeighbourBlock.indices()[sNB] + start;
|
||||
}
|
||||
}
|
||||
|
||||
// Perform sort
|
||||
|
||||
{
|
||||
labelList copyOwner(owner.size());
|
||||
|
||||
forAll(sortingIndices, sI)
|
||||
{
|
||||
copyOwner[sI] = owner[sortingIndices[sI]];
|
||||
}
|
||||
|
||||
owner = copyOwner;
|
||||
}
|
||||
|
||||
{
|
||||
labelList copyNeighbour(neighbour.size());
|
||||
|
||||
forAll(sortingIndices, sI)
|
||||
{
|
||||
copyNeighbour[sI] = neighbour[sortingIndices[sI]];
|
||||
}
|
||||
|
||||
neighbour = copyNeighbour;
|
||||
}
|
||||
|
||||
{
|
||||
faceList copyFaces(faces.size());
|
||||
|
||||
forAll(sortingIndices, sI)
|
||||
{
|
||||
copyFaces[sI] = faces[sortingIndices[sI]];
|
||||
}
|
||||
|
||||
faces = copyFaces;
|
||||
}
|
||||
|
||||
// ~~~~~~~~ add patch information ~~~~~~~~~~~
|
||||
|
||||
label nBoundaryFaces = 0;
|
||||
|
||||
forAll(patchFaces, p)
|
||||
{
|
||||
patchFaces[p].shrink();
|
||||
|
||||
patchOwners[p].shrink();
|
||||
|
||||
patchSizes[p] = patchFaces[p].size();
|
||||
|
||||
patchStarts[p] = nInternalFaces + nBoundaryFaces;
|
||||
|
||||
nBoundaryFaces += patchSizes[p];
|
||||
}
|
||||
|
||||
faces.setSize(nInternalFaces + nBoundaryFaces);
|
||||
|
||||
owner.setSize(nInternalFaces + nBoundaryFaces);
|
||||
|
||||
forAll(patchFaces, p)
|
||||
{
|
||||
forAll(patchFaces[p], f)
|
||||
{
|
||||
faces[dualFacei] = patchFaces[p][f];
|
||||
|
||||
owner[dualFacei] = patchOwners[p][f];
|
||||
|
||||
dualFacei++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
68
applications/utilities/mesh/generation/CV3DMesher/controls.C
Normal file
68
applications/utilities/mesh/generation/CV3DMesher/controls.C
Normal file
@ -0,0 +1,68 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV3D.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::CV3D::controls::controls(const IOdictionary& controlDict)
|
||||
:
|
||||
relaxationFactorStart
|
||||
(
|
||||
readScalar(controlDict.lookup("relaxationFactorStart"))
|
||||
),
|
||||
relaxationFactorEnd(readScalar(controlDict.lookup("relaxationFactorEnd"))),
|
||||
minCellSize(readScalar(controlDict.lookup("minCellSize"))),
|
||||
minCellSize2(Foam::sqr(minCellSize)),
|
||||
includedAngle(readScalar(controlDict.lookup("includedAngle"))),
|
||||
maxQuadAngle(readScalar(controlDict.lookup("maxQuadAngle"))),
|
||||
squares(controlDict.lookup("squares")),
|
||||
nearWallAlignedDist
|
||||
(
|
||||
readScalar(controlDict.lookup("nearWallAlignedDist"))*minCellSize
|
||||
),
|
||||
nearWallAlignedDist2(Foam::sqr(nearWallAlignedDist)),
|
||||
relaxOrientation(controlDict.lookup("relaxOrientation")),
|
||||
insertSurfaceNearestPointPairs
|
||||
(
|
||||
controlDict.lookup("insertSurfaceNearestPointPairs")
|
||||
),
|
||||
mirrorPoints(controlDict.lookup("mirrorPoints")),
|
||||
insertSurfaceNearPointPairs
|
||||
(
|
||||
controlDict.lookup("insertSurfaceNearPointPairs")
|
||||
),
|
||||
writeInitialTriangulation(controlDict.lookup("writeInitialTriangulation")),
|
||||
writeFeatureTriangulation(controlDict.lookup("writeFeatureTriangulation")),
|
||||
writeNearestTriangulation(controlDict.lookup("writeNearestTriangulation")),
|
||||
writeInsertedPointPairs(controlDict.lookup("writeInsertedPointPairs")),
|
||||
writeFinalTriangulation(controlDict.lookup("writeFinalTriangulation")),
|
||||
randomiseInitialGrid(controlDict.lookup("randomiseInitialGrid")),
|
||||
randomPerturbation(readScalar(controlDict.lookup("randomPerturbation")))
|
||||
{}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
154
applications/utilities/mesh/generation/CV3DMesher/indexedCell.H
Normal file
154
applications/utilities/mesh/generation/CV3DMesher/indexedCell.H
Normal file
@ -0,0 +1,154 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
indexedCell
|
||||
|
||||
Description
|
||||
An indexed form of CGAL::Triangulation_cell_base_3<K> used to keep
|
||||
track of the vertices in the triangulation.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef indexedCell_H
|
||||
#define indexedCell_H
|
||||
|
||||
#include <CGAL/Triangulation_3.h>
|
||||
#include "indexedVertex.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class indexedCell Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Gt, class Cb=CGAL::Triangulation_cell_base_3<Gt> >
|
||||
class indexedCell
|
||||
:
|
||||
public Cb
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- The index for this triangle Cell
|
||||
// -1: triangle and changed and associated data needs updating
|
||||
// >=0: index of cells, set by external update algorithm
|
||||
int index_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
enum cellTypes
|
||||
{
|
||||
UNCHANGED = 0,
|
||||
CHANGED = -1,
|
||||
SAVE_CHANGED = -2
|
||||
};
|
||||
|
||||
typedef typename Cb::Vertex_handle Vertex_handle;
|
||||
typedef typename Cb::Cell_handle Cell_handle;
|
||||
|
||||
template < typename TDS2 >
|
||||
struct Rebind_TDS
|
||||
{
|
||||
typedef typename Cb::template Rebind_TDS<TDS2>::Other Cb2;
|
||||
typedef indexedCell<Gt, Cb2> Other;
|
||||
};
|
||||
|
||||
|
||||
indexedCell()
|
||||
:
|
||||
Cb(),
|
||||
index_(CHANGED)
|
||||
{}
|
||||
|
||||
indexedCell
|
||||
(
|
||||
Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3
|
||||
)
|
||||
:
|
||||
Cb(v0, v1, v2, v3),
|
||||
index_(CHANGED)
|
||||
{}
|
||||
|
||||
indexedCell
|
||||
(
|
||||
Vertex_handle v0,
|
||||
Vertex_handle v1,
|
||||
Vertex_handle v2,
|
||||
Vertex_handle v3,
|
||||
Cell_handle n0,
|
||||
Cell_handle n1,
|
||||
Cell_handle n2,
|
||||
Cell_handle n3
|
||||
)
|
||||
:
|
||||
Cb(v0, v1, v2, v3, n0, n1, n2, n3),
|
||||
index_(CHANGED)
|
||||
{}
|
||||
|
||||
void set_vertex(int i, Vertex_handle v)
|
||||
{
|
||||
index_ = CHANGED;
|
||||
Cb::set_vertex(i, v);
|
||||
}
|
||||
|
||||
void set_vertices()
|
||||
{
|
||||
index_ = CHANGED;
|
||||
Cb::set_vertices();
|
||||
}
|
||||
|
||||
void set_vertices
|
||||
(
|
||||
Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3
|
||||
)
|
||||
{
|
||||
index_ = CHANGED;
|
||||
Cb::set_vertices(v0, v1, v2, v3);
|
||||
}
|
||||
|
||||
int& cellIndex()
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
int cellIndex() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace CGAL
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,315 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
indexedVertex
|
||||
|
||||
Description
|
||||
An indexed form of CGAL::Triangulation_vertex_base_3<K> used to keep
|
||||
track of the vertices in the triangulation.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef indexedVertex_H
|
||||
#define indexedVertex_H
|
||||
|
||||
#include <CGAL/Triangulation_3.h>
|
||||
#include "List.H"
|
||||
#include "vector.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace CGAL
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class indexedVertex Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Gt, class Vb=CGAL::Triangulation_vertex_base_3<Gt> >
|
||||
class indexedVertex
|
||||
:
|
||||
public Vb
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- The index for this triangle vertex
|
||||
int index_;
|
||||
|
||||
//- type of pair-point :
|
||||
// NEAR_BOUNDARY_POINT : internal near boundary point.
|
||||
// INTERNAL_POINT : internal point.
|
||||
// FAR_POINT : far-point.
|
||||
// >= 0 : part of point-pair. Index of other point.
|
||||
// Lowest numbered is inside one (master).
|
||||
int type_;
|
||||
|
||||
Foam::List<Foam::vector> alignmentDirections_;
|
||||
|
||||
Foam::scalar distanceToClosestSurface_;
|
||||
|
||||
Foam::label indexOfClosestPatch_;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
enum pointTypes
|
||||
{
|
||||
NEAR_BOUNDARY_POINT = -4,
|
||||
INTERNAL_POINT = -3,
|
||||
MIRROR_POINT = -2,
|
||||
FAR_POINT = -1
|
||||
};
|
||||
|
||||
typedef typename Vb::Vertex_handle Vertex_handle;
|
||||
typedef typename Vb::Cell_handle Cell_handle;
|
||||
typedef typename Vb::Point Point;
|
||||
|
||||
template<typename TDS2>
|
||||
struct Rebind_TDS
|
||||
{
|
||||
typedef typename Vb::template Rebind_TDS<TDS2>::Other Vb2;
|
||||
typedef indexedVertex<Gt,Vb2> Other;
|
||||
};
|
||||
|
||||
indexedVertex()
|
||||
:
|
||||
Vb(),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT),
|
||||
alignmentDirections_(0),
|
||||
distanceToClosestSurface_(-1),
|
||||
indexOfClosestPatch_(-1)
|
||||
{}
|
||||
|
||||
indexedVertex(const Point& p)
|
||||
:
|
||||
Vb(p),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT),
|
||||
alignmentDirections_(0),
|
||||
distanceToClosestSurface_(-1),
|
||||
indexOfClosestPatch_(-1)
|
||||
{}
|
||||
|
||||
indexedVertex(const Point& p, Cell_handle f)
|
||||
:
|
||||
Vb(f, p),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT),
|
||||
alignmentDirections_(0),
|
||||
distanceToClosestSurface_(-1),
|
||||
indexOfClosestPatch_(-1)
|
||||
{}
|
||||
|
||||
indexedVertex(Cell_handle f)
|
||||
:
|
||||
Vb(f),
|
||||
index_(INTERNAL_POINT),
|
||||
type_(INTERNAL_POINT),
|
||||
alignmentDirections_(0),
|
||||
distanceToClosestSurface_(-1),
|
||||
indexOfClosestPatch_(-1)
|
||||
{}
|
||||
|
||||
|
||||
int& index()
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
int index() const
|
||||
{
|
||||
return index_;
|
||||
}
|
||||
|
||||
int& type()
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
int type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
inline Foam::List<Foam::vector>& alignmentDirections()
|
||||
{
|
||||
return alignmentDirections_;
|
||||
}
|
||||
|
||||
inline const Foam::List<Foam::vector>& alignmentDirections() const
|
||||
{
|
||||
return alignmentDirections_;
|
||||
}
|
||||
|
||||
inline Foam::scalar& distanceToClosestSurface()
|
||||
{
|
||||
return distanceToClosestSurface_;
|
||||
}
|
||||
|
||||
inline Foam::label& indexOfClosestPatch()
|
||||
{
|
||||
return indexOfClosestPatch_;
|
||||
}
|
||||
|
||||
inline bool uninitialised() const
|
||||
{
|
||||
return type_ == INTERNAL_POINT && index_ == INTERNAL_POINT;
|
||||
}
|
||||
|
||||
//- Is point a far-point
|
||||
inline bool farPoint() const
|
||||
{
|
||||
return type_ == FAR_POINT;
|
||||
}
|
||||
|
||||
//- Is point internal, i.e. not on boundary
|
||||
inline bool internalPoint() const
|
||||
{
|
||||
return type_ <= INTERNAL_POINT;
|
||||
}
|
||||
|
||||
//- Is point internal and near the boundary
|
||||
inline bool nearBoundary() const
|
||||
{
|
||||
return type_ == NEAR_BOUNDARY_POINT;
|
||||
}
|
||||
|
||||
//- Set the point to be near the boundary
|
||||
inline void setNearBoundary()
|
||||
{
|
||||
type_ = NEAR_BOUNDARY_POINT;
|
||||
}
|
||||
|
||||
//- Is point a mirror point
|
||||
inline bool mirrorPoint() const
|
||||
{
|
||||
return type_ == MIRROR_POINT;
|
||||
}
|
||||
|
||||
//- Either master or slave of pointPair.
|
||||
inline bool pairPoint() const
|
||||
{
|
||||
return type_ >= 0;
|
||||
}
|
||||
|
||||
//- Master of a pointPair is the lowest numbered one.
|
||||
inline bool ppMaster() const
|
||||
{
|
||||
if (type_ > index_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//- Slave of a pointPair is the highest numbered one.
|
||||
inline bool ppSlave() const
|
||||
{
|
||||
if (type_ >= 0 && type_ < index_)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//- Either original internal point or master of pointPair.
|
||||
inline bool internalOrBoundaryPoint() const
|
||||
{
|
||||
return internalPoint() || ppMaster();
|
||||
}
|
||||
|
||||
//- Is point near the boundary or part of the boundary definition
|
||||
inline bool nearOrOnBoundary() const
|
||||
{
|
||||
return pairPoint() || mirrorPoint() || nearBoundary();
|
||||
}
|
||||
|
||||
//- Do the two given vertices consitute a boundary point-pair
|
||||
inline friend bool pointPair
|
||||
(
|
||||
const indexedVertex& v0,
|
||||
const indexedVertex& v1
|
||||
)
|
||||
{
|
||||
return v0.index_ == v1.type_ || v1.index_ == v0.type_;
|
||||
}
|
||||
|
||||
//- Do the three given vertices consitute a boundary triangle
|
||||
inline friend bool boundaryTriangle
|
||||
(
|
||||
const indexedVertex& v0,
|
||||
const indexedVertex& v1,
|
||||
const indexedVertex& v2
|
||||
)
|
||||
{
|
||||
return (v0.pairPoint() && pointPair(v1, v2))
|
||||
|| (v1.pairPoint() && pointPair(v2, v0))
|
||||
|| (v2.pairPoint() && pointPair(v0, v1));
|
||||
}
|
||||
|
||||
//- Do the three given vertices consitute an outside triangle
|
||||
inline friend bool outsideTriangle
|
||||
(
|
||||
const indexedVertex& v0,
|
||||
const indexedVertex& v1,
|
||||
const indexedVertex& v2
|
||||
)
|
||||
{
|
||||
return (v0.farPoint() || v0.ppSlave())
|
||||
|| (v1.farPoint() || v1.ppSlave())
|
||||
|| (v2.farPoint() || v2.ppSlave());
|
||||
}
|
||||
|
||||
|
||||
// inline void operator=(const Triangulation::Finite_vertices_iterator vit)
|
||||
// {
|
||||
// Vb::operator=indexedVertex(vit->point());
|
||||
|
||||
// this->index_ = vit->index();
|
||||
|
||||
// this->type_ = vit->type();
|
||||
|
||||
// this->displacementSum_ = vit->displacementSum();
|
||||
// }
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace CGAL
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,56 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV3D.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::CV3D::markNearBoundaryPoints()
|
||||
{
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
vit++
|
||||
)
|
||||
{
|
||||
if (vit->internalPoint())
|
||||
{
|
||||
point vert(topoint(vit->point()));
|
||||
|
||||
pointIndexHit pHit =
|
||||
qSurf_.tree().findNearest(vert, 4*controls_.minCellSize2);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
vit->setNearBoundary();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,615 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV3D.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::CV3D::insertFeaturePoints()
|
||||
{
|
||||
Info<< nl << "Inserting feature points" << endl;
|
||||
|
||||
const edgeList& edges = qSurf_.edges();
|
||||
const pointField& localPts = qSurf_.localPoints();
|
||||
|
||||
const labelList& featPoints = qSurf_.features().featurePoints();
|
||||
labelListList featPointFeatEdges = qSurf_.featurePointFeatureEdges();
|
||||
|
||||
scalar planeErrorAngle = 0.1*(180.0 - controls_.includedAngle);
|
||||
|
||||
scalar planeErrorAngleCos =
|
||||
cos(mathematicalConstant::pi*planeErrorAngle/180.0);
|
||||
|
||||
forAll(featPoints, i)
|
||||
{
|
||||
label ptI = featPoints[i];
|
||||
const point& featPt = localPts[ptI];
|
||||
|
||||
Info<< nl <<"Feature at " << featPt << endl;
|
||||
|
||||
const labelList& featEdges = featPointFeatEdges[i];
|
||||
|
||||
DynamicList<label> convexEdges(0);
|
||||
DynamicList<label> concaveEdges(0);
|
||||
|
||||
List<vector> planeNormals(2*featEdges.size());
|
||||
|
||||
// Classify the edges around the feature point.
|
||||
forAll(featEdges, fE)
|
||||
{
|
||||
label edgeI = featEdges[fE];
|
||||
|
||||
// Pick up the two faces adjacent to the feature edge
|
||||
const labelList& eFaces = qSurf_.edgeFaces()[edgeI];
|
||||
|
||||
label faceA = eFaces[0];
|
||||
vector nA = qSurf_.faceNormals()[faceA];
|
||||
|
||||
label faceB = eFaces[1];
|
||||
vector nB = qSurf_.faceNormals()[faceB];
|
||||
|
||||
point faceAVert =
|
||||
localPts[triSurfaceTools::oppositeVertex(qSurf_, faceA, edgeI)];
|
||||
|
||||
// Determine convex or concave angle
|
||||
if (((faceAVert - featPt) & nB) < 0)
|
||||
{
|
||||
// Convex feature edge
|
||||
convexEdges.append(edgeI);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Concave feature edge
|
||||
concaveEdges.append(edgeI);
|
||||
}
|
||||
|
||||
planeNormals[2*fE] = nA;
|
||||
planeNormals[2*fE + 1] = nB;
|
||||
}
|
||||
|
||||
convexEdges.shrink();
|
||||
concaveEdges.shrink();
|
||||
|
||||
// Identify the normals of the faces attached to feature edges to
|
||||
// identify the unique planes to be reconstructed. The triangulated
|
||||
// surface will usually not mean that two feature edges that should
|
||||
// bound a plane are attached to the same face.
|
||||
|
||||
List<vector> uniquePlaneNormals(featEdges.size());
|
||||
|
||||
List<bool> planeMatchedStatus(2*featEdges.size(), bool(false));
|
||||
|
||||
label uniquePlaneNormalI = 0;
|
||||
|
||||
// Examine the plane normals to identify unique planes.
|
||||
forAll(planeNormals, nA)
|
||||
{
|
||||
const vector& normalA = planeNormals[nA];
|
||||
|
||||
scalar maxNormalDotProduct = -SMALL;
|
||||
|
||||
label matchingNormal = -1;
|
||||
|
||||
if (!planeMatchedStatus[nA])
|
||||
{
|
||||
forAll(planeNormals, nB)
|
||||
{
|
||||
if (nA == nB)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!planeMatchedStatus[nB])
|
||||
{
|
||||
const vector& normalB = planeNormals[nB];
|
||||
|
||||
scalar normalDotProduct = normalA & normalB;
|
||||
|
||||
if (normalDotProduct > maxNormalDotProduct)
|
||||
{
|
||||
maxNormalDotProduct = normalDotProduct;
|
||||
|
||||
matchingNormal = nB;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchingNormal >= 0)
|
||||
{
|
||||
if (maxNormalDotProduct < planeErrorAngleCos)
|
||||
{
|
||||
FatalErrorIn("insertFeaturePoints")
|
||||
<< "Matching planes are not similar enough "
|
||||
<< "at point located at "
|
||||
<< featPt << nl
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
const vector& normalB = planeNormals[matchingNormal];
|
||||
|
||||
uniquePlaneNormals[uniquePlaneNormalI] =
|
||||
(normalA + normalB)/(mag(normalA + normalB) + VSMALL);
|
||||
|
||||
uniquePlaneNormalI++;
|
||||
|
||||
planeMatchedStatus[nA] = true;
|
||||
planeMatchedStatus[matchingNormal] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (concaveEdges.size() == 0)
|
||||
{
|
||||
Info<< tab << "Convex feature, "
|
||||
<< convexEdges.size() << " edges." << endl;
|
||||
|
||||
vector cornerNormal = sum(uniquePlaneNormals);
|
||||
cornerNormal /= mag(cornerNormal);
|
||||
|
||||
point internalPt = featPt - tols_.ppDist*cornerNormal;
|
||||
label internalPtIndex =
|
||||
insertPoint(internalPt, number_of_vertices() + 1);
|
||||
|
||||
forAll (uniquePlaneNormals, uPN)
|
||||
{
|
||||
const vector& n = uniquePlaneNormals[uPN];
|
||||
|
||||
plane planeN = plane(featPt, n);
|
||||
|
||||
point externalPt =
|
||||
internalPt + 2.0 * planeN.distance(internalPt) * n;
|
||||
|
||||
insertPoint(externalPt, internalPtIndex);
|
||||
}
|
||||
|
||||
}
|
||||
else if (convexEdges.size() == 0)
|
||||
{
|
||||
Info<< tab << "Concave feature, "
|
||||
<< concaveEdges.size() << " edges." << endl;
|
||||
|
||||
vector cornerNormal = sum(uniquePlaneNormals);
|
||||
cornerNormal /= mag(cornerNormal);
|
||||
|
||||
point externalPt = featPt + tols_.ppDist*cornerNormal;
|
||||
|
||||
label externalPtIndex = number_of_vertices() + concaveEdges.size();
|
||||
|
||||
label internalPtIndex = -1;
|
||||
|
||||
forAll (uniquePlaneNormals, uPN)
|
||||
{
|
||||
const vector& n = uniquePlaneNormals[uPN];
|
||||
|
||||
plane planeN = plane(featPt, n);
|
||||
|
||||
point internalPt = externalPt
|
||||
- 2.0 * planeN.distance(externalPt) * n;
|
||||
|
||||
internalPtIndex = insertPoint(internalPt, externalPtIndex);
|
||||
}
|
||||
|
||||
insertPoint(externalPt,internalPtIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< tab << "Mixed feature: convex, concave = "
|
||||
<< convexEdges.size() << ", " << concaveEdges.size() << endl;
|
||||
|
||||
if (convexEdges.size() + concaveEdges.size() > 3)
|
||||
{
|
||||
Info<< concaveEdges.size() + convexEdges.size()
|
||||
<< " mixed edge feature."
|
||||
<< " NOT IMPLEMENTED." << endl;
|
||||
}
|
||||
else if (convexEdges.size() > concaveEdges.size())
|
||||
{
|
||||
// Find which planes are joined to the concave edge
|
||||
|
||||
List<label> concaveEdgePlanes(2,label(-1));
|
||||
|
||||
label concaveEdgeI = concaveEdges[0];
|
||||
|
||||
// Pick up the two faces adjacent to the concave feature edge
|
||||
const labelList& eFaces = qSurf_.edgeFaces()[concaveEdgeI];
|
||||
|
||||
label faceA = eFaces[0];
|
||||
|
||||
vector nA = qSurf_.faceNormals()[faceA];
|
||||
|
||||
scalar maxNormalDotProduct = -SMALL;
|
||||
|
||||
forAll(uniquePlaneNormals, uPN)
|
||||
{
|
||||
scalar normalDotProduct = nA & uniquePlaneNormals[uPN];
|
||||
|
||||
if (normalDotProduct > maxNormalDotProduct)
|
||||
{
|
||||
maxNormalDotProduct = normalDotProduct;
|
||||
|
||||
concaveEdgePlanes[0] = uPN;
|
||||
}
|
||||
}
|
||||
|
||||
label faceB = eFaces[1];
|
||||
vector nB = qSurf_.faceNormals()[faceB];
|
||||
|
||||
maxNormalDotProduct = -SMALL;
|
||||
|
||||
forAll(uniquePlaneNormals, uPN)
|
||||
{
|
||||
scalar normalDotProduct = nB & uniquePlaneNormals[uPN];
|
||||
|
||||
if (normalDotProduct > maxNormalDotProduct)
|
||||
{
|
||||
maxNormalDotProduct = normalDotProduct;
|
||||
|
||||
concaveEdgePlanes[1] = uPN;
|
||||
}
|
||||
}
|
||||
|
||||
const vector& concaveEdgePlaneANormal =
|
||||
uniquePlaneNormals[concaveEdgePlanes[0]];
|
||||
|
||||
const vector& concaveEdgePlaneBNormal =
|
||||
uniquePlaneNormals[concaveEdgePlanes[1]];
|
||||
|
||||
label convexEdgesPlaneI;
|
||||
|
||||
if (findIndex(concaveEdgePlanes, 0) == -1)
|
||||
{
|
||||
convexEdgesPlaneI = 0;
|
||||
}
|
||||
else if (findIndex(concaveEdgePlanes, 1) == -1)
|
||||
{
|
||||
convexEdgesPlaneI = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
convexEdgesPlaneI = 2;
|
||||
}
|
||||
|
||||
const vector& convexEdgesPlaneNormal =
|
||||
uniquePlaneNormals[convexEdgesPlaneI];
|
||||
|
||||
const edge& concaveEdge = edges[concaveEdgeI];
|
||||
|
||||
// Check direction of edge, if the feature point is at the end()
|
||||
// the reverse direction.
|
||||
|
||||
scalar edgeDirection = 1.0;
|
||||
|
||||
if (ptI == concaveEdge.end())
|
||||
{
|
||||
edgeDirection *= -1.0;
|
||||
}
|
||||
|
||||
// Intersect planes parallel to the concave edge planes offset
|
||||
// by ppDist and the plane defined by featPt and the edge
|
||||
// vector.
|
||||
plane planeA
|
||||
(
|
||||
featPt + tols_.ppDist*concaveEdgePlaneANormal,
|
||||
concaveEdgePlaneANormal
|
||||
);
|
||||
|
||||
plane planeB
|
||||
(
|
||||
featPt + tols_.ppDist*concaveEdgePlaneBNormal,
|
||||
concaveEdgePlaneBNormal
|
||||
);
|
||||
|
||||
point concaveEdgeLocalFeatPt = featPt
|
||||
+ tols_.ppDist*edgeDirection
|
||||
* concaveEdge.vec(localPts)/concaveEdge.mag(localPts);
|
||||
|
||||
// Finding the nearest point on the intersecting line to the
|
||||
// edge point. Floating point errors often encountered using
|
||||
// planePlaneIntersect
|
||||
|
||||
plane planeF(concaveEdgeLocalFeatPt, concaveEdge.vec(localPts));
|
||||
|
||||
point concaveEdgeExternalPt =
|
||||
planeF.planePlaneIntersect(planeA,planeB);
|
||||
|
||||
label concaveEdgeExternalPtI = number_of_vertices() + 4;
|
||||
|
||||
// Redefine planes to be on the feature surfaces to project
|
||||
// through
|
||||
|
||||
planeA = plane(featPt, concaveEdgePlaneANormal);
|
||||
|
||||
planeB = plane(featPt, concaveEdgePlaneBNormal);
|
||||
|
||||
point internalPtA = concaveEdgeExternalPt
|
||||
- 2*planeA.distance(concaveEdgeExternalPt)
|
||||
*concaveEdgePlaneANormal;
|
||||
|
||||
label internalPtAI =
|
||||
insertPoint(internalPtA, concaveEdgeExternalPtI);
|
||||
|
||||
point internalPtB = concaveEdgeExternalPt
|
||||
- 2*planeB.distance(concaveEdgeExternalPt)
|
||||
*concaveEdgePlaneBNormal;
|
||||
|
||||
label internalPtBI =
|
||||
insertPoint(internalPtB, concaveEdgeExternalPtI);
|
||||
|
||||
plane planeC(featPt, convexEdgesPlaneNormal);
|
||||
|
||||
point externalPtD = internalPtA +
|
||||
2*planeC.distance(internalPtA) * convexEdgesPlaneNormal;
|
||||
|
||||
insertPoint(externalPtD, internalPtAI);
|
||||
|
||||
point externalPtE = internalPtB +
|
||||
2*planeC.distance(internalPtB) * convexEdgesPlaneNormal;
|
||||
|
||||
insertPoint(externalPtE, internalPtBI);
|
||||
|
||||
insertPoint(concaveEdgeExternalPt, internalPtAI);
|
||||
|
||||
scalar totalAngle = 180/mathematicalConstant::pi *
|
||||
(
|
||||
mathematicalConstant::pi +
|
||||
acos(mag(concaveEdgePlaneANormal & concaveEdgePlaneBNormal))
|
||||
);
|
||||
|
||||
if (totalAngle > controls_.maxQuadAngle)
|
||||
{
|
||||
// Add additional mitering points
|
||||
|
||||
vector concaveEdgeNormal =
|
||||
edgeDirection*concaveEdge.vec(localPts)
|
||||
/concaveEdge.mag(localPts);
|
||||
|
||||
scalar angleSign = 1.0;
|
||||
|
||||
if
|
||||
(
|
||||
qSurf_.outside
|
||||
(
|
||||
featPt - convexEdgesPlaneNormal*tols_.ppDist
|
||||
)
|
||||
)
|
||||
{
|
||||
angleSign = -1.0;
|
||||
}
|
||||
|
||||
scalar phi = angleSign
|
||||
*acos(concaveEdgeNormal & -convexEdgesPlaneNormal);
|
||||
|
||||
scalar guard =
|
||||
(
|
||||
1 + sin(phi)*tols_.ppDist/mag
|
||||
(
|
||||
concaveEdgeLocalFeatPt - concaveEdgeExternalPt
|
||||
)
|
||||
)/cos(phi) - 1;
|
||||
|
||||
point internalPtF = concaveEdgeExternalPt + (2 + guard)
|
||||
*(concaveEdgeLocalFeatPt - concaveEdgeExternalPt);
|
||||
|
||||
label internalPtFI =
|
||||
insertPoint(internalPtF, number_of_vertices() + 1);
|
||||
|
||||
point externalPtG = internalPtF +
|
||||
2*planeC.distance(internalPtF) * convexEdgesPlaneNormal;
|
||||
insertPoint(externalPtG, internalPtFI);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Find which planes are joined to the convex edge
|
||||
|
||||
List<label> convexEdgePlanes(2,label(-1));
|
||||
|
||||
label convexEdgeI = convexEdges[0];
|
||||
|
||||
// Pick up the two faces adjacent to the convex feature edge
|
||||
const labelList& eFaces = qSurf_.edgeFaces()[convexEdgeI];
|
||||
|
||||
label faceA = eFaces[0];
|
||||
vector nA = qSurf_.faceNormals()[faceA];
|
||||
|
||||
scalar maxNormalDotProduct = -SMALL;
|
||||
|
||||
forAll(uniquePlaneNormals, uPN)
|
||||
{
|
||||
scalar normalDotProduct = nA & uniquePlaneNormals[uPN];
|
||||
|
||||
if (normalDotProduct > maxNormalDotProduct)
|
||||
{
|
||||
maxNormalDotProduct = normalDotProduct;
|
||||
|
||||
convexEdgePlanes[0] = uPN;
|
||||
}
|
||||
}
|
||||
|
||||
label faceB = eFaces[1];
|
||||
vector nB = qSurf_.faceNormals()[faceB];
|
||||
|
||||
maxNormalDotProduct = -SMALL;
|
||||
|
||||
forAll(uniquePlaneNormals, uPN)
|
||||
{
|
||||
scalar normalDotProduct = nB & uniquePlaneNormals[uPN];
|
||||
|
||||
if (normalDotProduct > maxNormalDotProduct)
|
||||
{
|
||||
maxNormalDotProduct = normalDotProduct;
|
||||
|
||||
convexEdgePlanes[1] = uPN;
|
||||
}
|
||||
}
|
||||
|
||||
const vector& convexEdgePlaneANormal =
|
||||
uniquePlaneNormals[convexEdgePlanes[0]];
|
||||
const vector& convexEdgePlaneBNormal =
|
||||
uniquePlaneNormals[convexEdgePlanes[1]];
|
||||
|
||||
label concaveEdgesPlaneI;
|
||||
|
||||
if (findIndex(convexEdgePlanes, 0) == -1)
|
||||
{
|
||||
concaveEdgesPlaneI = 0;
|
||||
}
|
||||
else if (findIndex(convexEdgePlanes, 1) == -1)
|
||||
{
|
||||
concaveEdgesPlaneI = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
concaveEdgesPlaneI = 2;
|
||||
}
|
||||
|
||||
const vector& concaveEdgesPlaneNormal =
|
||||
uniquePlaneNormals[concaveEdgesPlaneI];
|
||||
|
||||
const edge& convexEdge = edges[convexEdgeI];
|
||||
|
||||
// Check direction of edge, if the feature point is at the end()
|
||||
// the reverse direction.
|
||||
|
||||
scalar edgeDirection = 1.0;
|
||||
|
||||
if (ptI == convexEdge.end())
|
||||
{
|
||||
edgeDirection *= -1.0;
|
||||
}
|
||||
|
||||
// Intersect planes parallel to the convex edge planes offset by
|
||||
// ppDist and the plane defined by featPt and the edge vector.
|
||||
plane planeA
|
||||
(
|
||||
featPt - tols_.ppDist*convexEdgePlaneANormal,
|
||||
convexEdgePlaneANormal
|
||||
);
|
||||
|
||||
plane planeB
|
||||
(
|
||||
featPt - tols_.ppDist*convexEdgePlaneBNormal,
|
||||
convexEdgePlaneBNormal
|
||||
);
|
||||
|
||||
point convexEdgeLocalFeatPt = featPt
|
||||
+ tols_.ppDist*edgeDirection
|
||||
* convexEdge.vec(localPts)/convexEdge.mag(localPts);
|
||||
|
||||
|
||||
// Finding the nearest point on the intersecting line to the
|
||||
// edge point. Floating point errors often encountered using
|
||||
// planePlaneIntersect
|
||||
|
||||
plane planeF(convexEdgeLocalFeatPt, convexEdge.vec(localPts));
|
||||
|
||||
point convexEdgeInternalPt =
|
||||
planeF.planePlaneIntersect(planeA,planeB);
|
||||
|
||||
planeA = plane(featPt, convexEdgePlaneANormal);
|
||||
|
||||
planeB = plane(featPt, convexEdgePlaneBNormal);
|
||||
|
||||
point externalPtA = convexEdgeInternalPt
|
||||
+ 2*planeA.distance(convexEdgeInternalPt)
|
||||
* convexEdgePlaneANormal;
|
||||
label externalPtAI = number_of_vertices() + 3;
|
||||
|
||||
point externalPtB = convexEdgeInternalPt
|
||||
+ 2*planeB.distance(convexEdgeInternalPt)
|
||||
* convexEdgePlaneBNormal;
|
||||
|
||||
label externalPtBI = number_of_vertices() + 4;
|
||||
|
||||
label convexEdgeInternalPtI = insertPoint
|
||||
(
|
||||
convexEdgeInternalPt,
|
||||
externalPtAI
|
||||
);
|
||||
|
||||
plane planeC(featPt, concaveEdgesPlaneNormal);
|
||||
|
||||
point internalPtD = externalPtA -
|
||||
2*planeC.distance(externalPtA) * concaveEdgesPlaneNormal;
|
||||
insertPoint(internalPtD, externalPtAI);
|
||||
|
||||
point internalPtE = externalPtB -
|
||||
2*planeC.distance(externalPtB) * concaveEdgesPlaneNormal;
|
||||
insertPoint(internalPtE, externalPtBI);
|
||||
|
||||
insertPoint(externalPtA, convexEdgeInternalPtI);
|
||||
|
||||
insertPoint(externalPtB, convexEdgeInternalPtI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
featureConstrainingVertices_.setSize(number_of_vertices());
|
||||
|
||||
label featPtI = 0;
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
vit++
|
||||
)
|
||||
{
|
||||
featureConstrainingVertices_[featPtI] = Vb(vit->point());
|
||||
|
||||
featureConstrainingVertices_[featPtI].index() = vit->index();
|
||||
|
||||
featureConstrainingVertices_[featPtI].type() = vit->type();
|
||||
|
||||
featPtI++;
|
||||
}
|
||||
|
||||
if (controls_.writeFeatureTriangulation)
|
||||
{
|
||||
writePoints("feat_allPoints.obj", false);
|
||||
writePoints("feat_points.obj", true);
|
||||
writeTriangles("feat_triangles.obj", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV3D::reinsertFeaturePoints()
|
||||
{
|
||||
if (featureConstrainingVertices_.size())
|
||||
{
|
||||
forAll(featureConstrainingVertices_, f)
|
||||
{
|
||||
insertVb(featureConstrainingVertices_[f]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WarningIn("Foam::CV3D::reinsertFeaturePoints")
|
||||
<< "No stored feature points to reinsert." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,45 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV3D.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::CV3D::insertSurfaceNearPointPairs()
|
||||
{
|
||||
Info<< "insertSurfaceNearPointPairs: " << nl << endl;
|
||||
|
||||
label nNearPoints = 0;
|
||||
|
||||
// This needs a rethink from scratch in 3D.
|
||||
// Probably iterating around the facets rather than edges
|
||||
// Remember about the incident_edges, cells etc
|
||||
|
||||
Info<< nNearPoints << " point-pairs inserted" << endl;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,988 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV3D.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
bool Foam::CV3D::dualCellSurfaceIntersection
|
||||
(
|
||||
const Triangulation::Finite_vertices_iterator& vit
|
||||
) const
|
||||
{
|
||||
std::list<Facet> facets;
|
||||
incident_facets(vit, std::back_inserter(facets));
|
||||
|
||||
for
|
||||
(
|
||||
std::list<Facet>::iterator fit=facets.begin();
|
||||
fit != facets.end();
|
||||
++fit
|
||||
)
|
||||
{
|
||||
if
|
||||
(
|
||||
is_infinite(fit->first)
|
||||
|| is_infinite(fit->first->neighbor(fit->second))
|
||||
)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
point dE0 = topoint(dual(fit->first));
|
||||
|
||||
// If edge end is outside bounding box then edge cuts boundary
|
||||
if (!qSurf_.bb().contains(dE0))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
point dE1 = topoint(dual(fit->first->neighbor(fit->second)));
|
||||
|
||||
// If other edge end is outside bounding box then edge cuts boundary
|
||||
if (!qSurf_.bb().contains(dE1))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (magSqr(dE1 - dE0) > tols_.minEdgeLen2)
|
||||
{
|
||||
pointIndexHit pHit = qSurf_.tree().findLineAny(dE0, dE1);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV3D::smoothEdgePositions
|
||||
(
|
||||
DynamicList<point>& edgePoints,
|
||||
DynamicList<label>& edgeLabels
|
||||
) const
|
||||
{
|
||||
const pointField& localPts = qSurf_.localPoints();
|
||||
const edgeList& edges = qSurf_.edges();
|
||||
|
||||
// Sort by edge label then by distance from the start of the edge
|
||||
|
||||
SortableList<label> sortedEdgeLabels(edgeLabels);
|
||||
|
||||
labelList sortingIndices = sortedEdgeLabels.indices();
|
||||
|
||||
{
|
||||
labelList copyEdgeLabels(edgeLabels.size());
|
||||
|
||||
forAll(sortingIndices, sI)
|
||||
{
|
||||
copyEdgeLabels[sI] = edgeLabels[sortingIndices[sI]];
|
||||
}
|
||||
|
||||
edgeLabels.transfer(copyEdgeLabels);
|
||||
}
|
||||
|
||||
{
|
||||
List<point> copyEdgePoints(edgePoints.size());
|
||||
|
||||
forAll(sortingIndices, sI)
|
||||
{
|
||||
copyEdgePoints[sI] = edgePoints[sortingIndices[sI]];
|
||||
}
|
||||
|
||||
edgePoints.transfer(copyEdgePoints);
|
||||
}
|
||||
|
||||
List<scalar> edgeDistances(edgePoints.size());
|
||||
|
||||
forAll(edgeDistances, eD)
|
||||
{
|
||||
const point& edgeStart = localPts[edges[edgeLabels[eD]].start()];
|
||||
|
||||
edgeDistances[eD] = mag(edgeStart - edgePoints[eD]);
|
||||
}
|
||||
|
||||
// Sort by edgeDistances in blocks of edgeLabel
|
||||
|
||||
DynamicList<label> edgeLabelJumps;
|
||||
|
||||
// Force first edgeLabel to be a jump
|
||||
edgeLabelJumps.append(0);
|
||||
|
||||
for (label eL = 1; eL < edgeLabels.size(); eL++)
|
||||
{
|
||||
if (edgeLabels[eL] > edgeLabels[eL-1])
|
||||
{
|
||||
edgeLabelJumps.append(eL);
|
||||
}
|
||||
}
|
||||
|
||||
edgeLabelJumps.shrink();
|
||||
|
||||
forAll(edgeLabelJumps, eLJ)
|
||||
{
|
||||
label start = edgeLabelJumps[eLJ];
|
||||
|
||||
label length;
|
||||
|
||||
if (eLJ == edgeLabelJumps.size() - 1)
|
||||
{
|
||||
length = edgeLabels.size() - start;
|
||||
}
|
||||
else
|
||||
{
|
||||
length = edgeLabelJumps[eLJ + 1] - start;
|
||||
}
|
||||
|
||||
SubList<scalar> edgeDistanceBlock(edgeDistances, length, start);
|
||||
|
||||
SortableList<scalar> sortedEdgeDistanceBlock(edgeDistanceBlock);
|
||||
|
||||
forAll(sortedEdgeDistanceBlock, sEDB)
|
||||
{
|
||||
sortingIndices[start + sEDB] =
|
||||
sortedEdgeDistanceBlock.indices()[sEDB] + start;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
List<point> copyEdgePoints(edgePoints.size());
|
||||
|
||||
forAll(sortingIndices, sI)
|
||||
{
|
||||
copyEdgePoints[sI] = edgePoints[sortingIndices[sI]];
|
||||
}
|
||||
|
||||
edgePoints.transfer(copyEdgePoints);
|
||||
}
|
||||
|
||||
{
|
||||
List<scalar> copyEdgeDistances(edgeDistances.size());
|
||||
|
||||
forAll(sortingIndices, sI)
|
||||
{
|
||||
copyEdgeDistances[sI] = edgeDistances[sortingIndices[sI]];
|
||||
}
|
||||
|
||||
edgeDistances.transfer(copyEdgeDistances);
|
||||
}
|
||||
|
||||
// Create a List to hold each edge, process them individually, then
|
||||
// recombine the edges into a single list.
|
||||
|
||||
List<List<point> > edgePointIndividualLists(edgeLabelJumps.size());
|
||||
|
||||
List<List<scalar> > edgeDistanceIndividualLists(edgeLabelJumps.size());
|
||||
|
||||
List<label> edgeLabelIndividualList(edgeLabelJumps.size());
|
||||
|
||||
forAll(edgeLabelJumps, eLJ)
|
||||
{
|
||||
label start = edgeLabelJumps[eLJ];
|
||||
|
||||
label edgeI = edgeLabels[start];
|
||||
|
||||
label length;
|
||||
|
||||
if (eLJ == edgeLabelJumps.size() - 1)
|
||||
{
|
||||
length = edgeLabels.size() - start;
|
||||
}
|
||||
else
|
||||
{
|
||||
length = edgeLabelJumps[eLJ + 1] - start;
|
||||
}
|
||||
|
||||
edgePointIndividualLists[eLJ] = SubList<point>
|
||||
(
|
||||
edgePoints,
|
||||
length,
|
||||
start
|
||||
);
|
||||
|
||||
edgeDistanceIndividualLists[eLJ] = SubList<scalar>
|
||||
(
|
||||
edgeDistances,
|
||||
length,
|
||||
start
|
||||
);
|
||||
|
||||
edgeLabelIndividualList[eLJ] = edgeI;
|
||||
}
|
||||
|
||||
edgePoints.clear();
|
||||
edgeDistances.clear();
|
||||
edgeLabels.clear();
|
||||
|
||||
forAll(edgeLabelIndividualList, e)
|
||||
{
|
||||
label edgeI = edgeLabelIndividualList[e];
|
||||
|
||||
smoothEdge
|
||||
(
|
||||
edgePointIndividualLists[e],
|
||||
edgeDistanceIndividualLists[e],
|
||||
edgeI
|
||||
);
|
||||
|
||||
const List<point>& tempEdgePoints = edgePointIndividualLists[e];
|
||||
|
||||
forAll(tempEdgePoints, tEP)
|
||||
{
|
||||
edgePoints.append(tempEdgePoints[tEP]);
|
||||
|
||||
edgeLabels.append(edgeI);
|
||||
}
|
||||
}
|
||||
|
||||
edgePoints.shrink();
|
||||
|
||||
edgeLabels.shrink();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Foam::CV3D::smoothEdge
|
||||
(
|
||||
List<point>& edgePoints,
|
||||
List<scalar>& edgeDistances,
|
||||
const label edgeI
|
||||
) const
|
||||
{
|
||||
const pointField& localPts = qSurf_.localPoints();
|
||||
const edgeList& edges = qSurf_.edges();
|
||||
|
||||
// Process the points along each edge (in blocks of edgeLabel) performing 3
|
||||
// functions:
|
||||
// 1: move points away from feature points
|
||||
// 2: aggregate tight groups of points into one point
|
||||
// 3: adjust the spacing of remaining points on a pair by pair basis to
|
||||
// remove excess points and add points to long uncontrolled spans.
|
||||
|
||||
|
||||
const edge& e(edges[edgeI]);
|
||||
|
||||
const point& eStart(localPts[e.start()]);
|
||||
|
||||
const point& eEnd(localPts[e.end()]);
|
||||
|
||||
scalar edgeLength = mag(eStart - eEnd);
|
||||
|
||||
if (edgeLength < 2*tols_.featurePointGuard)
|
||||
{
|
||||
Info<< "edge " << edgeI
|
||||
<< " is too short with respect to the featurePointGuard "
|
||||
<< "distance to allow edge control points to be placed."
|
||||
<< nl << "Edge length = " << edgeLength
|
||||
<< nl <<endl;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// part 1
|
||||
{
|
||||
DynamicList<point> tempEdgePoints;
|
||||
|
||||
bool startGuardPlaced = false;
|
||||
|
||||
bool endGuardPlaced = false;
|
||||
|
||||
forAll (edgePoints, eP)
|
||||
{
|
||||
const point& edgePoint = edgePoints[eP];
|
||||
|
||||
const scalar& edgeDist = edgeDistances[eP];
|
||||
|
||||
if
|
||||
(
|
||||
edgeDist < tols_.featurePointGuard
|
||||
&& !startGuardPlaced
|
||||
)
|
||||
{
|
||||
tempEdgePoints.append
|
||||
(
|
||||
eStart + (edgePoint - eStart)
|
||||
* tols_.featurePointGuard/edgeDist
|
||||
);
|
||||
|
||||
startGuardPlaced = true;
|
||||
}
|
||||
else if
|
||||
(
|
||||
edgeDist > (edgeLength - tols_.featurePointGuard)
|
||||
&& !endGuardPlaced
|
||||
)
|
||||
{
|
||||
tempEdgePoints.append
|
||||
(
|
||||
eEnd + (edgePoint - eEnd)
|
||||
* tols_.featurePointGuard/(edgeLength - edgeDist)
|
||||
);
|
||||
|
||||
endGuardPlaced = true;
|
||||
}
|
||||
else if
|
||||
(
|
||||
edgeDist > tols_.featurePointGuard
|
||||
&& edgeDist < (edgeLength - tols_.featurePointGuard)
|
||||
)
|
||||
{
|
||||
tempEdgePoints.append(edgePoint);
|
||||
}
|
||||
}
|
||||
|
||||
edgePoints.transfer(tempEdgePoints.shrink());
|
||||
}
|
||||
|
||||
// Recalculate edge distances.
|
||||
|
||||
edgeDistances.setSize(edgePoints.size());
|
||||
|
||||
forAll(edgeDistances, eD)
|
||||
{
|
||||
edgeDistances[eD] = mag(eStart - edgePoints[eD]);
|
||||
}
|
||||
|
||||
// part 2
|
||||
{
|
||||
DynamicList<point> tempEdgePoints;
|
||||
|
||||
label groupSize = 0;
|
||||
|
||||
point newEdgePoint(vector::zero);
|
||||
|
||||
// if (edgePoints.size() == 1)
|
||||
// {
|
||||
// tempEdgePoints.append(edgePoints[0]);
|
||||
// }
|
||||
// else if
|
||||
// (
|
||||
// (edgeDistances[1] - edgeDistances[0]) > tols_.edgeGroupSpacing
|
||||
// )
|
||||
// {
|
||||
// tempEdgePoints.append(edgePoints[0]);
|
||||
// }
|
||||
|
||||
if (edgePoints.size() > 1)
|
||||
{
|
||||
if ((edgeDistances[1] - edgeDistances[0]) < tols_.edgeGroupSpacing)
|
||||
{
|
||||
// ...the first two points on the edge start a group
|
||||
|
||||
newEdgePoint += edgePoints[0];
|
||||
|
||||
groupSize++;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempEdgePoints.append(edgePoints[0]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// ...add the first point by default
|
||||
|
||||
tempEdgePoints.append(edgePoints[0]);
|
||||
}
|
||||
|
||||
for (label eP = 1; eP < edgePoints.size(); eP++)
|
||||
{
|
||||
const scalar& edgeDist = edgeDistances[eP];
|
||||
const scalar& previousEdgeDist = edgeDistances[eP - 1];
|
||||
|
||||
if ((edgeDist - previousEdgeDist) < tols_.edgeGroupSpacing)
|
||||
{
|
||||
newEdgePoint += edgePoints[eP];
|
||||
|
||||
groupSize++;
|
||||
}
|
||||
else if (groupSize > 0)
|
||||
{
|
||||
// A point group has been formed and has finished
|
||||
|
||||
newEdgePoint /= groupSize;
|
||||
|
||||
tempEdgePoints.append(newEdgePoint);
|
||||
|
||||
newEdgePoint = vector::zero;
|
||||
|
||||
groupSize = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempEdgePoints.append(edgePoints[eP]);
|
||||
}
|
||||
}
|
||||
|
||||
if (groupSize > 0)
|
||||
{
|
||||
// A point group has been formed at the end of the edge and needs to
|
||||
// be finished.
|
||||
|
||||
newEdgePoint /= groupSize;
|
||||
|
||||
tempEdgePoints.append(newEdgePoint);
|
||||
}
|
||||
|
||||
edgePoints.transfer(tempEdgePoints.shrink());
|
||||
}
|
||||
|
||||
// Recalculate edge distances.
|
||||
|
||||
edgeDistances.setSize(edgePoints.size());
|
||||
|
||||
forAll(edgeDistances, eD)
|
||||
{
|
||||
edgeDistances[eD] = mag(eStart - edgePoints[eD]);
|
||||
}
|
||||
|
||||
// part 3
|
||||
{
|
||||
// Special treatment for gaps between closest point to start
|
||||
|
||||
DynamicList<point> tempEdgePoints;
|
||||
|
||||
if (edgeDistances[0] - tols_.featurePointGuard > tols_.maxEdgeSpacing)
|
||||
{
|
||||
scalar gap = edgeDistances[0] - tols_.featurePointGuard;
|
||||
|
||||
label nInsertions = label(gap/tols_.maxEdgeSpacing);
|
||||
|
||||
// Info<< "Gap at start of edge of " << gap
|
||||
// << ". Inserting " << nInsertions << " points" << endl;
|
||||
|
||||
scalar spacing = gap / (nInsertions + 1);
|
||||
|
||||
for (label nI = 1; nI <= nInsertions; nI++)
|
||||
{
|
||||
tempEdgePoints.append
|
||||
(
|
||||
eStart + (eEnd - eStart)
|
||||
* (nI * spacing + tols_.featurePointGuard) /edgeLength
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Identify gaps in middle of edges.
|
||||
// Insert first point by default.
|
||||
|
||||
tempEdgePoints.append(edgePoints[0]);
|
||||
|
||||
for (label eP = 1; eP < edgePoints.size(); eP++)
|
||||
{
|
||||
const scalar& edgeDist = edgeDistances[eP];
|
||||
const scalar& previousEdgeDist = edgeDistances[eP - 1];
|
||||
|
||||
if ((edgeDist - previousEdgeDist) > tols_.maxEdgeSpacing)
|
||||
{
|
||||
scalar gap = edgeDist - previousEdgeDist;
|
||||
|
||||
label nInsertions = label(gap/tols_.maxEdgeSpacing);
|
||||
|
||||
// Info<< "Gap in edge of " << gap
|
||||
// << ". Inserting " << nInsertions << " points" << endl;
|
||||
|
||||
scalar spacing = gap / (nInsertions + 1);
|
||||
|
||||
for (label nI = 1; nI<= nInsertions; nI++)
|
||||
{
|
||||
tempEdgePoints.append
|
||||
(
|
||||
eStart + (eEnd - eStart)
|
||||
* (nI * spacing + previousEdgeDist) /edgeLength
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
tempEdgePoints.append(edgePoints[eP]);
|
||||
}
|
||||
|
||||
// Special treatment for gaps between closest point to end
|
||||
|
||||
if
|
||||
(
|
||||
(edgeLength - edgeDistances[edgeDistances.size() - 1]
|
||||
- tols_.featurePointGuard)
|
||||
> tols_.maxEdgeSpacing
|
||||
)
|
||||
{
|
||||
scalar lastPointDist = edgeDistances[edgeDistances.size() - 1];
|
||||
|
||||
const point& lastPoint = edgePoints[edgePoints.size() - 1];
|
||||
|
||||
scalar gap = edgeLength - lastPointDist - tols_.featurePointGuard;
|
||||
|
||||
label nInsertions = label(gap/tols_.maxEdgeSpacing);
|
||||
|
||||
// Info<< "Gap at end of edge of " << gap
|
||||
// << ". Inserting " << nInsertions << " points" << endl;
|
||||
|
||||
scalar spacing = gap / (nInsertions + 1);
|
||||
|
||||
for (label nI = 1; nI <= nInsertions; nI++)
|
||||
{
|
||||
tempEdgePoints.append
|
||||
(
|
||||
lastPoint + (eEnd - lastPoint)
|
||||
* nI * spacing / gap
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
edgePoints.transfer(tempEdgePoints.shrink());
|
||||
|
||||
// Remove pairs of points that are too close together.
|
||||
|
||||
label nPointsRemoved = 1;
|
||||
|
||||
while (nPointsRemoved > 0)
|
||||
{
|
||||
nPointsRemoved = 0;
|
||||
|
||||
// Recalculate edge distances.
|
||||
|
||||
edgeDistances.setSize(edgePoints.size());
|
||||
|
||||
forAll(edgeDistances, eD)
|
||||
{
|
||||
edgeDistances[eD] = mag(eStart - edgePoints[eD]);
|
||||
}
|
||||
|
||||
// Insert first point
|
||||
tempEdgePoints.append(edgePoints[0]);
|
||||
|
||||
bool previousPointMustBeKept = false;
|
||||
|
||||
for (label eP = 1; eP < edgePoints.size(); eP++)
|
||||
{
|
||||
const scalar& edgeDist = edgeDistances[eP];
|
||||
const scalar& previousEdgeDist = edgeDistances[eP - 1];
|
||||
|
||||
if ((edgeDist - previousEdgeDist) < tols_.minEdgeSpacing)
|
||||
{
|
||||
if (!previousPointMustBeKept)
|
||||
{
|
||||
tempEdgePoints.remove();
|
||||
}
|
||||
|
||||
const point& currentPoint = edgePoints[eP];
|
||||
|
||||
const point& previousPoint = edgePoints[eP - 1];
|
||||
|
||||
tempEdgePoints.append(0.5*(previousPoint + currentPoint));
|
||||
|
||||
nPointsRemoved++;
|
||||
|
||||
previousPointMustBeKept = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
tempEdgePoints.append(edgePoints[eP]);
|
||||
|
||||
previousPointMustBeKept = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Info<< edgeI << tab
|
||||
//<< nPointsRemoved << " points removed." << endl;
|
||||
|
||||
edgePoints.transfer(tempEdgePoints.shrink());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV3D::insertPointPairs
|
||||
(
|
||||
const DynamicList<point>& nearSurfacePoints,
|
||||
const DynamicList<point>& surfacePoints,
|
||||
const DynamicList<label>& surfaceTris,
|
||||
const fileName fName
|
||||
)
|
||||
{
|
||||
if (controls_.mirrorPoints)
|
||||
{
|
||||
forAll(surfacePoints, ppi)
|
||||
{
|
||||
insertMirrorPoint
|
||||
(
|
||||
nearSurfacePoints[ppi],
|
||||
surfacePoints[ppi]
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
forAll(surfacePoints, ppi)
|
||||
{
|
||||
insertPointPair
|
||||
(
|
||||
tols_.ppDist,
|
||||
surfacePoints[ppi],
|
||||
qSurf_.faceNormals()[surfaceTris[ppi]]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Info<< surfacePoints.size() << " point-pairs inserted" << endl;
|
||||
|
||||
if (controls_.writeInsertedPointPairs)
|
||||
{
|
||||
OFstream str(fName);
|
||||
label vertI = 0;
|
||||
|
||||
forAll(surfacePoints, ppi)
|
||||
{
|
||||
meshTools::writeOBJ(str, surfacePoints[ppi]);
|
||||
vertI++;
|
||||
}
|
||||
|
||||
Info<< "insertPointPairs: Written " << surfacePoints.size()
|
||||
<< " inserted point-pair locations to file "
|
||||
<< str.name() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV3D::insertEdgePointGroups
|
||||
(
|
||||
const DynamicList<point>& edgePoints,
|
||||
const DynamicList<label>& edgeLabels,
|
||||
const fileName fName
|
||||
)
|
||||
{
|
||||
const pointField& localPts = qSurf_.localPoints();
|
||||
|
||||
forAll(edgePoints, eP)
|
||||
{
|
||||
const point& edgePt = edgePoints[eP];
|
||||
|
||||
const label edgeI = edgeLabels[eP];
|
||||
|
||||
// Pick up the two faces adjacent to the feature edge
|
||||
const labelList& eFaces = qSurf_.edgeFaces()[edgeI];
|
||||
|
||||
label faceA = eFaces[0];
|
||||
vector nA = qSurf_.faceNormals()[faceA];
|
||||
|
||||
label faceB = eFaces[1];
|
||||
vector nB = qSurf_.faceNormals()[faceB];
|
||||
|
||||
// Intersect planes parallel to faceA and faceB offset by ppDist
|
||||
// and the plane defined by edgePt and the edge vector.
|
||||
plane planeA(edgePt - tols_.ppDist*nA, nA);
|
||||
plane planeB(edgePt - tols_.ppDist*nB, nB);
|
||||
|
||||
// Finding the nearest point on the intersecting line to the edge point.
|
||||
// Floating point errors often encountered using planePlaneIntersect
|
||||
// plane planeF(edgePt, (nA^nB));
|
||||
// point refPt = planeF.planePlaneIntersect(planeA,planeB);
|
||||
|
||||
plane::ray planeIntersect(planeA.planeIntersect(planeB));
|
||||
|
||||
pointHit refPtHit = linePointRef
|
||||
(
|
||||
planeIntersect.refPoint() + 2*tols_.span*planeIntersect.dir(),
|
||||
planeIntersect.refPoint() - 2*tols_.span*planeIntersect.dir()
|
||||
).nearestDist(edgePt);
|
||||
|
||||
point refPt = refPtHit.hitPoint();
|
||||
|
||||
point faceAVert =
|
||||
localPts[triSurfaceTools::oppositeVertex(qSurf_, faceA, edgeI)];
|
||||
|
||||
// Determine convex or concave angle
|
||||
if (((faceAVert - edgePt) & nB) < 0)
|
||||
{
|
||||
// Convex. So refPt will be inside domain and hence a master point
|
||||
|
||||
// Insert the master point refering the the first slave
|
||||
label masterPtIndex = insertPoint(refPt, number_of_vertices() + 1);
|
||||
|
||||
// Insert the slave points by reflecting refPt in both faces.
|
||||
// with each slave refering to the master
|
||||
|
||||
point reflectedA = refPt + 2*((edgePt - refPt) & nA)*nA;
|
||||
insertPoint(reflectedA, masterPtIndex);
|
||||
|
||||
point reflectedB = refPt + 2*((edgePt - refPt) & nB)*nB;
|
||||
insertPoint(reflectedB, masterPtIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Concave. master and reflected points inside the domain.
|
||||
// Generate reflected master to be outside.
|
||||
point reflMasterPt = refPt + 2*(edgePt - refPt);
|
||||
|
||||
// Reflect refPt in both faces.
|
||||
point reflectedA =
|
||||
reflMasterPt + 2*((edgePt - reflMasterPt) & nA)*nA;
|
||||
|
||||
point reflectedB =
|
||||
reflMasterPt + 2*((edgePt - reflMasterPt) & nB)*nB;
|
||||
|
||||
scalar totalAngle =
|
||||
180*(mathematicalConstant::pi + acos(mag(nA & nB)))
|
||||
/mathematicalConstant::pi;
|
||||
|
||||
// Number of quadrants the angle should be split into
|
||||
int nQuads = int(totalAngle/controls_.maxQuadAngle) + 1;
|
||||
|
||||
// The number of additional master points needed to obtain the
|
||||
// required number of quadrants.
|
||||
int nAddPoints = min(max(nQuads - 2, 0), 2);
|
||||
|
||||
// index of reflMaster
|
||||
label reflectedMaster = number_of_vertices() + 2 + nAddPoints;
|
||||
|
||||
// Master A is inside.
|
||||
label reflectedAI = insertPoint(reflectedA, reflectedMaster);
|
||||
|
||||
// Master B is inside.
|
||||
insertPoint(reflectedB, reflectedMaster);
|
||||
|
||||
if (nAddPoints == 1)
|
||||
{
|
||||
// One additinal point is the reflection of the slave point,
|
||||
// i.e. the original reference point
|
||||
insertPoint(refPt, reflectedMaster);
|
||||
}
|
||||
else if (nAddPoints == 2)
|
||||
{
|
||||
point reflectedAa = refPt
|
||||
- ((edgePt - reflMasterPt) & nB)*nB;
|
||||
insertPoint(reflectedAa, reflectedMaster);
|
||||
|
||||
point reflectedBb = refPt
|
||||
- ((edgePt - reflMasterPt) & nA)*nA;
|
||||
insertPoint(reflectedBb, reflectedMaster);
|
||||
}
|
||||
|
||||
// Slave is outside.
|
||||
insertPoint(reflMasterPt, reflectedAI);
|
||||
}
|
||||
}
|
||||
|
||||
Info<< edgePoints.size() << " edge-control locations inserted" << endl;
|
||||
|
||||
if (controls_.writeInsertedPointPairs)
|
||||
{
|
||||
OFstream str(fName);
|
||||
label vertI = 0;
|
||||
|
||||
forAll(edgePoints, eP)
|
||||
{
|
||||
meshTools::writeOBJ(str, edgePoints[eP]);
|
||||
vertI++;
|
||||
}
|
||||
|
||||
Info<< "insertEdgePointGroups: Written " << edgePoints.size()
|
||||
<< " inserted edge-control locations to file "
|
||||
<< str.name() << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::CV3D::insertSurfaceNearestPointPairs()
|
||||
{
|
||||
Info<< nl << "insertSurfaceNearestPointPairs: " << endl;
|
||||
|
||||
label nSurfacePointsEst = number_of_vertices();
|
||||
|
||||
scalar distanceFactor = 8.0;
|
||||
scalar distanceFactor2 = Foam::sqr(distanceFactor);
|
||||
|
||||
if (qSurf_.features().featureEdges().size())
|
||||
{
|
||||
DynamicList<point> nearSurfacePoints(nSurfacePointsEst);
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit =
|
||||
finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
vit++
|
||||
)
|
||||
{
|
||||
if (vit->internalPoint())
|
||||
{
|
||||
point vert(topoint(vit->point()));
|
||||
|
||||
pointIndexHit pHit = qSurf_.tree().findNearest
|
||||
(
|
||||
vert,
|
||||
distanceFactor2*controls_.minCellSize2
|
||||
);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
vit->setNearBoundary();
|
||||
|
||||
if (dualCellSurfaceIntersection(vit))
|
||||
{
|
||||
nearSurfacePoints.append(vert);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pointField nearSurfacePointsForEdges(nearSurfacePoints.shrink());
|
||||
|
||||
labelList allEdgeLabels;
|
||||
labelList allEdgeEndPoints;
|
||||
pointField allEdgePoints;
|
||||
|
||||
qSurf_.features().nearestSurfEdge
|
||||
(
|
||||
qSurf_.features().featureEdges(),
|
||||
nearSurfacePointsForEdges,
|
||||
vector::one * distanceFactor * controls_.minCellSize,
|
||||
allEdgeLabels,
|
||||
allEdgeEndPoints,
|
||||
allEdgePoints
|
||||
);
|
||||
|
||||
DynamicList<label> edgeLabels(allEdgeLabels.size());
|
||||
DynamicList<vector> edgePoints(allEdgePoints.size());
|
||||
|
||||
forAll(allEdgePoints, eP)
|
||||
{
|
||||
if (allEdgeLabels[eP] >= 0 && allEdgeEndPoints[eP] < 0)
|
||||
{
|
||||
edgeLabels.append(allEdgeLabels[eP]);
|
||||
edgePoints.append(allEdgePoints[eP]);
|
||||
}
|
||||
}
|
||||
|
||||
edgePoints.shrink();
|
||||
edgeLabels.shrink();
|
||||
|
||||
if (edgePoints.size())
|
||||
{
|
||||
Warning<< "Edge point insertion disabled." << endl;
|
||||
|
||||
// smoothEdgePositions(edgePoints, edgeLabels);
|
||||
|
||||
// insertEdgePointGroups
|
||||
// (
|
||||
// edgePoints,
|
||||
// edgeLabels,
|
||||
// "surfaceNearestEdgePoints.obj"
|
||||
// );
|
||||
}
|
||||
}
|
||||
|
||||
DynamicList<point> allNearSurfacePoints(nSurfacePointsEst);
|
||||
DynamicList<point> allSurfacePoints(nSurfacePointsEst);
|
||||
DynamicList<label> allSurfaceTris(nSurfacePointsEst);
|
||||
|
||||
for
|
||||
(
|
||||
Triangulation::Finite_vertices_iterator vit = finite_vertices_begin();
|
||||
vit != finite_vertices_end();
|
||||
vit++
|
||||
)
|
||||
{
|
||||
if (vit->internalPoint())
|
||||
{
|
||||
point vert(topoint(vit->point()));
|
||||
|
||||
pointIndexHit pHit = qSurf_.tree().findNearest
|
||||
(
|
||||
vert,
|
||||
distanceFactor2*controls_.minCellSize2
|
||||
);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
vit->setNearBoundary();
|
||||
|
||||
if (dualCellSurfaceIntersection(vit))
|
||||
{
|
||||
allNearSurfacePoints.append(vert);
|
||||
allSurfacePoints.append(pHit.hitPoint());
|
||||
allSurfaceTris.append(pHit.index());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pointField surfacePointsForEdges(allSurfacePoints.shrink());
|
||||
|
||||
labelList allEdgeLabels;
|
||||
labelList allEdgeEndPoints;
|
||||
pointField allEdgePoints;
|
||||
|
||||
qSurf_.features().nearestSurfEdge
|
||||
(
|
||||
qSurf_.features().featureEdges(),
|
||||
surfacePointsForEdges,
|
||||
vector::one * 2.0 * tols_.featureEdgeGuard,
|
||||
allEdgeLabels,
|
||||
allEdgeEndPoints,
|
||||
allEdgePoints
|
||||
);
|
||||
|
||||
DynamicList<point> nearSurfacePoints(nSurfacePointsEst);
|
||||
DynamicList<point> surfacePoints(nSurfacePointsEst);
|
||||
DynamicList<label> surfaceTris(nSurfacePointsEst);
|
||||
|
||||
forAll(allEdgePoints, eP)
|
||||
{
|
||||
if (allEdgeLabels[eP] == -1)
|
||||
{
|
||||
nearSurfacePoints.append(allNearSurfacePoints[eP]);
|
||||
surfacePoints.append(allSurfacePoints[eP]);
|
||||
surfaceTris.append(allSurfaceTris[eP]);
|
||||
}
|
||||
}
|
||||
|
||||
Info<< nl << "Number of surface conformation points not placed because "
|
||||
<< nl << "they were too close to a feature edge = "
|
||||
<< allSurfacePoints.size() - surfacePoints.size()
|
||||
<< endl;
|
||||
|
||||
nearSurfacePoints.shrink();
|
||||
surfacePoints.shrink();
|
||||
surfaceTris.shrink();
|
||||
|
||||
insertPointPairs
|
||||
(
|
||||
nearSurfacePoints,
|
||||
surfacePoints,
|
||||
surfaceTris,
|
||||
"surfaceNearestIntersections.obj"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
248
applications/utilities/mesh/generation/CV3DMesher/querySurface.C
Normal file
248
applications/utilities/mesh/generation/CV3DMesher/querySurface.C
Normal file
@ -0,0 +1,248 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "querySurface.H"
|
||||
#include "mathematicalConstants.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::querySurface::querySurface
|
||||
(
|
||||
const fileName& surfaceFileName,
|
||||
const scalar& includedAngle
|
||||
)
|
||||
:
|
||||
triSurface(surfaceFileName),
|
||||
rndGen_(12345),
|
||||
bb_(localPoints()),
|
||||
tree_
|
||||
(
|
||||
treeDataTriSurface(*this),
|
||||
bb_.extend(rndGen_, 1e-3), // slightly randomize bb
|
||||
8, // maxLevel
|
||||
4, //10, // leafsize
|
||||
10.0 //3.0 // duplicity
|
||||
),
|
||||
sFeat_(*this, includedAngle)
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::querySurface::~querySurface()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::labelListList Foam::querySurface::featurePointFeatureEdges() const
|
||||
{
|
||||
const labelList& featPoints = features().featurePoints();
|
||||
|
||||
const labelList& featEdges = features().featureEdges();
|
||||
|
||||
const edgeList& edges = this->edges();
|
||||
|
||||
List<DynamicList<label> > tempFeatPointFeatEdges(featPoints.size());
|
||||
|
||||
forAll(featPoints, pI)
|
||||
{
|
||||
label fP = featPoints[pI];
|
||||
|
||||
forAll(featEdges, eI)
|
||||
{
|
||||
label fE = featEdges[eI];
|
||||
|
||||
const edge& e(edges[fE]);
|
||||
|
||||
if (e.start() == fP || e.end() == fP)
|
||||
{
|
||||
tempFeatPointFeatEdges[pI].append(fE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
labelListList featPointFeatEdges(tempFeatPointFeatEdges.size());
|
||||
|
||||
forAll(featPointFeatEdges, fPFE)
|
||||
{
|
||||
featPointFeatEdges[fPFE].transfer(tempFeatPointFeatEdges[fPFE].shrink());
|
||||
}
|
||||
|
||||
return featPointFeatEdges;
|
||||
}
|
||||
|
||||
Foam::indexedOctree<Foam::treeDataTriSurface>::volumeType
|
||||
Foam::querySurface::insideOutside
|
||||
(
|
||||
const scalar searchSpan2,
|
||||
const point& pt
|
||||
) const
|
||||
{
|
||||
if (!bb_.contains(pt))
|
||||
{
|
||||
return indexedOctree<treeDataTriSurface>::OUTSIDE;
|
||||
}
|
||||
|
||||
pointIndexHit pHit = tree_.findNearest(pt, searchSpan2);
|
||||
|
||||
if (!pHit.hit())
|
||||
{
|
||||
return tree_.getVolumeType(pt);
|
||||
}
|
||||
else
|
||||
{
|
||||
return indexedOctree<treeDataTriSurface>::MIXED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if point is inside surface
|
||||
bool Foam::querySurface::inside(const point& pt) const
|
||||
{
|
||||
if (!bb_.contains(pt))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return
|
||||
(
|
||||
tree_.getVolumeType(pt) == indexedOctree<treeDataTriSurface>::INSIDE
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Check if point is outside surface
|
||||
bool Foam::querySurface::outside(const point& pt) const
|
||||
{
|
||||
if (!bb_.contains(pt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return
|
||||
(
|
||||
tree_.getVolumeType(pt) == indexedOctree<treeDataTriSurface>::OUTSIDE
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Check if point is inside surface by at least dist2
|
||||
bool Foam::querySurface::wellInside(const point& pt, const scalar dist2) const
|
||||
{
|
||||
if (!bb_.contains(pt))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
pointIndexHit pHit = tree_.findNearest(pt, dist2);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return
|
||||
tree_.getVolumeType(pt)
|
||||
== indexedOctree<treeDataTriSurface>::INSIDE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check if point is outside surface by at least dist2
|
||||
bool Foam::querySurface::wellOutside(const point& pt, const scalar dist2) const
|
||||
{
|
||||
if (!bb_.contains(pt))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
pointIndexHit pHit = tree_.findNearest(pt, dist2);
|
||||
|
||||
if (pHit.hit())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return
|
||||
tree_.getVolumeType(pt)
|
||||
== indexedOctree<treeDataTriSurface>::OUTSIDE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::querySurface::featurePoint(const label ptI) const
|
||||
{
|
||||
if (findIndex(features().featurePoints(), ptI) >= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::querySurface::writeTreeOBJ() const
|
||||
{
|
||||
OFstream str("tree.obj");
|
||||
label vertI = 0;
|
||||
|
||||
const List<indexedOctree<treeDataTriSurface>::node>& nodes = tree_.nodes();
|
||||
|
||||
forAll(nodes, nodeI)
|
||||
{
|
||||
const indexedOctree<treeDataTriSurface>::node& nod = nodes[nodeI];
|
||||
|
||||
const treeBoundBox& bb = nod.bb_;
|
||||
|
||||
const pointField points(bb.points());
|
||||
|
||||
label startVertI = vertI;
|
||||
|
||||
forAll(points, i)
|
||||
{
|
||||
meshTools::writeOBJ(str, points[i]);
|
||||
vertI++;
|
||||
}
|
||||
|
||||
const edgeList edges(treeBoundBox::edges);
|
||||
|
||||
forAll(edges, i)
|
||||
{
|
||||
const edge& e = edges[i];
|
||||
|
||||
str << "l " << e[0]+startVertI+1 << ' ' << e[1]+startVertI+1
|
||||
<< nl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
162
applications/utilities/mesh/generation/CV3DMesher/querySurface.H
Normal file
162
applications/utilities/mesh/generation/CV3DMesher/querySurface.H
Normal file
@ -0,0 +1,162 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
querySurface
|
||||
|
||||
Description
|
||||
Searchable triSurface using an octree to speed-up queries.
|
||||
|
||||
SourceFiles
|
||||
querySurface.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef querySurface_H
|
||||
#define querySurface_H
|
||||
|
||||
#include "triSurface.H"
|
||||
#include "treeDataTriSurface.H"
|
||||
#include "indexedOctree.H"
|
||||
#include "surfaceFeatures.H"
|
||||
#include "Random.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class querySurface Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class querySurface
|
||||
:
|
||||
public triSurface
|
||||
{
|
||||
// Private data
|
||||
|
||||
Random rndGen_;
|
||||
|
||||
// Bounding box of surface. Used for relative tolerances.
|
||||
treeBoundBox bb_;
|
||||
|
||||
// Search engine on surface
|
||||
indexedOctree<treeDataTriSurface> tree_;
|
||||
|
||||
surfaceFeatures sFeat_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
querySurface(const querySurface&);
|
||||
|
||||
//- Disallow default bitwise assignment
|
||||
void operator=(const querySurface&);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Construct given file name of the surface
|
||||
querySurface
|
||||
(
|
||||
const fileName& surfaceFileName,
|
||||
const scalar& includedAngle
|
||||
);
|
||||
|
||||
|
||||
// Destructor
|
||||
|
||||
~querySurface();
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
const treeBoundBox& bb() const
|
||||
{
|
||||
return bb_;
|
||||
}
|
||||
|
||||
const indexedOctree<treeDataTriSurface>& tree() const
|
||||
{
|
||||
return tree_;
|
||||
}
|
||||
|
||||
const surfaceFeatures& features() const
|
||||
{
|
||||
return sFeat_;
|
||||
}
|
||||
|
||||
|
||||
// Query
|
||||
|
||||
labelListList featurePointFeatureEdges() const;
|
||||
|
||||
//- Returns inside, outside or mixed (= close to surface)
|
||||
indexedOctree<Foam::treeDataTriSurface>::volumeType insideOutside
|
||||
(
|
||||
const scalar searchSpan2,
|
||||
const point& pt
|
||||
) const;
|
||||
|
||||
//- Check if point is inside surface
|
||||
bool inside(const point& pt) const;
|
||||
|
||||
//- Check if point is outside surface
|
||||
bool outside(const point& pt) const;
|
||||
|
||||
//- Check if point is inside surface by at least dist2
|
||||
bool wellInside(const point& pt, const scalar dist2) const;
|
||||
|
||||
//- Check if point is outside surface by at least dist2
|
||||
bool wellOutside(const point& pt, const scalar dist2) const;
|
||||
|
||||
//- Check if a point index is a feature point
|
||||
bool featurePoint(const label ptI) const;
|
||||
|
||||
|
||||
// Write
|
||||
|
||||
void writeTreeOBJ() const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
//#include "querySurfaceI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,77 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / 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
|
||||
|
||||
\*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "CV3D.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::CV3D::tolerances::tolerances
|
||||
(
|
||||
const IOdictionary& controlDict,
|
||||
const scalar minCellSize,
|
||||
const boundBox& bb
|
||||
)
|
||||
:
|
||||
span
|
||||
(
|
||||
max(mag(bb.max().x()), mag(bb.min().x()))
|
||||
+ max(mag(bb.max().y()), mag(bb.min().y()))
|
||||
+ max(mag(bb.max().z()), mag(bb.min().z()))
|
||||
),
|
||||
span2(Foam::sqr(span)),
|
||||
|
||||
minEdgeLen(readScalar(controlDict.lookup("minEdgeLenCoeff"))*minCellSize),
|
||||
minEdgeLen2(Foam::sqr(minEdgeLen)),
|
||||
|
||||
ppDist(readScalar(controlDict.lookup("ppDistCoeff"))*minCellSize),
|
||||
ppDist2(Foam::sqr(ppDist)),
|
||||
|
||||
edgeGroupSpacing
|
||||
(
|
||||
readScalar(controlDict.lookup("edgeGroupSpacingCoeff"))*minCellSize
|
||||
),
|
||||
|
||||
featurePointGuard
|
||||
(
|
||||
readScalar(controlDict.lookup("featurePointGuardCoeff"))*minCellSize
|
||||
),
|
||||
|
||||
featureEdgeGuard
|
||||
(
|
||||
readScalar(controlDict.lookup("featureEdgeGuardCoeff"))*minCellSize
|
||||
),
|
||||
|
||||
minEdgeSpacing
|
||||
(
|
||||
readScalar(controlDict.lookup("minEdgeSpacingCoeff"))*minCellSize
|
||||
),
|
||||
maxEdgeSpacing
|
||||
(
|
||||
readScalar(controlDict.lookup("maxEdgeSpacingCoeff"))*minCellSize
|
||||
)
|
||||
{}
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user