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.
290 lines
9.8 KiB
C
290 lines
9.8 KiB
C
3 weeks ago
|
/*=========================================================================
|
||
|
|
||
|
Program: Visualization Toolkit
|
||
|
Module: vtkPolyDataInternals.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 vtkPolyDataInternals
|
||
|
* @brief Store mapping from vtkPolyData cell ids to internal cell array ids.
|
||
|
*
|
||
|
* Optimized data structure for storing internal cell ids and type information
|
||
|
* for vtkPolyData datasets.
|
||
|
*
|
||
|
* Since vtkPolyData only supports a handful of types, the type information
|
||
|
* is compressed to four bits -- the first two indicate which internal
|
||
|
* vtkCellArray object a cell is stored in (verts, lines, polys, strips), and
|
||
|
* the second two bits indicate which type of cell (e.g. lines vs polylines,
|
||
|
* triangles vs quads vs polygons, etc), as well as whether or not the cell
|
||
|
* has been deleted from the vtkPolyData.
|
||
|
*
|
||
|
* These four bits are stored at the top of a 64 bit index, and the remaining
|
||
|
* 60 bits store the cell id. This implies that the internal cell arrays cannot
|
||
|
* store more than 2^60 cells each, a reasonable limit for modern hardware.
|
||
|
*
|
||
|
* TaggedCellId structure:
|
||
|
* 66 66 555555555544444444443333333333222222222211111111110000000000
|
||
|
* 32 10 987654321098765432109876543210987654321098765432109876543210
|
||
|
* +--+--+------------------------------------------------------------+
|
||
|
* |00|00|000000000000000000000000000000000000000000000000000000000000|
|
||
|
* +^-+^-+^-----------------------------------------------------------+
|
||
|
* | | |
|
||
|
* | | |> Bottom 60 bits of cellId
|
||
|
* | |> Type variant / deleted
|
||
|
* |> Target cell array
|
||
|
*
|
||
|
* The supported cell types are:
|
||
|
*
|
||
|
* - VTK_VERTEX
|
||
|
* - VTK_POLY_VERTEX
|
||
|
* - VTK_LINE
|
||
|
* - VTK_POLY_LINE
|
||
|
* - VTK_TRIANGLE
|
||
|
* - VTK_QUAD
|
||
|
* - VTK_POLYGON
|
||
|
* - VTK_TRIANGLE_STRIP
|
||
|
*/
|
||
|
|
||
|
#ifndef vtkPolyDataInternals_h
|
||
|
#define vtkPolyDataInternals_h
|
||
|
|
||
|
#ifndef __VTK_WRAP__ // Don't wrap this class.
|
||
|
|
||
|
#include "vtkCommonDataModelModule.h" // For export macro
|
||
|
|
||
|
#include "vtkCellType.h"
|
||
|
#include "vtkObject.h"
|
||
|
#include "vtkType.h"
|
||
|
|
||
|
#include <cstdlib> // for std::size_t
|
||
|
#include <vector> // for CellMap implementation.
|
||
|
|
||
|
namespace vtkPolyData_detail
|
||
|
{
|
||
|
|
||
|
static constexpr vtkTypeUInt64 CELLID_MASK = 0x0fffffffffffffffull;
|
||
|
static constexpr vtkTypeUInt64 SHIFTED_TYPE_INDEX_MASK = 0xf000000000000000ull;
|
||
|
static constexpr vtkTypeUInt64 TARGET_MASK = 0x3ull << 62;
|
||
|
static constexpr vtkTypeUInt64 TYPE_VARIANT_MASK = 0x3ull << 60;
|
||
|
|
||
|
// Enumeration of internal cell array targets.
|
||
|
enum class Target : vtkTypeUInt64
|
||
|
{
|
||
|
Verts = 0x0ull << 62,
|
||
|
Lines = 0x1ull << 62,
|
||
|
Polys = 0x2ull << 62,
|
||
|
Strips = 0x3ull << 62,
|
||
|
};
|
||
|
|
||
|
// Enumeration of type variants.
|
||
|
enum class TypeVariant : vtkTypeUInt64
|
||
|
{
|
||
|
Dead = 0x0ull << 60,
|
||
|
Var1 = 0x1ull << 60,
|
||
|
Var2 = 0x2ull << 60,
|
||
|
Var3 = 0x3ull << 60,
|
||
|
};
|
||
|
|
||
|
// Lookup table to convert a type index (TaggedCellId.GetTypeIndex()) into
|
||
|
// a VTK cell type.
|
||
|
// The type index is the highest four bits of the encoded value, eg. the
|
||
|
// target and type variant information.
|
||
|
static constexpr unsigned char TypeTable[16] = {
|
||
|
VTK_EMPTY_CELL, // 0000b | Verts | Dead
|
||
|
VTK_VERTEX, // 0001b | Verts | Var1
|
||
|
VTK_POLY_VERTEX, // 0010b | Verts | Var2
|
||
|
VTK_EMPTY_CELL, // 0011b | Verts | Var3
|
||
|
VTK_EMPTY_CELL, // 0100b | Lines | Dead
|
||
|
VTK_LINE, // 0101b | Lines | Var1
|
||
|
VTK_POLY_LINE, // 0110b | Lines | Var2
|
||
|
VTK_EMPTY_CELL, // 0111b | Lines | Var3
|
||
|
VTK_EMPTY_CELL, // 1000b | Polys | Dead
|
||
|
VTK_TRIANGLE, // 1001b | Polys | Var1
|
||
|
VTK_QUAD, // 1010b | Polys | Var2
|
||
|
VTK_POLYGON, // 1011b | Polys | Var3
|
||
|
VTK_EMPTY_CELL, // 1100b | Strips | Dead
|
||
|
VTK_TRIANGLE_STRIP, // 1101b | Strips | Var1
|
||
|
VTK_EMPTY_CELL, // 1110b | Strips | Var2
|
||
|
VTK_EMPTY_CELL, // 1111b | Strips | Var3
|
||
|
};
|
||
|
|
||
|
// Convenience method to concatenate a target and type variant into the low
|
||
|
// four bits of a single byte. Used to build the TargetVarTable.
|
||
|
static constexpr unsigned char GenTargetVar(Target target, TypeVariant var) noexcept
|
||
|
{
|
||
|
return static_cast<unsigned char>(
|
||
|
(static_cast<vtkTypeUInt64>(target) | static_cast<vtkTypeUInt64>(var)) >> 60);
|
||
|
}
|
||
|
|
||
|
// Lookup table that maps a VTK cell type (eg. VTK_TRIANGLE) into a target +
|
||
|
// type variant byte.
|
||
|
static constexpr unsigned char TargetVarTable[10] = {
|
||
|
GenTargetVar(Target::Verts, TypeVariant::Dead), // 0 | VTK_EMPTY_CELL
|
||
|
GenTargetVar(Target::Verts, TypeVariant::Var1), // 1 | VTK_VERTEX
|
||
|
GenTargetVar(Target::Verts, TypeVariant::Var2), // 2 | VTK_POLY_VERTEX
|
||
|
GenTargetVar(Target::Lines, TypeVariant::Var1), // 3 | VTK_LINE
|
||
|
GenTargetVar(Target::Lines, TypeVariant::Var2), // 4 | VTK_POLY_LINE
|
||
|
GenTargetVar(Target::Polys, TypeVariant::Var1), // 5 | VTK_TRIANGLE
|
||
|
GenTargetVar(Target::Strips, TypeVariant::Var1), // 6 | VTK_TRIANGLE_STRIP
|
||
|
GenTargetVar(Target::Polys, TypeVariant::Var3), // 7 | VTK_POLYGON
|
||
|
GenTargetVar(Target::Polys, TypeVariant::Var2), // 8 | VTK_PIXEL (treat as quad)
|
||
|
GenTargetVar(Target::Polys, TypeVariant::Var2), // 9 | VTK_QUAD
|
||
|
};
|
||
|
|
||
|
// Thin wrapper around a vtkTypeUInt64 that encodes a target cell array,
|
||
|
// cell type, deleted status, and 60-bit cell id.
|
||
|
struct VTKCOMMONDATAMODEL_EXPORT TaggedCellId
|
||
|
{
|
||
|
// Encode a cell id and a VTK cell type (eg. VTK_TRIANGLE) into a
|
||
|
// vtkTypeUInt64.
|
||
|
static vtkTypeUInt64 Encode(vtkIdType cellId, VTKCellType type) noexcept
|
||
|
{
|
||
|
const size_t typeIndex = static_cast<size_t>(type);
|
||
|
return ((static_cast<vtkTypeUInt64>(cellId) & CELLID_MASK) |
|
||
|
(static_cast<vtkTypeUInt64>(TargetVarTable[typeIndex]) << 60));
|
||
|
}
|
||
|
|
||
|
TaggedCellId() noexcept = default;
|
||
|
|
||
|
// Create a TaggedCellId from a cellId and cell type (e.g. VTK_TRIANGLE).
|
||
|
TaggedCellId(vtkIdType cellId, VTKCellType cellType) noexcept : Value(Encode(cellId, cellType)) {}
|
||
|
|
||
|
TaggedCellId(const TaggedCellId&) noexcept = default;
|
||
|
TaggedCellId(TaggedCellId&&) noexcept = default;
|
||
|
TaggedCellId& operator=(const TaggedCellId&) noexcept = default;
|
||
|
TaggedCellId& operator=(TaggedCellId&&) noexcept = default;
|
||
|
|
||
|
// Get an enum value describing the internal vtkCellArray target used to
|
||
|
// store this cell.
|
||
|
Target GetTarget() const noexcept { return static_cast<Target>(this->Value & TARGET_MASK); }
|
||
|
|
||
|
// Get the VTK cell type value (eg. VTK_TRIANGLE) as a single byte.
|
||
|
unsigned char GetCellType() const noexcept { return TypeTable[this->GetTypeIndex()]; }
|
||
|
|
||
|
// Get the cell id used by the target vtkCellArray to store this cell.
|
||
|
vtkIdType GetCellId() const noexcept { return static_cast<vtkIdType>(this->Value & CELLID_MASK); }
|
||
|
|
||
|
// Update the cell id. Most useful with the CellMap::InsertNextCell(type)
|
||
|
// signature.
|
||
|
void SetCellId(vtkIdType cellId) noexcept
|
||
|
{
|
||
|
this->Value &= SHIFTED_TYPE_INDEX_MASK;
|
||
|
this->Value |= (static_cast<vtkTypeUInt64>(cellId) & CELLID_MASK);
|
||
|
}
|
||
|
|
||
|
// Mark this cell as deleted.
|
||
|
void MarkDeleted() noexcept { this->Value &= ~TYPE_VARIANT_MASK; }
|
||
|
|
||
|
// Returns true if the cell has been deleted.
|
||
|
bool IsDeleted() const noexcept { return (this->Value & TYPE_VARIANT_MASK) == 0; }
|
||
|
|
||
|
private:
|
||
|
vtkTypeUInt64 Value;
|
||
|
|
||
|
// These shouldn't be needed outside of this struct. You're probably looking
|
||
|
// for GetCellType() instead.
|
||
|
TypeVariant GetTypeVariant() const noexcept
|
||
|
{
|
||
|
return static_cast<TypeVariant>(this->Value & TYPE_VARIANT_MASK);
|
||
|
}
|
||
|
std::size_t GetTypeIndex() const noexcept { return static_cast<std::size_t>(this->Value >> 60); }
|
||
|
};
|
||
|
|
||
|
// Thin wrapper around a std::vector<TaggedCellId> to allow shallow copying, etc
|
||
|
class VTKCOMMONDATAMODEL_EXPORT CellMap : public vtkObject
|
||
|
{
|
||
|
public:
|
||
|
static CellMap* New();
|
||
|
vtkTypeMacro(CellMap, vtkObject);
|
||
|
|
||
|
static bool ValidateCellType(VTKCellType cellType) noexcept
|
||
|
{
|
||
|
// 1-9 excluding 8 (VTK_PIXEL):
|
||
|
return cellType > 0 && cellType <= 10 && cellType != VTK_PIXEL;
|
||
|
}
|
||
|
|
||
|
static bool ValidateCellId(vtkIdType cellId) noexcept
|
||
|
{
|
||
|
// is positive, won't truncate:
|
||
|
return (
|
||
|
(static_cast<vtkTypeUInt64>(cellId) & CELLID_MASK) == static_cast<vtkTypeUInt64>(cellId));
|
||
|
}
|
||
|
|
||
|
void DeepCopy(CellMap* other)
|
||
|
{
|
||
|
if (other)
|
||
|
{
|
||
|
this->Map = other->Map;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this->Map.clear();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void SetCapacity(vtkIdType numCells) { this->Map.reserve(static_cast<std::size_t>(numCells)); }
|
||
|
|
||
|
TaggedCellId& GetTag(vtkIdType cellId) { return this->Map[static_cast<std::size_t>(cellId)]; }
|
||
|
|
||
|
const TaggedCellId& GetTag(vtkIdType cellId) const
|
||
|
{
|
||
|
return this->Map[static_cast<std::size_t>(cellId)];
|
||
|
}
|
||
|
|
||
|
// Caller must ValidateCellType first.
|
||
|
void InsertNextCell(vtkIdType cellId, VTKCellType cellType)
|
||
|
{
|
||
|
this->Map.emplace_back(cellId, cellType);
|
||
|
}
|
||
|
|
||
|
// Caller must ValidateCellType and ValidateCellId first.
|
||
|
// useful for reusing the target lookup from cellType and then calling
|
||
|
// TaggedCellId::SetCellId later.
|
||
|
TaggedCellId& InsertNextCell(VTKCellType cellType)
|
||
|
{
|
||
|
this->Map.emplace_back(vtkIdType(0), cellType);
|
||
|
return this->Map.back();
|
||
|
}
|
||
|
|
||
|
vtkIdType GetNumberOfCells() const { return static_cast<vtkIdType>(this->Map.size()); }
|
||
|
|
||
|
void Reset() { this->Map.clear(); }
|
||
|
|
||
|
void Squeeze()
|
||
|
{
|
||
|
this->Map.shrink_to_fit(); // yaaaaay c++11
|
||
|
}
|
||
|
|
||
|
// In rounded-up kibibytes, as is VTK's custom:
|
||
|
unsigned long GetActualMemorySize() const
|
||
|
{
|
||
|
return static_cast<unsigned long>(sizeof(TaggedCellId) * this->Map.capacity() + 1023) / 1024;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
CellMap();
|
||
|
~CellMap() override;
|
||
|
|
||
|
std::vector<TaggedCellId> Map;
|
||
|
|
||
|
private:
|
||
|
CellMap(const CellMap&) = delete;
|
||
|
CellMap& operator=(const CellMap&) = delete;
|
||
|
};
|
||
|
|
||
|
} // end namespace vtkPolyData_detail
|
||
|
|
||
|
#endif // __VTK_WRAP__
|
||
|
#endif // vtkPolyDataInternals.h
|
||
|
|
||
|
// VTK-HeaderTest-Exclude: vtkPolyDataInternals.h
|