36 #include <type_traits> 40 #include <vtkCellData.h> 41 #include <vtkDataSet.h> 42 #include <vtkIdTypeArray.h> 43 #include <vtkInformation.h> 44 #include <vtkInformationVector.h> 45 #include <vtkIntArray.h> 47 #include <vtkObjectFactory.h> 48 #include <vtkPointData.h> 49 #include <vtkPolyData.h> 50 #include <vtkRectilinearGrid.h> 58 BoundaryCell(vtkIdType source,
int side,
int region)
61 void setTwin(vtkIdType otherSource,
int otherSide,
int otherRegion) {
63 this->
sides[1] = otherSide;
65 if (otherRegion < this->
regions[0]) {
68 std::swap(this->regions[0], this->regions[1]);
79 using data_type = std::vector<
80 std::vector<std::pair<std::array<vtkIdType, 2>, BoundaryCell>>>;
85 :
public std::iterator<std::forward_iterator_tag, const BoundaryCell> {
87 const_iterator(data_type::const_iterator
outerIter,
89 data_type::value_type::const_iterator
innerIter)
95 reference
operator*() {
return innerIter->second; }
96 pointer operator->() {
return &innerIter->second; }
97 const_iterator &operator++() {
99 if (innerIter == outerIter->end()) {
102 if (outerIter == endOuterIter) {
105 }
while (outerIter->empty());
106 innerIter = outerIter->begin();
110 const_iterator operator++(
int) {
115 friend bool operator==(
const const_iterator &l,
const const_iterator &r) {
116 return (l.outerIter == r.outerIter && l.innerIter == r.innerIter) ||
117 (l.outerIter == l.endOuterIter && r.outerIter == r.endOuterIter);
119 friend bool operator!=(
const const_iterator &l,
const const_iterator &r) {
130 const_iterator begin()
const {
131 auto beginOuter =
data.begin();
132 const auto endOuter =
data.end();
133 while (beginOuter->empty()) {
135 if (beginOuter == endOuter) {
136 return {beginOuter, endOuter, {}};
139 return {beginOuter, endOuter, beginOuter->begin()};
142 const_iterator end()
const {
143 auto endIter =
data.end();
144 return {endIter, endIter, {}};
147 void insert(vtkIdType source,
int side, vtkIdList *
points,
int numPoints,
149 auto pointsBegin = points->GetPointer(0);
150 auto numPointsKey = std::min(numPoints, 3);
151 auto pointsEnd = pointsBegin + numPoints;
152 auto pointsMiddle = pointsBegin + numPointsKey;
154 std::partial_sort(pointsBegin, pointsMiddle, pointsEnd);
155 insertImpl(
data[pointsBegin[1]],
156 {pointsBegin[0], numPointsKey < 3 ? -1 : pointsBegin[2]}, source,
160 void insertTri(vtkIdType source,
int face, vtkIdType point0, vtkIdType point1,
161 vtkIdType point2,
int region) {
162 if (point0 > point1) std::swap(point0, point1);
163 if (point0 > point2) std::swap(point0, point2);
164 if (point1 > point2) std::swap(point1, point2);
165 insertImpl(this->
data[point1], {point0, point2}, source, face, region);
168 void insertQuad(vtkIdType source,
int face, vtkIdType point0,
169 vtkIdType point1, vtkIdType point2, vtkIdType point3,
171 if (point0 > point1) std::swap(point0, point1);
172 if (point2 > point3) std::swap(point2, point3);
173 if (point0 > point2) std::swap(point0, point2);
174 if (point1 > point3) std::swap(point1, point3);
175 if (point1 > point2) std::swap(point1, point2);
176 insertImpl(this->
data[point1], {point0, point2}, source, face, region);
181 void insertTetFaces(vtkIdType source,
const vtkIdType *points,
int region) {
182 insertTri(source, 0, points[0], points[1], points[3], region);
183 insertTri(source, 1, points[1], points[2], points[3], region);
184 insertTri(source, 2, points[2], points[0], points[3], region);
185 insertTri(source, 3, points[0], points[2], points[1], region);
188 void insertWedgeFaces(vtkIdType source,
const vtkIdType *points,
int region) {
189 insertTri(source, 0, points[0], points[1], points[2], region);
190 insertTri(source, 1, points[3], points[5], points[4], region);
191 insertQuad(source, 2, points[0], points[3], points[4], points[1], region);
192 insertQuad(source, 3, points[1], points[4], points[5], points[2], region);
193 insertQuad(source, 4, points[2], points[5], points[3], points[0], region);
196 void insertHexFaces(vtkIdType source,
const vtkIdType *points,
int region) {
197 insertQuad(source, 0, points[0], points[4], points[7], points[3], region);
198 insertQuad(source, 1, points[1], points[2], points[6], points[5], region);
199 insertQuad(source, 2, points[0], points[1], points[5], points[4], region);
200 insertQuad(source, 3, points[3], points[7], points[6], points[2], region);
201 insertQuad(source, 4, points[0], points[3], points[2], points[1], region);
202 insertQuad(source, 5, points[4], points[5], points[6], points[7], region);
205 data_type::value_type::size_type size()
const {
return total_size; }
217 void insertImpl(std::decay<decltype(data)>::type::value_type &bucket,
218 std::array<vtkIdType, 2> key,
int source,
int side,
220 auto matchFind = std::find_if(
221 bucket.begin(), bucket.end(),
222 [&key](
const std::decay<decltype(bucket)>::type::value_type &x) {
223 return x.first == key;
225 if (matchFind != bucket.end()) {
226 if (matchFind->second.regions[0] == region) {
228 *matchFind = bucket.back();
233 matchFind->second.setTwin(source, side, region);
237 bucket.emplace_back(std::piecewise_construct, std::forward_as_tuple(key),
238 std::forward_as_tuple(source, side, region));
249 int port, vtkInformation *info) {
250 info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(),
"vtkDataSet");
255 vtkInformation *request, vtkInformationVector **inputVector,
256 vtkInformationVector *outputVector) {
258 vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
259 vtkInformation *outInfo = outputVector->GetInformationObject(0);
263 vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
265 vtkPolyData::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT()));
267 if (input->CheckAttributes()) {
271 const vtkIdType numCells = input->GetNumberOfCells();
273 vtkDebugMacro(<<
"Number of cells is zero, no data to process.");
276 vtkNew<vtkCellArray> newCells{};
278 newCells->Allocate(numCells);
281 auto regionArr = vtkArrayDownCast<vtkIntArray>(
282 input->GetCellData()->GetAbstractArray(this->MaterialArrayName.c_str()));
283 for (vtkIdType i = 0; i < numCells; ++i) {
284 auto cell = input->GetCell(i);
285 auto region = regionArr->GetTypedComponent(i, 0);
287 if (cell->GetCellDimension() != this->GetDimension()) {
291 if (this->GetDimension() == 2) {
292 for (
int j = 0; j < cell->GetNumberOfEdges(); ++j) {
293 auto edge = cell->GetEdge(j);
294 boundaryCellSet.insert(i, j, edge->GetPointIds(), 2, region);
297 switch (static_cast<VTKCellType>(cell->GetCellType())) {
299 case VTK_QUADRATIC_TETRA:
300 case VTK_HIGHER_ORDER_TETRAHEDRON:
301 case VTK_LAGRANGE_TETRAHEDRON: {
302 auto points = cell->GetPointIds()->GetPointer(0);
303 boundaryCellSet.insertTetFaces(i,
points, region);
307 case VTK_QUADRATIC_HEXAHEDRON:
308 case VTK_TRIQUADRATIC_HEXAHEDRON:
309 case VTK_BIQUADRATIC_QUADRATIC_HEXAHEDRON:
310 case VTK_HIGHER_ORDER_HEXAHEDRON:
311 case VTK_LAGRANGE_HEXAHEDRON: {
312 auto points = cell->GetPointIds()->GetPointer(0);
313 boundaryCellSet.insertHexFaces(i,
points, region);
317 case VTK_QUADRATIC_WEDGE:
318 case VTK_QUADRATIC_LINEAR_WEDGE:
319 case VTK_BIQUADRATIC_QUADRATIC_WEDGE:
320 case VTK_HIGHER_ORDER_WEDGE:
321 case VTK_LAGRANGE_WEDGE: {
322 auto points = cell->GetPointIds()->GetPointer(0);
323 boundaryCellSet.insertWedgeFaces(i,
points, region);
327 for (
int j = 0; j < cell->GetNumberOfFaces(); ++j) {
328 auto face = cell->GetFace(j);
332 boundaryCellSet.insert(i, j, face->GetPointIds(),
333 face->GetNumberOfEdges(), region);
341 vtkSmartPointer<vtkIdTypeArray> origCellId{};
342 vtkSmartPointer<vtkIntArray> cellSideId{}, surfRegionId{};
343 if (!this->GetOrigCellArrayName().empty()) {
345 origCellId->SetName(this->GetOrigCellArrayName().c_str());
346 origCellId->SetNumberOfComponents(2);
347 origCellId->SetNumberOfTuples(boundaryCellSet.size());
349 if (!this->GetCellSideArrayName().empty()) {
351 cellSideId->SetName(this->GetCellSideArrayName().c_str());
352 cellSideId->SetNumberOfComponents(2);
353 cellSideId->SetNumberOfTuples(boundaryCellSet.size());
355 if (!this->GetBoundaryRegionArrayName().empty()) {
357 surfRegionId->SetName(this->GetBoundaryRegionArrayName().c_str());
358 surfRegionId->SetNumberOfTuples(boundaryCellSet.size());
362 std::map<std::array<int, 2>,
int> oldRegions2SurfRegions{};
363 for (
const auto &boundaryCell : boundaryCellSet) {
364 auto origCellToInsert = input->GetCell(boundaryCell.sources[0]);
365 auto sideToInsert = this->GetDimension() == 2
366 ? origCellToInsert->GetEdge(boundaryCell.sides[0])
367 : origCellToInsert->GetFace(boundaryCell.sides[0]);
368 auto sideIdx = newCells->InsertNextCell(
369 this->GetDimension() == 2 ? 2 : sideToInsert->GetNumberOfEdges(),
370 sideToInsert->GetPointIds()->GetPointer(0));
372 origCellId->SetTypedTuple(sideIdx, boundaryCell.sources.data());
375 cellSideId->SetTypedTuple(sideIdx, boundaryCell.sides.data());
377 auto surfRegionIter = oldRegions2SurfRegions.emplace(
378 boundaryCell.regions, oldRegions2SurfRegions.size());
380 surfRegionId->SetTypedComponent(sideIdx, 0, surfRegionIter.first->second);
385 if (!this->GetRegionToMaterialArrayName().empty()) {
386 vtkNew<vtkIntArray> region2MaterialId;
387 region2MaterialId->SetName(this->GetRegionToMaterialArrayName().c_str());
388 region2MaterialId->SetNumberOfComponents(2);
389 region2MaterialId->SetNumberOfTuples(oldRegions2SurfRegions.size());
390 for (
const auto &old2newRegion : oldRegions2SurfRegions) {
391 auto newRegion = old2newRegion.second;
392 region2MaterialId->SetComponent(newRegion, 0, old2newRegion.first[0]);
393 region2MaterialId->SetComponent(newRegion, 1, old2newRegion.first[1]);
395 output->GetFieldData()->AddArray(region2MaterialId);
398 if (
auto pointSet = vtkPointSet::SafeDownCast(input)) {
399 output->SetPoints(pointSet->GetPoints());
400 }
else if (
auto rectGrid = vtkRectilinearGrid::SafeDownCast(input)) {
401 rectGrid->GetPoints(output->GetPoints());
403 auto outPoints = output->GetPoints();
404 outPoints->Initialize();
405 outPoints->SetNumberOfPoints(input->GetNumberOfPoints());
406 for (vtkIdType i = 0; i < input->GetNumberOfPoints(); ++i) {
407 outPoints->SetPoint(i, input->GetPoint(i));
410 output->GetPointData()->ShallowCopy(input->GetPointData());
412 if (this->GetDimension() == 2) {
413 output->SetLines(newCells);
415 output->SetPolys(newCells);
418 vtkCellData *outputCD = output->GetCellData();
419 outputCD->AddArray(origCellId);
420 outputCD->AddArray(cellSideId);
421 outputCD->AddArray(surfRegionId);
423 if (output->CheckAttributes()) {
data_type data
Edge/face with sorted point ids (a, b, c, ...) is located at some index i in data[b], with data[b][i].first == [a, c] (for edges, third point id treated as -1).
geoMeshBase * New(MeshType meshType)
Create a new mesh object.
int FillInputPortInformation(int port, vtkInformation *info) override
int RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector) override
data_type::value_type::const_iterator innerIter
Like vtkDataSetRegionSurfaceFilter, this filter extracts boundaries of materials, including both inte...
std::array< int, 2 > regions
std::vector< T > operator*(T a, const std::vector< T > &x)
std::vector< vtkIdType > points
points given by id in .inp file
std::array< int, 2 > sides
data_type::value_type::size_type total_size
vtkStandardNewMacro(exoGeoMesh)
data_type::const_iterator outerIter
const data_type::const_iterator endOuterIter
std::array< vtkIdType, 2 > sources