diff --git a/Applications/Utils/MeshEdit/CMakeLists.txt b/Applications/Utils/MeshEdit/CMakeLists.txt index 1da08d52564b28f66526c60fc1548406174559a8..39327f0445e6bc82bf13d2423211c75c03b74ae9 100644 --- a/Applications/Utils/MeshEdit/CMakeLists.txt +++ b/Applications/Utils/MeshEdit/CMakeLists.txt @@ -14,6 +14,7 @@ set(TOOLS moveMeshNodes NodeReordering queryMesh + RemoveGhostNodes removeMeshElements ResetPropertiesInPolygonalRegion reviseMesh diff --git a/Applications/Utils/MeshEdit/RemoveGhostNodes.cpp b/Applications/Utils/MeshEdit/RemoveGhostNodes.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ae25278943ae330f496822832ca1c4848b946c7 --- /dev/null +++ b/Applications/Utils/MeshEdit/RemoveGhostNodes.cpp @@ -0,0 +1,99 @@ +/** + * \file + * + * @copyright + * Copyright (c) 2012-2020, OpenGeoSys Community (http://www.opengeosys.org) + * Distributed under a Modified BSD License. + * See accompanying file LICENSE.txt or + * http://www.opengeosys.org/LICENSE.txt + */ + +#include <tclap/CmdLine.h> + +#include "Applications/ApplicationsLib/LogogSetup.h" +#include "InfoLib/GitInfo.h" + +#include "MeshLib/IO/writeMeshToFile.h" +#include "vtkCleanUnstructuredGrid.h" + +#include <vtkSmartPointer.h> +#include <vtkUnstructuredGrid.h> +#include <vtkXMLPUnstructuredGridReader.h> +#include <vtkRemoveGhosts.h> + +int main (int argc, char* argv[]) +{ + ApplicationsLib::LogogSetup logog_setup; +/* + TCLAP::CmdLine cmd( + "Reads a 3D unstructured mesh and samples it onto a structured grid of " + "the same extent. Cell properties are mapped onto the grid (sampled at " + "the centre-points of each cube), node properties are ignored. Note, " + "that a large cube size may result in an undersampling of the original " + "mesh structure.\nCube sizes are defines by x/y/z-parameters. For " + "equilateral cubes, only the x-parameter needs to be set.\n\n" + "OpenGeoSys-6 software, version " + + GitInfoLib::GitInfo::ogs_version + + ".\n" + "Copyright (c) 2012-2020, OpenGeoSys Community " + "(http://www.opengeosys.org)", + ' ', GitInfoLib::GitInfo::ogs_version); + + TCLAP::ValueArg<double> z_arg("z", "cellsize-z", + "edge length of cubes in z-direction (depth)", + false, 1000, "floating point number"); + cmd.add(z_arg); + + TCLAP::ValueArg<double> y_arg( + "y", "cellsize-y", "edge length of cubes in y-direction (latitude)", + false, 1000, "floating point number"); + cmd.add(y_arg); + + TCLAP::ValueArg<double> x_arg( + "x", "cellsize-x", + "edge length of cubes in x-direction (longitude) or all directions, if " + "y and z are not set", + true, 1000, "floating point number"); + cmd.add(x_arg); + + TCLAP::ValueArg<std::string> output_arg( + "o", "output", "the output grid (*.vtu)", true, "", "output.vtu"); + cmd.add(output_arg); + + TCLAP::ValueArg<std::string> input_arg("i", "input", + "the 3D input mesh (*.vtu, *.msh)", + true, "", "input.vtu"); + cmd.add(input_arg); + cmd.parse(argc, argv); + + if ((y_arg.isSet() && !z_arg.isSet()) || + ((!y_arg.isSet() && z_arg.isSet()))) + { + ERR("For equilateral cubes, only x needs to be set. For unequal " + "cuboids, all three edge lengths (x/y/z) need to be specified.") + return -1; + } + + double const x_size = x_arg.getValue(); + double const y_size = (y_arg.isSet()) ? y_arg.getValue() : x_arg.getValue(); + double const z_size = (z_arg.isSet()) ? z_arg.getValue() : x_arg.getValue(); + std::array<double, 3> const cellsize = { x_size, y_size, z_size }; +*/ + std::string input_file = "c:/Projects/RemoveGhostNodes/Mesh3D.pvtu"; + vtkSmartPointer<vtkXMLPUnstructuredGridReader> reader = + vtkSmartPointer<vtkXMLPUnstructuredGridReader>::New(); + reader->SetFileName(input_file.c_str()); + //reader->SetFileName(input_arg.getValue().c_str()); + reader->Update(); + vtkSmartPointer<vtkUnstructuredGrid> mesh = reader->GetOutput(); + + vtkSmartPointer<vtkRemoveGhosts> ghosts = + vtkSmartPointer<vtkRemoveGhosts>::New(); + ghosts->SetInputConnection(reader->GetOutputPort()); + + + //if (MeshLib::IO::writeMeshToFile(*grid, output_arg.getValue()) != 0) + // return EXIT_FAILURE; + + return EXIT_SUCCESS; +} diff --git a/Applications/Utils/MeshEdit/vtkCleanUnstructuredGrid.cpp b/Applications/Utils/MeshEdit/vtkCleanUnstructuredGrid.cpp new file mode 100644 index 0000000000000000000000000000000000000000..37d6febe325375dcab617586d5750c4b377cd9f0 --- /dev/null +++ b/Applications/Utils/MeshEdit/vtkCleanUnstructuredGrid.cpp @@ -0,0 +1,232 @@ +/*========================================================================= + +Program: ParaView +Module: vtkCleanUnstructuredGrid.cxx + +Copyright (c) Kitware, Inc. +All rights reserved. +See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ +#include "vtkCleanUnstructuredGrid.h" + +#include "vtkCell.h" +#include "vtkCellData.h" +#include "vtkCollection.h" +#include "vtkDataSet.h" +#include "vtkIncrementalPointLocator.h" +#include "vtkInformation.h" +#include "vtkInformationVector.h" +#include "vtkIntArray.h" +#include "vtkMergePoints.h" +#include "vtkObjectFactory.h" +#include "vtkPointData.h" +#include "vtkPointSet.h" +#include "vtkPoints.h" +#include "vtkRectilinearGrid.h" +#include "vtkUnstructuredGrid.h" + +vtkStandardNewMacro(vtkCleanUnstructuredGrid); +vtkCxxSetObjectMacro(vtkCleanUnstructuredGrid, Locator, vtkIncrementalPointLocator); + +//---------------------------------------------------------------------------- +vtkCleanUnstructuredGrid::~vtkCleanUnstructuredGrid() +{ + this->SetLocator(nullptr); +} + +//---------------------------------------------------------------------------- +void vtkCleanUnstructuredGrid::PrintSelf(ostream& os, vtkIndent indent) +{ + this->Superclass::PrintSelf(os, indent); +} + +//---------------------------------------------------------------------------- +int vtkCleanUnstructuredGrid::RequestData(vtkInformation* vtkNotUsed(request), + vtkInformationVector** inputVector, vtkInformationVector* outputVector) +{ + vtkInformation* inInfo = inputVector[0]->GetInformationObject(0); + vtkInformation* outInfo = outputVector->GetInformationObject(0); + + vtkDataSet* input = vtkDataSet::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT())); + vtkUnstructuredGrid* output = + vtkUnstructuredGrid::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())); + + if (input->GetNumberOfCells() == 0) + { + // set up a ugrid with same data arrays as input, but + // no points, cells or data. + output->Allocate(1); + output->GetPointData()->CopyAllocate(input->GetPointData(), VTK_CELL_SIZE); + output->GetCellData()->CopyAllocate(input->GetCellData(), 1); + vtkPoints* pts = vtkPoints::New(); + output->SetPoints(pts); + pts->Delete(); + return 1; + } + + output->GetPointData()->CopyAllocate(input->GetPointData()); + output->GetCellData()->PassData(input->GetCellData()); + + // First, create a new points array that eliminate duplicate points. + // Also create a mapping from the old point id to the new. + vtkPoints* newPts = vtkPoints::New(); + + // Set the desired precision for the points in the output. + if (this->OutputPointsPrecision == vtkAlgorithm::DEFAULT_PRECISION) + { + // The logical behaviour would be to use the data type from the input. + // However, input is a vtkDataSet, which has no point data type; only the + // derived class vtkPointSet has a vtkPoints attribute, so only for that + // the logical practice can be applied, while for others (currently + // vtkImageData and vtkRectilinearGrid) the data type is the default + // for vtkPoints - which is VTK_FLOAT. + vtkPointSet* ps = vtkPointSet::SafeDownCast(input); + if (ps) + { + newPts->SetDataType(ps->GetPoints()->GetDataType()); + } + } + else if (this->OutputPointsPrecision == vtkAlgorithm::SINGLE_PRECISION) + { + newPts->SetDataType(VTK_FLOAT); + } + else if (this->OutputPointsPrecision == vtkAlgorithm::DOUBLE_PRECISION) + { + newPts->SetDataType(VTK_DOUBLE); + } + + vtkIdType num = input->GetNumberOfPoints(); + vtkIdType id; + vtkIdType newId; + vtkIdType* ptMap = new vtkIdType[num]; + double pt[3]; + + this->CreateDefaultLocator(input); + if (this->ToleranceIsAbsolute) + { + this->Locator->SetTolerance(this->AbsoluteTolerance); + } + else + { + this->Locator->SetTolerance(this->Tolerance * input->GetLength()); + } + double bounds[6]; + input->GetBounds(bounds); + this->Locator->InitPointInsertion(newPts, bounds); + + vtkIdType progressStep = num / 100; + if (progressStep == 0) + { + progressStep = 1; + } + for (id = 0; id < num; ++id) + { + if (id % progressStep == 0) + { + this->UpdateProgress(0.8 * ((float)id / num)); + } + input->GetPoint(id, pt); + if (this->Locator->InsertUniquePoint(pt, newId)) + { + output->GetPointData()->CopyData(input->GetPointData(), id, newId); + } + ptMap[id] = newId; + } + output->SetPoints(newPts); + newPts->Delete(); + + // Now copy the cells. + vtkIdList* cellPoints = vtkIdList::New(); + num = input->GetNumberOfCells(); + output->Allocate(num); + for (id = 0; id < num; ++id) + { + if (id % progressStep == 0) + { + this->UpdateProgress(0.8 + 0.2 * ((float)id / num)); + } + // special handling for polyhedron cells + if (vtkUnstructuredGrid::SafeDownCast(input) && input->GetCellType(id) == VTK_POLYHEDRON) + { + vtkUnstructuredGrid::SafeDownCast(input)->GetFaceStream(id, cellPoints); + vtkUnstructuredGrid::ConvertFaceStreamPointIds(cellPoints, ptMap); + } + else + { + input->GetCellPoints(id, cellPoints); + for (int i = 0; i < cellPoints->GetNumberOfIds(); i++) + { + int cellPtId = cellPoints->GetId(i); + newId = ptMap[cellPtId]; + cellPoints->SetId(i, newId); + } + } + output->InsertNextCell(input->GetCellType(id), cellPoints); + } + + delete[] ptMap; + cellPoints->Delete(); + output->Squeeze(); + + return 1; +} + +//---------------------------------------------------------------------------- +int vtkCleanUnstructuredGrid::FillInputPortInformation(int vtkNotUsed(port), vtkInformation* info) +{ + info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet"); + return 1; +} + +//---------------------------------------------------------------------------- +void vtkCleanUnstructuredGrid::CreateDefaultLocator(vtkDataSet* input) +{ + double tol; + if (this->ToleranceIsAbsolute) + { + tol = this->AbsoluteTolerance; + } + else + { + if (input) + { + tol = this->Tolerance * input->GetLength(); + } + else + { + tol = this->Tolerance; + } + } + + if (this->Locator == nullptr) + { + if (tol == 0.0) + { + this->Locator = vtkMergePoints::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } + else + { + this->Locator = vtkPointLocator::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } + } + else + { + // check that the tolerance wasn't changed from zero to non-zero + if ((tol > 0.0) && (this->GetLocator()->GetTolerance() == 0.0)) + { + this->SetLocator(nullptr); + this->Locator = vtkPointLocator::New(); + this->Locator->Register(this); + this->Locator->Delete(); + } + } +} diff --git a/Applications/Utils/MeshEdit/vtkCleanUnstructuredGrid.h b/Applications/Utils/MeshEdit/vtkCleanUnstructuredGrid.h new file mode 100644 index 0000000000000000000000000000000000000000..e13ad9522fbf2c13bf869cec3f7ca72e7f68b3e3 --- /dev/null +++ b/Applications/Utils/MeshEdit/vtkCleanUnstructuredGrid.h @@ -0,0 +1,108 @@ +/*========================================================================= + + Program: ParaView + Module: vtkCleanUnstructuredGrid.h + + Copyright (c) Kitware, Inc. + All rights reserved. + See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notice for more information. + +=========================================================================*/ + +/** + * @class vtkCleanUnstructuredGrid + * @brief merge duplicate points + * + * + * vtkCleanUnstructuredGrid is a filter that takes unstructured grid data as + * input and generates unstructured grid data as output. vtkCleanUnstructuredGrid can + * merge duplicate points (with coincident coordinates) using the vtkMergePoints object + * to merge points. + * + * @sa + * vtkCleanPolyData +*/ + +#ifndef vtkCleanUnstructuredGrid_h +#define vtkCleanUnstructuredGrid_h + +//#include "vtkPVVTKExtensionsFiltersGeneralModule.h" //needed for exports +#include "vtkUnstructuredGridAlgorithm.h" + +class vtkIncrementalPointLocator; +class vtkDataSet; + +class /*VTKPVVTKEXTENSIONSFILTERSGENERAL_EXPORT*/ vtkCleanUnstructuredGrid + : public vtkUnstructuredGridAlgorithm +{ +public: + static vtkCleanUnstructuredGrid* New(); + + vtkTypeMacro(vtkCleanUnstructuredGrid, vtkUnstructuredGridAlgorithm); + + // By default ToleranceIsAbsolute is false and Tolerance is + // a fraction of Bounding box diagonal, if true, AbsoluteTolerance is + // used when adding points to locator (merging) + vtkSetMacro(ToleranceIsAbsolute, bool); + vtkBooleanMacro(ToleranceIsAbsolute, bool); + vtkGetMacro(ToleranceIsAbsolute, bool); + + // Specify tolerance in terms of fraction of bounding box length. + // Default is 0.0. + vtkSetClampMacro(Tolerance, double, 0.0, 1.0); + vtkGetMacro(Tolerance, double); + + // Specify tolerance in absolute terms. Default is 1.0. + vtkSetClampMacro(AbsoluteTolerance, double, 0.0, VTK_DOUBLE_MAX); + vtkGetMacro(AbsoluteTolerance, double); + + //@{ + /** + * Set/Get a spatial locator for speeding the search process. By + * default an instance of vtkMergePoints is used. + */ + virtual void SetLocator(vtkIncrementalPointLocator* locator); + vtkGetObjectMacro(Locator, vtkIncrementalPointLocator); + //@} + + // Create default locator. Used to create one when none is specified. + void CreateDefaultLocator(vtkDataSet* input = nullptr); + + // Release locator + void ReleaseLocator() { this->SetLocator(nullptr); } + + //@{ + /** + * Set/get the desired precision for the output types. See the documentation + * for the vtkAlgorithm::DesiredOutputPrecision enum for an explanation of + * the available precision settings. + */ + vtkSetMacro(OutputPointsPrecision, int); + vtkGetMacro(OutputPointsPrecision, int); + //@} + + void PrintSelf(ostream& os, vtkIndent indent) override; + +protected: + vtkCleanUnstructuredGrid() = default; + ~vtkCleanUnstructuredGrid() override; + + // options for managing point merging tolerance + bool ToleranceIsAbsolute = false; + double Tolerance = 0.0; + double AbsoluteTolerance = 1.0; + vtkIncrementalPointLocator* Locator = nullptr; + int OutputPointsPrecision = vtkAlgorithm::DEFAULT_PRECISION; + + int RequestData(vtkInformation*, vtkInformationVector**, vtkInformationVector*) override; + int FillInputPortInformation(int port, vtkInformation* info) override; + +private: + vtkCleanUnstructuredGrid(const vtkCleanUnstructuredGrid&) = delete; + void operator=(const vtkCleanUnstructuredGrid&) = delete; +}; +#endif