You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

184 lines
7.5 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkMultiObjectMassProperties.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm 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 vtkMultiObjectMassProperties
* @brief compute volume and area of objects in a polygonal mesh
*
* vtkMultiObjectMassProperties estimates the volume and the surface area of
* a polygonal mesh. Multiple, valid closed objects may be represented, and
* each object is assumed to be defined as a polyhedron defined by polygonal
* faces (i.e., the faces do not have to be triangles). The algorithm
* computes the total volume and area, as well as per object values which are
* placed in data arrays. Note that an object is valid only if it is manifold
* and closed (i.e., each edge is used exactly two times by two different
* polygons). Invalid objects are processed but may produce inaccurate
* results. Inconsistent polygon ordering is also allowed.
*
* The algorithm is composed of two basic parts. First a connected traversal
* is performed to identify objects, detect whether the objects are valid,
* and ensure that the composing polygons are ordered consistently. Next, in
* threaded execution, a parallel process of computing areas and volumes is
* performed. It is possible to skip the first part if the SkipValidityCheck
* is enabled, AND a vtkIdTypeArray data array named "ObjectIds" is
* associated with the polygon input (i.e., cell data) that enumerates which
* object every polygon belongs to (i.e., indictaes that it is a boundary
* polygon of a specified object).
*
* The algorithm implemented here is inspired by this paper:
* http://chenlab.ece.cornell.edu/Publication/Cha/icip01_Cha.pdf. Also see
* the Stackflow entry: https://stackoverflow.com/questions/1406029/
* how-to-calculate-the-volume-of-a-3d-mesh-object-the-surface-of-which-is-made-up.
* The general assumption here is that the model is of closed surface. Also,
* this approach requires triangulating the polygons so triangle meshes are
* processed much faster. Finally, the volume and area calculations are done
* in paraellel (threaded) after a connectivity pass is made (used to
* identify objects and verify that they are manifold and closed).
*
* The output contains six additional data arrays. The arrays
* "ObjectValidity", "ObjectVolumes" and "ObjectAreas" are placed in the
* output field data. These are arrays which indicate which objects are
* valid; the volume of each object; and the surface area of each
* object. Three additional arrays are placed in the output cell data, and
* indicate, on a per polygons basis, which object the polygon bounds
* "ObjectIds"; the polygon area "Areas"; and the contribution of volume
* "Volumes". Additionally, the TotalVolume and TotalArea is available after
* the filter executes (i.e., the sum of the ObjectVolumes and ObjectAreas
* arrays).
*
* Per object validity, as mentioned previously, is reported in the
* ObjectValidity array. However another variable, AllValid, is set after
* filter execution which indicates whether all objects are valid (!=0) or
* not. This information can be used as a shortcut in case you want to skip
* validity checking on an object-by-object basis.
*
* @warning
* This filter operates on the polygonal data contained in the input
* vtkPolyData. Other types (verts, lines, triangle strips) are ignored and
* not passed to the output. The input polys and points, as well as
* associated point and cell data, are passed through to the output.
*
* @warning
* This filter is similar to vtkMassProperties. However vtkMassProperties
* operates on triangle meshes and assumes only a single, closed, properly
* oriented surface is represented. vtkMultiObjectMassProperties performs
* additional topological and connectivity operations to identify separate
* objects, and confirms that they are manifold. It also accommodates
* inconsistent ordering.
*
* @warning
* This class has been threaded with vtkSMPTools. Using TBB or other
* non-sequential type (set in the CMake variable
* VTK_SMP_IMPLEMENTATION_TYPE) may improve performance significantly.
*
* @sa
* vtkMassProperties
*/
#ifndef vtkMultiObjectMassProperties_h
#define vtkMultiObjectMassProperties_h
#include "vtkFiltersCoreModule.h" // For export macro
#include "vtkPolyDataAlgorithm.h"
class vtkDoubleArray;
class vtkUnsignedCharArray;
class vtkIdTypeArray;
class VTKFILTERSCORE_EXPORT vtkMultiObjectMassProperties : public vtkPolyDataAlgorithm
{
public:
//@{
/**
* Standard methods for construction, type and printing.
*/
static vtkMultiObjectMassProperties* New();
vtkTypeMacro(vtkMultiObjectMassProperties, vtkPolyDataAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent) override;
//@}
//@{
/**
* Indicate whether to skip the validity check (the first part of the
* algorithm). By default this is off; however even if enabled validity
* skipping will only occur if a vtkIdTypeArray named "ObjectIds" is also
* provided on input to the filter.
*/
vtkSetMacro(SkipValidityCheck, vtkTypeBool);
vtkGetMacro(SkipValidityCheck, vtkTypeBool);
vtkBooleanMacro(SkipValidityCheck, vtkTypeBool);
//@}
/**
* Return the number of objects identified. This is valid only after the
* filter executes. Check the ObjectValidity array which indicates which of
* these identified objects are valid. Invalid objects may have incorrect
* volume and area values.
*/
vtkIdType GetNumberOfObjects() { return this->NumberOfObjects; }
/**
* Return whether all objects are valid or not. This is valid only after the
* filter executes.
*/
vtkTypeBool GetAllValid() { return this->AllValid; }
/**
* Return the summed volume of all objects. This is valid only after the
* filter executes.
*/
double GetTotalVolume() { return this->TotalVolume; }
/**
* Return the summed area of all objects. This is valid only after the
* filter executes.
*/
double GetTotalArea() { return this->TotalArea; }
protected:
vtkMultiObjectMassProperties();
~vtkMultiObjectMassProperties() override;
int RequestData(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
// Data members supporting API
vtkTypeBool SkipValidityCheck;
vtkTypeBool AllValid;
double TotalVolume;
double TotalArea;
// Internal data members supporting algorithm execution
vtkIdType NumberOfObjects; // number of objects identified
vtkIdTypeArray* ObjectIds; // for each input polygon, the object id that the polygon is in
vtkUnsignedCharArray* ObjectValidity; // is it a valid object?
vtkDoubleArray* ObjectVolumes; // what is the object volume (if valid)?
vtkDoubleArray* ObjectAreas; // what is the total object area?
vtkIdList* CellNeighbors; // avoid repetitive new/delete
vtkIdList* Wave; // processing wave
vtkIdList* Wave2;
// Connected traversal to identify objects
void TraverseAndMark(
vtkPolyData* output, vtkIdType* objectIds, vtkDataArray* valid, unsigned char* orient);
private:
vtkMultiObjectMassProperties(const vtkMultiObjectMassProperties&) = delete;
void operator=(const vtkMultiObjectMassProperties&) = delete;
};
#endif