Added functions to searchableSurface to get coordinates and store/retrieve an elementwise field.
Added numbering on searhableSurfaceCollection.
This commit is contained in:
parent
4d4276fd6d
commit
8f656fffab
@ -912,41 +912,6 @@ Foam::distributedTriSurfaceMesh::independentlyDistributedBbs
|
||||
}
|
||||
|
||||
|
||||
void Foam::distributedTriSurfaceMesh::calcBounds
|
||||
(
|
||||
boundBox& bb,
|
||||
label& nPoints
|
||||
) const
|
||||
{
|
||||
// Unfortunately nPoints constructs meshPoints() so do compact version
|
||||
// ourselves
|
||||
|
||||
PackedBoolList pointIsUsed(points().size());
|
||||
|
||||
nPoints = 0;
|
||||
bb.min() = point(VGREAT, VGREAT, VGREAT);
|
||||
bb.max() = point(-VGREAT, -VGREAT, -VGREAT);
|
||||
|
||||
const triSurface& s = static_cast<const triSurface&>(*this);
|
||||
|
||||
forAll(s, triI)
|
||||
{
|
||||
const labelledTri& f = s[triI];
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
label pointI = f[fp];
|
||||
if (pointIsUsed.set(pointI, 1u))
|
||||
{
|
||||
bb.min() = ::Foam::min(bb.min(), points()[pointI]);
|
||||
bb.max() = ::Foam::max(bb.max(), points()[pointI]);
|
||||
nPoints++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Does any part of triangle overlap bb.
|
||||
bool Foam::distributedTriSurfaceMesh::overlaps
|
||||
(
|
||||
@ -1935,20 +1900,7 @@ void Foam::distributedTriSurfaceMesh::getNormal
|
||||
{
|
||||
if (!Pstream::parRun())
|
||||
{
|
||||
normal.setSize(info.size());
|
||||
|
||||
forAll(info, i)
|
||||
{
|
||||
if (info[i].hit())
|
||||
{
|
||||
normal[i] = faceNormals()[info[i].index()];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set to what?
|
||||
normal[i] = vector::zero;
|
||||
}
|
||||
}
|
||||
triSurfaceMesh::getNormal(info, normal);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2006,70 +1958,64 @@ void Foam::distributedTriSurfaceMesh::getNormal
|
||||
|
||||
void Foam::distributedTriSurfaceMesh::getField
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<pointIndexHit>& info,
|
||||
labelList& values
|
||||
) const
|
||||
{
|
||||
const triSurfaceLabelField& fld = lookupObject<triSurfaceLabelField>
|
||||
(
|
||||
fieldName
|
||||
);
|
||||
|
||||
|
||||
if (!Pstream::parRun())
|
||||
{
|
||||
values.setSize(info.size());
|
||||
forAll(info, i)
|
||||
{
|
||||
if (info[i].hit())
|
||||
{
|
||||
values[i] = fld[info[i].index()];
|
||||
}
|
||||
}
|
||||
triSurfaceMesh::getField(info, values);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Get query data (= local index of triangle)
|
||||
// ~~~~~~~~~~~~~~
|
||||
|
||||
labelList triangleIndex(info.size());
|
||||
autoPtr<mapDistribute> mapPtr
|
||||
(
|
||||
calcLocalQueries
|
||||
(
|
||||
info,
|
||||
triangleIndex
|
||||
)
|
||||
);
|
||||
const mapDistribute& map = mapPtr();
|
||||
|
||||
|
||||
// Do my tests
|
||||
// ~~~~~~~~~~~
|
||||
|
||||
values.setSize(triangleIndex.size());
|
||||
|
||||
forAll(triangleIndex, i)
|
||||
if (foundObject<triSurfaceLabelField>("values"))
|
||||
{
|
||||
label triI = triangleIndex[i];
|
||||
values[i] = fld[triI];
|
||||
const triSurfaceLabelField& fld = lookupObject<triSurfaceLabelField>
|
||||
(
|
||||
"values"
|
||||
);
|
||||
|
||||
|
||||
// Get query data (= local index of triangle)
|
||||
// ~~~~~~~~~~~~~~
|
||||
|
||||
labelList triangleIndex(info.size());
|
||||
autoPtr<mapDistribute> mapPtr
|
||||
(
|
||||
calcLocalQueries
|
||||
(
|
||||
info,
|
||||
triangleIndex
|
||||
)
|
||||
);
|
||||
const mapDistribute& map = mapPtr();
|
||||
|
||||
|
||||
// Do my tests
|
||||
// ~~~~~~~~~~~
|
||||
|
||||
values.setSize(triangleIndex.size());
|
||||
|
||||
forAll(triangleIndex, i)
|
||||
{
|
||||
label triI = triangleIndex[i];
|
||||
values[i] = fld[triI];
|
||||
}
|
||||
|
||||
|
||||
// Send back results
|
||||
// ~~~~~~~~~~~~~~~~~
|
||||
|
||||
map.distribute
|
||||
(
|
||||
Pstream::nonBlocking,
|
||||
List<labelPair>(0),
|
||||
info.size(),
|
||||
map.constructMap(), // what to send
|
||||
map.subMap(), // what to receive
|
||||
values
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// Send back results
|
||||
// ~~~~~~~~~~~~~~~~~
|
||||
|
||||
map.distribute
|
||||
(
|
||||
Pstream::nonBlocking,
|
||||
List<labelPair>(0),
|
||||
info.size(),
|
||||
map.constructMap(), // what to send
|
||||
map.subMap(), // what to receive
|
||||
values
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
@ -217,9 +217,6 @@ private:
|
||||
const triSurface&
|
||||
);
|
||||
|
||||
//- Calculate surface bounding box
|
||||
void calcBounds(boundBox& bb, label& nPoints) const;
|
||||
|
||||
//- Does any part of triangle overlap bb.
|
||||
static bool overlaps
|
||||
(
|
||||
@ -418,7 +415,7 @@ public:
|
||||
// Should really be split into a routine to determine decomposition
|
||||
// and one that does actual distribution but determining
|
||||
// decomposition with duplicate triangle merging requires
|
||||
// same amoun as work as actual distribution.
|
||||
// same amount as work as actual distribution.
|
||||
virtual void distribute
|
||||
(
|
||||
const List<treeBoundBox>&,
|
||||
@ -430,14 +427,9 @@ public:
|
||||
|
||||
// Other
|
||||
|
||||
//- Specific to triSurfaceMesh: from a set of hits (points and
|
||||
//- WIP. From a set of hits (points and
|
||||
// indices) get the specified field. Misses do not get set.
|
||||
virtual void getField
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<pointIndexHit>&,
|
||||
labelList& values
|
||||
) const;
|
||||
virtual void getField(const List<pointIndexHit>&, labelList&) const;
|
||||
|
||||
//- Subset the part of surface that is overlapping bounds.
|
||||
static triSurface overlappingSurface
|
||||
|
@ -229,6 +229,21 @@ const Foam::wordList& Foam::searchableBox::regions() const
|
||||
}
|
||||
|
||||
|
||||
Foam::pointField Foam::searchableBox::coordinates() const
|
||||
{
|
||||
pointField ctrs(6);
|
||||
|
||||
const pointField pts = treeBoundBox::points();
|
||||
const faceList& fcs = treeBoundBox::faces;
|
||||
|
||||
forAll(fcs, i)
|
||||
{
|
||||
ctrs[i] = fcs[i].centre(pts);
|
||||
}
|
||||
return ctrs;
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::searchableBox::findNearest
|
||||
(
|
||||
const point& sample,
|
||||
|
@ -127,6 +127,9 @@ public:
|
||||
return 6;
|
||||
}
|
||||
|
||||
//- Get representative set of element coordinates
|
||||
// Usually the element centres (should be of length size()).
|
||||
virtual pointField coordinates() const;
|
||||
|
||||
// Single point queries.
|
||||
|
||||
|
@ -40,6 +40,14 @@ addToRunTimeSelectionTable(searchableSurface, searchableCylinder, dict);
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::pointField Foam::searchableCylinder::coordinates() const
|
||||
{
|
||||
pointField ctrs(1, 0.5*(point1_ + point2_));
|
||||
|
||||
return ctrs;
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::searchableCylinder::findNearest
|
||||
(
|
||||
const point& sample,
|
||||
|
@ -150,6 +150,10 @@ public:
|
||||
return 1;
|
||||
}
|
||||
|
||||
//- Get representative set of element coordinates
|
||||
// Usually the element centres (should be of length size()).
|
||||
virtual pointField coordinates() const;
|
||||
|
||||
|
||||
// Multiple point queries.
|
||||
|
||||
|
@ -26,7 +26,7 @@ Class
|
||||
Foam::searchablePlane
|
||||
|
||||
Description
|
||||
Searching on plane. See plane.H
|
||||
Searching on (infinite) plane. See plane.H
|
||||
|
||||
SourceFiles
|
||||
searchablePlane.C
|
||||
@ -122,6 +122,14 @@ public:
|
||||
return 1;
|
||||
}
|
||||
|
||||
//- Get representative set of element coordinates
|
||||
// Usually the element centres (should be of length size()).
|
||||
virtual pointField coordinates() const
|
||||
{
|
||||
//notImplemented("searchablePlane::coordinates()")
|
||||
return pointField(1, refPoint());
|
||||
}
|
||||
|
||||
|
||||
// Multiple point queries.
|
||||
|
||||
|
@ -145,6 +145,13 @@ public:
|
||||
return 1;
|
||||
}
|
||||
|
||||
//- Get representative set of element coordinates
|
||||
// Usually the element centres (should be of length size()).
|
||||
virtual pointField coordinates() const
|
||||
{
|
||||
return pointField(1, origin_);
|
||||
}
|
||||
|
||||
|
||||
// Multiple point queries.
|
||||
|
||||
|
@ -133,6 +133,13 @@ public:
|
||||
return 1;
|
||||
}
|
||||
|
||||
//- Get representative set of element coordinates
|
||||
// Usually the element centres (should be of length size()).
|
||||
virtual pointField coordinates() const
|
||||
{
|
||||
return pointField(1, centre_);
|
||||
}
|
||||
|
||||
|
||||
// Multiple point queries.
|
||||
|
||||
|
@ -190,6 +190,10 @@ public:
|
||||
return size();
|
||||
}
|
||||
|
||||
//- Get representative set of element coordinates
|
||||
// Usually the element centres (should be of length size()).
|
||||
virtual pointField coordinates() const = 0;
|
||||
|
||||
|
||||
// Single point queries.
|
||||
|
||||
@ -319,6 +323,18 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
//- WIP. Store element-wise field.
|
||||
virtual void setField(const labelList& values)
|
||||
{}
|
||||
|
||||
//- WIP. From a set of hits (points and
|
||||
// indices) get the specified field. Misses do not get set. Return
|
||||
// empty field if not supported.
|
||||
virtual void getField(const List<pointIndexHit>&, labelList& values)
|
||||
const
|
||||
{
|
||||
values.clear();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
@ -101,7 +101,11 @@ void Foam::searchableSurfaceCollection::findNearest
|
||||
minDistSqr[pointI] = distSqr;
|
||||
nearestInfo[pointI].setPoint(globalPt);
|
||||
nearestInfo[pointI].setHit();
|
||||
nearestInfo[pointI].setIndex(hitInfo[pointI].index());
|
||||
nearestInfo[pointI].setIndex
|
||||
(
|
||||
hitInfo[pointI].index()
|
||||
+ indexOffset_[surfI]
|
||||
);
|
||||
nearestSurf[pointI] = surfI;
|
||||
}
|
||||
}
|
||||
@ -110,6 +114,62 @@ void Foam::searchableSurfaceCollection::findNearest
|
||||
}
|
||||
|
||||
|
||||
// Sort hits into per-surface bins. Misses are rejected. Maintains map back
|
||||
// to position
|
||||
void Foam::searchableSurfaceCollection::sortHits
|
||||
(
|
||||
const List<pointIndexHit>& info,
|
||||
List<List<pointIndexHit> >& surfInfo,
|
||||
labelListList& infoMap
|
||||
) const
|
||||
{
|
||||
// Count hits per surface.
|
||||
labelList nHits(subGeom_.size(), 0);
|
||||
|
||||
forAll(info, pointI)
|
||||
{
|
||||
if (info[pointI].hit())
|
||||
{
|
||||
label index = info[pointI].index();
|
||||
label surfI = findLower(indexOffset_, index+1);
|
||||
nHits[surfI]++;
|
||||
}
|
||||
}
|
||||
|
||||
// Per surface the hit
|
||||
surfInfo.setSize(subGeom_.size());
|
||||
// Per surface the original position
|
||||
infoMap.setSize(subGeom_.size());
|
||||
|
||||
forAll(surfInfo, surfI)
|
||||
{
|
||||
surfInfo[surfI].setSize(nHits[surfI]);
|
||||
infoMap[surfI].setSize(nHits[surfI]);
|
||||
}
|
||||
nHits = 0;
|
||||
|
||||
forAll(info, pointI)
|
||||
{
|
||||
if (info[pointI].hit())
|
||||
{
|
||||
label index = info[pointI].index();
|
||||
label surfI = findLower(indexOffset_, index+1);
|
||||
|
||||
// Store for correct surface and adapt indices back to local
|
||||
// ones
|
||||
label localI = nHits[surfI]++;
|
||||
surfInfo[surfI][localI] = pointIndexHit
|
||||
(
|
||||
info[pointI].hit(),
|
||||
info[pointI].rawPoint(),
|
||||
index-indexOffset_[surfI]
|
||||
);
|
||||
infoMap[surfI][localI] = pointI;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::searchableSurfaceCollection::searchableSurfaceCollection
|
||||
@ -123,11 +183,13 @@ Foam::searchableSurfaceCollection::searchableSurfaceCollection
|
||||
scale_(dict.size()),
|
||||
transform_(dict.size()),
|
||||
subGeom_(dict.size()),
|
||||
mergeSubRegions_(dict.lookup("mergeSubRegions"))
|
||||
mergeSubRegions_(dict.lookup("mergeSubRegions")),
|
||||
indexOffset_(dict.size()+1)
|
||||
{
|
||||
Info<< "SearchableCollection : " << name() << endl;
|
||||
|
||||
label surfI = 0;
|
||||
label startIndex = 0;
|
||||
forAllConstIter(dictionary, dict, iter)
|
||||
{
|
||||
if (dict.isDict(iter().keyword()))
|
||||
@ -153,8 +215,24 @@ Foam::searchableSurfaceCollection::searchableSurfaceCollection
|
||||
const searchableSurface& s =
|
||||
io.db().lookupObject<searchableSurface>(subGeomName);
|
||||
|
||||
// I don't know yet how to handle the globalSize combined with
|
||||
// regionOffset. Would cause non-consecutive indices locally
|
||||
// if all indices offset by globalSize() of the local region...
|
||||
if (s.size() != s.globalSize())
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"searchableSurfaceCollection::searchableSurfaceCollection"
|
||||
"(const IOobject&, const dictionary&)"
|
||||
) << "Cannot use a distributed surface in a collection."
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
subGeom_.set(surfI, &const_cast<searchableSurface&>(s));
|
||||
|
||||
indexOffset_[surfI] = startIndex;
|
||||
startIndex += subGeom_[surfI].size();
|
||||
|
||||
Info<< " instance : " << instance_[surfI] << endl;
|
||||
Info<< " surface : " << s.name() << endl;
|
||||
Info<< " scale : " << scale_[surfI] << endl;
|
||||
@ -163,10 +241,13 @@ Foam::searchableSurfaceCollection::searchableSurfaceCollection
|
||||
surfI++;
|
||||
}
|
||||
}
|
||||
indexOffset_[surfI] = startIndex;
|
||||
|
||||
instance_.setSize(surfI);
|
||||
scale_.setSize(surfI);
|
||||
transform_.setSize(surfI);
|
||||
subGeom_.setSize(surfI);
|
||||
indexOffset_.setSize(surfI+1);
|
||||
}
|
||||
|
||||
|
||||
@ -212,12 +293,36 @@ const Foam::wordList& Foam::searchableSurfaceCollection::regions() const
|
||||
|
||||
Foam::label Foam::searchableSurfaceCollection::size() const
|
||||
{
|
||||
label n = 0;
|
||||
return indexOffset_[indexOffset_.size()-1];
|
||||
}
|
||||
|
||||
|
||||
Foam::pointField Foam::searchableSurfaceCollection::coordinates() const
|
||||
{
|
||||
// Get overall size
|
||||
pointField coords(size());
|
||||
|
||||
// Append individual coordinates
|
||||
label coordI = 0;
|
||||
|
||||
forAll(subGeom_, surfI)
|
||||
{
|
||||
n += subGeom_[surfI].size();
|
||||
const pointField subCoords = subGeom_[surfI].coordinates();
|
||||
|
||||
forAll(subCoords, i)
|
||||
{
|
||||
coords[coordI++] = transform_[surfI].globalPosition
|
||||
(
|
||||
cmptMultiply
|
||||
(
|
||||
subCoords[i],
|
||||
scale_[surfI]
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return n;
|
||||
|
||||
return coords;
|
||||
}
|
||||
|
||||
|
||||
@ -296,6 +401,11 @@ void Foam::searchableSurfaceCollection::findLine
|
||||
);
|
||||
info[pointI] = hitInfo[pointI];
|
||||
info[pointI].rawPoint() = nearest[pointI];
|
||||
info[pointI].setIndex
|
||||
(
|
||||
hitInfo[pointI].index()
|
||||
+ indexOffset_[surfI]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -397,82 +507,42 @@ void Foam::searchableSurfaceCollection::getRegion
|
||||
}
|
||||
else
|
||||
{
|
||||
// Multiple surfaces. Sort by surface.
|
||||
|
||||
// Per surface the hit
|
||||
List<List<pointIndexHit> > surfInfo;
|
||||
// Per surface the original position
|
||||
List<List<label> > infoMap;
|
||||
sortHits(info, surfInfo, infoMap);
|
||||
|
||||
region.setSize(info.size());
|
||||
region = -1;
|
||||
|
||||
// Which region did point come from. Retest for now to see which
|
||||
// surface it originates from - crap solution! Should use global indices
|
||||
// in index inside pointIndexHit to do this better.
|
||||
// Do region tests
|
||||
|
||||
pointField samples(info.size());
|
||||
forAll(info, pointI)
|
||||
if (mergeSubRegions_)
|
||||
{
|
||||
if (info[pointI].hit())
|
||||
// Actually no need for surfInfo. Just take region for surface.
|
||||
forAll(infoMap, surfI)
|
||||
{
|
||||
samples[pointI] = info[pointI].hitPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
samples[pointI] = vector::zero;
|
||||
}
|
||||
}
|
||||
//scalarField minDistSqr(info.size(), SMALL);
|
||||
scalarField minDistSqr(info.size(), GREAT);
|
||||
|
||||
labelList nearestSurf;
|
||||
List<pointIndexHit> nearestInfo;
|
||||
findNearest
|
||||
(
|
||||
samples,
|
||||
minDistSqr,
|
||||
nearestInfo,
|
||||
nearestSurf
|
||||
);
|
||||
|
||||
// Check
|
||||
{
|
||||
forAll(info, pointI)
|
||||
{
|
||||
if (info[pointI].hit() && nearestSurf[pointI] == -1)
|
||||
const labelList& map = infoMap[surfI];
|
||||
forAll(map, i)
|
||||
{
|
||||
FatalErrorIn
|
||||
(
|
||||
"searchableSurfaceCollection::getRegion(..)"
|
||||
) << "pointI:" << pointI
|
||||
<< " sample:" << samples[pointI]
|
||||
<< " nearest:" << nearestInfo[pointI]
|
||||
<< " nearestsurf:" << nearestSurf[pointI]
|
||||
<< abort(FatalError);
|
||||
region[map[i]] = regionOffset_[surfI];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
forAll(subGeom_, surfI)
|
||||
else
|
||||
{
|
||||
// Collect points from my surface
|
||||
labelList indices(findIndices(nearestSurf, surfI));
|
||||
|
||||
if (mergeSubRegions_)
|
||||
{
|
||||
forAll(indices, i)
|
||||
{
|
||||
region[indices[i]] = regionOffset_[surfI];
|
||||
}
|
||||
}
|
||||
else
|
||||
forAll(infoMap, surfI)
|
||||
{
|
||||
labelList surfRegion;
|
||||
subGeom_[surfI].getRegion
|
||||
(
|
||||
List<pointIndexHit>
|
||||
(
|
||||
UIndirectList<pointIndexHit>(info, indices)
|
||||
),
|
||||
surfRegion
|
||||
);
|
||||
forAll(indices, i)
|
||||
subGeom_[surfI].getRegion(surfInfo[surfI], surfRegion);
|
||||
|
||||
const labelList& map = infoMap[surfI];
|
||||
forAll(map, i)
|
||||
{
|
||||
region[indices[i]] = regionOffset_[surfI] + surfRegion[i];
|
||||
region[map[i]] = regionOffset_[surfI] + surfRegion[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -494,52 +564,26 @@ void Foam::searchableSurfaceCollection::getNormal
|
||||
}
|
||||
else
|
||||
{
|
||||
// Multiple surfaces. Sort by surface.
|
||||
|
||||
// Per surface the hit
|
||||
List<List<pointIndexHit> > surfInfo;
|
||||
// Per surface the original position
|
||||
List<List<label> > infoMap;
|
||||
sortHits(info, surfInfo, infoMap);
|
||||
|
||||
normal.setSize(info.size());
|
||||
|
||||
// See above - crap retest to find surface point originates from.
|
||||
pointField samples(info.size());
|
||||
forAll(info, pointI)
|
||||
// Do region tests
|
||||
forAll(surfInfo, surfI)
|
||||
{
|
||||
if (info[pointI].hit())
|
||||
{
|
||||
samples[pointI] = info[pointI].hitPoint();
|
||||
}
|
||||
else
|
||||
{
|
||||
samples[pointI] = vector::zero;
|
||||
}
|
||||
}
|
||||
//scalarField minDistSqr(info.size(), SMALL);
|
||||
scalarField minDistSqr(info.size(), GREAT);
|
||||
|
||||
labelList nearestSurf;
|
||||
List<pointIndexHit> nearestInfo;
|
||||
findNearest
|
||||
(
|
||||
samples,
|
||||
minDistSqr,
|
||||
nearestInfo,
|
||||
nearestSurf
|
||||
);
|
||||
|
||||
|
||||
forAll(subGeom_, surfI)
|
||||
{
|
||||
// Collect points from my surface
|
||||
labelList indices(findIndices(nearestSurf, surfI));
|
||||
|
||||
vectorField surfNormal;
|
||||
subGeom_[surfI].getNormal
|
||||
(
|
||||
List<pointIndexHit>
|
||||
(
|
||||
UIndirectList<pointIndexHit>(info, indices)
|
||||
),
|
||||
surfNormal
|
||||
);
|
||||
forAll(indices, i)
|
||||
subGeom_[surfI].getNormal(surfInfo[surfI], surfNormal);
|
||||
|
||||
const labelList& map = infoMap[surfI];
|
||||
forAll(map, i)
|
||||
{
|
||||
normal[indices[i]] = surfNormal[i];
|
||||
normal[map[i]] = surfNormal[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -561,4 +605,99 @@ void Foam::searchableSurfaceCollection::getVolumeType
|
||||
}
|
||||
|
||||
|
||||
void Foam::searchableSurfaceCollection::distribute
|
||||
(
|
||||
const List<treeBoundBox>& bbs,
|
||||
const bool keepNonLocal,
|
||||
autoPtr<mapDistribute>& faceMap,
|
||||
autoPtr<mapDistribute>& pointMap
|
||||
)
|
||||
{
|
||||
forAll(subGeom_, surfI)
|
||||
{
|
||||
// Note:Tranform the bounding boxes? Something like
|
||||
// pointField bbPoints =
|
||||
// cmptDivide
|
||||
// (
|
||||
// transform_[surfI].localPosition
|
||||
// (
|
||||
// bbs[i].points()
|
||||
// ),
|
||||
// scale_[surfI]
|
||||
// );
|
||||
// treeBoundBox newBb(bbPoints);
|
||||
|
||||
// Note: what to do with faceMap, pointMap from multiple surfaces?
|
||||
subGeom_[surfI].distribute
|
||||
(
|
||||
bbs,
|
||||
keepNonLocal,
|
||||
faceMap,
|
||||
pointMap
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::searchableSurfaceCollection::setField(const labelList& values)
|
||||
{
|
||||
forAll(subGeom_, surfI)
|
||||
{
|
||||
subGeom_[surfI].setField
|
||||
(
|
||||
static_cast<const labelList&>
|
||||
(
|
||||
SubList<label>
|
||||
(
|
||||
values,
|
||||
subGeom_[surfI].size(),
|
||||
indexOffset_[surfI]
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::searchableSurfaceCollection::getField
|
||||
(
|
||||
const List<pointIndexHit>& info,
|
||||
labelList& values
|
||||
) const
|
||||
{
|
||||
if (subGeom_.size() == 0)
|
||||
{}
|
||||
else if (subGeom_.size() == 1)
|
||||
{
|
||||
subGeom_[0].getField(info, values);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Multiple surfaces. Sort by surface.
|
||||
|
||||
// Per surface the hit
|
||||
List<List<pointIndexHit> > surfInfo;
|
||||
// Per surface the original position
|
||||
List<List<label> > infoMap;
|
||||
sortHits(info, surfInfo, infoMap);
|
||||
|
||||
values.setSize(info.size());
|
||||
//?Misses do not get set? values = 0;
|
||||
|
||||
// Do surface tests
|
||||
forAll(surfInfo, surfI)
|
||||
{
|
||||
labelList surfValues;
|
||||
subGeom_[surfI].getField(surfInfo[surfI], surfValues);
|
||||
|
||||
const labelList& map = infoMap[surfI];
|
||||
forAll(map, i)
|
||||
{
|
||||
values[map[i]] = surfValues[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
@ -77,6 +77,10 @@ private:
|
||||
|
||||
Switch mergeSubRegions_;
|
||||
|
||||
//- offsets for indices coming from different surfaces
|
||||
// (sized with size() of each surface)
|
||||
labelList indexOffset_;
|
||||
|
||||
//- Region names
|
||||
mutable wordList regions_;
|
||||
//- From individual regions to collection regions
|
||||
@ -95,6 +99,15 @@ private:
|
||||
labelList& nearestSurf
|
||||
) const;
|
||||
|
||||
//- Sort hits into per-surface bins. Misses are rejected.
|
||||
// Maintains map back to position
|
||||
void sortHits
|
||||
(
|
||||
const List<pointIndexHit>& info,
|
||||
List<List<pointIndexHit> >& surfInfo,
|
||||
labelListList& infoMap
|
||||
) const;
|
||||
|
||||
|
||||
//- Disallow default bitwise copy construct
|
||||
searchableSurfaceCollection(const searchableSurfaceCollection&);
|
||||
@ -161,6 +174,10 @@ public:
|
||||
//- Range of local indices that can be returned.
|
||||
virtual label size() const;
|
||||
|
||||
//- Get representative set of element coordinates
|
||||
// Usually the element centres (should be of length size()).
|
||||
virtual pointField coordinates() const;
|
||||
|
||||
|
||||
// Multiple point queries.
|
||||
|
||||
@ -215,6 +232,27 @@ public:
|
||||
List<volumeType>&
|
||||
) const;
|
||||
|
||||
// Other
|
||||
|
||||
//- Set bounds of surface. Bounds currently set as list of
|
||||
// bounding boxes. The bounds are hints to the surface as for
|
||||
// the range of queries it can expect. faceMap/pointMap can be
|
||||
// set if the surface has done any redistribution.
|
||||
virtual void distribute
|
||||
(
|
||||
const List<treeBoundBox>&,
|
||||
const bool keepNonLocal,
|
||||
autoPtr<mapDistribute>& faceMap,
|
||||
autoPtr<mapDistribute>& pointMap
|
||||
);
|
||||
|
||||
//- WIP. Store element-wise field.
|
||||
virtual void setField(const labelList& values);
|
||||
|
||||
//- WIP. From a set of hits (points and
|
||||
// indices) get the specified field. Misses do not get set. Return
|
||||
// empty field if not supported.
|
||||
virtual void getField(const List<pointIndexHit>&, labelList&) const;
|
||||
|
||||
// regIOobject implementation
|
||||
|
||||
|
@ -151,6 +151,13 @@ public:
|
||||
return surface().size();
|
||||
}
|
||||
|
||||
//- Get representative set of element coordinates
|
||||
// Usually the element centres (should be of length size()).
|
||||
virtual pointField coordinates() const
|
||||
{
|
||||
return surface().coordinates();
|
||||
}
|
||||
|
||||
|
||||
// Multiple point queries.
|
||||
|
||||
@ -225,6 +232,41 @@ public:
|
||||
}
|
||||
|
||||
|
||||
// Other
|
||||
|
||||
//- Set bounds of surface. Bounds currently set as list of
|
||||
// bounding boxes. The bounds are hints to the surface as for
|
||||
// the range of queries it can expect. faceMap/pointMap can be
|
||||
// set if the surface has done any redistribution.
|
||||
virtual void distribute
|
||||
(
|
||||
const List<treeBoundBox>& bbs,
|
||||
const bool keepNonLocal,
|
||||
autoPtr<mapDistribute>& faceMap,
|
||||
autoPtr<mapDistribute>& pointMap
|
||||
)
|
||||
{
|
||||
subGeom_[0].distribute(bbs, keepNonLocal, faceMap, pointMap);
|
||||
}
|
||||
|
||||
//- WIP. Store element-wise field.
|
||||
virtual void setField(const labelList& values)
|
||||
{
|
||||
subGeom_[0].setField(values);
|
||||
}
|
||||
|
||||
//- WIP. From a set of hits (points and
|
||||
// indices) get the specified field. Misses do not get set. Return
|
||||
// empty field if not supported.
|
||||
virtual void getField
|
||||
(
|
||||
const List<pointIndexHit>& info,
|
||||
labelList& values
|
||||
) const
|
||||
{
|
||||
surface().getField(info, values);
|
||||
}
|
||||
|
||||
// regIOobject implementation
|
||||
|
||||
bool writeData(Ostream& os) const
|
||||
|
@ -30,6 +30,7 @@ License
|
||||
#include "EdgeMap.H"
|
||||
#include "triSurfaceFields.H"
|
||||
#include "Time.H"
|
||||
#include "PackedBoolList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
@ -281,6 +282,36 @@ void Foam::triSurfaceMesh::getNextIntersections
|
||||
}
|
||||
|
||||
|
||||
void Foam::triSurfaceMesh::calcBounds(boundBox& bb, label& nPoints) const
|
||||
{
|
||||
// Unfortunately nPoints constructs meshPoints() so do compact version
|
||||
// ourselves
|
||||
|
||||
const triSurface& s = static_cast<const triSurface&>(*this);
|
||||
|
||||
PackedBoolList pointIsUsed(points().size());
|
||||
|
||||
nPoints = 0;
|
||||
bb = boundBox::invertedBox;
|
||||
|
||||
forAll(s, triI)
|
||||
{
|
||||
const labelledTri& f = s[triI];
|
||||
|
||||
forAll(f, fp)
|
||||
{
|
||||
label pointI = f[fp];
|
||||
if (pointIsUsed.set(pointI, 1u))
|
||||
{
|
||||
bb.min() = ::Foam::min(bb.min(), points()[pointI]);
|
||||
bb.max() = ::Foam::max(bb.max(), points()[pointI]);
|
||||
nPoints++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s)
|
||||
@ -301,6 +332,7 @@ Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io, const triSurface& s)
|
||||
),
|
||||
triSurface(s),
|
||||
tolerance_(indexedOctree<treeDataTriSurface>::perturbTol()),
|
||||
maxTreeDepth_(10),
|
||||
surfaceClosed_(-1)
|
||||
{}
|
||||
|
||||
@ -344,6 +376,7 @@ Foam::triSurfaceMesh::triSurfaceMesh(const IOobject& io)
|
||||
)
|
||||
),
|
||||
tolerance_(indexedOctree<treeDataTriSurface>::perturbTol()),
|
||||
maxTreeDepth_(10),
|
||||
surfaceClosed_(-1)
|
||||
{}
|
||||
|
||||
@ -390,6 +423,7 @@ Foam::triSurfaceMesh::triSurfaceMesh
|
||||
)
|
||||
),
|
||||
tolerance_(indexedOctree<treeDataTriSurface>::perturbTol()),
|
||||
maxTreeDepth_(10),
|
||||
surfaceClosed_(-1)
|
||||
{
|
||||
scalar scaleFactor = 0;
|
||||
@ -410,6 +444,14 @@ Foam::triSurfaceMesh::triSurfaceMesh
|
||||
Info<< searchableSurface::name() << " : using intersection tolerance "
|
||||
<< tolerance_ << endl;
|
||||
}
|
||||
|
||||
|
||||
// Have optional non-standard tree-depth to limit storage.
|
||||
if (dict.readIfPresent("maxTreeDepth", maxTreeDepth_) && maxTreeDepth_ > 0)
|
||||
{
|
||||
Info<< searchableSurface::name() << " : using maximum tree depth "
|
||||
<< maxTreeDepth_ << endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -431,6 +473,17 @@ void Foam::triSurfaceMesh::clearOut()
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::pointField Foam::triSurfaceMesh::coordinates() const
|
||||
{
|
||||
// Use copy to calculate face centres so they don't get stored
|
||||
return PrimitivePatch<labelledTri, SubList, const pointField&>
|
||||
(
|
||||
SubList<labelledTri>(*this, triSurface::size()),
|
||||
triSurface::points()
|
||||
).faceCentres();
|
||||
}
|
||||
|
||||
|
||||
void Foam::triSurfaceMesh::movePoints(const pointField& newPoints)
|
||||
{
|
||||
tree_.clear();
|
||||
@ -444,15 +497,28 @@ const Foam::indexedOctree<Foam::treeDataTriSurface>&
|
||||
{
|
||||
if (tree_.empty())
|
||||
{
|
||||
// Calculate bb without constructing local point numbering.
|
||||
treeBoundBox bb;
|
||||
label nPoints;
|
||||
calcBounds(bb, nPoints);
|
||||
|
||||
if (nPoints != points().size())
|
||||
{
|
||||
WarningIn("triSurfaceMesh::tree() const")
|
||||
<< "Surface " << searchableSurface::name()
|
||||
<< " does not have compact point numbering."
|
||||
<< " Of " << points().size() << " only " << nPoints
|
||||
<< " are used. This might give problems in some routines."
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
// Random number generator. Bit dodgy since not exactly random ;-)
|
||||
Random rndGen(65431);
|
||||
|
||||
// Slightly extended bb. Slightly off-centred just so on symmetric
|
||||
// geometry there are less face/edge aligned items.
|
||||
treeBoundBox bb
|
||||
(
|
||||
treeBoundBox(points(), meshPoints()).extend(rndGen, 1E-4)
|
||||
);
|
||||
bb = bb.extend(rndGen, 1E-4);
|
||||
bb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
|
||||
bb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
|
||||
|
||||
@ -465,9 +531,9 @@ const Foam::indexedOctree<Foam::treeDataTriSurface>&
|
||||
(
|
||||
treeDataTriSurface(*this),
|
||||
bb,
|
||||
10, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
maxTreeDepth_, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
)
|
||||
);
|
||||
|
||||
@ -494,15 +560,17 @@ const Foam::indexedOctree<Foam::treeDataEdge>&
|
||||
+ nInternalEdges()
|
||||
);
|
||||
|
||||
treeBoundBox bb;
|
||||
label nPoints;
|
||||
calcBounds(bb, nPoints);
|
||||
|
||||
// Random number generator. Bit dodgy since not exactly random ;-)
|
||||
Random rndGen(65431);
|
||||
|
||||
// Slightly extended bb. Slightly off-centred just so on symmetric
|
||||
// geometry there are less face/edge aligned items.
|
||||
treeBoundBox bb
|
||||
(
|
||||
treeBoundBox(points(), meshPoints()).extend(rndGen, 1E-4)
|
||||
);
|
||||
|
||||
bb = bb.extend(rndGen, 1E-4);
|
||||
bb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
|
||||
bb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
|
||||
|
||||
@ -517,10 +585,10 @@ const Foam::indexedOctree<Foam::treeDataEdge>&
|
||||
localPoints(), // points
|
||||
bEdges // selected edges
|
||||
),
|
||||
bb, // bb
|
||||
8, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
bb, // bb
|
||||
maxTreeDepth_, // maxLevel
|
||||
10, // leafsize
|
||||
3.0 // duplicity
|
||||
)
|
||||
);
|
||||
}
|
||||
@ -754,24 +822,53 @@ void Foam::triSurfaceMesh::getNormal
|
||||
}
|
||||
|
||||
|
||||
void Foam::triSurfaceMesh::setField(const labelList& values)
|
||||
{
|
||||
autoPtr<triSurfaceLabelField> fldPtr
|
||||
(
|
||||
new triSurfaceLabelField
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"values",
|
||||
objectRegistry::time().timeName(), // instance
|
||||
"triSurface", // local
|
||||
*this,
|
||||
IOobject::NO_READ,
|
||||
IOobject::AUTO_WRITE
|
||||
),
|
||||
*this,
|
||||
dimless,
|
||||
labelField(values)
|
||||
)
|
||||
);
|
||||
|
||||
// Store field on triMesh
|
||||
fldPtr.ptr()->store();
|
||||
}
|
||||
|
||||
|
||||
void Foam::triSurfaceMesh::getField
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<pointIndexHit>& info,
|
||||
labelList& values
|
||||
) const
|
||||
{
|
||||
const triSurfaceLabelField& fld = lookupObject<triSurfaceLabelField>
|
||||
(
|
||||
fieldName
|
||||
);
|
||||
|
||||
values.setSize(info.size());
|
||||
forAll(info, i)
|
||||
if (foundObject<triSurfaceLabelField>("values"))
|
||||
{
|
||||
if (info[i].hit())
|
||||
values.setSize(info.size());
|
||||
|
||||
const triSurfaceLabelField& fld = lookupObject<triSurfaceLabelField>
|
||||
(
|
||||
"values"
|
||||
);
|
||||
|
||||
forAll(info, i)
|
||||
{
|
||||
values[i] = fld[info[i].index()];
|
||||
if (info[i].hit())
|
||||
{
|
||||
values[i] = fld[info[i].index()];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,9 @@ private:
|
||||
//- Optional tolerance to use in searches
|
||||
scalar tolerance_;
|
||||
|
||||
//- Optional max tree depth of octree
|
||||
label maxTreeDepth_;
|
||||
|
||||
//- Search tree (triangles)
|
||||
mutable autoPtr<indexedOctree<treeDataTriSurface> > tree_;
|
||||
|
||||
@ -129,6 +132,11 @@ private:
|
||||
void operator=(const triSurfaceMesh&);
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
//- Calculate (number of)used points and their bounding box
|
||||
void calcBounds(boundBox& bb, label& nPoints) const;
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
@ -185,6 +193,10 @@ public:
|
||||
return triSurface::size();
|
||||
}
|
||||
|
||||
//- Get representative set of element coordinates
|
||||
// Usually the element centres (should be of length size()).
|
||||
virtual pointField coordinates() const;
|
||||
|
||||
virtual void findNearest
|
||||
(
|
||||
const pointField& sample,
|
||||
@ -236,6 +248,8 @@ public:
|
||||
List<volumeType>&
|
||||
) const;
|
||||
|
||||
// Other
|
||||
|
||||
//- Set bounds of surface. Bounds currently set as list of
|
||||
// bounding boxes. The bounds are hints to the surface as for
|
||||
// the range of queries it can expect. faceMap/pointMap can be
|
||||
@ -249,16 +263,12 @@ public:
|
||||
)
|
||||
{}
|
||||
|
||||
// Other
|
||||
//- WIP. Store element-wise field.
|
||||
virtual void setField(const labelList& values);
|
||||
|
||||
//- Specific to triSurfaceMesh: from a set of hits (points and
|
||||
//- WIP. From a set of hits (points and
|
||||
// indices) get the specified field. Misses do not get set.
|
||||
virtual void getField
|
||||
(
|
||||
const word& fieldName,
|
||||
const List<pointIndexHit>&,
|
||||
labelList& values
|
||||
) const;
|
||||
virtual void getField(const List<pointIndexHit>&, labelList&) const;
|
||||
|
||||
|
||||
// regIOobject implementation
|
||||
|
Loading…
Reference in New Issue
Block a user