Showing preview only (591K chars total). Download the full file or copy to clipboard to get everything.
Repository: zippy84/vtkbool
Branch: master
Commit: 167d78255bc0
Files: 37
Total size: 571.4 KB
Directory structure:
gitextract_hxnqu4v5/
├── .github/
│ ├── FUNDING.yml
│ └── workflows/
│ └── cmake.yml
├── CITATION.cff
├── CMakeLists.txt
├── Contact.cxx
├── Contact.h
├── LICENSE
├── Merger.cxx
├── Merger.h
├── Optimize.cxx
├── Optimize.h
├── README.md
├── Utilities.cxx
├── Utilities.h
├── module/
│ ├── CMakeLists.txt
│ └── vtk.module
├── paraview/
│ ├── CMakeLists.txt
│ ├── module/
│ │ ├── CMakeLists.txt
│ │ ├── vtk.module
│ │ └── vtkPolyDataBooleanFilter.xml
│ └── paraview.plugin
├── run_some_tests.sh
├── testing/
│ ├── data/
│ │ ├── branched.vtk
│ │ ├── branched3.vtk
│ │ ├── branched4.vtk
│ │ ├── branched6.vtk
│ │ ├── cross.vtk
│ │ ├── merger.vtk
│ │ └── non-manifold.vtk
│ ├── generate_frieze.py
│ ├── pytest.ini
│ ├── test_congruence.cxx
│ ├── test_filter.py
│ ├── test_merger.cxx
│ └── test_python.py
├── vtkPolyDataBooleanFilter.cxx
└── vtkPolyDataBooleanFilter.h
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
ko_fi: zippy84
================================================
FILE: .github/workflows/cmake.yml
================================================
name: CMake
on:
push:
branches:
- '*'
jobs:
Build:
runs-on: ${{matrix.os}}
strategy:
matrix:
os: [ubuntu-22.04, ubuntu-latest]
cxx: [g++, clang++]
build_type: [Debug, Release]
steps:
- uses: actions/checkout@v3
- name: Install Deps
run: |
sudo apt-get update
sudo apt-get -y upgrade
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata
sudo apt-get -y install libvtk9-dev python3-vtk9 python3-pytest
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{matrix.build_type}}
env:
CXX: ${{matrix.cxx}}
CXXFLAGS: ${{matrix.cxxflags}}
- name: Build
run: cmake --build ${{github.workspace}}/build --config ${{matrix.build_type}}
- name: Test
working-directory: ${{github.workspace}}/build
run: ctest --output-on-failure -C ${{matrix.build_type}}
Coverage:
if: github.ref == 'refs/heads/master'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install Deps
run: |
sudo apt-get update
sudo apt-get -y upgrade
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y tzdata
sudo apt-get -y install libvtk9-dev python3-vtk9 python3-pytest gcovr
- name: Configure CMake
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=Profile -DVTKBOOL_COVERAGE=ON
- name: Build
run: cmake --build ${{github.workspace}}/build
- name: Test
working-directory: ${{github.workspace}}/build
run: |
ctest --output-on-failure
gcovr -r .. . --exclude-throw-branches --xml -o coverage.xml
- name: Upload coverage reports to Codecov
uses: codecov/codecov-action@v3
with:
token: ${{secrets.CODECOV_TOKEN}}
================================================
FILE: CITATION.cff
================================================
cff-version: 1.2.0
title: vtkbool
message: 'If you use this software, please cite it as below.'
type: software
authors:
- family-names: Römer
given-names: Ronald
identifiers:
- type: doi
value: 10.5281/zenodo.10461186
repository-code: 'https://github.com/zippy84/vtkbool'
license: Apache-2.0
version: 3.2.0
================================================
FILE: CMakeLists.txt
================================================
# Copyright 2012-2025 Ronald Römer
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(vtkbool
VERSION 3.2
HOMEPAGE_URL https://github.com/zippy84/vtkbool)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_OUTPUT_EXTENSION_REPLACE 1)
if(MSVC)
add_compile_options(/EHsc)
add_compile_definitions(_SCL_SECURE_NO_WARNINGS)
add_compile_definitions(_USE_MATH_DEFINES)
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
else()
add_compile_options(-Wall -Wextra -fPIC -Wconversion)
endif()
option(VTKBOOL_PARAVIEW "" OFF)
option(VTKBOOL_DEBUG "" OFF)
option(VTKBOOL_COVERAGE "" OFF)
mark_as_advanced(VTKBOOL_DEBUG)
mark_as_advanced(VTKBOOL_COVERAGE)
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND VTKBOOL_COVERAGE)
set(CMAKE_C_FLAGS_PROFILE --coverage)
set(CMAKE_CXX_FLAGS_PROFILE --coverage)
add_link_options("--coverage")
endif()
include_directories(".")
if(VTKBOOL_DEBUG)
add_definitions(-DDEBUG)
endif()
if(VTKBOOL_PARAVIEW)
find_package(ParaView REQUIRED)
if(ParaView_FOUND)
paraview_plugin_scan(
PLUGIN_FILES "${CMAKE_CURRENT_SOURCE_DIR}/paraview/paraview.plugin"
PROVIDES_PLUGINS plugins
ENABLE_BY_DEFAULT ON)
set(BUILD_SHARED_LIBS ON)
include(GNUInstallDirs)
paraview_plugin_build(
PLUGINS ${plugins})
endif()
else()
find_package(VTK REQUIRED COMPONENTS FiltersSources IOLegacy FiltersExtraction FiltersGeometry FiltersModeling FiltersFlowPaths OPTIONAL_COMPONENTS WrappingPythonCore NO_MODULE)
if(VTK_FOUND)
if(VTK_VERSION VERSION_LESS "9.0.0")
message(FATAL_ERROR "vtkbool requires VTK 9.0.0 or newer.")
endif()
vtk_module_scan(
MODULE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/module/vtk.module"
REQUEST_MODULES vtkbool
PROVIDES_MODULES modules
ENABLE_TESTS ON)
set(BUILD_SHARED_LIBS ON)
include(GNUInstallDirs)
vtk_module_build(MODULES ${modules})
if (VTK_WrappingPythonCore_FOUND)
vtk_module_wrap_python(
MODULES ${modules}
PYTHON_PACKAGE "vtkbool"
BUILD_STATIC OFF
INSTALL_HEADERS OFF)
include(CTest)
vtk_module_python_default_destination(python_default_destination)
add_test(NAME "import_vtkbool"
COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/testing/test_python.py)
set_property(TEST "import_vtkbool" APPEND PROPERTY ENVIRONMENT "PYTHONPATH=${CMAKE_BINARY_DIR}/${python_default_destination}/vtkbool")
add_test(NAME "test_filter"
COMMAND ${Python3_EXECUTABLE} -m pytest
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/testing)
set_property(TEST "test_filter" APPEND PROPERTY ENVIRONMENT "PYTHONPATH=${CMAKE_BINARY_DIR}/${python_default_destination}/vtkbool")
add_executable(test_merger testing/test_merger.cxx)
target_link_libraries(test_merger PRIVATE vtkbool ${VTK_LIBRARIES})
add_executable(test_congruence testing/test_congruence.cxx)
target_link_libraries(test_congruence PRIVATE vtkbool ${VTK_LIBRARIES})
vtk_module_autoinit(
TARGETS test_merger test_congruence
MODULES ${VTK_LIBRARIES}
)
add_test(NAME "test_merger"
COMMAND test_merger
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/testing)
add_test(NAME "test_congruence"
COMMAND test_congruence
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/testing)
add_test(NAME "generate_frieze"
COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/testing/generate_frieze.py
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}/testing)
set_property(TEST "generate_frieze" APPEND PROPERTY ENVIRONMENT "PYTHONPATH=${CMAKE_BINARY_DIR}/${python_default_destination}/vtkbool")
endif()
endif()
endif()
================================================
FILE: Contact.cxx
================================================
/*
Copyright 2012-2025 Ronald Römer
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "Contact.h"
#include "Optimize.h"
#include <vtkCleanPolyData.h>
#include <vtkCellIterator.h>
#include <vtkCellData.h>
#include <vtkTriangleStrip.h>
#include <vtkArrayIteratorTemplate.h>
// #define _debA 0
// #define _debB 0
#if (defined(_debA) && defined(_debB))
vtkIdType _idA, _idB;
#endif
vtkSmartPointer<vtkPolyData> Clean (vtkPolyData *pd) {
auto clean = vtkSmartPointer<vtkCleanPolyData>::New();
clean->SetOutputPointsPrecision(vtkAlgorithm::DOUBLE_PRECISION);
clean->SetTolerance(1e-6);
clean->ConvertLinesToPointsOff();
clean->ConvertPolysToLinesOff();
clean->ConvertStripsToPolysOff();
clean->SetInputData(pd);
clean->Update();
auto cleaned = clean->GetOutput();
vtkIdType numCells = cleaned->GetNumberOfCells();
auto newPd = vtkSmartPointer<vtkPolyData>::New();
newPd->SetPoints(cleaned->GetPoints());
newPd->Allocate(numCells);
auto cellIds = vtkSmartPointer<vtkIdTypeArray>::New();
cellIds->SetName("OrigCellIds");
cellIds->Allocate(numCells);
vtkCellIterator *cellItr = cleaned->NewCellIterator();
vtkIdType cellId;
vtkIdList *ptIds;
vtkIdType num;
const vtkIdType *pts;
for (cellItr->InitTraversal(); !cellItr->IsDoneWithTraversal(); cellItr->GoToNextCell()) {
cellId = cellItr->GetCellId();
ptIds = cellItr->GetPointIds();
if (cellItr->GetCellType() == VTK_TRIANGLE || cellItr->GetCellType() == VTK_POLYGON) {
newPd->InsertNextCell(cellItr->GetCellType(), ptIds);
cellIds->InsertNextValue(cellId);
} else if (cellItr->GetCellType() == VTK_TRIANGLE_STRIP) {
auto cells = vtkSmartPointer<vtkCellArray>::New();
vtkTriangleStrip::DecomposeStrip(cellItr->GetNumberOfPoints(), ptIds->GetPointer(0), cells);
for (cells->InitTraversal(); cells->GetNextCell(num, pts);) {
if (pts[0] != pts[1] && pts[1] != pts[2] && pts[2] != pts[0]) {
newPd->InsertNextCell(VTK_TRIANGLE, num, pts);
cellIds->InsertNextValue(cellId);
}
}
} else if (cellItr->GetCellType() == VTK_QUAD) {
double pA[3], pB[3], pC[3], pD[3];
cleaned->GetPoint(ptIds->GetId(0), pA);
cleaned->GetPoint(ptIds->GetId(1), pB);
cleaned->GetPoint(ptIds->GetId(2), pC);
cleaned->GetPoint(ptIds->GetId(3), pD);
double det = vtkMath::Determinant3x3(pB[0]-pA[0], pC[0]-pA[0], pD[0]-pA[0],
pB[1]-pA[1], pC[1]-pA[1], pD[1]-pA[1],
pB[2]-pA[2], pC[2]-pA[2], pD[2]-pA[2]);
if (std::abs(det) < 1e-10) {
newPd->InsertNextCell(VTK_POLYGON, ptIds);
cellIds->InsertNextValue(cellId);
} else {
const vtkIdType cellA[] = {ptIds->GetId(0), ptIds->GetId(1), ptIds->GetId(2)};
const vtkIdType cellB[] = {ptIds->GetId(2), ptIds->GetId(3), ptIds->GetId(0)};
newPd->InsertNextCell(VTK_TRIANGLE, 3, cellA);
cellIds->InsertNextValue(cellId);
newPd->InsertNextCell(VTK_TRIANGLE, 3, cellB);
cellIds->InsertNextValue(cellId);
}
}
}
cellItr->Delete();
newPd->GetCellData()->SetScalars(cellIds);
newPd->Squeeze();
return newPd;
}
Contact::Contact (vtkPolyData *newPdA, vtkPolyData *newPdB) : newPdA(newPdA), newPdB(newPdB) {
assert(newPdA->GetCellData()->GetScalars("OrigCellIds") != nullptr);
assert(newPdB->GetCellData()->GetScalars("OrigCellIds") != nullptr);
pts = vtkSmartPointer<vtkPoints>::New();
pts->SetDataTypeToDouble();
lines = vtkSmartPointer<vtkPolyData>::New();
lines->SetPoints(pts);
lines->Allocate(1000);
contA = vtkSmartPointer<vtkIdTypeArray>::New();
contB = vtkSmartPointer<vtkIdTypeArray>::New();
contA->Allocate(1000);
contB->Allocate(1000);
contA->SetName("cA");
contB->SetName("cB");
lines->GetCellData()->AddArray(contA);
lines->GetCellData()->AddArray(contB);
sourcesA = vtkSmartPointer<vtkIdTypeArray>::New();
sourcesB = vtkSmartPointer<vtkIdTypeArray>::New();
sourcesA->Allocate(1000);
sourcesB->Allocate(1000);
sourcesA->SetNumberOfComponents(2);
sourcesB->SetNumberOfComponents(2);
sourcesA->SetName("sourcesA");
sourcesB->SetName("sourcesB");
lines->GetCellData()->AddArray(sourcesA);
lines->GetCellData()->AddArray(sourcesB);
touchesEdgesA = false;
touchesEdgesB = false;
GetNonManifoldEdges(newPdA, edgesA);
GetNonManifoldEdges(newPdB, edgesB);
treeA = vtkSmartPointer<vtkOBBTree>::New();
treeA->SetDataSet(newPdA);
treeA->BuildLocator();
treeB = vtkSmartPointer<vtkOBBTree>::New();
treeB->SetDataSet(newPdB);
treeB->BuildLocator();
}
vtkSmartPointer<vtkPolyData> Contact::GetLines (vtkPolyData *pdA, vtkLinearTransform *transA, vtkPolyData *pdB, vtkLinearTransform *transB) {
auto matrix = vtkSmartPointer<vtkMatrix4x4>::New();
if (pdA != nullptr) {
newPdA = pdA;
}
if (pdB != nullptr) {
newPdB = pdB;
}
auto matrixA = vtkSmartPointer<vtkMatrix4x4>::New();
if (transA != nullptr) {
matrixA = transA->GetMatrix();
}
auto matrixB = vtkSmartPointer<vtkMatrix4x4>::New();
if (transB != nullptr) {
matrixB = transB->GetMatrix();
}
auto tmpMatrix = vtkSmartPointer<vtkMatrix4x4>::New();
vtkMatrix4x4::Invert(matrixA, tmpMatrix);
vtkMatrix4x4::Multiply4x4(tmpMatrix, matrixB, matrix);
sourcesA->Reset();
sourcesB->Reset();
contA->Reset();
contB->Reset();
lines->Reset();
treeA->IntersectWithOBBTree(treeB, matrix, InterNodes, this);
IntersectReplacements();
if (touchesEdgesA || touchesEdgesB) {
throw std::runtime_error("Intersection goes through non-manifold edges.");
}
auto clean = vtkSmartPointer<vtkCleanPolyData>::New();
clean->SetInputData(lines);
clean->ToleranceIsAbsoluteOn();
clean->SetAbsoluteTolerance(1e-5);
clean->Update();
auto cleaned = clean->GetOutput();
vtkCellIterator *cellItr = cleaned->NewCellIterator();
vtkIdType cellId;
for (cellItr->InitTraversal(); !cellItr->IsDoneWithTraversal(); cellItr->GoToNextCell()) {
cellId = cellItr->GetCellId();
if (cellItr->GetCellType() != VTK_LINE) {
cleaned->DeleteCell(cellId);
}
}
cellItr->Delete();
cleaned->RemoveDeletedCells();
return cleaned;
}
void Contact::GetNonManifoldEdges (vtkPolyData *pd, NonManifoldEdgesType &edges) {
pd->BuildLinks();
vtkCellIterator *cellItr = pd->NewCellIterator();
vtkIdType cellId;
vtkIdList *ptIds;
auto neigs = vtkSmartPointer<vtkIdList>::New();
vtkIdType i, j, k;
vtkIdType idA, idB;
vtkIdType n;
vtkIdType num;
const vtkIdType *pts;
vtkIdType a, b;
for (cellItr->InitTraversal(); !cellItr->IsDoneWithTraversal(); cellItr->GoToNextCell()) {
cellId = cellItr->GetCellId();
ptIds = cellItr->GetPointIds();
for (i = 0; i < ptIds->GetNumberOfIds(); i++) {
j = i+1;
if (j == ptIds->GetNumberOfIds()) {
j = 0;
}
idA = ptIds->GetId(i);
idB = ptIds->GetId(j);
pd->GetCellEdgeNeighbors(cellId, idA, idB, neigs);
if (neigs->GetNumberOfIds() > 1) {
n = 0;
for (k = 0; k < neigs->GetNumberOfIds(); k++) {
pd->GetCellPoints(neigs->GetId(k), num, pts);
for (a = 0; a < num; a++) {
b = a+1;
if (b == num) {
b = 0;
}
if (pts[a] == idB && pts[b] == idA) {
n++;
}
}
}
if (n > 1) {
edges.emplace(idA, idB);
edges.emplace(idB, idA);
}
}
}
}
cellItr->Delete();
}
void Contact::InterEdgeLine (InterPtsType &interPts, const Point3d &pA, const Point3d &pB, Src src) {
// schnitt mit x-achse
double v[3];
Point3d::GetVec(pA, pB, v);
double w[] = {-v[1], v[0]};
double c = w[0]*pA.x+w[1]*pA.y;
if (std::abs(w[0]) < 1e-10) {
if (std::abs(pA.y) < 1e-5 && std::abs(pB.y) < 1e-5) {
interPts.emplace_back(pA.x, 0, 0, pA.x, pA.id, pB.id, End::A, src, PointSrc::Copied);
interPts.emplace_back(pB.x, 0, 0, pB.x, pA.id, pB.id, End::B, src, PointSrc::Copied);
}
} else {
double yA = pA.y-1e-6*v[1];
double yB = pB.y+1e-6*v[1];
if (std::signbit(yA) != std::signbit(yB)) {
double x = c/w[0];
double sA[] = {pA.x-x, pA.y};
double sB[] = {pB.x-x, pB.y};
double dA = sA[0]*sA[0]+sA[1]*sA[1];
double dB = sB[0]*sB[0]+sB[1]*sB[1];
End end = dA < 1e-12 ? End::A : (dB < 1e-12 ? End::B : End::None);
interPts.emplace_back(x, 0, 0, x, pA.id, pB.id, end, src, PointSrc::Calculated);
}
}
}
bool Contact::InterPolyLine (InterPtsType &interPts, const Base2 &base, const Poly &poly, Src src) {
#if (defined(_debA) && defined(_debB))
if (_idA == _debA && _idB == _debB) {
std::cout << "InterPolyLine()" << std::endl;
}
#endif
Poly::const_iterator itrA, itrB;
double q[3];
for (itrA = poly.begin(); itrA != poly.end(); ++itrA) {
itrB = itrA+1;
if (itrB == poly.end()) {
itrB = poly.begin();
}
InterEdgeLine(interPts, *itrA, *itrB, src); // schnitt mit x-achse
}
for (auto& p : interPts) {
base.BackTransform(p.pt, q);
std::copy_n(q, 3, p.pt);
}
std::sort(interPts.begin(), interPts.end(), [](auto &a, auto &b) { return a.t < b.t; });
struct Cmp {
const double tol = 1e-5;
bool operator() (const InterPt &lhs, const InterPt &rhs) const {
if (lhs.pointSrc == PointSrc::Copied && rhs.pointSrc == PointSrc::Copied) {
if (lhs.GetEnd() == rhs.GetEnd()) {
return false;
}
} else if (lhs.pointSrc == PointSrc::Copied) {
const vtkIdType end = lhs.GetEnd();
if (end == rhs.edge.f || end == rhs.edge.g) {
return false;
}
} else if (rhs.pointSrc == PointSrc::Copied) {
const vtkIdType end = rhs.GetEnd();
if (end == lhs.edge.f || end == lhs.edge.g) {
return false;
}
}
const double d = lhs.t-rhs.t;
if (std::abs(d) < tol) {
return false;
} else {
return d < 0;
}
}
};
std::map<InterPt, InterPtsType, Cmp> grouped;
std::vector<InterPtsType> sortedPts;
for (auto &p : interPts) {
grouped[p].push_back(p);
}
for (auto& [k, v] : grouped) {
std::sort(v.begin(), v.end(), [](const InterPt &lhs, const InterPt &rhs) { return lhs.pointSrc > rhs.pointSrc; });
sortedPts.push_back(v);
}
std::map<vtkIdType, double> allEnds;
decltype(sortedPts)::iterator itr;
for (itr = sortedPts.begin(); itr != sortedPts.end(); ++itr) {
if (itr == sortedPts.begin()) {
if (itr->size() == 2) {
itr->pop_back();
}
} else if (itr == sortedPts.end()-1) {
if (itr->size() == 2) {
itr->pop_back();
}
} else if (itr->size() == 1 && itr->back().end != End::None) {
itr->push_back(itr->back());
}
if (itr->back().end != End::None) {
auto p = itr->back();
allEnds.emplace(p.end == End::A ? p.edge.f : p.edge.g, p.t);
}
// hier schneidet sich das polygon selbst
if (itr->size() > 2) {
return false;
}
if (itr->size() == 2) {
// schnitt durch kongruente kanten
if (itr->back().end == End::None) {
return false;
}
auto &edgeA = itr->front().edge;
auto &edgeB = itr->back().edge;
if (edgeA.f == edgeB.g && edgeB.f == edgeA.g) {
return false;
}
}
}
std::map<vtkIdType, std::reference_wrapper<const Point3d>> pts;
for (auto &p : poly) {
pts.emplace(p.id, p);
}
vtkIdType ind;
vtkIdType prev, next;
for (itr = sortedPts.begin(); itr != sortedPts.end(); ++itr) {
auto p = itr->back();
if (p.end == End::None) {
continue;
}
if (p.end == End::A) {
ind = p.edge.f;
next = p.edge.g;
auto _itr = std::find_if(poly.begin(), poly.end(), [&ind](auto &p) { return p.id == ind; });
if (_itr == poly.begin()) {
prev = poly.back().id;
} else {
prev = std::prev(_itr)->id;
}
} else {
ind = p.edge.g;
prev = p.edge.f;
auto _itr = std::find_if(poly.begin(), poly.end(), [&ind](auto &p) { return p.id == ind; });
if (_itr == poly.end()-1) {
next = poly.front().id;
} else {
next = std::next(_itr)->id;
}
}
if (itr->size() == 2) {
if (allEnds.count(prev) == 0 && allEnds.count(next) == 1) {
const Point3d &q = pts.at(prev);
if ((allEnds.at(next) < p.t && q.y < 0) || (allEnds.at(next) > p.t && q.y > 0)) {
itr->pop_back();
}
} else if (allEnds.count(prev) == 1 && allEnds.count(next) == 0) {
const Point3d &q = pts.at(next);
if ((allEnds.at(prev) < p.t && q.y > 0) || (allEnds.at(prev) > p.t && q.y < 0)) {
itr->pop_back();
}
}
}
if (allEnds.count(prev) == 0 && allEnds.count(next) == 0) {
const Point3d &a = pts.at(prev);
const Point3d &b = pts.at(next);
if (std::signbit(a.y) != std::signbit(b.y)) {
if (itr->size() == 2) {
itr->pop_back();
}
} else {
if ((a.x > b.x) == std::signbit(a.y)) {
itr->clear();
}
}
}
}
InterPtsType _interPts;
for (const auto &pts : sortedPts) {
std::copy(pts.begin(), pts.end(), std::back_inserter(_interPts));
}
interPts.swap(_interPts);
#if (defined(_debA) && defined(_debB))
if (_idA == _debA && _idB == _debB) {
for (auto &p : interPts) {
std::cout << p << std::endl;
}
}
#endif
return true;
}
void Contact::InterPolys (vtkIdType idA, vtkIdType idB) {
#if (defined(_debA) && defined(_debB))
_idA = idA; _idB = idB;
if (_idA == _debA && _idB == _debB) {
std::cout << "InterPolys(" << idA << ", " << idB << ")" << std::endl;
}
#endif
vtkIdType numA, numB;
const vtkIdType *ptsA, *ptsB;
newPdA->GetCellPoints(idA, numA, ptsA);
newPdB->GetCellPoints(idB, numB, ptsB);
Poly polyA, polyB;
GetPoly(newPdA->GetPoints(), numA, ptsA, polyA);
GetPoly(newPdB->GetPoints(), numB, ptsB, polyB);
double nA[3], nB[3], r[3], s[3];
ComputeNormal(polyA, nA);
ComputeNormal(polyB, nB);
#if (defined(_debA) && defined(_debB))
if (_idA == _debA && _idB == _debB) {
std::cout << "nA [" << nA[0] << ", " << nA[1] << ", " << nA[2] << "]" << std::endl;
std::cout << "nB [" << nB[0] << ", " << nB[1] << ", " << nB[2] << "]" << std::endl;
}
#endif
if (vtkMath::Dot(nA, nB) > .9999999999) {
return;
}
double dA = polyA[0].x*nA[0]+polyA[0].y*nA[1]+polyA[0].z*nA[2];
double dB = polyB[0].x*nB[0]+polyB[0].y*nB[1]+polyB[0].z*nB[2];
vtkMath::Cross(nA, nB, r);
vtkMath::Normalize(r);
std::array<std::tuple<int, int, int, double>, 3> dets {
std::make_tuple(0, 1, 2, nA[0]*nB[1]-nB[0]*nA[1]),
std::make_tuple(0, 2, 1, nA[0]*nB[2]-nB[0]*nA[2]),
std::make_tuple(1, 2, 0, nA[1]*nB[2]-nB[1]*nA[2])
};
const auto& [i, j, k, det] = *std::max_element(dets.begin(), dets.end(), [](auto &a, auto &b) { return std::abs(std::get<3>(a)) < std::abs(std::get<3>(b)); });
s[i] = (dA*nB[j]-dB*nA[j])/det;
s[j] = (dB*nA[i]-dA*nB[i])/det;
s[k] = 0;
#if (defined(_debA) && defined(_debB))
if (_idA == _debA && _idB == _debB) {
std::cout << "det " << det << std::endl;
std::cout << "r [" << r[0] << ", " << r[1] << ", " << r[2] << "]" << std::endl;
std::cout << "s [" << s[0] << ", " << s[1] << ", " << s[2] << "]" << std::endl;
}
#endif
Base2 baseA(s, r, nA);
Base2 baseB(s, r, nB);
Poly transA, transB;
FlattenPoly2(polyA, transA, baseA);
FlattenPoly2(polyB, transB, baseB);
#if (defined(_debA) && defined(_debB))
if (_idA == _debA && _idB == _debB) {
std::cout << "transA {";
for (auto& p : transA) {
std::cout << p << ", ";
}
std::cout << std::endl;
std::cout << "transB {";
for (auto& p : transB) {
std::cout << p << ", ";
}
std::cout << std::endl;
}
#endif
bool isPlanarA = std::find_if(transA.begin(), transA.end(), [](auto &p) { return std::abs(p.z) > 1e-6; }) == transA.end();
bool isPlanarB = std::find_if(transB.begin(), transB.end(), [](auto &p) { return std::abs(p.z) > 1e-6; }) == transB.end();
bool hasReplA = replsA.count(idA) == 1;
bool hasReplB = replsB.count(idB) == 1;
if (!isPlanarA && !hasReplA && newPdA->GetCellType(idA) != VTK_TRIANGLE) {
try {
auto newIds = PreventEqualCaptPoints::TriangulateCell(newPdA, idA, {});
replsA.emplace(idA, newIds);
hasReplA = true;
} catch (...) {}
}
if (!isPlanarB && !hasReplB && newPdB->GetCellType(idB) != VTK_TRIANGLE) {
try {
auto newIds = PreventEqualCaptPoints::TriangulateCell(newPdB, idB, {});
replsB.emplace(idB, newIds);
hasReplB = true;
} catch (...) {}
}
if (hasReplA || hasReplB) {
pairs.emplace_back(idA, idB);
return;
}
InterPtsType intersPtsA, intersPtsB;
if (!InterPolyLine(intersPtsA, baseA, transA, Src::A)) {
throw std::runtime_error("Found invalid intersection points.");
}
if (!InterPolyLine(intersPtsB, baseB, transB, Src::B)) {
throw std::runtime_error("Found invalid intersection points.");
}
if (!CheckInters(intersPtsA, newPdA)) {
std::stringstream ss;
ss << "Intersection points do not lie on the edges (cells " << idA << ", " << idB << ").";
throw std::runtime_error(ss.str());
}
if (!CheckInters(intersPtsB, newPdB)) {
std::stringstream ss;
ss << "Intersection points do not lie on the edges (cells " << idA << ", " << idB << ").";
throw std::runtime_error(ss.str());
}
if ((intersPtsA.size() & 1) == 0 && (intersPtsB.size() & 1) == 0) {
AddContactLines(intersPtsA, intersPtsB, idA, idB);
}
}
bool Contact::CheckInters (const InterPtsType &interPts, vtkPolyData *pd) {
#if (defined(_debA) && defined(_debB))
if (_idA == _debA && _idB == _debB) {
std::cout << "CheckInters()" << std::endl;
}
#endif
double ptA[3],
ptB[3],
v[3],
w[3],
k,
l,
alpha,
d;
for (auto &p : interPts) {
#if (defined(_debA) && defined(_debB))
if (_idA == _debA && _idB == _debB) {
std::cout << p << std::endl;
}
#endif
pd->GetPoint(p.edge.f, ptA);
pd->GetPoint(p.edge.g, ptB);
vtkMath::Subtract(ptA, ptB, v);
vtkMath::Normalize(v);
vtkMath::Subtract(ptA, p.pt, w);
k = vtkMath::Norm(w);
l = vtkMath::Dot(v, w);
alpha = std::acos(l/k);
#if (defined(_debA) && defined(_debB))
if (_idA == _debA && _idB == _debB) {
std::cout << "alpha " << alpha << std::endl;
}
#endif
if (std::isnan(alpha)) {
continue;
}
d = std::sin(alpha)*k;
#if (defined(_debA) && defined(_debB))
if (_idA == _debA && _idB == _debB) {
std::cout << "d " << d << std::endl;
}
#endif
if (d < 1e-5) {
continue;
}
return false;
}
return true;
}
void Contact::OverlapLines (OverlapsType &overlaps, InterPtsType &intersA, InterPtsType &intersB) {
auto Add = [](InterPt &a, InterPt &b, InterPt &c, InterPt &d) {
a.Merge(c);
b.Merge(d);
return std::make_tuple(a, b);
};
InterPtsType::iterator itr, itr2;
for (itr = intersA.begin(); itr != intersA.end(); itr += 2) {
for (itr2 = intersB.begin(); itr2 != intersB.end(); itr2 += 2) {
if (itr->t <= itr2->t && (itr+1)->t > itr2->t) {
if ((itr2+1)->t < (itr+1)->t) {
overlaps.push_back(Add(*itr2, *(itr2+1), *itr, *(itr+1)));
} else {
overlaps.push_back(Add(*itr2, *(itr+1), *itr, *(itr2+1)));
}
} else if (itr2->t <= itr->t && (itr2+1)->t > itr->t) {
if ((itr+1)->t < (itr2+1)->t) {
overlaps.push_back(Add(*itr, *(itr+1), *itr2, *(itr2+1)));
} else {
overlaps.push_back(Add(*itr, *(itr2+1), *itr2, *(itr+1)));
}
}
}
}
}
void Contact::AddContactLines (InterPtsType &intersA, InterPtsType &intersB, vtkIdType idA, vtkIdType idB) {
if (intersA.size() == 0 || intersB.size() == 0) {
return;
}
OverlapsType overlaps;
OverlapLines(overlaps, intersA, intersB);
OverlapsType::const_iterator itr;
for (itr = overlaps.begin(); itr != overlaps.end(); ++itr) {
auto &f = std::get<0>(*itr);
auto &s = std::get<1>(*itr);
if ((f.src == Src::A && edgesA.count(f.edge) == 1) || (s.src == Src::A && edgesA.count(s.edge) == 1)) {
touchesEdgesA = true;
}
if ((f.src == Src::B && edgesB.count(f.edge) == 1) || (s.src == Src::B && edgesB.count(s.edge) == 1)) {
touchesEdgesB = true;
}
vtkIdList *linePts = vtkIdList::New();
linePts->InsertNextId(pts->InsertNextPoint(f.pt));
linePts->InsertNextId(pts->InsertNextPoint(s.pt));
lines->InsertNextCell(VTK_LINE, linePts);
linePts->Delete();
const vtkIdType tupleA[] = {f.srcA, s.srcA};
const vtkIdType tupleB[] = {f.srcB, s.srcB};
sourcesA->InsertNextTypedTuple(tupleA);
sourcesB->InsertNextTypedTuple(tupleB);
contA->InsertNextValue(idA);
contB->InsertNextValue(idB);
}
}
int Contact::InterNodes (vtkOBBNode *nodeA, vtkOBBNode *nodeB, vtkMatrix4x4 *vtkNotUsed(matrix), void *ptr) {
auto _this = reinterpret_cast<Contact*>(ptr);
vtkIdList *cellsA = nodeA->Cells;
vtkIdList *cellsB = nodeB->Cells;
vtkIdType numCellsA = cellsA->GetNumberOfIds();
vtkIdType numCellsB = cellsB->GetNumberOfIds();
vtkIdType i, j, cellA, cellB;
for (i = 0; i < numCellsA; i++) {
cellA = cellsA->GetId(i);
for (j = 0; j < numCellsB; j++) {
cellB = cellsB->GetId(j);
_this->InterPolys(cellA, cellB);
}
}
return 0;
}
void Contact::IntersectReplacements () {
if (pairs.empty()) {
return;
}
while (!pairs.empty()) {
vtkIdType i;
auto iterA = vtkArrayIteratorTemplate<vtkIdType>::New();
iterA->Initialize(contA);
auto iterB = vtkArrayIteratorTemplate<vtkIdType>::New();
iterB->Initialize(contB);
for (i = 0; i < iterA->GetNumberOfValues(); i++) {
if (replsA.count(iterA->GetValue(i)) == 1 || replsB.count(iterB->GetValue(i)) == 1) {
lines->DeleteCell(i);
pairs.emplace_back(iterA->GetValue(i), iterB->GetValue(i));
}
}
PairsType current;
current.swap(pairs);
for (auto& [a, b] : current) {
auto itrA = replsA.find(a);
auto itrB = replsB.find(b);
IdsType cellsA, cellsB;
if (itrA == replsA.end()) {
cellsA.push_back(a);
} else {
auto ids = itrA->second;
std::copy(ids.begin(), ids.end(), std::back_inserter(cellsA));
}
if (itrB == replsB.end()) {
cellsB.push_back(b);
} else {
auto ids = itrB->second;
std::copy(ids.begin(), ids.end(), std::back_inserter(cellsB));
}
for (auto &idA : cellsA) {
for (auto &idB : cellsB) {
InterPolys(idA, idB);
}
}
}
}
lines->RemoveDeletedCells();
contA = vtkIdTypeArray::SafeDownCast(lines->GetCellData()->GetScalars("cA"));
contB = vtkIdTypeArray::SafeDownCast(lines->GetCellData()->GetScalars("cB"));
sourcesA = vtkIdTypeArray::SafeDownCast(lines->GetCellData()->GetScalars("sourcesA"));
sourcesB = vtkIdTypeArray::SafeDownCast(lines->GetCellData()->GetScalars("sourcesB"));
// contA und contB aktualisieren
auto oldCellIdsA = vtkSmartPointer<vtkIdTypeArray>::New();
auto oldCellIdsB = vtkSmartPointer<vtkIdTypeArray>::New();
oldCellIdsA->SetName("OldCellIds");
oldCellIdsB->SetName("OldCellIds");
vtkIdType numCellsA = newPdA->GetNumberOfCells();
vtkIdType numCellsB = newPdB->GetNumberOfCells();
oldCellIdsA->SetNumberOfValues(numCellsA);
oldCellIdsB->SetNumberOfValues(numCellsB);
vtkIdType i;
for (i = 0; i < numCellsA; i++) {
oldCellIdsA->SetValue(i, i);
}
for (i = 0; i < numCellsB; i++) {
oldCellIdsB->SetValue(i, i);
}
newPdA->GetCellData()->AddArray(oldCellIdsA);
newPdB->GetCellData()->AddArray(oldCellIdsB);
for (auto& [k, v] : replsA) {
newPdA->DeleteCell(k);
}
for (auto& [k, v] : replsB) {
newPdB->DeleteCell(k);
}
newPdA->RemoveDeletedCells();
newPdB->RemoveDeletedCells();
numCellsA = newPdA->GetNumberOfCells();
numCellsB = newPdB->GetNumberOfCells();
oldCellIdsA = vtkIdTypeArray::SafeDownCast(newPdA->GetCellData()->GetScalars("OldCellIds"));
oldCellIdsB = vtkIdTypeArray::SafeDownCast(newPdB->GetCellData()->GetScalars("OldCellIds"));
std::map<vtkIdType, vtkIdType> newCellIdsA, newCellIdsB;
auto iterA = vtkArrayIteratorTemplate<vtkIdType>::New();
iterA->Initialize(oldCellIdsA);
for (i = 0; i < numCellsA; i++) {
newCellIdsA.emplace(iterA->GetValue(i), i);
}
auto iterB = vtkArrayIteratorTemplate<vtkIdType>::New();
iterB->Initialize(oldCellIdsB);
for (i = 0; i < numCellsB; i++) {
newCellIdsB.emplace(iterB->GetValue(i), i);
}
vtkIdType numLines = lines->GetNumberOfCells();
try {
auto _iterA = vtkArrayIteratorTemplate<vtkIdType>::New();
_iterA->Initialize(contA);
for (i = 0; i < numLines; i++) {
_iterA->SetValue(i, newCellIdsA.at(_iterA->GetValue(i)));
}
auto _iterB = vtkArrayIteratorTemplate<vtkIdType>::New();
_iterB->Initialize(contB);
for (i = 0; i < numLines; i++) {
_iterB->SetValue(i, newCellIdsB.at(_iterB->GetValue(i)));
}
} catch (const std::out_of_range &e) {
throw std::runtime_error("");
}
newPdA->GetCellData()->RemoveArray("OldCellIds");
newPdB->GetCellData()->RemoveArray("OldCellIds");
}
================================================
FILE: Contact.h
================================================
/*
Copyright 2012-2025 Ronald Römer
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __Contact_h
#define __Contact_h
#include "Utilities.h"
#include <vtkOBBTree.h>
#include <vtkMatrix4x4.h>
#include <vtkLinearTransform.h>
enum class Src {
A,
B
};
enum class End {
None,
A,
B
};
enum class PointSrc {
Calculated,
Copied
};
class InterPt {
public:
InterPt () = delete;
InterPt (double x, double y, double z, double t, vtkIdType a, vtkIdType b, End end, Src src, PointSrc pointSrc) : t(t), edge(a, b), end(end), src(src), srcA(NOTSET), srcB(NOTSET), pointSrc(pointSrc) {
pt[0] = x;
pt[1] = y;
pt[2] = z;
}
double pt[3], t;
Pair edge;
End end;
Src src;
vtkIdType srcA, srcB;
PointSrc pointSrc;
friend std::ostream& operator<< (std::ostream &out, const InterPt &s) {
out << "pt [" << s.pt[0] << ", " << s.pt[1] << ", " << s.pt[2] << "]"
<< ", t " << s.t
<< ", edge " << s.edge
<< ", end " << s.end
<< ", src " << s.src
<< ", pointSrc " << s.pointSrc;
return out;
}
void Merge (const InterPt &other) {
assert(src != other.src);
if (src == Src::A) {
srcA = GetEnd();
} else {
srcB = GetEnd();
}
if (std::abs(other.t-t) < 1e-5) {
if (other.src == Src::A) {
srcA = other.GetEnd();
} else {
srcB = other.GetEnd();
}
}
}
inline vtkIdType GetEnd () const {
if (end == End::A) {
return edge.f;
}
if (end == End::B) {
return edge.g;
}
return NOTSET;
}
};
typedef std::vector<InterPt> InterPtsType;
typedef std::vector<std::tuple<InterPt, InterPt>> OverlapsType;
typedef std::set<Pair> NonManifoldEdgesType;
typedef std::vector<std::pair<vtkIdType, vtkIdType>> PairsType;
vtkSmartPointer<vtkPolyData> Clean (vtkPolyData *pd);
class Contact {
public:
Contact () = delete;
Contact (vtkPolyData *newPdA, vtkPolyData *newPdB);
vtkPolyData *newPdA, *newPdB;
vtkSmartPointer<vtkPoints> pts;
vtkSmartPointer<vtkPolyData> lines;
vtkSmartPointer<vtkIdTypeArray> contA, contB, sourcesA, sourcesB;
bool touchesEdgesA, touchesEdgesB;
NonManifoldEdgesType edgesA, edgesB;
vtkSmartPointer<vtkOBBTree> treeA, treeB;
vtkSmartPointer<vtkPolyData> GetLines (vtkPolyData *pdA = nullptr, vtkLinearTransform *transA = nullptr, vtkPolyData *pdB = nullptr, vtkLinearTransform *transB = nullptr);
void GetNonManifoldEdges (vtkPolyData *pd, NonManifoldEdgesType &edges);
void InterEdgeLine (InterPtsType &interPts, const Point3d &pA, const Point3d &pB, Src src);
bool InterPolyLine (InterPtsType &interPts, const Base2 &base, const Poly &poly, Src src);
void InterPolys (vtkIdType idA, vtkIdType idB);
bool CheckInters (const InterPtsType &interPts, vtkPolyData *pd);
void OverlapLines (OverlapsType &overlaps, InterPtsType &intersA, InterPtsType &intersB);
void AddContactLines (InterPtsType &intersA, InterPtsType &intersB, vtkIdType idA, vtkIdType idB);
static int InterNodes (vtkOBBNode *nodeA, vtkOBBNode *nodeB, vtkMatrix4x4 *vtkNotUsed(matrix), void *ptr);
PairsType pairs;
std::map<vtkIdType, IdsType> replsA, replsB;
void IntersectReplacements ();
};
#endif
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
================================================
FILE: Merger.cxx
================================================
/*
Copyright 2012-2025 Ronald Römer
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "Merger.h"
#include <vtkCellData.h>
Merger::Merger (vtkPolyData *pd, const PStrips &pStrips, const StripsType &strips, const IdsType &descIds, vtkIdType origId) : pd(pd), pStrips(pStrips), origId(origId) {
const StripPtsType &pts = pStrips.pts;
const Base &base = pStrips.base;
vtkIdType i, num;
const vtkIdType *cell;
double pt[3];
for (auto id : descIds) {
pd->GetCellPoints(id, num, cell);
Poly p;
for (i = 0; i < num; i++) {
pd->GetPoint(cell[i], pt);
double proj[2];
Transform(pt, proj, base);
p.emplace_back(proj[0], proj[1], 0, cell[i]);
}
polys.push_back(p);
pd->DeleteCell(id);
}
for (auto &strip : strips) {
Poly p;
for (auto &sp : strip) {
const double *pt = pts.at(sp.ind).pt;
double proj[2];
Transform(pt, proj, base);
p.emplace_back(proj[0], proj[1], 0, NOTSET, sp.ind);
}
p.pop_back();
double n[3];
ComputeNormal(p, n);
if (n[2] < 0) {
Poly q(p.rbegin(), p.rend());
p.swap(q);
}
innerIds.push_back(polys.size());
polys.push_back(p);
}
}
void Merger::Run () {
// mergen mit hilfe von vtkKdTree und vtkModifiedBSPTree
vtkPoints *pdPts = pd->GetPoints();
vtkIdTypeArray *origCellIds = vtkIdTypeArray::SafeDownCast(pd->GetCellData()->GetScalars("OrigCellIds"));
assert(origCellIds != nullptr);
std::vector<GroupType> groups(polys.size());
PolysType::const_iterator itrA, itrB;
std::size_t i {0};
for (itrA = polys.begin(); itrA != polys.end(); ++itrA) {
if (std::find(innerIds.begin(), innerIds.end(), i) != innerIds.end()) {
std::size_t j {0};
for (itrB = polys.begin(); itrB != polys.end(); ++itrB) {
if (itrA != itrB && PointInPoly(*itrB, *itrA->begin())) {
groups[j].push_back(i);
}
j++;
}
}
i++;
}
std::size_t parent = 0;
for (auto &group : groups) {
GroupType parents;
for (auto &index : group) {
const GroupType &_group = groups[index];
parents.insert(parents.end(), _group.begin(), _group.end());
}
std::sort(group.begin(), group.end());
std::sort(parents.begin(), parents.end());
GroupType _group {parent++};
std::set_difference(group.begin(), group.end(), parents.begin(), parents.end(), std::back_inserter(_group));
#ifdef DEBUG
std::cout << "[";
for (auto &index : _group) {
std::cout << index << ", ";
}
std::cout << "]" << std::endl;
#endif
PolysType merged;
MergeGroup(_group, merged);
std::map<vtkIdType, vtkIdType> newIds;
for (auto &poly : merged) {
auto newCell = vtkSmartPointer<vtkIdList>::New();
for (auto &p : poly) {
vtkIdType id = p.id;
if (id == NOTSET) {
auto itr = newIds.find(p.otherId);
if (itr == newIds.end()) {
auto &q = pStrips.pts.at(p.otherId);
id = pdPts->InsertNextPoint(q.pt);
newIds.emplace(p.otherId, id);
} else {
id = itr->second;
}
}
newCell->InsertNextId(id);
}
pd->InsertNextCell(VTK_POLYGON, newCell);
origCellIds->InsertNextValue(origId);
}
}
}
void Merger::MergeGroup (const GroupType &group, PolysType &merged) {
if (group.size() == 1) {
merged.push_back(polys.at(group.back()));
return;
}
auto pts = vtkSmartPointer<vtkPoints>::New();
pts->SetDataTypeToDouble();
IndexedPolysType indexedPolys;
ReferencedPointsType refPts;
SourcesType sources;
std::size_t src = 0;
for (auto &index : group) {
const Poly &poly = polys.at(index);
IndexedPoly ids;
for (auto &p : poly) {
vtkIdType id = pts->InsertNextPoint(p.x, p.y, p.z);
ids.push_back(id);
sources.emplace(id, src);
refPts.emplace(id, p);
}
indexedPolys.push_back(std::move(ids));
src++;
}
auto kdTree = vtkSmartPointer<vtkKdTree>::New();
kdTree->OmitZPartitioning();
kdTree->BuildLocatorFromPoints(pts);
auto linesA = vtkSmartPointer<vtkPolyData>::New();
linesA->SetPoints(pts);
linesA->Allocate(1);
IndexedPoly::const_iterator itrA, itrB;
for (const auto &ids : indexedPolys) {
for (itrA = ids.begin(); itrA != ids.end(); ++itrA) {
itrB = itrA+1;
if (itrB == ids.end()) {
itrB = ids.begin();
}
vtkIdList *line = vtkIdList::New();
line->InsertNextId(*itrA);
line->InsertNextId(*itrB);
linesA->InsertNextCell(VTK_LINE, line);
line->Delete();
}
}
#ifdef DEBUG
WriteVTK("linesA.vtk", linesA);
#endif
auto bspTreeA = vtkSmartPointer<vtkModifiedBSPTree>::New();
bspTreeA->SetDataSet(linesA);
int n = 0;
PolyConnsType polyConns;
FindConns(linesA, kdTree, bspTreeA, polyConns, indexedPolys, sources, n);
PolyConnsType connected {{0, {}}};
_IdsType restricted; // keine der conns darf im gleichen punkt beginnen
auto linesB = vtkSmartPointer<vtkPolyData>::New();
linesB->SetPoints(pts);
linesB->Allocate(1);
auto bspTreeB = vtkSmartPointer<vtkModifiedBSPTree>::New();
bspTreeB->SetDataSet(linesB);
ConnsType firstConns;
std::size_t i, numPolys = indexedPolys.size();
double ptA[3], ptB[3];
while (connected.size() < numPolys) {
bool foundOne = false;
for (i = 1; i < numPolys; i++) {
if (connected.count(i) == 0) {
const ConnsType &conns = polyConns[i];
for (auto &conn : conns) {
if (connected.count(sources.at(conn.j)) == 1
&& restricted.count(conn.j) == 0) {
pts->GetPoint(conn.i, ptA);
pts->GetPoint(conn.j, ptB);
if (bspTreeB->IntersectWithLine(ptA, ptB, 1e-5, nullptr, nullptr) == 0) {
connected[sources.at(conn.i)].push_back(conn);
// das andere poly auch aktualisieren
connected[sources.at(conn.j)].emplace_back(conn.d, conn.j, conn.i);
restricted.insert(conn.i);
restricted.insert(conn.j);
vtkIdList *line = vtkIdList::New();
line->InsertNextId(conn.i);
line->InsertNextId(conn.j);
linesB->InsertNextCell(VTK_LINE, line);
line->Delete();
bspTreeB->Modified();
foundOne = true;
firstConns.push_back(conn);
break;
}
}
}
}
}
if (!foundOne) {
if (!FindConns(linesA, kdTree, bspTreeA, polyConns, indexedPolys, sources, n)) {
throw std::runtime_error("Merging failed.");
}
}
}
std::map<std::size_t, std::vector<std::size_t>> chains;
PolyConnsType::const_iterator itrC;
for (itrC = connected.begin(); itrC != connected.end(); ++itrC) {
auto &chain = chains[itrC->first];
chain.push_back(itrC->first);
while (chain.back() != 0) {
chain.push_back(sources.at(connected.at(chain.back()).front().j));
}
}
#ifdef DEBUG
std::cout << connected;
decltype(chains)::const_iterator itrD;
for (itrD = chains.begin(); itrD != chains.end(); ++itrD) {
std::cout << itrD->first << ": [";
for (auto &id : itrD->second) {
std::cout << id << ", ";
}
std::cout << "]" << std::endl;
}
#endif
std::set<std::size_t> solved {0};
std::deque<std::size_t> searchInds;
for (i = 1; i < numPolys; i++) {
if (connected.at(i).size() == 1) {
searchInds.push_back(i);
}
}
while (!searchInds.empty()) {
PriosType prios;
for (auto ind : searchInds) {
PolyPriosType polyPrios;
#ifdef DEBUG
std::cout << "ind " << ind << std::endl;
#endif
const Conn &first = connected.at(ind).back();
for (auto &conn : polyConns.at(ind)) {
auto &src = sources.at(conn.j);
if (polyPrios.count(src) == 1) {
continue;
}
if (conn.i != first.i
&& conn.j != first.j
&& restricted.count(conn.i) == 0
&& restricted.count(conn.j) == 0) {
pts->GetPoint(conn.i, ptA);
pts->GetPoint(conn.j, ptB);
if (bspTreeB->IntersectWithLine(ptA, ptB, 1e-5, nullptr, nullptr) == 0) {
auto &chainA = chains.at(ind),
&chainB = chains.at(src);
std::set<std::size_t> _chainA(chainA.begin(), chainA.end()),
_chainB(chainB.begin(), chainB.end());
// gemeinsame eltern
std::set<std::size_t> shared;
std::set_intersection(_chainA.begin(), _chainA.end(), _chainB.begin(), _chainB.end(), std::inserter(shared, shared.end()));
// gemeinsame eltern müssen sich alle in solved befinden
if (std::includes(solved.begin(), solved.end(), shared.begin(), shared.end())) {
std::set<std::size_t> solvable;
std::set_difference(_chainA.begin(), _chainA.end(), solved.begin(), solved.end(), std::inserter(solvable, solvable.end()));
std::set_difference(_chainB.begin(), _chainB.end(), solved.begin(), solved.end(), std::inserter(solvable, solvable.end()));
polyPrios.emplace(std::piecewise_construct,
std::forward_as_tuple(src),
std::forward_as_tuple(conn, solvable, -conn.d));
}
}
}
}
PolyPriosType::const_iterator itr;
for (itr = polyPrios.begin(); itr != polyPrios.end(); ++itr) {
prios.insert(itr->second);
}
}
if (!prios.empty()) {
auto &prio = *prios.rbegin();
#ifdef DEBUG
std::cout << "found " << prio << std::endl;
#endif
auto &conns = connected.at(sources.at(prio.conn.i));
conns.push_back(prio.conn);
connected.at(sources.at(prio.conn.j)).emplace_back(prio.conn.d, prio.conn.j, prio.conn.i);
restricted.insert(prio.conn.i);
restricted.insert(prio.conn.j);
vtkIdList *line = vtkIdList::New();
line->InsertNextId(prio.conn.i);
line->InsertNextId(prio.conn.j);
linesB->InsertNextCell(VTK_LINE, line);
line->Delete();
bspTreeB->Modified();
solved.insert(prio.solvable.begin(), prio.solvable.end());
searchInds.erase(std::find(searchInds.begin(), searchInds.end(), sources.at(prio.conn.i)));
auto itr = std::find(searchInds.begin(), searchInds.end(), sources.at(prio.conn.j));
if (itr != searchInds.end()) {
searchInds.erase(itr);
}
} else {
if (!FindConns(linesA, kdTree, bspTreeA, polyConns, indexedPolys, sources, n)) {
break;
}
}
}
#ifdef DEBUG
std::cout << connected;
#endif
// fallback
double pt[3];
if (!searchInds.empty()) {
for (auto ind : searchInds) {
std::vector<std::size_t> newChain;
for (auto c : chains.at(ind)) {
if (solved.find(c) != solved.end()) {
break;
}
newChain.push_back(c);
}
ConnsType &conns = connected.at(ind);
decltype(newChain)::const_reverse_iterator itr;
for (itr = newChain.rbegin(); itr != newChain.rend(); itr++) {
// gesucht ist hier die kürzeste verbindung
#ifdef DEBUG
std::cout << "itr " << *itr << std::endl;
#endif
// polyConns.at(*itr) ist nach d sortiert
std::shared_ptr<Conn> found;
for (auto &conn : polyConns.at(*itr)) {
auto &src = sources.at(conn.j);
if (solved.find(src) != solved.end()) {
if (restricted.count(conn.i) == 0
// && restricted.count(conn.j) == 0
&& std::find_if(conns.begin(), conns.end(), [&conn](const Conn &other) { return conn.i == other.i || conn.j == other.j; }) == conns.end()) {
pts->GetPoint(conn.i, ptA);
pts->GetPoint(conn.j, ptB);
auto intersPts = vtkSmartPointer<vtkPoints>::New();
intersPts->SetDataTypeToDouble();
auto c = bspTreeB->IntersectWithLine(ptA, ptB, 1e-5, intersPts, nullptr);
if (c == 0) {
found = std::make_shared<Conn>(conn);
break;
}
// wenn schnittpunkte existieren, dann müssen alle mit ptB übereinstimmen
vtkIdType i, numPts = intersPts->GetNumberOfPoints();
std::set<Point3d> foundPts {{ptB[0], ptB[1], ptB[2]}};
for (i = 0; i < numPts; i++) {
intersPts->GetPoint(i, pt);
foundPts.emplace(pt[0], pt[1], pt[2]);
}
if (foundPts.size() == 1) {
found = std::make_shared<Conn>(conn);
break;
}
}
}
}
if (found) {
#ifdef DEBUG
std::cout << "found " << *found << std::endl;
#endif
conns.push_back(*found);
connected.at(sources.at(found->j)).emplace_back(found->d, found->j, found->i);
restricted.insert(found->i);
restricted.insert(found->j);
vtkIdList *line = vtkIdList::New();
line->InsertNextId(found->i);
line->InsertNextId(found->j);
linesB->InsertNextCell(VTK_LINE, line);
line->Delete();
bspTreeB->Modified();
solved.insert(*itr);
} else {
throw std::runtime_error("Merging failed.");
}
}
}
}
#ifdef DEBUG
WriteVTK("linesB.vtk", linesB);
#endif
ConnsType2 usedConns(firstConns.begin(), firstConns.end());
IndexedPoly polyA {indexedPolys.front()};
MergeStage1(indexedPolys, refPts, sources, firstConns, polyA);
IndexedPolysType splitted {polyA};
ConnsType2 leftConns;
for (itrC = connected.begin(); itrC != connected.end(); ++itrC) {
if (itrC->first == 0) {
continue;
}
auto &conns = itrC->second;
ConnsType::const_iterator itr;
for (itr = conns.begin()+1; itr != conns.end(); ++itr) {
Conn conn(0, itr->j, itr->i);
if (usedConns.find(conn) == usedConns.end()) {
if (itr->i < itr->j) {
leftConns.emplace(0, itr->i, itr->j);
} else {
leftConns.insert(std::move(conn));
}
}
}
}
#ifdef DEBUG
std::cout << "leftConns: [";
for (auto &conn : leftConns) {
std::cout << conn << ", ";
}
std::cout << "]" << std::endl;
#endif
MergeStage2(leftConns, refPts, usedConns, splitted);
PolysType newPolys;
GetPolys(refPts, splitted, newPolys);
#ifdef DEBUG
WritePolys("merged_stage2.vtk", newPolys);
#endif
std::move(newPolys.begin(), newPolys.end(), std::back_inserter(merged));
}
bool Merger::FindConns (vtkPolyData *lines, vtkSmartPointer<vtkKdTree> kdTree, vtkSmartPointer<vtkModifiedBSPTree> bspTree, PolyConnsType &polyConns, const IndexedPolysType &indexedPolys, const SourcesType &sources, int &n) {
vtkPoints *pts = lines->GetPoints();
if (n > pts->GetNumberOfPoints()) {
return false;
}
n += 10;
auto foundPts = vtkSmartPointer<vtkIdList>::New();
vtkIdType i, numPts;
vtkIdType idB;
auto lineIds = vtkSmartPointer<vtkIdList>::New();
double ptA[3], ptB[3];
bool good;
vtkIdType j;
vtkIdType _idA, _idB;
std::map<std::size_t, std::set<Conn, ConnCmp>> _polyConns;
auto line = vtkSmartPointer<vtkIdList>::New();
for (const auto &ids : indexedPolys) {
for (vtkIdType idA : ids) {
pts->GetPoint(idA, ptA);
kdTree->FindClosestNPoints(n, ptA, foundPts);
numPts = foundPts->GetNumberOfIds();
for (i = 0; i < numPts; i++) {
idB = foundPts->GetId(i);
auto srcA = sources.at(idA),
srcB = sources.at(idB);
if (srcA == srcB) {
continue;
}
pts->GetPoint(idB, ptB);
good = true;
if (bspTree->IntersectWithLine(ptA, ptB, 1e-5, nullptr, lineIds) == 1) {
for (j = 0; j < lineIds->GetNumberOfIds(); j++) {
lines->GetCellPoints(lineIds->GetId(j), line);
_idA = line->GetId(0);
_idB = line->GetId(1);
if (_idA != idA && _idA != idB
&& _idB != idA && _idB != idB) {
good = false;
break;
}
}
}
if (good) {
double d = vtkMath::Distance2BetweenPoints(ptA, ptB);
_polyConns[srcA].emplace(d, idA, idB);
_polyConns[srcB].emplace(d, idB, idA);
}
}
}
}
decltype(_polyConns)::const_iterator itr;
for (itr = _polyConns.begin(); itr != _polyConns.end(); ++itr) {
auto &_conns = itr->second;
ConnsType conns(_conns.begin(), _conns.end());
std::sort(conns.begin(), conns.end());
polyConns[itr->first].swap(conns);
}
return true;
}
void Merger::MergeStage1 (const IndexedPolysType &indexedPolys, [[maybe_unused]] const ReferencedPointsType &refPts, const SourcesType &sources, const ConnsType &conns, IndexedPoly &polyA) {
for (const auto &conn : conns) {
auto itrA = std::find(polyA.begin(), polyA.end(), conn.j);
assert(itrA != polyA.end());
IndexedPoly polyB(indexedPolys.at(sources.at(conn.i)));
auto itrB = std::find(polyB.begin(), polyB.end(), conn.i);
assert(itrB != polyB.end());
std::rotate(polyA.begin(), itrA, polyA.end());
std::rotate(polyB.begin(), itrB, polyB.end());
IndexedPoly newPoly {polyA};
newPoly.push_back(polyA.front());
newPoly.push_back(polyB.front());
newPoly.insert(newPoly.end(), polyB.rbegin(), polyB.rend());
polyA.swap(newPoly);
}
#ifdef DEBUG
PolysType newPolys;
GetPolys(refPts, {polyA}, newPolys);
WritePolys("merged_stage1.vtk", newPolys);
#endif
}
void Merger::MergeStage2 (const ConnsType2 &conns, const ReferencedPointsType &refPts, const ConnsType2 &usedConns, IndexedPolysType &splitted) {
std::set<Point3d> endPts;
for (const Conn &conn : usedConns) {
endPts.emplace(refPts.at(conn.i));
endPts.emplace(refPts.at(conn.j));
}
IndexedPolysType::iterator itr;
double vA[3], vB[3], w[3], ang, phi;
const double n[] = {0, 0, 1};
IndexedPoly::iterator itrA, itrB;
IndexedPoly::iterator prev, next;
for (auto &conn : conns) {
for (itr = splitted.begin(); itr != splitted.end(); ++itr) {
IndexedPoly poly(itr->begin(), itr->end());
if (endPts.count(refPts.at(conn.i)) == 0) {
itrA = std::find(poly.begin(), poly.end(), conn.i);
} else {
Point3d::GetVec(refPts.at(conn.i), refPts.at(conn.j), w);
itrA = poly.begin();
while ((itrA = std::find(itrA, poly.end(), conn.i)) != poly.end()) {
next = itrA+1;
if (next == poly.end()) {
next = poly.begin();
}
if (itrA == poly.begin()) {
prev = poly.end()-1;
} else {
prev = itrA-1;
}
Point3d::GetVec(refPts.at(conn.i), refPts.at(*next), vA);
Point3d::GetVec(refPts.at(conn.i), refPts.at(*prev), vB);
ang = GetAngle(vA, vB, n);
phi = GetAngle(vA, w, n);
if (phi < ang) {
break;
}
++itrA;
}
}
if (itrA == poly.end()) {
continue;
}
std::rotate(poly.begin(), itrA, poly.end());
if (endPts.count(refPts.at(conn.j)) == 0) {
itrB = std::find(poly.begin(), poly.end(), conn.j);
} else {
Point3d::GetVec(refPts.at(conn.j), refPts.at(conn.i), w);
itrB = poly.begin();
while ((itrB = std::find(itrB, poly.end(), conn.j)) != poly.end()) {
next = itrB+1;
if (next == poly.end()) {
next = poly.begin();
}
if (itrB == poly.begin()) {
prev = poly.end()-1;
} else {
prev = itrB-1;
}
Point3d::GetVec(refPts.at(conn.j), refPts.at(*next), vA);
Point3d::GetVec(refPts.at(conn.j), refPts.at(*prev), vB);
ang = GetAngle(vA, vB, n);
phi = GetAngle(vA, w, n);
if (phi < ang) {
break;
}
++itrB;
}
}
if (itrB == poly.end()) {
continue;
}
IndexedPoly newPolyA(poly.begin(), itrB+1);
IndexedPoly newPolyB(itrB, poly.end());
newPolyB.push_back(poly.front());
splitted.erase(itr);
splitted.push_back(std::move(newPolyA));
splitted.push_back(std::move(newPolyB));
endPts.emplace(refPts.at(conn.i));
endPts.emplace(refPts.at(conn.j));
break;
}
}
}
================================================
FILE: Merger.h
================================================
/*
Copyright 2012-2025 Ronald Römer
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __Merger_h
#define __Merger_h
#include "vtkPolyDataBooleanFilter.h"
typedef std::vector<std::size_t> GroupType;
typedef std::map<vtkIdType, std::size_t> SourcesType;
class Conn {
public:
Conn () = delete;
Conn (double d, vtkIdType i, vtkIdType j) : d(d), i(i), j(j) {}
double d;
vtkIdType i, j;
bool operator< (const Conn &other) const {
return d < other.d;
}
friend std::ostream& operator<< (std::ostream &out, const Conn &c) {
out << "Conn(d=" << c.d
<< ", i=" << c.i
<< ", j=" << c.j
<< ")";
return out;
}
};
struct ConnCmp {
bool operator() (const Conn &a, const Conn &b) const {
return std::tie(a.i, a.j) < std::tie(b.i, b.j);
}
};
typedef std::vector<Conn> ConnsType;
typedef std::map<std::size_t, ConnsType> PolyConnsType;
typedef std::set<Conn, ConnCmp> ConnsType2;
inline std::ostream& operator<< (std::ostream &out, const PolyConnsType& polyConns) {
PolyConnsType::const_iterator itr;
for (itr = polyConns.begin(); itr != polyConns.end(); ++itr) {
out << itr->first << ": [";
for (auto &conn : itr->second) {
out << conn << ", ";
}
out << "]" << std::endl;
}
return out;
}
class Prio {
public:
Prio () = delete;
Prio (const Conn &conn, const std::set<std::size_t> &solvable, double d) : conn(conn), solvable(solvable), d(d) {}
Conn conn;
std::set<std::size_t> solvable;
double d;
friend std::ostream& operator<< (std::ostream &out, const Prio &p) {
out << "Prio(conn=" << p.conn
<< ", d=" << p.d
<< ")";
return out;
}
};
struct Cmp {
bool operator() (const Prio &a, const Prio &b) const {
const auto _a = a.solvable.size(),
_b = b.solvable.size();
return std::tie(_a, a.d) < std::tie(_b, b.d);
}
};
typedef std::set<Prio, Cmp> PriosType;
typedef std::map<std::size_t, Prio> PolyPriosType;
class Merger {
vtkPolyData *pd;
const PStrips &pStrips;
vtkIdType origId;
PolysType polys;
std::vector<std::size_t> innerIds;
public:
Merger () = delete;
Merger (vtkPolyData *pd, const PStrips &pStrips, const StripsType &strips, const IdsType &descIds, vtkIdType origId);
void Run ();
private:
void MergeGroup (const GroupType &group, PolysType &merged);
bool FindConns (vtkPolyData *lines, vtkSmartPointer<vtkKdTree> kdTree, vtkSmartPointer<vtkModifiedBSPTree> bspTree, PolyConnsType &polyConns, const IndexedPolysType &indexedPolys, const SourcesType &sources, int &n);
void MergeStage1 (const IndexedPolysType &indexedPolys, const ReferencedPointsType &refPts, const SourcesType &sources, const ConnsType &conns, IndexedPoly &polyA);
void MergeStage2 (const ConnsType2 &conns, const ReferencedPointsType &refPts, const ConnsType2 &usedConns, IndexedPolysType &splitted);
};
#endif
================================================
FILE: Optimize.cxx
================================================
/*
Copyright 2012-2025 Ronald Römer
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "Optimize.h"
#include <vtkCellArrayIterator.h>
#include <vtkModifiedBSPTree.h>
#include <vtkCellData.h>
#include <vtkPolygon.h>
#include <vtkSmartPointer.h>
// #define _DEBUG
PreventEqualCaptPoints::PreventEqualCaptPoints (vtkPolyData *pdA, vtkPolyData *pdB) : pdA(pdA), pdB(pdB) {}
void PreventEqualCaptPoints::Run () {
#ifdef _DEBUG
WriteVTK("captA.vtk", pdA);
WriteVTK("captB.vtk", pdB);
#endif
pdA->BuildLinks();
pdB->BuildLinks();
Find(pdA, pdB, "A");
#ifdef _DEBUG
WriteVTK("modB.vtk", pdB);
#endif
Find(pdB, pdA, "B");
#ifdef _DEBUG
WriteVTK("modA.vtk", pdA);
#endif
}
void PreventEqualCaptPoints::Find (vtkPolyData *pd, vtkPolyData *other, [[maybe_unused]] const std::string &name) {
#ifdef _DEBUG
std::cout << "Find(" << name << ")" << std::endl;
#endif
vtkIdType num;
const vtkIdType *poly;
vtkIdType i, j;
std::set<Pair> lines;
auto polyItr = vtk::TakeSmartPointer(pd->GetPolys()->NewIterator());
for (polyItr->GoToFirstCell(); !polyItr->IsDoneWithTraversal(); polyItr->GoToNextCell()) {
polyItr->GetCurrentCell(num, poly);
for (i = 0; i < num; i++) {
j = i+1;
if (j == num) {
j = 0;
}
if (poly[i] < poly[j]) {
lines.emplace(poly[i], poly[j]);
} else {
lines.emplace(poly[j], poly[i]);
}
}
}
auto tree = vtkSmartPointer<vtkModifiedBSPTree>::New();
tree->SetDataSet(other);
tree->BuildLocator();
auto pts = vtkSmartPointer<vtkPoints>::New();
pts->SetDataTypeToDouble();
auto cells = vtkSmartPointer<vtkIdList>::New();
double pA[3], pB[3];
vtkIdType cellId;
double tr[2];
#ifdef _DEBUG
auto pdVerts = vtkSmartPointer<vtkPolyData>::New();
pdVerts->Allocate(1);
auto ptsVerts = vtkSmartPointer<vtkPoints>::New();
ptsVerts->SetDataTypeToDouble();
#endif
std::map<vtkIdType, std::vector<SnapPoint>> pointSnaps;
std::map<Point3d, std::vector<SnapEdge>> edgeSnaps;
for (auto &line : lines) {
pd->GetPoint(line.f, pA);
pd->GetPoint(line.g, pB);
if (tree->IntersectWithLine(pA, pB, 1e-5, pts, cells) == 0) {
continue;
}
for (i = 0; i < pts->GetNumberOfPoints(); i++) {
const double *pt = pts->GetPoint(i);
Point3d sA(pt[0], pt[1], pt[2]);
cellId = cells->GetId(i);
other->GetCellPoints(cellId, num, poly);
Base base(other->GetPoints(), num, poly);
Poly polyA, polyB;
GetPoly(other->GetPoints(), num, poly, polyA);
FlattenPoly(polyA, polyB, base);
Transform(pt, tr, base);
Point3d sB(tr[0], tr[1], 0);
if (PointInPoly(polyB, sB)) {
#ifdef _DEBUG
auto vert = vtkSmartPointer<vtkIdList>::New();
vert->InsertNextId(ptsVerts->InsertNextPoint(pt));
pdVerts->InsertNextCell(VTK_VERTEX, vert);
#endif
// snap auf ecke oder kante?
auto snap = std::find_if(polyA.begin(), polyA.end(), [&](const Point3d &p) { return Point3d::GetDist(p, sA) < 1e-10; });
if (snap != polyA.end()) {
double d = Point3d::GetDist(*snap, sA);
pointSnaps[snap->id].emplace_back(cellId, line, *snap, sA, d);
} else {
// projektion auf kante
auto edgeProj = GetEdgeProj(polyA, sA);
if (edgeProj != nullptr) {
edgeSnaps[edgeProj->proj].emplace_back(cellId, line, edgeProj->edge, edgeProj->proj, sA, edgeProj->d);
}
}
}
}
}
for (const auto& [id, snaps] : pointSnaps) {
if (snaps.size() > 1) {
#ifdef _DEBUG
std::cout << "id " << id << ", snaps" << std::endl;
for (const auto &s : snaps) {
std::cout << s << std::endl;
}
#endif
std::set<Pair> allLines;
std::transform(snaps.begin(), snaps.end(), std::inserter(allLines, allLines.end()), [](const SnapPoint &p) { return p.line; });
#ifdef _DEBUG
std::cout << "allLines" << std::endl;
for (const auto &line : allLines) {
std::cout << line << std::endl;
}
#endif
auto itrA = snaps.begin();
decltype(itrA) itrB;
double d;
bool collapse = true;
for (; itrA != snaps.end()-1 && collapse; ++itrA) {
for (itrB = itrA+1; itrB < snaps.end(); ++itrB) {
d = Point3d::GetDist(itrA->inter, itrB->inter);
#ifdef _DEBUG
std::cout << d << std::endl;
#endif
if (d > 1e-10) {
collapse = false;
break;
}
}
}
if (collapse) {
continue;
}
if (allLines.size() == 1) {
std::shared_ptr<Point3d> proj;
ProjOnLine(pd, snaps.back().line, snaps.back().point, proj);
PreventEqualCaptPoints::MovePoint(other, id, *proj);
} else {
// gemeinsamen punkt ermitteln
std::set<vtkIdType> allIds;
for (auto &line : allLines) {
allIds.insert(line.f);
allIds.insert(line.g);
}
if (allIds.size() == allLines.size()+1) {
std::vector<Pair> _allLines(allLines.begin(), allLines.end());
vtkIdType s = _allLines[0] & _allLines[1];
#ifdef _DEBUG
std::cout << "line "
<< _allLines[0]
<< " & "
<< _allLines[1]
<< " -> "
<< s
<< std::endl;
#endif
double pt[3];
pd->GetPoint(s, pt);
Point3d p(pt[0], pt[1], pt[2]);
PreventEqualCaptPoints::MovePoint(other, id, p);
} else {
throw std::runtime_error("");
}
}
}
}
using Snap = std::tuple<SnapEdge, Point3d, double>;
struct Cmp {
bool operator() (const Snap &l, const Snap &r) const {
return std::get<2>(l) < std::get<2>(r);
}
};
std::map<Pair, std::set<Snap, Cmp>> allEdgeSnaps;
double pt[3], t;
for (const auto& [proj, snaps] : edgeSnaps) {
if (snaps.size() > 1) {
if (snaps.size() > 2) {
#ifdef _DEBUG
std::cout << proj << std::endl;
for (const auto &s : snaps) {
std::cout << s << std::endl;
auto &line = s.line;
pd->GetPoint(line.f, pA);
pd->GetPoint(line.g, pB);
std::cout << Point3d(pA[0], pA[1], pA[2]) << std::endl;
std::cout << Point3d(pB[0], pB[1], pB[2]) << std::endl;
}
#endif
continue;
}
const auto &snapA = snaps[0];
const auto &snapB = snaps[1];
{
Pair edge(snapA.edge);
if (edge.f > edge.g) {
std::swap(edge.f, edge.g);
}
std::shared_ptr<Point3d> p;
if (snapA.line == snapB.line) {
ProjOnLine(pd, snapA.line, snapA.proj, p);
} else {
vtkIdType s = snapA.line & snapB.line;
pd->GetPoint(s, pt);
p = std::make_shared<Point3d>(pt[0], pt[1], pt[2]);
}
other->GetPoint(edge.f, pt);
Point3d q(pt[0], pt[1], pt[2]);
t = Point3d::GetDist(q, snapA.proj);
allEdgeSnaps[edge].emplace(snapA, *p, t);
}
}
}
std::map<vtkIdType, Edges> newCells;
for (const auto& [edge, data] : allEdgeSnaps) {
Points pts;
for (const auto &d : data) {
const auto &p = std::get<1>(d);
pts.emplace_back(p.x, p.y, p.z, other->GetPoints()->InsertNextPoint(p.x, p.y, p.z));
}
const auto &first = std::get<0>(*(data.begin()));
auto neigs = vtkSmartPointer<vtkIdList>::New();
other->GetCellEdgeNeighbors(first.cellId, first.edge.f, first.edge.g, neigs);
if (neigs->GetNumberOfIds() != 1) {
throw std::runtime_error("");
}
vtkIdType neig = neigs->GetId(0);
auto _edge = Pair(first.edge.g, first.edge.f);
if (edge == first.edge) {
std::for_each(pts.begin(), pts.end(), [&](const Point3d &p) { newCells[first.cellId][first.edge].emplace_back(p); });
std::for_each(pts.rbegin(), pts.rend(), [&](const Point3d &p) { newCells[neig][_edge].emplace_back(p); });
} else {
std::for_each(pts.rbegin(), pts.rend(), [&](const Point3d &p) { newCells[first.cellId][first.edge].emplace_back(p); });
std::for_each(pts.begin(), pts.end(), [&](const Point3d &p) { newCells[neig][_edge].emplace_back(p); });
}
}
for (const auto& [cellId, edges] : newCells) {
PreventEqualCaptPoints::TriangulateCell(other, cellId, edges);
other->DeleteCell(cellId);
}
other->RemoveDeletedCells();
#ifdef _DEBUG
pdVerts->SetPoints(ptsVerts);
auto fileName = "verts" + name + ".vtk";
WriteVTK(fileName.c_str(), pdVerts);
#endif
}
IdsType PreventEqualCaptPoints::TriangulateCell (vtkPolyData *pd, vtkIdType cellId, const Edges &edges) {
vtkIdTypeArray *origCellIds = vtkIdTypeArray::SafeDownCast(pd->GetCellData()->GetScalars("OrigCellIds"));
IdsType newCellIds;
vtkIdType num;
const vtkIdType *poly;
pd->GetCellPoints(cellId, num, poly);
Poly _poly;
double pt[3];
vtkIdType i, j;
vtkIdType newNum = num;
for (i = 0; i < num; i++) {
j = i+1;
if (j == num) {
j = 0;
}
pd->GetPoint(poly[i], pt);
_poly.emplace_back(pt[0], pt[1], pt[2], poly[i]);
Pair edge(poly[i], poly[j]);
auto itr = edges.find(edge);
if (itr != edges.end()) {
auto &pts = itr->second;
for (const auto &p : pts) {
_poly.emplace_back(p);
newNum++;
}
}
}
auto vtkPoly = vtkSmartPointer<vtkPolygon>::New();
vtkPoly->GetPointIds()->SetNumberOfIds(newNum);
vtkPoly->GetPoints()->SetNumberOfPoints(newNum);
Base base(pd->GetPoints(), num, poly);
Poly flattened;
FlattenPoly(_poly, flattened, base);
for (const auto &p : flattened) {
vtkPoly->GetPointIds()->SetId(p.id, p.id);
vtkPoly->GetPoints()->SetPoint(p.id, p.x, p.y, p.z);
}
auto triangles = vtkSmartPointer<vtkIdList>::New();
#if (VTK_MAJOR_VERSION >= 9 && VTK_MINOR_VERSION > 3)
if (vtkPoly->TriangulateLocalIds(0, triangles) != 1) {
throw std::runtime_error("");
}
#else
if (vtkPoly->Triangulate(triangles) != 1) {
throw std::runtime_error("");
}
#endif
auto ids = vtkSmartPointer<vtkIdList>::New();
for (const auto &p : _poly) {
ids->InsertNextId(p.id);
}
double pA[3], pB[3], pC[3];
for (i = 0; i < triangles->GetNumberOfIds(); i += 3) {
pd->GetPoint(ids->GetId(triangles->GetId(i)), pA);
pd->GetPoint(ids->GetId(triangles->GetId(i+1)), pB);
pd->GetPoint(ids->GetId(triangles->GetId(i+2)), pC);
Poly p = { {pA[0], pA[1], pA[2]}, {pB[0], pB[1], pB[2]}, {pC[0], pC[1], pC[2]} };
double quality = GetTriangleQuality(p);
if (quality < 0.001) {
throw std::runtime_error("");
}
}
vtkIdType origId = origCellIds->GetValue(cellId);
auto triangle = vtkSmartPointer<vtkIdList>::New();
triangle->SetNumberOfIds(3);
for (i = 0; i < triangles->GetNumberOfIds(); i += 3) {
triangle->SetId(0, ids->GetId(triangles->GetId(i)));
triangle->SetId(1, ids->GetId(triangles->GetId(i+1)));
triangle->SetId(2, ids->GetId(triangles->GetId(i+2)));
newCellIds.push_back(pd->InsertNextCell(VTK_TRIANGLE, triangle));
origCellIds->InsertNextValue(origId);
}
return newCellIds;
}
void PreventEqualCaptPoints::MovePoint (vtkPolyData *pd, vtkIdType ind, const Point3d &p) {
auto cells = vtkSmartPointer<vtkIdList>::New();
pd->GetPointCells(ind, cells);
vtkIdType i, cellId;
for (i = 0; i < cells->GetNumberOfIds(); i++) {
cellId = cells->GetId(i);
if (pd->GetCellType(cellId) == VTK_POLYGON) {
PreventEqualCaptPoints::TriangulateCell(pd, cellId, {});
pd->DeleteCell(cellId);
}
}
#ifdef _DEBUG
double pt[3];
pd->GetPoints()->GetPoint(ind, pt);
Point3d q(pt[0], pt[1], pt[2]);
std::cout << q
<< " -> "
<< p
<< std::endl;
#endif
pd->GetPoints()->SetPoint(ind, p.x, p.y, p.z);
}
================================================
FILE: Optimize.h
================================================
/*
Copyright 2012-2025 Ronald Römer
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __Optimize_h
#define __Optimize_h
#include "Utilities.h"
typedef std::map<Pair, Points> Edges;
class SnapPoint {
public:
SnapPoint () = delete;
SnapPoint (vtkIdType cellId, const Pair &line, const Point3d &point, const Point3d &inter, double d) : cellId(cellId), line(line), point(point), inter(inter), d(d) {}
vtkIdType cellId;
Pair line;
Point3d point;
Point3d inter;
double d;
friend std::ostream& operator<< (std::ostream &out, const SnapPoint &s) {
out << "cellId " << s.cellId
<< ", line " << s.line
<< ", point " << s.point
<< ", inter " << s.inter
<< ", d " << s.d;
return out;
}
};
class SnapEdge {
public:
SnapEdge () = delete;
SnapEdge (vtkIdType cellId, const Pair &line, const Pair &edge, const Point3d &proj, const Point3d &inter, double d) : cellId(cellId), line(line), edge(edge), proj(proj), inter(inter), d(d) {}
vtkIdType cellId;
Pair line;
Pair edge;
Point3d proj;
Point3d inter;
double d;
friend std::ostream& operator<< (std::ostream &out, const SnapEdge &s) {
out << "cellId " << s.cellId
<< ", line " << s.line
<< ", edge " << s.edge
<< ", proj " << s.proj
<< ", inter " << s.inter
<< ", d " << s.d;
return out;
}
};
class PreventEqualCaptPoints {
vtkPolyData *pdA, *pdB;
public:
static IdsType TriangulateCell (vtkPolyData *pd, vtkIdType cellId, const Edges &edges);
static void MovePoint (vtkPolyData *pd, vtkIdType ind, const Point3d &p);
PreventEqualCaptPoints () = delete;
PreventEqualCaptPoints (vtkPolyData *pdA, vtkPolyData *pdB);
void Run ();
private:
void Find (vtkPolyData *pd, vtkPolyData *other, const std::string &name);
};
#endif
================================================
FILE: README.md
================================================
# vtkbool [](https://github.com/zippy84/vtkbool/actions/workflows/cmake.yml) [](https://codecov.io/gh/zippy84/vtkbool) [](https://zenodo.org/doi/10.5281/zenodo.10461186)
## About
This is an extension of the graphics library VTK. The goal of the extension is to equip the library with rebust boolean operations on polygonal meshes. I started the project at the end of my studies in mechanical engineering at the University of Applied Sciences ([HTWK](http://htwk-leipzig.de/)) in Leipzig. I used VTK to develop a program, which I had to create for a paper. At this time I would have wished, that this feature already exists. There was several implementations from third parties, but after some tests, I came to the conclusion, that none of them worked correct. I decided to start with my own implementation. This library is the result of my efforts.
## Features
- based on VTK
- 4 operation types available (union, intersection, difference and difference2 - difference with interchanged operands)
- triangulation is not needed
- all types of polygonal cells are supported (triangles, quads, polygons, triangle-strips)
- triangle-strips and quads will be transformed into triangles (quads only if their points are not on the same plane)
- non-convex polygons are allowed
- meshes can be stacked (coplanar polygons are right handled)
- the meshes don’t need to be watertight
- CellData is passed (attached by the rules of vtkAppendPolyData)
- contact-lines are available in the 3th output
- the filter is able to embed holes
- compileable as ParaView plugin
- Python wrapped
## Limitations
- the filter assumes well defined triangles, quads and polygons
- PointData is not preserved - you have to do your own mapping with *OrigCellIdsA* and *OrigCellIdsB*
## Requirements
- CMake >= 3.12
- VTK >= 9.0
- C++17 compiler
### Optional
- ParaView >= 5.0
- Python 3.x
## Library
To include vtkbool into your program, you have to compile it as a library. All you need is an installation of VTK with header files. If you have installed VTK over your package manager, CMake is able to find the required files. Otherwise you have to set **VTK\_DIR** manually. It must be a path like */home/zippy/VTK9/lib/cmake/vtk-9.1* or *C:/Users/zippy/VTK9/lib/cmake/vtk-9.1*.
The usage of the library is very simple. Look at the example in the section below. You can set the operation mode by calling one of the named methods:
- `SetOperModeToNone`
- `SetOperModeToUnion`
- `SetOperModeToIntersection`
- `SetOperModeToDifference`
- `SetOperModeToDifference2`
The alternative is the more generic `SetOperMode`. The method must be called with the number of the desired operation, an integer between 0 and 4, with the same meaning as mentioned before. The default is Union.
### C++ Example
Create a directory somewhere in your file system, download vtkbool and unpack it into that.
```
mkdir example
cd example
git clone https://github.com/zippy84/vtkbool.git
```
Then create the following two files:
**test.cxx**
```C++
#include <vtkSmartPointer.h>
#include <vtkCubeSource.h>
#include <vtkCylinderSource.h>
#include <vtkPolyDataWriter.h>
#include "vtkPolyDataBooleanFilter.h"
int main (int argc, char *argv[]) {
auto cube = vtkSmartPointer<vtkCubeSource>::New();
cube->SetYLength(.5);
auto cyl = vtkSmartPointer<vtkCylinderSource>::New();
cyl->SetResolution(32);
cyl->SetHeight(.5);
cyl->SetCenter(0, .5, 0);
auto bf = vtkSmartPointer<vtkPolyDataBooleanFilter>::New();
bf->SetInputConnection(0, cube->GetOutputPort());
bf->SetInputConnection(1, cyl->GetOutputPort());
bf->SetOperModeToDifference();
auto writer = vtkSmartPointer<vtkPolyDataWriter>::New();
writer->SetInputConnection(bf->GetOutputPort());
writer->SetFileName("result.vtk");
writer->Update();
return 0;
}
```
**CMakeLists.txt**
```CMake
cmake_minimum_required(VERSION 3.12 FATAL_ERROR)
project(test)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# find_package(VTK REQUIRED COMPONENTS FiltersSources IOLegacy)
find_package(VTK REQUIRED COMPONENTS FiltersSources IOLegacy FiltersExtraction FiltersGeometry FiltersModeling FiltersFlowPaths WrappingPythonCore)
if(VTK_FOUND)
include_directories(vtkbool)
add_subdirectory(vtkbool)
add_executable(test test.cxx)
target_link_libraries(test PRIVATE vtkbool ${VTK_LIBRARIES})
vtk_module_autoinit(
TARGETS test
MODULES ${VTK_LIBRARIES}
)
endif(VTK_FOUND)
```
Inside the `example` directory, create a subdirectory called `build` and `cd` into it. You should have a directory structure that looks something like this:
```
example
├── build
├── CMakeLists.txt
├── test.cxx
└── vtkbool
├── CMakeLists.txt
├── ...
└── vtkPolyDataBooleanFilter.h
```
From inside the `build` directory, run `ccmake ..`, follow the instructions, and finally type `make`.
Running `./test` will now produce the `result.vtk` file.
## ParaView Plugin
To build the plugin you have to compile ParaView from source. Download the current version from <http://www.paraview.org> and follow the compilation instructions. As soon as ParaView is compiled, it may take a while, you can build the plugin by activating the **VTKBOOL_PARAVIEW** option within CMake. In CMake you also have to point to **ParaView_DIR** if CMake can't found it and it is not installed in a common location like */usr/lib* or */usr/local/lib*. Make sure **PARAVIEW_INSTALL_DEVELOPMENT_FILES** is set.
When everything has been compiled successfully, you can install the plugin.
## Python
The Python module will be generated automatically, if three conditions are met:
- vtkbool is configured as a library
- Python 3 is installed with header files
- VTK itself is wrapped to Python
After a successful compilation, the module can be used as follows:
```python
#!/usr/bin/env python
import sys
sys.path.append('/path/to/your/build/directory') # also look into the python files in the testing directory
from vtkmodules.vtkFiltersSources import vtkCubeSource, vtkSphereSource
from vtkmodules.vtkIOLegacy import vtkPolyDataWriter
from vtkbool import vtkPolyDataBooleanFilter
cube = vtkCubeSource()
sphere = vtkSphereSource()
sphere.SetCenter(.5, .5, .5)
sphere.SetThetaResolution(20)
sphere.SetPhiResolution(20)
bf = vtkPolyDataBooleanFilter()
bf.SetInputConnection(0, cube.GetOutputPort())
bf.SetInputConnection(1, sphere.GetOutputPort())
bf.SetOperModeToDifference()
# write the result, if you want ...
writer = vtkPolyDataWriter()
writer.SetInputConnection(bf.GetOutputPort())
writer.SetFileName('result.vtk')
writer.Update()
```
Or with VTK >= 9.4:
```python
#!/usr/bin/env python
import sys
sys.path.append('/path/to/your/build/directory')
from vtkmodules.vtkFiltersSources import vtkCubeSource, vtkSphereSource
from vtkmodules.vtkIOLegacy import vtkPolyDataWriter
from vtkmodules.util.execution_model import select_ports
from vtkbool import vtkPolyDataBooleanFilter, OPER_DIFFERENCE
cube = vtkCubeSource()
sphere = vtkSphereSource(center=[.5, .5, .5], theta_resolution=20, phi_resolution=20)
bf = vtkPolyDataBooleanFilter(oper_mode=OPER_DIFFERENCE)
cube >> bf
sphere >> select_ports(1, bf)
(bf >> vtkPolyDataWriter(file_name='result.vtk')).update()
```
## Conda
The library is also available at [conda-forge](https://anaconda.org/conda-forge/vtkbool). In your virtual environment you can install the package with:
```
conda install -c conda-forge vtkbool
```
Unlike in the python example, you need to import it like this:
```python
from vtkbool.vtkbool import vtkPolyDataBooleanFilter
```
## Errors and their meaning
- *Contact failed with ...*
- *Found invalid intersection points.*
This problem occurs when an intersection point is located on congruent edges of a self-intersecting polygon.
- *Intersection points do not lie on the edges (cells a, b).*
At least one intersection point does not lie on the boundary of the intersected polygon. The points of the polygon do not lie on a plane. The polygon is degenerated.
- *Intersection goes through non-manifold edges.*
Non-manifold edges are generally not a problem. Unless they are part of the intersection.
- *Cannot prevent equal capture points.*
A capture point is the projection of a point onto one of the edges of the intersected polygon. This point, not the projection, is usually used by two lines that are assigned to the two adjacent polygons, sharing this edge. There is a case where two different points have the same projection. The error occurs when the problem could not be solved.
- *There is no contact.*
What it says.
- *At least one line-end has only one neighbor.*
The intersection is incomplete. Therefore the cell cannot be divided.
- *Strips are invalid.*
There are intersection lines that intersect themselves. Either one of the inputs contains an assembly or there is one self-intersecting polygon that is involved in the intersection.
- *CutCells failed.*
Will be printed out only, if some holes couldn't be merged into their outer polygons.
- *Boolean operation failed.*
A boolean operation can fail at the end, if some of the intersection lines are not part of the result.
## Copyright
2012-2025 Ronald Römer
## License
Apache License, Version 2.0
================================================
FILE: Utilities.cxx
================================================
/*
Copyright 2012-2025 Ronald Römer
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "Utilities.h"
#include <cmath>
#include <vtkPoints.h>
#include <vtkIdList.h>
#include <vtkMath.h>
#include <vtkPolyData.h>
#include <vtkDataWriter.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataWriter.h>
double ComputeNormal (vtkPoints *pts, double *n, vtkIdType num, const vtkIdType *poly) {
n[0] = 0; n[1] = 0; n[2] = 0;
double pA[3], pB[3];
vtkIdType i, a, b;
for (i = 0; i < num; i++) {
a = poly[i];
b = poly[i+1 == num ? 0 : i+1];
pts->GetPoint(a, pA);
pts->GetPoint(b, pB);
n[0] += (pA[1]-pB[1])*(pA[2]+pB[2]);
n[1] += (pA[2]-pB[2])*(pA[0]+pB[0]);
n[2] += (pA[0]-pB[0])*(pA[1]+pB[1]);
}
return vtkMath::Normalize(n);
}
void FindPoints (vtkKdTreePointLocator *pl, const double *pt, vtkIdList *pts, double tol) {
pts->Reset();
vtkPolyData *pd = vtkPolyData::SafeDownCast(pl->GetDataSet());
vtkIdList *closest = vtkIdList::New();
pl->FindPointsWithinRadius(std::max(1e-3, tol), pt, closest);
vtkIdType i, numPts = closest->GetNumberOfIds();
double c[3], v[3];
for (i = 0; i < numPts; i++) {
pd->GetPoint(closest->GetId(i), c);
vtkMath::Subtract(pt, c, v);
if (vtkMath::Norm(v) < tol) {
pts->InsertNextId(closest->GetId(i));
}
}
closest->Delete();
}
#ifdef DEBUG
void WriteVTK (const char *name, vtkPolyData *pd) {
std::cout << "Writing " << name << std::endl;
vtkPolyDataWriter *w = vtkPolyDataWriter::New();
w->SetInputData(pd);
w->SetFileName(name);
w->Update();
w->Delete();
}
#endif
double GetAngle (const double *vA, const double *vB, const double *n) {
// http://math.stackexchange.com/questions/878785/how-to-find-an-angle-in-range0-360-between-2-vectors
double _vA[3];
vtkMath::Cross(n, vA, _vA);
double ang = std::atan2(vtkMath::Dot(_vA, vB), vtkMath::Dot(vA, vB));
if (ang < 0) {
ang += 2*M_PI;
}
return ang;
}
Base::Base (vtkPoints *pts, vtkIdType num, const vtkIdType *poly) {
ComputeNormal(pts, n, num, poly);
double ptA[3],
ptB[3];
pts->GetPoint(poly[0], ptA);
pts->GetPoint(poly[1], ptB);
ei[0] = ptB[0]-ptA[0];
ei[1] = ptB[1]-ptA[1];
ei[2] = ptB[2]-ptA[2];
vtkMath::Normalize(ei);
ej[0] = n[1]*ei[2]-n[2]*ei[1];
ej[1] = -n[0]*ei[2]+n[2]*ei[0];
ej[2] = n[0]*ei[1]-n[1]*ei[0];
vtkMath::Normalize(ej);
d = n[0]*ptA[0]+n[1]*ptA[1]+n[2]*ptA[2];
}
void Transform (const double *in, double *out, const Base &base) {
double x = base.ei[0]*in[0]+base.ei[1]*in[1]+base.ei[2]*in[2],
y = base.ej[0]*in[0]+base.ej[1]*in[1]+base.ej[2]*in[2];
out[0] = x;
out[1] = y;
}
/*void BackTransform (const double *in, double *out, const Base &base) {
double x = in[0]*base.ei[0]+in[1]*base.ej[0]+base.d*base.n[0],
y = in[0]*base.ei[1]+in[1]*base.ej[1]+base.d*base.n[1],
z = in[0]*base.ei[2]+in[1]*base.ej[2]+base.d*base.n[2];
out[0] = x;
out[1] = y;
out[2] = z;
}*/
double ComputeNormal (const Poly &poly, double *n) {
n[0] = 0; n[1] = 0; n[2] = 0;
Poly::const_iterator itrA, itrB;
for (itrA = poly.begin(); itrA != poly.end(); ++itrA) {
itrB = itrA+1;
if (itrB == poly.end()) {
itrB = poly.begin();
}
const Point3d &ptA = *itrA,
&ptB = *itrB;
n[0] += (ptA.y-ptB.y)*(ptA.z+ptB.z);
n[1] += (ptA.z-ptB.z)*(ptA.x+ptB.x);
n[2] += (ptA.x-ptB.x)*(ptA.y+ptB.y);
}
return vtkMath::Normalize(n);
}
bool PointInPoly (const Poly &poly, const Point3d &p) {
bool in = false;
Poly::const_iterator itrA, itrB;
for (itrA = poly.begin(); itrA != poly.end(); ++itrA) {
itrB = itrA+1;
if (itrB == poly.end()) {
itrB = poly.begin();
}
const Point3d &ptA = *itrA,
&ptB = *itrB;
if ((ptA.x <= p.x || ptB.x <= p.x)
&& ((ptA.y < p.y && ptB.y >= p.y)
|| (ptB.y < p.y && ptA.y >= p.y))) {
// schnittpunkt mit bounding box und strahlensatz
if (ptA.x+(p.y-ptA.y)*(ptB.x-ptA.x)/(ptB.y-ptA.y) < p.x) {
in = !in;
}
}
}
return in;
}
#ifdef DEBUG
void WritePolys (const char *name, const PolysType &polys) {
auto pts = vtkSmartPointer<vtkPoints>::New();
pts->SetDataTypeToDouble();
auto pd = vtkSmartPointer<vtkPolyData>::New();
pd->SetPoints(pts);
pd->Allocate(1);
for (auto &poly : polys) {
auto cell = vtkSmartPointer<vtkIdList>::New();
for (auto &p : poly) {
cell->InsertNextId(pts->InsertNextPoint(p.x, p.y, p.z));
}
pd->InsertNextCell(VTK_POLYGON, cell);
}
WriteVTK(name, pd);
}
#endif
void GetPolys (const ReferencedPointsType &pts, const IndexedPolysType &indexedPolys, PolysType &polys) {
for (const auto &poly : indexedPolys) {
Poly newPoly;
for (auto &id : poly) {
newPoly.push_back(pts.at(id));
}
polys.push_back(std::move(newPoly));
}
}
void GetPoly (vtkPoints *pts, vtkIdType num, const vtkIdType *poly, Poly &out) {
vtkIdType i;
double p[3];
for (i = 0; i < num; i++) {
pts->GetPoint(poly[i], p);
out.emplace_back(p[0], p[1], p[2], poly[i]);
}
}
void FlattenPoly (const Poly &poly, Poly &out, const Base &base) {
double pt[3], tr[2];
vtkIdType i = 0;
for (auto &p : poly) {
pt[0] = p.x;
pt[1] = p.y;
pt[2] = p.z;
Transform(pt, tr, base);
out.emplace_back(tr[0], tr[1], 0, i++);
}
}
void FlattenPoly2 (const Poly &poly, Poly &out, const Base2 &base) {
double pt[3], tr[3];
for (auto &p : poly) {
pt[0] = p.x;
pt[1] = p.y;
pt[2] = p.z;
base.Transform(pt, tr);
out.emplace_back(tr[0], tr[1], tr[2], p.id);
}
}
std::shared_ptr<Proj> GetEdgeProj (const Poly &poly, const Point3d &p) {
Poly::const_iterator itrA, itrB;
double d, t;
std::shared_ptr<Point3d> proj;
for (itrA = poly.begin(); itrA != poly.end(); ++itrA) {
itrB = itrA+1;
if (itrB == poly.end()) {
itrB = poly.begin();
}
ProjOnLine(*itrA, *itrB, p, &d, &t, proj);
if (d > 0 && d < 1e-5 && t > 0 && t < 1) {
return std::make_shared<Proj>(itrA->id, itrB->id, *proj, d);
}
}
return nullptr;
}
void ProjOnLine (const Point3d &a, const Point3d &b, const Point3d &p, double *d, double *t, std::shared_ptr<Point3d> &proj) {
double v[3], w[3];
double v_ = Point3d::GetVec(a, b, v);
double w_ = Point3d::GetVec(a, p, w);
double pr = std::min(std::max(vtkMath::Dot(v, w), -1.), 1.);
*d = std::sin(std::acos(pr))*w_;
vtkMath::MultiplyScalar(v, std::sqrt(w_*w_-*d**d));
proj = std::make_shared<Point3d>(a.x+v[0], a.y+v[1], a.z+v[2]);
*t = pr*w_/v_;
}
void ProjOnLine (vtkPolyData *pd, const Pair &line, const Point3d &p, std::shared_ptr<Point3d> &proj) {
double pA[3], pB[3];
pd->GetPoint(line.f, pA);
pd->GetPoint(line.g, pB);
Point3d a(pA[0], pA[1], pA[2]);
Point3d b(pB[0], pB[1], pB[2]);
double d, t;
ProjOnLine(a, b, p, &d, &t, proj);
}
vtkSmartPointer<vtkPolyData> CreatePolyData (const PolysType &polys) {
auto pts = vtkSmartPointer<vtkPoints>::New();
pts->SetDataTypeToDouble();
auto pd = vtkSmartPointer<vtkPolyData>::New();
pd->SetPoints(pts);
pd->Allocate(100);
for (const auto &poly : polys) {
auto cell = vtkSmartPointer<vtkIdList>::New();
for (const auto &p : poly) {
cell->InsertNextId(pts->InsertNextPoint(p.x, p.y, p.z));
}
pd->InsertNextCell(VTK_POLYGON, cell);
}
pd->Squeeze();
return pd;
}
double GetTriangleQuality (const Poly &poly) {
double n[3];
double l = ComputeNormal(poly, n);
double d = 0;
Poly::const_iterator itrA, itrB;
for (itrA = poly.begin(); itrA != poly.end(); ++itrA) {
itrB = itrA+1;
if (itrB == poly.end()) {
itrB = poly.begin();
}
d += std::sqrt(Point3d::GetDist(*itrA, *itrB));
}
return 10.392304845413264*l/(d*d);
}
================================================
FILE: Utilities.h
================================================
/*
Copyright 2012-2025 Ronald Römer
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef __Utilities_h
#define __Utilities_h
#include <iostream>
#include <type_traits>
#include <functional>
#include <vector>
#include <deque>
#include <map>
#include <set>
#include <memory>
#include <vtkPolyData.h>
#include <vtkKdTreePointLocator.h>
#include <vtkPoints.h>
#include <vtkIdList.h>
#include <vtkMath.h>
#include <vtkSmartPointer.h>
#define NOTSET -1
double GetAngle (const double *vA, const double *vB, const double *n);
double ComputeNormal (vtkPoints *pts, double *n, vtkIdType num, const vtkIdType *poly);
void FindPoints (vtkKdTreePointLocator *pl, const double *pt, vtkIdList *pts, double tol = 1e-6);
#ifdef DEBUG
void WriteVTK (const char *name, vtkPolyData *pd);
#endif
class Point3d {
public:
const double x, y, z;
vtkIdType id, otherId;
Point3d () = delete;
Point3d (const double x, const double y, const double z, vtkIdType id = NOTSET, vtkIdType otherId = NOTSET) : x(x), y(y), z(z), id(id), otherId(otherId) {}
bool operator< (const Point3d &other) const {
const long x1 = std::lround(x*1e5),
y1 = std::lround(y*1e5),
z1 = std::lround(z*1e5),
x2 = std::lround(other.x*1e5),
y2 = std::lround(other.y*1e5),
z2 = std::lround(other.z*1e5);
return std::tie(x1, y1, z1) < std::tie(x2, y2, z2);
}
bool operator== (const Point3d &other) const {
return !(*this < other) && !(other < *this);
}
friend std::ostream& operator<< (std::ostream &out, const Point3d &p) {
out << "Point3d(x=" << p.x
<< ", y=" << p.y
<< ", z=" << p.z
<< ", id=" << p.id
<< ", otherId=" << p.otherId << ")";
return out;
}
static double GetVec (const Point3d &a, const Point3d &b, double *v) {
v[0] = b.x-a.x;
v[1] = b.y-a.y;
v[2] = b.z-a.z;
return vtkMath::Normalize(v);
}
static double GetDist (const Point3d &a, const Point3d &b) {
double dx = b.x-a.x;
double dy = b.y-a.y;
double dz = b.z-a.z;
return dx*dx+dy*dy+dz*dz;
}
};
typedef std::vector<vtkIdType> IdsType;
typedef std::set<vtkIdType> _IdsType;
class Pair {
public:
vtkIdType f, g;
Pair () = delete;
Pair (vtkIdType f, vtkIdType g) : f(f), g(g) {}
bool operator< (const Pair &other) const {
return std::tie(f, g) < std::tie(other.f, other.g);
}
bool operator== (const Pair &other) const {
return f == other.f && g == other.g;
}
vtkIdType operator& (const Pair &other) const {
if (f == other.f || f == other.g) {
return f;
}
return g;
}
friend std::ostream& operator<< (std::ostream &out, const Pair &p) {
out << "(" << p.f << ", " << p.g << ")";
return out;
}
};
class Base {
public:
Base () {}
Base (vtkPoints *pts, vtkIdType num, const vtkIdType *poly);
double n[3], ei[3], ej[3], d;
};
void Transform (const double *in, double *out, const Base &base);
// void BackTransform (const double *in, double *out, const Base &base);
class Base2 {
public:
Base2 () {}
Base2 (double *_t, double *_ei, double *_ek) {
std::copy_n(_t, 3, t);
std::copy_n(_ei, 3, ei);
std::copy_n(_ek, 3, ek);
ej[0] = ek[1]*ei[2]-ek[2]*ei[1];
ej[1] = -ek[0]*ei[2]+ek[2]*ei[0];
ej[2] = ek[0]*ei[1]-ek[1]*ei[0];
vtkMath::Normalize(ej);
}
void Transform (const double *in, double *out) const {
double R[][3] = {
{ ei[0], ei[1], ei[2] },
{ ej[0], ej[1], ej[2] },
{ ek[0], ek[1], ek[2] }
};
double _t[] = { in[0]-t[0], in[1]-t[1], in[2]-t[2] };
out[0] = R[0][0]*_t[0]+R[0][1]*_t[1]+R[0][2]*_t[2];
out[1] = R[1][0]*_t[0]+R[1][1]*_t[1]+R[1][2]*_t[2];
out[2] = R[2][0]*_t[0]+R[2][1]*_t[1]+R[2][2]*_t[2];
}
void BackTransform (const double *in, double *out) const {
double R[][3] = {
{ ei[0], ej[0], ek[0] },
{ ei[1], ej[1], ek[1] },
{ ei[2], ej[2], ek[2] }
};
double _out[] = {
R[0][0]*in[0]+R[0][1]*in[1]+R[0][2]*in[2],
R[1][0]*in[0]+R[1][1]*in[1]+R[1][2]*in[2],
R[2][0]*in[0]+R[2][1]*in[1]+R[2][2]*in[2]
};
out[0] = _out[0]+t[0];
out[1] = _out[1]+t[1];
out[2] = _out[2]+t[2];
}
double t[3], ei[3], ej[3], ek[3];
};
template<typename T>
std::ostream& operator<< (typename std::enable_if<std::is_enum<T>::value, std::ostream>::type& stream, const T& e) {
return stream << static_cast<typename std::underlying_type<T>::type>(e);
}
typedef std::vector<Point3d> Poly, Points;
typedef std::vector<Poly> PolysType;
double ComputeNormal (const Poly &poly, double *n);
bool PointInPoly (const Poly &poly, const Point3d &p);
#ifdef DEBUG
void WritePolys (const char *name, const PolysType &polys);
#endif
typedef std::deque<vtkIdType> IndexedPoly;
typedef std::vector<IndexedPoly> IndexedPolysType;
typedef std::map<vtkIdType, std::reference_wrapper<const Point3d>> ReferencedPointsType;
void GetPolys (const ReferencedPointsType &pts, const IndexedPolysType &indexedPolys, PolysType &polys);
void GetPoly (vtkPoints *pts, vtkIdType num, const vtkIdType *poly, Poly &out);
void FlattenPoly (const Poly &poly, Poly &out, const Base &base);
void FlattenPoly2 (const Poly &poly, Poly &out, const Base2 &base);
class Proj {
public:
Proj (vtkIdType a, vtkIdType b, const Point3d &proj, double d) : edge(a, b), proj(proj), d(d) {}
Pair edge;
Point3d proj;
double d;
};
std::shared_ptr<Proj> GetEdgeProj (const Poly &poly, const Point3d &p);
void ProjOnLine (const Point3d &a, const Point3d &b, const Point3d &p, double *d, double *t, std::shared_ptr<Point3d> &proj);
void ProjOnLine (vtkPolyData *pd, const Pair &line, const Point3d &p, std::shared_ptr<Point3d> &proj);
vtkSmartPointer<vtkPolyData> CreatePolyData (const PolysType &polys);
double GetTriangleQuality (const Poly &poly);
#endif
================================================
FILE: module/CMakeLists.txt
================================================
set(srcs
../Utilities.cxx
../Optimize.cxx
../Contact.cxx
../Merger.cxx
../vtkPolyDataBooleanFilter.cxx
)
set(headers
../vtkPolyDataBooleanFilter.h
)
vtk_module_add_module(vtkbool
SOURCES ${srcs}
HEADERS ${headers}
)
================================================
FILE: module/vtk.module
================================================
NAME
vtkbool
DEPENDS
VTK::CommonCore
VTK::CommonExecutionModel
VTK::FiltersPoints
VTK::IOLegacy
VTK::FiltersFlowPaths
TEST_DEPENDS
VTK::FiltersSources
DESCRIPTION
This module contains a class to do polydata boolean operations.
================================================
FILE: paraview/CMakeLists.txt
================================================
paraview_add_plugin(PolyDataBooleanFilter
VERSION "${vtkbool_VERSION}"
MODULES vtkbool
MODULE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/module/vtk.module")
================================================
FILE: paraview/module/CMakeLists.txt
================================================
set(srcs
../../Utilities.cxx
../../Optimize.cxx
../../Contact.cxx
../../Merger.cxx
../../vtkPolyDataBooleanFilter.cxx
)
set(headers
../../vtkPolyDataBooleanFilter.h
)
vtk_module_add_module(vtkbool
FORCE_STATIC
SOURCES ${srcs}
HEADERS ${headers}
)
paraview_add_server_manager_xmls(
XMLS vtkPolyDataBooleanFilter.xml
)
================================================
FILE: paraview/module/vtk.module
================================================
NAME
vtkbool
DEPENDS
VTK::CommonCore
VTK::CommonExecutionModel
VTK::FiltersPoints
VTK::IOLegacy
VTK::FiltersFlowPaths
TEST_DEPENDS
VTK::FiltersSources
================================================
FILE: paraview/module/vtkPolyDataBooleanFilter.xml
================================================
<ServerManagerConfiguration>
<ProxyGroup name="filters">
<SourceProxy name="PolyDataBooleanFilter" class="vtkPolyDataBooleanFilter" label="PolyDataBooleanFilter">
<Documentation short_help="A boolean filter for polydata inputs." long_help=""></Documentation>
<InputProperty name="InputA" command="SetInputConnection" port_index="0">
<ProxyGroupDomain name="groups">
<Group name="sources"/>
<Group name="filters"/>
</ProxyGroupDomain>
<DataTypeDomain name="input_type">
<DataType value="vtkPolyData"/>
</DataTypeDomain>
<Documentation>
First polydata.
</Documentation>
</InputProperty>
<InputProperty name="InputB" command="SetInputConnection" port_index="1">
<ProxyGroupDomain name="groups">
<Group name="sources"/>
<Group name="filters"/>
</ProxyGroupDomain>
<DataTypeDomain name="input_type">
<DataType value="vtkPolyData"/>
</DataTypeDomain>
<Documentation>
Second polydata.
</Documentation>
</InputProperty>
<IntVectorProperty name="OperMode" command="SetOperMode" number_of_elements="1" default_values="1">
<EnumerationDomain name="enum">
<Entry value="1" text="Union"/>
<Entry value="2" text="Intersection"/>
<Entry value="3" text="Difference"/>
<Entry value="4" text="Difference2"/>
</EnumerationDomain>
<Documentation>
Sets the operation mode.
</Documentation>
</IntVectorProperty>
<Hints>
<ShowInMenu category="Extensions"/>
</Hints>
</SourceProxy>
</ProxyGroup>
</ServerManagerConfiguration>
================================================
FILE: paraview/paraview.plugin
================================================
NAME
PolyDataBooleanFilter
REQUIRES_MODULES
VTK::CommonCore
VTK::FiltersCore
DESCRIPTION
This module contains a class to do polydata boolean operations.
================================================
FILE: run_some_tests.sh
================================================
#!/bin/bash
export PYTHONPATH=/home/zippy/vtkbool/build/lib/python3.13/site-packages/vtkbool:$PYTHONPATH
pushd testing
# pytest test_filter.py::test_triangle_strips -s
# pytest test_filter.py::test_equal_capt_pts -s
# pytest test_filter.py::test_equal_capt_pts_2 -s
# pytest test_filter.py::test_equal_capt_pts_3 -s
# gdb --args python -m pytest test_filter.py::test_simple -s
pytest test_filter.py
# pytest test_filter.py::test_simple -s
popd
================================================
FILE: testing/data/branched.vtk
================================================
# vtk DataFile Version 5.1
vtk output
ASCII
DATASET POLYDATA
POINTS 622 double
0.082297295332 0 0.86818063259 0.078269377351 0.025431262329 0.86818063259 0 0 0.875
0.066579908133 0.048373136669 0.86818063259 0.048373136669 0.066579908133 0.86818063259 0.025431262329 0.078269377351 0.86818063259
5.0392558428e-18 0.082297295332 0.86818063259 -0.025431262329 0.078269377351 0.86818063259 -0.048373136669 0.066579908133 0.86818063259
-0.066579908133 0.048373136669 0.86818063259 -0.078269377351 0.025431262329 0.86818063259 -0.082297295332 1.0078511686e-17 0.86818063259
-0.078269377351 -0.025431262329 0.86818063259 -0.066579908133 -0.048373136669 0.86818063259 -0.048373136669 -0.066579908133 0.86818063259
-0.025431262329 -0.078269377351 0.86818063259 -1.5117767942e-17 -0.082297295332 0.86818063259 0.025431262329 -0.078269377351 0.86818063259
0.048373136669 -0.066579908133 0.86818063259 0.066579908133 -0.048373136669 0.86818063259 0.078269377351 -0.025431262329 0.86818063259
0.16234973073 0 0.84790861607 0.15440377593 0.050168827176 0.84790861607 0.23797369003 0 0.81473690271
0.2263264358 0.073537915945 0.81473690271 0.30710634589 0 0.76957023144 0.29207551479 0.0949010849 0.76957023144
0.36786195636 0 0.71364080906 0.34985750914 0.11367559433 0.71364080906 0.41858324409 0 0.64847409725
0.39809632301 0.12934933603 0.64847409725 0.45788666606 0 0.57584768534 0.43547609448 0.14149476588 0.57584768534
0.48470014334 0 0.4977427423 0.4609772265 0.14978057146 0.4977427423 0.49829223752 0 0.41628968716
0.47390407324 0.15398077667 0.41628968716 0.49829223752 0 0.33371031284 0.47390407324 0.15398077667 0.33371031284
0.48470014334 0 0.2522572577 0.4609772265 0.14978057146 0.2522572577 0.45788666606 0 0.17415228486
0.43547609448 0.14149476588 0.17415228486 0.41858324409 0 0.10152591765 0.39809632301 0.12934933603 0.10152591765
0.36786195636 0 0.036359213293 0.34985750914 0.11367559433 0.036359213293 0.13134369254 0.095426782966 0.84790861607
0.19252476096 0.13987742364 0.81473690271 0.24845425785 0.1805125922 0.76957023144 0.29760658741 0.21622383595 0.71364080906
0.33864095807 0.24603705108 0.64847409725 0.37043809891 0.26913902164 0.57584768534 0.39213064313 0.2848995924 0.4977427423
0.40312689543 0.29288882017 0.41628968716 0.40312689543 0.29288882017 0.33371031284 0.39213064313 0.2848995924 0.2522572577
0.37043809891 0.26913902164 0.17415228486 0.33864095807 0.24603705108 0.10152591765 0.29760658741 0.21622383595 0.036359213293
0.095426782966 0.13134369254 0.84790861607 0.13987742364 0.19252476096 0.81473690271 0.1805125922 0.24845425785 0.76957023144
0.21622383595 0.29760658741 0.71364080906 0.24603705108 0.33864095807 0.64847409725 0.26913902164 0.37043809891 0.57584768534
0.2848995924 0.39213064313 0.4977427423 0.29288882017 0.40312689543 0.41628968716 0.29288882017 0.40312689543 0.33371031284
0.2848995924 0.39213064313 0.2522572577 0.26913902164 0.37043809891 0.17415228486 0.24603705108 0.33864095807 0.10152591765
0.21622383595 0.29760658741 0.036359213293 0.050168827176 0.15440377593 0.84790861607 0.073537915945 0.2263264358 0.81473690271
0.0949010849 0.29207551479 0.76957023144 0.11367559433 0.34985750914 0.71364080906 0.12934933603 0.39809632301 0.64847409725
0.14149476588 0.43547609448 0.57584768534 0.14978057146 0.4609772265 0.4977427423 0.15398077667 0.47390407324 0.41628968716
0.15398077667 0.47390407324 0.33371031284 0.14978057146 0.4609772265 0.2522572577 0.14149476588 0.43547609448 0.17415228486
0.12934933603 0.39809632301 0.10152591765 0.11367559433 0.34985750914 0.036359213293 9.9410541201e-18 0.16234973073 0.84790861607
1.4571686463e-17 0.23797369003 0.81473690271 1.880484115e-17 0.30710634589 0.76957023144 2.2525047905e-17 0.36786195636 0.71364080906
2.5630831518e-17 0.41858324409 0.64847409725 2.8037472151e-17 0.45788666606 0.57584768534 2.9679323096e-17 0.48470014334 0.4977427423
3.0511599142e-17 0.49829223752 0.41628968716 3.0511599142e-17 0.49829223752 0.33371031284 2.9679323096e-17 0.48470014334 0.2522572577
2.8037472151e-17 0.45788666606 0.17415228486 2.5630831518e-17 0.41858324409 0.10152591765 2.2525047905e-17 0.36786195636 0.036359213293
-0.050168827176 0.15440377593 0.84790861607 -0.073537915945 0.2263264358 0.81473690271 -0.0949010849 0.29207551479 0.76957023144
-0.11367559433 0.34985750914 0.71364080906 -0.12934933603 0.39809632301 0.64847409725 -0.14149476588 0.43547609448 0.57584768534
-0.14978057146 0.4609772265 0.4977427423 -0.15398077667 0.47390407324 0.41628968716 -0.15398077667 0.47390407324 0.33371031284
-0.14978057146 0.4609772265 0.2522572577 -0.14149476588 0.43547609448 0.17415228486 -0.12934933603 0.39809632301 0.10152591765
-0.11367559433 0.34985750914 0.036359213293 -0.095426782966 0.13134369254 0.84790861607 -0.13987742364 0.19252476096 0.81473690271
-0.1805125922 0.24845425785 0.76957023144 -0.21622383595 0.29760658741 0.71364080906 -0.24603705108 0.33864095807 0.64847409725
-0.26913902164 0.37043809891 0.57584768534 -0.2848995924 0.39213064313 0.4977427423 -0.29288882017 0.40312689543 0.41628968716
-0.29288882017 0.40312689543 0.33371031284 -0.2848995924 0.39213064313 0.2522572577 -0.26913902164 0.37043809891 0.17415228486
-0.24603705108 0.33864095807 0.10152591765 -0.21622383595 0.29760658741 0.036359213293 -0.13134369254 0.095426782966 0.84790861607
-0.19252476096 0.13987742364 0.81473690271 -0.24845425785 0.1805125922 0.76957023144 -0.29760658741 0.21622383595 0.71364080906
-0.33864095807 0.24603705108 0.64847409725 -0.37043809891 0.26913902164 0.57584768534 -0.39213064313 0.2848995924 0.4977427423
-0.40312689543 0.29288882017 0.41628968716 -0.40312689543 0.29288882017 0.33371031284 -0.39213064313 0.2848995924 0.2522572577
-0.37043809891 0.26913902164 0.17415228486 -0.33864095807 0.24603705108 0.10152591765 -0.29760658741 0.21622383595 0.036359213293
-0.15440377593 0.050168827176 0.84790861607 -0.2263264358 0.073537915945 0.81473690271 -0.29207551479 0.0949010849 0.76957023144
-0.34985750914 0.11367559433 0.71364080906 -0.39809632301 0.12934933603 0.64847409725 -0.43547609448 0.14149476588 0.57584768534
-0.4609772265 0.14978057146 0.4977427423 -0.47390407324 0.15398077667 0.41628968716 -0.47390407324 0.15398077667 0.33371031284
-0.4609772265 0.14978057146 0.2522572577 -0.43547609448 0.14149476588 0.17415228486 -0.39809632301 0.12934933603 0.10152591765
-0.34985750914 0.11367559433 0.036359213293 -0.16234973073 1.988210824e-17 0.84790861607 -0.23797369003 2.9143372925e-17 0.81473690271
-0.30710634589 3.76096823e-17 0.76957023144 -0.36786195636 4.5050095809e-17 0.71364080906 -0.41858324409 5.1261663035e-17 0.64847409725
-0.45788666606 5.6074944302e-17 0.57584768534 -0.48470014334 5.9358646193e-17 0.4977427423 -0.49829223752 6.1023198283e-17 0.41628968716
-0.49829223752 6.1023198283e-17 0.33371031284 -0.48470014334 5.9358646193e-17 0.2522572577 -0.45788666606 5.6074944302e-17 0.17415228486
-0.41858324409 5.1261663035e-17 0.10152591765 -0.36786195636 4.5050095809e-17 0.036359213293 -0.15440377593 -0.050168827176 0.84790861607
-0.2263264358 -0.073537915945 0.81473690271 -0.29207551479 -0.0949010849 0.76957023144 -0.34985750914 -0.11367559433 0.71364080906
-0.39809632301 -0.12934933603 0.64847409725 -0.43547609448 -0.14149476588 0.57584768534 -0.4609772265 -0.14978057146 0.4977427423
-0.47390407324 -0.15398077667 0.41628968716 -0.47390407324 -0.15398077667 0.33371031284 -0.4609772265 -0.14978057146 0.2522572577
-0.43547609448 -0.14149476588 0.17415228486 -0.39809632301 -0.12934933603 0.10152591765 -0.34985750914 -0.11367559433 0.036359213293
-0.13134369254 -0.095426782966 0.84790861607 -0.19252476096 -0.13987742364 0.81473690271 -0.24845425785 -0.1805125922 0.76957023144
-0.29760658741 -0.21622383595 0.71364080906 -0.33864095807 -0.24603705108 0.64847409725 -0.37043809891 -0.26913902164 0.57584768534
-0.39213064313 -0.2848995924 0.4977427423 -0.40312689543 -0.29288882017 0.41628968716 -0.40312689543 -0.29288882017 0.33371031284
-0.39213064313 -0.2848995924 0.2522572577 -0.37043809891 -0.26913902164 0.17415228486 -0.33864095807 -0.24603705108 0.10152591765
-0.29760658741 -0.21622383595 0.036359213293 -0.095426782966 -0.13134369254 0.84790861607 -0.13987742364 -0.19252476096 0.81473690271
-0.1805125922 -0.24845425785 0.76957023144 -0.21622383595 -0.29760658741 0.71364080906 -0.24603705108 -0.33864095807 0.64847409725
-0.26913902164 -0.37043809891 0.57584768534 -0.2848995924 -0.39213064313 0.4977427423 -0.29288882017 -0.40312689543 0.41628968716
-0.29288882017 -0.40312689543 0.33371031284 -0.2848995924 -0.39213064313 0.2522572577 -0.26913902164 -0.37043809891 0.17415228486
-0.24603705108 -0.33864095807 0.10152591765 -0.21622383595 -0.29760658741 0.036359213293 -0.050168827176 -0.15440377593 0.84790861607
-0.073537915945 -0.2263264358 0.81473690271 -0.0949010849 -0.29207551479 0.76957023144 -0.11367559433 -0.34985750914 0.71364080906
-0.12934933603 -0.39809632301 0.64847409725 -0.14149476588 -0.43547609448 0.57584768534 -0.14978057146 -0.4609772265 0.4977427423
-0.15398077667 -0.47390407324 0.41628968716 -0.15398077667 -0.47390407324 0.33371031284 -0.14978057146 -0.4609772265 0.2522572577
-0.14149476588 -0.43547609448 0.17415228486 -0.12934933603 -0.39809632301 0.10152591765 -0.11367559433 -0.34985750914 0.036359213293
-2.9823163188e-17 -0.16234973073 0.84790861607 -4.3715059388e-17 -0.23797369003 0.81473690271 -5.6414525104e-17 -0.30710634589 0.76957023144
-6.7575143714e-17 -0.36786195636 0.71364080906 -7.6892492899e-17 -0.41858324409 0.64847409725 -8.4112416453e-17 -0.45788666606 0.57584768534
-8.9037972598e-17 -0.48470014334 0.4977427423 -9.1534800733e-17 -0.49829223752 0.41628968716 -9.1534800733e-17 -0.49829223752 0.33371031284
-8.9037972598e-17 -0.48470014334 0.2522572577 -8.4112416453e-17 -0.45788666606 0.17415228486 -7.6892492899e-17 -0.41858324409 0.10152591765
-6.7575143714e-17 -0.36786195636 0.036359213293 0.050168827176 -0.15440377593 0.84790861607 0.073537915945 -0.2263264358 0.81473690271
0.0949010849 -0.29207551479 0.76957023144 0.11367559433 -0.34985750914 0.71364080906 0.12934933603 -0.39809632301 0.64847409725
0.14149476588 -0.43547609448 0.57584768534 0.14978057146 -0.4609772265 0.4977427423 0.15398077667 -0.47390407324 0.41628968716
0.15398077667 -0.47390407324 0.33371031284 0.14978057146 -0.4609772265 0.2522572577 0.14149476588 -0.43547609448 0.17415228486
0.12934933603 -0.39809632301 0.10152591765 0.11367559433 -0.34985750914 0.036359213293 0.095426782966 -0.13134369254 0.84790861607
0.13987742364 -0.19252476096 0.81473690271 0.1805125922 -0.24845425785 0.76957023144 0.21622383595 -0.29760658741 0.71364080906
0.24603705108 -0.33864095807 0.64847409725 0.26913902164 -0.37043809891 0.57584768534 0.2848995924 -0.39213064313 0.4977427423
0.29288882017 -0.40312689543 0.41628968716 0.29288882017 -0.40312689543 0.33371031284 0.2848995924 -0.39213064313 0.2522572577
0.26913902164 -0.37043809891 0.17415228486 0.24603705108 -0.33864095807 0.10152591765 0.21622383595 -0.29760658741 0.036359213293
0.13134369254 -0.095426782966 0.84790861607 0.19252476096 -0.13987742364 0.81473690271 0.24845425785 -0.1805125922 0.76957023144
0.29760658741 -0.21622383595 0.71364080906 0.33864095807 -0.24603705108 0.64847409725 0.37043809891 -0.26913902164 0.57584768534
0.39213064313 -0.2848995924 0.4977427423 0.40312689543 -0.29288882017 0.41628968716 0.40312689543 -0.29288882017 0.33371031284
0.39213064313 -0.2848995924 0.2522572577 0.37043809891 -0.26913902164 0.17415228486 0.33864095807 -0.24603705108 0.10152591765
0.29760658741 -0.21622383595 0.036359213293 0.15440377593 -0.050168827176 0.84790861607 0.2263264358 -0.073537915945 0.81473690271
0.29207551479 -0.0949010849 0.76957023144 0.34985750914 -0.11367559433 0.71364080906 0.39809632301 -0.12934933603 0.64847409725
0.43547609448 -0.14149476588 0.57584768534 0.4609772265 -0.14978057146 0.4977427423 0.47390407324 -0.15398077667 0.41628968716
0.47390407324 -0.15398077667 0.33371031284 0.4609772265 -0.14978057146 0.2522572577 0.43547609448 -0.14149476588 0.17415228486
0.39809632301 -0.12934933603 0.10152591765 0.34985750914 -0.11367559433 0.036359213293 0.32836531327 8.6818331113e-19 -2.8171179001e-17
0.3220653893 0.03977618435 -4.9487070846e-09 0.31859390657 0.06169429886 -4.9487070599e-09 0.31229398553 0.10147046475 2.5407916269e-17
0.29401088933 0.13735306108 5.1429095066e-09 0.28393623162 0.15712568324 5.1429095066e-09 0.2656531266 0.19300829687 6.9388939039e-18
0.23717652592 0.22148489755 0 0.22148489755 0.23717652592 0 0.19300829687 0.2656531266 0
0.15712568324 0.28393623162 -5.1429094891e-09 0.13735306108 0.29401088933 -5.1429095118e-09 0.10147046475 0.31229398553 -2.5197041461e-17
0.06169429886 0.31859390657 4.9487070318e-09 0.03977618435 0.3220653893 4.948707057e-09 1.8882986284e-17 0.32836531327 2.3493044647e-24
-0.03977618435 0.3220653893 -4.9487070858e-09 -0.06169429886 0.31859390657 -4.948707057e-09 -0.10147046475 0.31229398553 -4.4034066554e-18
-0.13735306108 0.29401088933 5.1429095118e-09 -0.15712568324 0.28393623162 5.1429095066e-09 -0.19300829687 0.2656531266 2.0768586122e-18
-0.22148489755 0.23717652592 0 -0.23717652592 0.22148489755 0 -0.2656531266 0.19300829687 0
-0.28393623162 0.15712568324 -5.1429094753e-09 -0.29401088933 0.13735306108 -5.1429095118e-09 -0.31229398553 0.10147046475 -2.5407916269e-17
-0.31859390657 0.06169429886 4.9487070561e-09 -0.3220653893 0.03977618435 4.9487070561e-09 -0.32836531327 3.8887509036e-17 4.8381435661e-24
-0.3220653893 -0.03977618435 -4.9487070852e-09 -0.31859390657 -0.06169429886 -4.9487070599e-09 -0.31229398553 -0.10147046475 -2.9741361642e-18
-0.29401088933 -0.13735306108 5.1429095066e-09 -0.28393623162 -0.15712568324 5.1429095066e-09 -0.2656531266 -0.19300829687 6.9388939039e-18
-0.23717652592 -0.22148489755 0 -0.22148489755 -0.23717652592 0 -0.19300829687 -0.2656531266 0
-0.15712568324 -0.28393623162 -5.1429094753e-09 -0.13735306108 -0.29401088933 -5.1429094753e-09 -0.10147046475 -0.31229398553 -2.540791296e-17
-0.06169429886 -0.31859390657 4.9487070561e-09 -0.03977618435 -0.3220653893 4.9487070565e-09 -5.8492876492e-17 -0.32836531327 -8.5284299912e-18
0.03977618435 -0.3220653893 -4.9487070556e-09 0.06169429886 -0.31859390657 -4.9487070591e-09 0.10147046475 -0.31229398553 -1.5448640187e-18
0.13735306108 -0.29401088933 5.1429095066e-09 0.15712568324 -0.28393623162 5.1429094891e-09 0.19300829687 -0.2656531266 -0
0.22148489755 -0.23717652592 -0 0.23717652592 -0.22148489755 -0 0.2656531266 -0.19300829687 -2.0768619209e-18
0.28393623162 -0.15712568324 -5.1429094753e-09 0.29401088933 -0.13735306108 -5.1429095118e-09 0.31229398553 -0.10147046475 2.9741345099e-18
0.31859390657 -0.06169429886 4.9487070561e-09 0.3220653893 -0.03977618435 4.9487070565e-09 0.082297295332 0 -0.86818063259
0 0 -0.875 0.078269377351 0.025431262329 -0.86818063259 0.066579908133 0.048373136669 -0.86818063259
0.048373136669 0.066579908133 -0.86818063259 0.025431262329 0.078269377351 -0.86818063259 5.0392558428e-18 0.082297295332 -0.86818063259
-0.025431262329 0.078269377351 -0.86818063259 -0.048373136669 0.066579908133 -0.86818063259 -0.066579908133 0.048373136669 -0.86818063259
-0.078269377351 0.025431262329 -0.86818063259 -0.082297295332 1.0078511686e-17 -0.86818063259 -0.078269377351 -0.025431262329 -0.86818063259
-0.066579908133 -0.048373136669 -0.86818063259 -0.048373136669 -0.066579908133 -0.86818063259 -0.025431262329 -0.078269377351 -0.86818063259
-1.5117767942e-17 -0.082297295332 -0.86818063259 0.025431262329 -0.078269377351 -0.86818063259 0.048373136669 -0.066579908133 -0.86818063259
0.066579908133 -0.048373136669 -0.86818063259 0.078269377351 -0.025431262329 -0.86818063259 0.36786195636 0 -0.036359213293
0.41858324409 0 -0.10152591765 0.39809632301 0.12934933603 -0.10152591765 0.34985750914 0.11367559433 -0.036359213293
0.45788666606 0 -0.17415228486 0.43547609448 0.14149476588 -0.17415228486 0.48470014334 0 -0.2522572577
0.4609772265 0.14978057146 -0.2522572577 0.49829223752 0 -0.33371031284 0.47390407324 0.15398077667 -0.33371031284
0.49829223752 0 -0.41628968716 0.47390407324 0.15398077667 -0.41628968716 0.48470014334 0 -0.4977427423
0.4609772265 0.14978057146 -0.4977427423 0.45788666606 0 -0.57584768534 0.43547609448 0.14149476588 -0.57584768534
0.41858324409 0 -0.64847409725 0.39809632301 0.12934933603 -0.64847409725 0.36786195636 0 -0.71364080906
0.34985750914 0.11367559433 -0.71364080906 0.30710634589 0 -0.76957023144 0.29207551479 0.0949010849 -0.76957023144
0.23797369003 0 -0.81473690271 0.2263264358 0.073537915945 -0.81473690271 0.16234973073 0 -0.84790861607
0.15440377593 0.050168827176 -0.84790861607 0.33864095807 0.24603705108 -0.10152591765 0.29760658741 0.21622383595 -0.036359213293
0.37043809891 0.26913902164 -0.17415228486 0.39213064313 0.2848995924 -0.2522572577 0.40312689543 0.29288882017 -0.33371031284
0.40312689543 0.29288882017 -0.41628968716 0.39213064313 0.2848995924 -0.4977427423 0.37043809891 0.26913902164 -0.57584768534
0.33864095807 0.24603705108 -0.64847409725 0.29760658741 0.21622383595 -0.71364080906 0.24845425785 0.1805125922 -0.76957023144
0.19252476096 0.13987742364 -0.81473690271 0.13134369254 0.095426782966 -0.84790861607 0.24603705108 0.33864095807 -0.10152591765
0.21622383595 0.29760658741 -0.036359213293 0.26913902164 0.37043809891 -0.17415228486 0.2848995924 0.39213064313 -0.2522572577
0.29288882017 0.40312689543 -0.33371031284 0.29288882017 0.40312689543 -0.41628968716 0.2848995924 0.39213064313 -0.4977427423
0.26913902164 0.37043809891 -0.57584768534 0.24603705108 0.33864095807 -0.64847409725 0.21622383595 0.29760658741 -0.71364080906
0.1805125922 0.24845425785 -0.76957023144 0.13987742364 0.19252476096 -0.81473690271 0.095426782966 0.13134369254 -0.84790861607
0.12934933603 0.39809632301 -0.10152591765 0.11367559433 0.34985750914 -0.036359213293 0.14149476588 0.43547609448 -0.17415228486
0.14978057146 0.4609772265 -0.2522572577 0.15398077667 0.47390407324 -0.33371031284 0.15398077667 0.47390407324 -0.41628968716
0.14978057146 0.4609772265 -0.4977427423 0.14149476588 0.43547609448 -0.57584768534 0.12934933603 0.39809632301 -0.64847409725
0.11367559433 0.34985750914 -0.71364080906 0.0949010849 0.29207551479 -0.76957023144 0.073537915945 0.2263264358 -0.81473690271
0.050168827176 0.15440377593 -0.84790861607 2.5630831518e-17 0.41858324409 -0.10152591765 2.2525047905e-17 0.36786195636 -0.036359213293
2.8037472151e-17 0.45788666606 -0.17415228486 2.9679323096e-17 0.48470014334 -0.2522572577 3.0511599142e-17 0.49829223752 -0.33371031284
3.0511599142e-17 0.49829223752 -0.41628968716 2.9679323096e-17 0.48470014334 -0.4977427423 2.8037472151e-17 0.45788666606 -0.57584768534
2.5630831518e-17 0.41858324409 -0.64847409725 2.2525047905e-17 0.36786195636 -0.71364080906 1.880484115e-17 0.30710634589 -0.76957023144
1.4571686463e-17 0.23797369003 -0.81473690271 9.9410541201e-18 0.16234973073 -0.84790861607 -0.12934933603 0.39809632301 -0.10152591765
-0.11367559433 0.34985750914 -0.036359213293 -0.14149476588 0.43547609448 -0.17415228486 -0.14978057146 0.4609772265 -0.2522572577
-0.15398077667 0.47390407324 -0.33371031284 -0.15398077667 0.47390407324 -0.41628968716 -0.14978057146 0.4609772265 -0.4977427423
-0.14149476588 0.43547609448 -0.57584768534 -0.12934933603 0.39809632301 -0.64847409725 -0.11367559433 0.34985750914 -0.71364080906
-0.0949010849 0.29207551479 -0.76957023144 -0.073537915945 0.2263264358 -0.81473690271 -0.050168827176 0.15440377593 -0.84790861607
-0.24603705108 0.33864095807 -0.10152591765 -0.21622383595 0.29760658741 -0.036359213293 -0.26913902164 0.37043809891 -0.17415228486
-0.2848995924 0.39213064313 -0.2522572577 -0.29288882017 0.40312689543 -0.33371031284 -0.29288882017 0.40312689543 -0.41628968716
-0.2848995924 0.39213064313 -0.4977427423 -0.26913902164 0.37043809891 -0.57584768534 -0.24603705108 0.33864095807 -0.64847409725
-0.21622383595 0.29760658741 -0.71364080906 -0.1805125922 0.24845425785 -0.76957023144 -0.13987742364 0.19252476096 -0.81473690271
-0.095426782966 0.13134369254 -0.84790861607 -0.33864095807 0.24603705108 -0.10152591765 -0.29760658741 0.21622383595 -0.036359213293
-0.37043809891 0.26913902164 -0.17415228486 -0.39213064313 0.2848995924 -0.2522572577 -0.40312689543 0.29288882017 -0.33371031284
-0.40312689543 0.29288882017 -0.41628968716 -0.39213064313 0.2848995924 -0.4977427423 -0.37043809891 0.26913902164 -0.57584768534
-0.33864095807 0.24603705108 -0.64847409725 -0.29760658741 0.21622383595 -0.71364080906 -0.24845425785 0.1805125922 -0.76957023144
-0.19252476096 0.13987742364 -0.81473690271 -0.13134369254 0.095426782966 -0.84790861607 -0.39809632301 0.12934933603 -0.10152591765
-0.34985750914 0.11367559433 -0.036359213293 -0.43547609448 0.14149476588 -0.17415228486 -0.4609772265 0.14978057146 -0.2522572577
-0.47390407324 0.15398077667 -0.33371031284 -0.47390407324 0.15398077667 -0.41628968716 -0.4609772265 0.14978057146 -0.4977427423
-0.43547609448 0.14149476588 -0.57584768534 -0.39809632301 0.12934933603 -0.64847409725 -0.34985750914 0.11367559433 -0.71364080906
-0.29207551479 0.0949010849 -0.76957023144 -0.2263264358 0.073537915945 -0.81473690271 -0.15440377593 0.050168827176 -0.84790861607
-0.41858324409 5.1261663035e-17 -0.10152591765 -0.36786195636 4.5050095809e-17 -0.036359213293 -0.45788666606 5.6074944302e-17 -0.17415228486
-0.48470014334 5.9358646193e-17 -0.2522572577 -0.49829223752 6.1023198283e-17 -0.33371031284 -0.49829223752 6.1023198283e-17 -0.41628968716
-0.48470014334 5.9358646193e-17 -0.4977427423 -0.45788666606 5.6074944302e-17 -0.57584768534 -0.41858324409 5.1261663035e-17 -0.64847409725
-0.36786195636 4.5050095809e-17 -0.71364080906 -0.30710634589 3.76096823e-17 -0.76957023144 -0.23797369003 2.9143372925e-17 -0.81473690271
-0.16234973073 1.988210824e-17 -0.84790861607 -0.39809632301 -0.12934933603 -0.10152591765 -0.34985750914 -0.11367559433 -0.036359213293
-0.43547609448 -0.14149476588 -0.17415228486 -0.4609772265 -0.14978057146 -0.2522572577 -0.47390407324 -0.15398077667 -0.33371031284
-0.47390407324 -0.15398077667 -0.41628968716 -0.4609772265 -0.14978057146 -0.4977427423 -0.43547609448 -0.14149476588 -0.57584768534
-0.39809632301 -0.12934933603 -0.64847409725 -0.34985750914 -0.11367559433 -0.71364080906 -0.29207551479 -0.0949010849 -0.76957023144
-0.2263264358 -0.073537915945 -0.81473690271 -0.15440377593 -0.050168827176 -0.84790861607 -0.33864095807 -0.24603705108 -0.10152591765
-0.29760658741 -0.21622383595 -0.036359213293 -0.37043809891 -0.26913902164 -0.17415228486 -0.39213064313 -0.2848995924 -0.2522572577
-0.40312689543 -0.29288882017 -0.33371031284 -0.40312689543 -0.29288882017 -0.41628968716 -0.39213064313 -0.2848995924 -0.4977427423
-0.37043809891 -0.26913902164 -0.57584768534 -0.33864095807 -0.24603705108 -0.64847409725 -0.29760658741 -0.21622383595 -0.71364080906
-0.24845425785 -0.1805125922 -0.76957023144 -0.19252476096 -0.13987742364 -0.81473690271 -0.13134369254 -0.095426782966 -0.84790861607
-0.24603705108 -0.33864095807 -0.10152591765 -0.21622383595 -0.29760658741 -0.036359213293 -0.26913902164 -0.37043809891 -0.17415228486
-0.2848995924 -0.39213064313 -0.2522572577 -0.29288882017 -0.40312689543 -0.33371031284 -0.29288882017 -0.40312689543 -0.41628968716
-0.2848995924 -0.39213064313 -0.4977427423 -0.26913902164 -0.37043809891 -0.57584768534 -0.24603705108 -0.33864095807 -0.64847409725
-0.21622383595 -0.29760658741 -0.71364080906 -0.1805125922 -0.24845425785 -0.76957023144 -0.13987742364 -0.19252476096 -0.81473690271
-0.095426782966 -0.13134369254 -0.84790861607 -0.12934933603 -0.39809632301 -0.10152591765 -0.11367559433 -0.34985750914 -0.036359213293
-0.14149476588 -0.43547609448 -0.17415228486 -0.14978057146 -0.4609772265 -0.2522572577 -0.15398077667 -0.47390407324 -0.33371031284
-0.15398077667 -0.47390407324 -0.41628968716 -0.14978057146 -0.4609772265 -0.4977427423 -0.14149476588 -0.43547609448 -0.57584768534
-0.12934933603 -0.39809632301 -0.64847409725 -0.11367559433 -0.34985750914 -0.71364080906 -0.0949010849 -0.29207551479 -0.76957023144
-0.073537915945 -0.2263264358 -0.81473690271 -0.050168827176 -0.15440377593 -0.84790861607 -7.6892492899e-17 -0.41858324409 -0.10152591765
-6.7575143714e-17 -0.36786195636 -0.036359213293 -8.4112416453e-17 -0.45788666606 -0.17415228486 -8.9037972598e-17 -0.48470014334 -0.2522572577
-9.1534800733e-17 -0.49829223752 -0.33371031284 -9.1534800733e-17 -0.49829223752 -0.41628968716 -8.9037972598e-17 -0.48470014334 -0.4977427423
-8.4112416453e-17 -0.45788666606 -0.57584768534 -7.6892492899e-17 -0.41858324409 -0.64847409725 -6.7575143714e-17 -0.36786195636 -0.71364080906
-5.6414525104e-17 -0.30710634589 -0.76957023144 -4.3715059388e-17 -0.23797369003 -0.81473690271 -2.9823163188e-17 -0.16234973073 -0.84790861607
0.12934933603 -0.39809632301 -0.10152591765 0.11367559433 -0.34985750914 -0.036359213293 0.14149476588 -0.43547609448 -0.17415228486
0.14978057146 -0.4609772265 -0.2522572577 0.15398077667 -0.47390407324 -0.33371031284 0.15398077667 -0.47390407324 -0.41628968716
0.14978057146 -0.4609772265 -0.4977427423 0.14149476588 -0.43547609448 -0.57584768534 0.12934933603 -0.39809632301 -0.64847409725
0.11367559433 -0.34985750914 -0.71364080906 0.0949010849 -0.29207551479 -0.76957023144 0.073537915945 -0.2263264358 -0.81473690271
0.050168827176 -0.15440377593 -0.84790861607 0.24603705108 -0.33864095807 -0.10152591765 0.21622383595 -0.29760658741 -0.036359213293
0.26913902164 -0.37043809891 -0.17415228486 0.2848995924 -0.39213064313 -0.2522572577 0.29288882017 -0.40312689543 -0.33371031284
0.29288882017 -0.40312689543 -0.41628968716 0.2848995924 -0.39213064313 -0.4977427423 0.26913902164 -0.37043809891 -0.57584768534
0.24603705108 -0.33864095807 -0.64847409725 0.21622383595 -0.29760658741 -0.71364080906 0.1805125922 -0.24845425785 -0.76957023144
0.13987742364 -0.19252476096 -0.81473690271 0.095426782966 -0.13134369254 -0.84790861607 0.33864095807 -0.24603705108 -0.10152591765
0.29760658741 -0.21622383595 -0.036359213293 0.37043809891 -0.26913902164 -0.17415228486 0.39213064313 -0.2848995924 -0.2522572577
0.40312689543 -0.29288882017 -0.33371031284 0.40312689543 -0.29288882017 -0.41628968716 0.39213064313 -0.2848995924 -0.4977427423
0.37043809891 -0.26913902164 -0.57584768534 0.33864095807 -0.24603705108 -0.64847409725 0.29760658741 -0.21622383595 -0.71364080906
0.24845425785 -0.1805125922 -0.76957023144 0.19252476096 -0.13987742364 -0.81473690271 0.13134369254 -0.095426782966 -0.84790861607
0.39809632301 -0.12934933603 -0.10152591765 0.34985750914 -0.11367559433 -0.036359213293 0.43547609448 -0.14149476588 -0.17415228486
0.4609772265 -0.14978057146 -0.2522572577 0.47390407324 -0.15398077667 -0.33371031284 0.47390407324 -0.15398077667 -0.41628968716
0.4609772265 -0.14978057146 -0.4977427423 0.43547609448 -0.14149476588 -0.57584768534 0.39809632301 -0.12934933603 -0.64847409725
0.34985750914 -0.11367559433 -0.71364080906 0.29207551479 -0.0949010849 -0.76957023144 0.2263264358 -0.073537915945 -0.81473690271
0.15440377593 -0.050168827176 -0.84790861607
POLYGONS 1161 3560
OFFSETS vtktypeint64
0 3 6 9 12 15 18 21 24
27 30 33 36 39 42 45 48 51
54 57 60 63 66 69 72 75 78
81 84 87 90 93 96 99 102 105
108 111 114 117 120 123 126 129 132
135 138 141 144 147 150 153 156 159
162 165 168 171 174 177 180 183 186
189 192 195 198 201 204 207 210 213
216 219 222 225 228 231 234 237 240
243 246 249 252 255 258 261 264 267
270 273 276 279 282 285 288 291 294
297 300 303 306 309 312 315 318 321
324 327 330 333 336 339 342 345 348
351 354 357 360 363 366 369 372 375
378 381 384 387 390 393 396 399 402
405 408 411 414 417 420 423 426 429
432 435 438 441 444 447 450 453 456
459 462 465 468 471 474 477 480 483
486 489 492 495 498 501 504 507 510
513 516 519 522 525 528 531 534 537
540 543 546 549 552 555 558 561 564
567 570 573 576 579 582 585 588 591
594 597 600 603 606 609 612 615 618
621 624 627 630 633 636 639 642 645
648 651 654 657 660 663 666 669 672
675 678 681 684 687 690 693 696 699
702 705 708 711 714 717 720 723 726
729 732 735 738 741 744 747 750 753
756 759 762 765 768 771 774 777 780
783 786 789 792 795 798 801 804 807
810 813 816 819 822 825 828 831 834
837 840 843 846 849 852 855 858 861
864 867 870 873 876 879 882 885 888
891 894 897 900 903 906 909 912 915
918 921 924 927 930 933 936 939 942
945 948 951 954 957 960 963 966 969
972 975 978 981 984 987 990 993 996
999 1002 1005 1008 1011 1014 1017 1020 1023
1026 1029 1032 1035 1038 1041 1044 1047 1050
1053 1056 1059 1062 1065 1068 1071 1074 1077
1080 1083 1086 1089 1092 1095 1098 1101 1104
1107 1110 1113 1116 1119 1122 1125 1128 1131
1134 1137 1140 1143 1146 1149 1152 1155 1158
1161 1164 1167 1170 1173 1176 1179 1182 1185
1188 1191 1194 1197 1200 1203 1206 1209 1212
1215 1218 1221 1224 1227 1230 1233 1236 1239
1242 1245 1248 1251 1254 1257 1260 1263 1266
1269 1272 1275 1278 1281 1284 1287 1290 1293
1296 1299 1302 1305 1308 1311 1314 1317 1320
1323 1326 1329 1332 1335 1338 1341 1344 1347
1350 1353 1356 1359 1362 1365 1368 1371 1374
1377 1380 1383 1386 1389 1392 1395 1398 1401
1404 1407 1410 1413 1416 1419 1422 1425 1428
1431 1434 1437 1440 1443 1446 1449 1452 1455
1458 1461 1464 1467 1470 1473 1476 1479 1482
1485 1488 1491 1494 1497 1500 1503 1506 1509
1512 1515 1518 1521 1524 1527 1530 1533 1536
1539 1542 1545 1548 1551 1554 1557 1560 1563
1566 1569 1572 1575 1578 1581 1584 1587 1590
1593 1596 1599 1602 1605 1608 1611 1614 1617
1620 1624 1628 1632 1636 1640 1644 1648 1652
1656 1660 1664 1668 1672 1676 1680 1684 1688
1692 1696 1700 1704 1708 1712 1716 1720 1724
1728 1732 1736 1740 1744 1748 1752 1756 1760
1764 1768 1772 1776 1780 1783 1786 1789 1792
1795 1798 1801 1804 1807 1810 1813 1816 1819
1822 1825 1828 1831 1834 1837 1840 1843 1846
1849 1852 1855 1858 1861 1864 1867 1870 1873
1876 1879 1882 1885 1888 1891 1894 1897 1900
1903 1906 1909 1912 1915 1918 1921 1924 1927
1930 1933 1936 1939 1942 1945 1948 1951 1954
1957 1960 1963 1966 1969 1972 1975 1978 1981
1984 1987 1990 1993 1996 1999 2002 2005 2008
2011 2014 2017 2020 2023 2026 2029 2032 2035
2038 2041 2044 2047 2050 2053 2056 2059 2062
2065 2068 2071 2074 2077 2080 2083 2086 2089
2092 2095 2098 2101 2104 2107 2110 2113 2116
2119 2122 2125 2128 2131 2134 2137 2140 2143
2146 2149 2152 2155 2158 2161 2164 2167 2170
2173 2176 2179 2182 2185 2188 2191 2194 2197
2200 2203 2206 2209 2212 2215 2218 2221 2224
2227 2230 2233 2236 2239 2242 2245 2248 2251
2254 2257 2260 2263 2266 2269 2272 2275 2278
2281 2284 2287 2290 2293 2296 2299 2302 2305
2308 2311 2314 2317 2320 2323 2326 2329 2332
2335 2338 2341 2344 2347 2350 2353 2356 2359
2362 2365 2368 2371 2374 2377 2380 2383 2386
2389 2392 2395 2398 2401 2404 2407 2410 2413
2416 2419 2422 2425 2428 2431 2434 2437 2440
2443 2446 2449 2452 2455 2458 2461 2464 2467
2470 2473 2476 2479 2482 2485 2488 2491 2494
2497 2500 2503 2506 2509 2512 2515 2518 2521
2524 2527 2530 2533 2536 2539 2542 2545 2548
2551 2554 2557 2560 2563 2566 2569 2572 2575
2578 2581 2584 2587 2590 2593 2596 2599 2602
2605 2608 2611 2614 2617 2620 2623 2626 2629
2632 2635 2638 2641 2644 2647 2650 2653 2656
2659 2662 2665 2668 2671 2674 2677 2680 2683
2686 2689 2692 2695 2698 2701 2704 2707 2710
2713 2716 2719 2722 2725 2728 2731 2734 2737
2740 2743 2746 2749 2752 2755 2758 2761 2764
2767 2770 2773 2776 2779 2782 2785 2788 2791
2794 2797 2800 2803 2806 2809 2812 2815 2818
2821 2824 2827 2830 2833 2836 2839 2842 2845
2848 2851 2854 2857 2860 2863 2866 2869 2872
2875 2878 2881 2884 2887 2890 2893 2896 2899
2902 2905 2908 2911 2914 2917 2920 2923 2926
2929 2932 2935 2938 2941 2944 2947 2950 2953
2956 2959 2962 2965 2968 2971 2974 2977 2980
2983 2986 2989 2992 2995 2998 3001 3004 3007
3010 3013 3016 3019 3022 3025 3028 3031 3034
3037 3040 3043 3046 3049 3052 3055 3058 3061
3064 3067 3070 3073 3076 3079 3082 3085 3088
3091 3094 3097 3100 3103 3106 3109 3112 3115
3118 3121 3124 3127 3130 3133 3136 3139 3142
3145 3148 3151 3154 3157 3160 3163 3166 3169
3172 3175 3178 3181 3184 3187 3190 3193 3196
3199 3202 3205 3208 3211 3214 3217 3220 3223
3226 3229 3232 3235 3238 3241 3244 3247 3250
3253 3256 3259 3262 3265 3268 3271 3274 3277
3280 3283 3286 3289 3292 3295 3298 3301 3304
3307 3310 3313 3316 3319 3322 3325 3328 3331
3334 3337 3340 3343 3346 3349 3352 3355 3358
3361 3364 3367 3370 3373 3376 3379 3382 3385
3388 3391 3394 3397 3400 3404 3408 3412 3416
3420 3424 3428 3432 3436 3440 3444 3448 3452
3456 3460 3464 3468 3472 3476 3480 3484 3488
3492 3496 3500 3504 3508 3512 3516 3520 3524
3528 3532 3536 3540 3544 3548 3552 3556 3560
CONNECTIVITY vtktypeint64
0 1 2 1 3 2 3 4 2
4 5 2 5 6 2 6 7 2
7 8 2 8 9 2 9 10 2
10 11 2 11 12 2 12 13 2
13 14 2 14 15 2 15 16 2
16 17 2 17 18 2 18 19 2
19 20 2 20 0 2 0 21 22
0 22 1 21 23 24 21 24 22
23 25 26 23 26 24 25 27 28
25 28 26 27 29 30 27 30 28
29 31 32 29 32 30 31 33 34
31 34 32 33 35 36 33 36 34
35 37 38 35 38 36 37 39 40
37 40 38 39 41 42 39 42 40
41 43 44 41 44 42 43 45 46
43 46 44 1 22 47 1 47 3
22 24 48 22 48 47 24 26 49
24 49 48 26 28 50 26 50 49
28 30 51 28 51 50 30 32 52
30 52 51 32 34 53 32 53 52
34 36 54 34 54 53 36 38 55
36 55 54 38 40 56 38 56 55
40 42 57 40 57 56 42 44 58
42 58 57 44 46 59 44 59 58
3 47 60 3 60 4 47 48 61
47 61 60 48 49 62 48 62 61
49 50 63 49 63 62 50 51 64
50 64 63 51 52 65 51 65 64
52 53 66 52 66 65 53 54 67
53 67 66 54 55 68 54 68 67
55 56 69 55 69 68 56 57 70
56 70 69 57 58 71 57 71 70
58 59 72 58 72 71 4 60 73
4 73 5 60 61 74 60 74 73
61 62 75 61 75 74 62 63 76
62 76 75 63 64 77 63 77 76
64 65 78 64 78 77 65 66 79
65 79 78 66 67 80 66 80 79
67 68 81 67 81 80 68 69 82
68 82 81 69 70 83 69 83 82
70 71 84 70 84 83 71 72 85
71 85 84 5 73 86 5 86 6
73 74 87 73 87 86 74 75 88
74 88 87 75 76 89 75 89 88
76 77 90 76 90 89 77 78 91
77 91 90 78 79 92 78 92 91
79 80 93 79 93 92 80 81 94
80 94 93 81 82 95 81 95 94
82 83 96 82 96 95 83 84 97
83 97 96 84 85 98 84 98 97
6 86 99 6 99 7 86 87 100
86 100 99 87 88 101 87 101 100
88 89 102 88 102 101 89 90 103
89 103 102 90 91 104 90 104 103
91 92 105 91 105 104 92 93 106
92 106 105 93 94 107 93 107 106
94 95 108 94 108 107 95 96 109
95 109 108 96 97 110 96 110 109
97 98 111 97 111 110 7 99 112
7 112 8 99 100 113 99 113 112
100 101 114 100 114 113 101 102 115
101 115 114 102 103 116 102 116 115
103 104 117 103 117 116 104 105 118
104 118 117 105 106 119 105 119 118
106 107 120 106 120 119 107 108 121
107 121 120 108 109 122 108 122 121
109 110 123 109 123 122 110 111 124
110 124 123 8 112 125 8 125 9
112 113 126 112 126 125 113 114 127
113 127 126 114 115 128 114 128 127
115 116 129 115 129 128 116 117 130
116 130 129 117 118 131 117 131 130
118 119 132 118 132 131 119 120 133
119 133 132 120 121 134 120 134 133
121 122 135 121 135 134 122 123 136
122 136 135 123 124 137 123 137 136
9 125 138 9 138 10 125 126 139
125 139 138 126 127 140 126 140 139
127 128 141 127 141 140 128 129 142
128 142 141 129 130 143 129 143 142
130 131 144 130 144 143 131 132 145
131 145 144 132 133 146 132 146 145
133 134 147 133 147 146 134 135 148
134 148 147 135 136 149 135 149 148
136 137 150 136 150 149 10 138 151
10 151 11 138 139 152 138 152 151
139 140 153 139 153 152 140 141 154
140 154 153 141 142 155 141 155 154
142 143 156 142 156 155 143 144 157
143 157 156 144 145 158 144 158 157
145 146 159 145 159 158 146 147 160
146 160 159 147 148 161 147 161 160
148 149 162 148 162 161 149 150 163
149 163 162 11 151 164 11 164 12
151 152 165 151 165 164 152 153 166
152 166 165 153 154 167 153 167 166
154 155 168 154 168 167 155 156 169
155 169 168 156 157 170 156 170 169
157 158 171 157 171 170 158 159 172
158 172 171 159 160 173 159 173 172
160 161 174 160 174 173 161 162 175
161 175 174 162 163 176 162 176 175
12 164 177 12 177 13 164 165 178
164 178 177 165 166 179 165 179 178
166 167 180 166 180 179 167 168 181
167 181 180 168 169 182 168 182 181
169 170 183 169 183 182 170 171 184
170 184 183 171 172 185 171 185 184
172 173 186 172 186 185 173 174 187
173 187 186 174 175 188 174 188 187
175 176 189 175 189 188 13 177 190
13 190 14 177 178 191 177 191 190
178 179 192 178 192 191 179 180 193
179 193 192 180 181 194 180 194 193
181 182 195 181 195 194 182 183 196
182 196 195 183 184 197 183 197 196
184 185 198 184 198 197 185 186 199
185 199 198 186 187 200 186 200 199
187 188 201 187 201 200 188 189 202
188 202 201 14 190 203 14 203 15
190 191 204 190 204 203 191 192 205
191 205 204 192 193 206 192 206 205
193 194 207 193 207 206 194 195 208
194 208 207 195 196 209 195 209 208
196 197 210 196 210 209 197 198 211
197 211 210 198 199 212 198 212 211
199 200 213 199 213 212 200 201 214
200 214 213 201 202 215 201 215 214
15 203 216 15 216 16 203 204 217
203 217 216 204 205 218 204 218 217
205 206 219 205 219 218 206 207 220
206 220 219 207 208 221 207 221 220
208 209 222 208 222 221 209 210 223
209 223 222 210 211 224 210 224 223
211 212 225 211 225 224 212 213 226
212 226 225 213 214 227 213 227 226
214 215 228 214 228 227 16 216 229
16 229 17 216 217 230 216 230 229
217 218 231 217 231 230 218 219 232
218 232 231 219 220 233 219 233 232
220 221 234 220 234 233 221 222 235
221 235 234 222 223 236 222 236 235
223 224 237 223 237 236 224 225 238
224 238 237 225 226 239 225 239 238
226 227 240 226 240 239 227 228 241
227 241 240 17 229 242 17 242 18
229 230 243 229 243 242 230 231 244
230 244 243 231 232 245 231 245 244
232 233 246 232 246 245 233 234 247
233 247 246 234 235 248 234 248 247
235 236 249 235 249 248 236 237 250
236 250 249 237 238 251 237 251 250
238 239 252 238 252 251 239 240 253
239 253 252 240 241 254 240 254 253
18 242 255 18 255 19 242 243 256
242 256 255 243 244 257 243 257 256
244 245 258 244 258 257 245 246 259
245 259 258 246 247 260 246 260 259
247 248 261 247 261 260 248 249 262
248 262 261 249 250 263 249 263 262
250 251 264 250 264 263 251 252 265
251 265 264 252 253 266 252 266 265
253 254 267 253 267 266 19 255 268
19 268 20 255 256 269 255 269 268
256 257 270 256 270 269 257 258 271
257 271 270 258 259 272 258 272 271
259 260 273 259 273 272 260 261 274
260 274 273 261 262 275 261 275 274
262 263 276 262 276 275 263 264 277
263 277 276 264 265 278 264 278 277
265 266 279 265 279 278 266 267 280
266 280 279 20 268 21 20 21 0
268 269 23 268 23 21 269 270 25
269 25 23 270 271 27 270 27 25
271 272 29 271 29 27 272 273 31
272 31 29 273 274 33 273 33 31
274 275 35 274 35 33 275 276 37
275 37 35 276 277 39 276 39 37
277 278 41 277 41 39 278 279 43
278 43 41 279 280 45 279 45 43
45 281 282 283 45 283 284 46 46
284 285 286 46 286 287 59 59 287
288 289 59 289 290 72 72 290 291
292 72 292 293 85 85 293 294 295
85 295 296 98 98 296 297 298 98
298 299 111 111 299 300 301 111 301
302 124 124 302 303 304 124 304 305
137 137 305 306 307 137 307 308 150
150 308 309 310 150 310 311 163 163
311 312 313 163 313 314 176 176 314
315 316 176 316 317 189 189 317 318
319 189 319 320 202 202 320 321 322
202 322 323 215 215 323 324 325 215
325 326 228 228 326 327 328 228 328
329 241 241 329 330 331 241 331 332
254 254 332 333 334 254 334 335 267
267 335 336 337 267 337 338 280 280
338 339 340 280 340 281 45 341 342
343 343 342 344 344 342 345 345 342
346 346 342 347 347 342 348 348 342
349 349 342 350 350 342 351 351 342
352 352 342 353 353 342 354 354 342
355 355 342 356 356 342 357 357 342
358 358 342 359 359 342 360 360 342
361 361 342 341 362 363 364 362 364
365 363 366 367 363 367 364 366 368
369 366 369 367 368 370 371 368 371
369 370 372 373 370 373 371 372 374
375 372 375 373 374 376 377 374 377
375 376 378 379 376 379 377 378 380
381 378 381 379 380 382 383 380 383
381 382 384 385 382 385 383 384 386
387 384 387 385 386 341 343 386 343
387 365 364 388 365 388 389 364 367
390 364 390 388 367 369 391 367 391
390 369 371 392 369 392 391 371 373
393 371 393 392 373 375 394 373 394
393 375 377 395 375 395 394 377 379
396 377 396 395 379 381 397 379 397
396 381 383 398 381 398 397 383 385
399 383 399 398 385 387 400 385 400
399 387 343 344 387 344 400 389 388
401 389 401 402 388 390 403 388 403
401 390 391 404 390 404 403 391 392
405 391 405 404 392 393 406 392 406
405 393 394 407 393 407 406 394 395
408 394 408 407 395 396 409 395 409
408 396 397 410 396 410 409 397 398
411 397 411 410 398 399 412 398 412
411 399 400 413 399 413 412 400 344
345 400 345 413 402 401 414 402 414
415 401 403 416 401 416 414 403 404
417 403 417 416 404 405 418 404 418
417 405 406 419 405 419 418 406 407
420 406 420 419 407 408 421 407 421
420 408 409 422 408 422 421 409 410
423 409 423 422 410 411 424 410 424
423 411 412 425 411 425 424 412 413
426 412 426 425 413 345 346 413 346
426 415 414 427 415 427 428 414 416
429 414 429 427 416 417 430 416 430
429 417 418 431 417 431 430 418 419
432 418 432 431 419 420 433 419 433
432 420 421 434 420 434 433 421 422
435 421 435 434 422 423 436 422 436
435 423 424 437 423 437 436 424 425
438 424 438 437 425 426 439 425 439
438 426 346 347 426 347 439 428 427
440 428 440 441 427 429 442 427 442
440 429 430 443 429 443 442 430 431
444 430 444 443 431 432 445 431 445
444 432 433 446 432 446 445 433 434
447 433 447 446 434 435 448 434 448
447 435 436 449 435 449 448 436 437
450 436 450 449 437 438 451 437 451
450 438 439 452 438 452 451 439 347
348 439 348 452 441 440 453 441 453
454 440 442 455 440 455 453 442 443
456 442 456 455 443 444 457 443 457
456 444 445 458 444 458 457 445 446
459 445 459 458 446 447 460 446 460
459 447 448 461 447 461 460 448 449
462 448 462 461 449 450 463 449 463
462 450 451 464 450 464 463 451 452
465 451 465 464 452 348 349 452 349
465 454 453 466 454 466 467 453 455
468 453 468 466 455 456 469 455 469
468 456 457 470 456 470 469 457 458
471 457 471 470 458 459 472 458 472
471 459 460 473 459 473 472 460 461
474 460 474 473 461 462 475 461 475
474 462 463 476 462 476 475 463 464
477 463 477 476 464 465 478 464 478
477 465 349 350 465 350 478 467 466
479 467 479 480 466 468 481 466 481
479 468 469 482 468 482 481 469 470
483 469 483 482 470 471 484 470 484
483 471 472 485 471 485 484 472 473
486 472 486 485 473 474 487 473 487
486 474 475 488 474 488 487 475 476
489 475 489 488 476 477 490 476 490
489 477 478 491 477 491 490 478 350
351 478 351 491 480 479 492 480 492
493 479 481 494 479 494 492 481 482
495 481 495 494 482 483 496 482 496
495 483 484 497 483 497 496 484 485
498 484 498 497 485 486 499 485 499
498 486 487 500 486 500 499 487 488
501 487 501 500 488 489 502 488 502
501 489 490 503 489 503 502 490 491
504 490 504 503 491 351 352 491 352
504 493 492 505 493 505 506 492 494
507 492 507 505 494 495 508 494 508
507 495 496 509 495 509 508 496 497
510 496 510 509 497 498 511 497 511
510 498 499 512 498 512 511 499 500
513 499 513 512 500 501 514 500 514
513 501 502 515 501 515 514 502 503
516 502 516 515 503 504 517 503 517
516 504 352 353 504 353 517 506 505
518 506 518 519 505 507 520 505 520
518 507 508 521 507 521 520 508 509
522 508 522 521 509 510 523 509 523
522 510 511 524 510 524 523 511 512
525 511 525 524 512 513 526 512 526
525 513 514 527 513 527 526 514 515
528 514 528 527 515 516 529 515 529
528 516 517 530 516 530 529 517 353
354 517 354 530 519 518 531 519 531
532 518 520 533 518 533 531 520 521
534 520 534 533 521 522 535 521 535
534 522 523 536 522 536 535 523 524
537 523 537 536 524 525 538 524 538
537 525 526 539 525 539 538 526 527
540 526 540 539 527 528 541 527 541
540 528 529 542 528 542 541 529 530
543 529 543 542 530 354 355 530 355
543 532 531 544 532 544 545 531 533
546 531 546 544 533 534 547 533 547
546 534 535 548 534 548 547 535 536
549 535 549 548 536 537 550 536 550
549 537 538 551 537 551 550 538 539
552 538 552 551 539 540 553 539 553
552 540 541 554 540 554 553 541 542
555 541 555 554 542 543 556 542 556
555 543 355 356 543 356 556 545 544
557 545 557 558 544 546 559 544 559
557 546 547 560 546 560 559 547 548
561 547 561 560 548 549 562 548 562
561 549 550 563 549 563 562 550 551
564 550 564 563 551 552 565 551 565
564 552 553 566 552 566 565 553 554
567 553 567 566 554 555 568 554 568
567 555 556 569 555 569 568 556 356
357 556 357 569 558 557 570 558 570
571 557 559 572 557 572 570 559 560
573 559 573 572 560 561 574 560 574
573 561 562 575 561 575 574 562 563
576 562 576 575 563 564 577 563 577
576 564 565 578 564 578 577 565 566
579 565 579 578 566 567 580 566 580
579 567 568 581 567 581 580 568 569
582 568 582 581 569 357 358 569 358
582 571 570 583 571 583 584 570 572
585 570 585 583 572 573 586 572 586
585 573 574 587 573 587 586 574 575
588 574 588 587 575 576 589 575 589
588 576 577 590 576 590 589 577 578
591 577 591 590 578 579 592 578 592
591 579 580 593 579 593 592 580 581
594 580 594 593 581 582 595 581 595
594 582 358 359 582 359 595 584 583
596 584 596 597 583 585 598 583 598
596 585 586 599 585 599 598 586 587
600 586 600 599 587 588 601 587 601
600 588 589 602 588 602 601 589 590
603 589 603 602 590 591 604 590 604
603 591 592 605 591 605 604 592 593
606 592 606 605 593 594 607 593 607
606 594 595 608 594 608 607 595 359
360 595 360 608 597 596 609 597 609
610 596 598 611 596 611 609 598 599
612 598 612 611 599 600 613 599 613
612 600 601 614 600 614 613 601 602
615 601 615 614 602 603 616 602 616
615 603 604 617 603 617 616 604 605
618 604 618 617 605 606 619 605 619
618 606 607 620 606 620 619 607 608
621 607 621 620 608 360 361 608 361
621 610 609 363 610 363 362 609 611
366 609 366 363 611 612 368 611 368
366 612 613 370 612 370 368 613 614
372 613 372 370 614 615 374 614 374
372 615 616 376 615 376 374 616 617
378 616 378 376 617 618 380 617 380
378 618 619 382 618 382 380 619 620
384 619 384 382 620 621 386 620 386
384 621 361 341 621 341 386 362 365
282 281 365 284 283 282 365 389 285
284 389 287 286 285 389 402 288 287
402 290 289 288 402 415 291 290 415
293 292 291 415 428 294 293 428 296
295 294 428 441 297 296 441 299 298
297 441 454 300 299 454 302 301 300
454 467 303 302 467 305 304 303 467
480 306 305 480 308 307 306 480 493
309 308 493 311 310 309 493 506 312
311 506 314 313 312 506 519 315 314
519 317 316 315 519 532 318 317 532
320 319 318 532 545 321 320 545 323
322 321 545 558 324 323 558 326 325
324 558 571 327 326 571 329 328 327
571 584 330 329 584 332 331 330 584
597 333 332 597 335 334 333 597 610
336 335 610 338 337 336 610 362 339
338 362 281 340 339
================================================
FILE: testing/data/branched3.vtk
================================================
# vtk DataFile Version 5.1
vtk output
ASCII
DATASET POLYDATA
POINTS 882 double
0.36786195636 0 0.33864077926 0.41858324409 0 0.27347406745 0.39809632301 0.12934933603 0.27347406745
0.34985750914 0.11367559433 0.33864077926 0.45788666606 0 0.20084771514 0.43547609448 0.14149476588 0.20084771514
0.48470014334 0 0.1227427423 0.4609772265 0.14978057146 0.1227427423 0.49829223752 0 0.041289672256
0.47390407324 0.15398077667 0.041289672256 0.49829223752 0 -0.041289672256 0.47390407324 0.15398077667 -0.041289672256
0.48470014334 0 -0.1227427423 0.4609772265 0.14978057146 -0.1227427423 0.45788666606 0 -0.20084771514
0.43547609448 0.14149476588 -0.20084771514 0.41858324409 0 -0.27347406745 0.39809632301 0.12934933603 -0.27347406745
0.36786195636 0 -0.33864077926 0.34985750914 0.11367559433 -0.33864077926 0.33864095807 0.24603705108 0.27347406745
0.29760658741 0.21622383595 0.33864077926 0.37043809891 0.26913902164 0.20084771514 0.39213064313 0.2848995924 0.1227427423
0.40312689543 0.29288882017 0.041289672256 0.40312689543 0.29288882017 -0.041289672256 0.39213064313 0.2848995924 -0.1227427423
0.37043809891 0.26913902164 -0.20084771514 0.33864095807 0.24603705108 -0.27347406745 0.29760658741 0.21622383595 -0.33864077926
0.24603705108 0.33864095807 0.27347406745 0.21622383595 0.29760658741 0.33864077926 0.26913902164 0.37043809891 0.20084771514
0.2848995924 0.39213064313 0.1227427423 0.29288882017 0.40312689543 0.041289672256 0.29288882017 0.40312689543 -0.041289672256
0.2848995924 0.39213064313 -0.1227427423 0.26913902164 0.37043809891 -0.20084771514 0.24603705108 0.33864095807 -0.27347406745
0.21622383595 0.29760658741 -0.33864077926 0.12934933603 0.39809632301 0.27347406745 0.11367559433 0.34985750914 0.33864077926
0.14149476588 0.43547609448 0.20084771514 0.14978057146 0.4609772265 0.1227427423 0.15398077667 0.47390407324 0.041289672256
0.15398077667 0.47390407324 -0.041289672256 0.14978057146 0.4609772265 -0.1227427423 0.14149476588 0.43547609448 -0.20084771514
0.12934933603 0.39809632301 -0.27347406745 0.11367559433 0.34985750914 -0.33864077926 2.5630831518e-17 0.41858324409 0.27347406745
2.2525047905e-17 0.36786195636 0.33864077926 2.8037472151e-17 0.45788666606 0.20084771514 2.9679323096e-17 0.48470014334 0.1227427423
3.0511599142e-17 0.49829223752 0.041289672256 3.0511599142e-17 0.49829223752 -0.041289672256 2.9679323096e-17 0.48470014334 -0.1227427423
2.8037472151e-17 0.45788666606 -0.20084771514 2.5630831518e-17 0.41858324409 -0.27347406745 2.2525047905e-17 0.36786195636 -0.33864077926
-0.12934933603 0.39809632301 0.27347406745 -0.11367559433 0.34985750914 0.33864077926 -0.14149476588 0.43547609448 0.20084771514
-0.14978057146 0.4609772265 0.1227427423 -0.15398077667 0.47390407324 0.041289672256 -0.15398077667 0.47390407324 -0.041289672256
-0.14978057146 0.4609772265 -0.1227427423 -0.14149476588 0.43547609448 -0.20084771514 -0.12934933603 0.39809632301 -0.27347406745
-0.11367559433 0.34985750914 -0.33864077926 -0.24603705108 0.33864095807 0.27347406745 -0.21622383595 0.29760658741 0.33864077926
-0.26913902164 0.37043809891 0.20084771514 -0.2848995924 0.39213064313 0.1227427423 -0.29288882017 0.40312689543 0.041289672256
-0.29288882017 0.40312689543 -0.041289672256 -0.2848995924 0.39213064313 -0.1227427423 -0.26913902164 0.37043809891 -0.20084771514
-0.24603705108 0.33864095807 -0.27347406745 -0.21622383595 0.29760658741 -0.33864077926 -0.33864095807 0.24603705108 0.27347406745
-0.29760658741 0.21622383595 0.33864077926 -0.37043809891 0.26913902164 0.20084771514 -0.39213064313 0.2848995924 0.1227427423
-0.40312689543 0.29288882017 0.041289672256 -0.40312689543 0.29288882017 -0.041289672256 -0.39213064313 0.2848995924 -0.1227427423
-0.37043809891 0.26913902164 -0.20084771514 -0.33864095807 0.24603705108 -0.27347406745 -0.29760658741 0.21622383595 -0.33864077926
-0.39809632301 0.12934933603 0.27347406745 -0.34985750914 0.11367559433 0.33864077926 -0.43547609448 0.14149476588 0.20084771514
-0.4609772265 0.14978057146 0.1227427423 -0.47390407324 0.15398077667 0.041289672256 -0.47390407324 0.15398077667 -0.041289672256
-0.4609772265 0.14978057146 -0.1227427423 -0.43547609448 0.14149476588 -0.20084771514 -0.39809632301 0.12934933603 -0.27347406745
-0.34985750914 0.11367559433 -0.33864077926 -0.41858324409 5.1261663035e-17 0.27347406745 -0.36786195636 4.5050095809e-17 0.33864077926
-0.45788666606 5.6074944302e-17 0.20084771514 -0.48470014334 5.9358646193e-17 0.1227427423 -0.49829223752 6.1023198283e-17 0.041289672256
-0.49829223752 6.1023198283e-17 -0.041289672256 -0.48470014334 5.9358646193e-17 -0.1227427423 -0.45788666606 5.6074944302e-17 -0.20084771514
-0.41858324409 5.1261663035e-17 -0.27347406745 -0.36786195636 4.5050095809e-17 -0.33864077926 -0.39809632301 -0.12934933603 0.27347406745
-0.34985750914 -0.11367559433 0.33864077926 -0.43547609448 -0.14149476588 0.20084771514 -0.4609772265 -0.14978057146 0.1227427423
-0.47390407324 -0.15398077667 0.041289672256 -0.47390407324 -0.15398077667 -0.041289672256 -0.4609772265 -0.14978057146 -0.1227427423
-0.43547609448 -0.14149476588 -0.20084771514 -0.39809632301 -0.12934933603 -0.27347406745 -0.34985750914 -0.11367559433 -0.33864077926
-0.33864095807 -0.24603705108 0.27347406745 -0.29760658741 -0.21622383595 0.33864077926 -0.37043809891 -0.26913902164 0.20084771514
-0.39213064313 -0.2848995924 0.1227427423 -0.40312689543 -0.29288882017 0.041289672256 -0.40312689543 -0.29288882017 -0.041289672256
-0.39213064313 -0.2848995924 -0.1227427423 -0.37043809891 -0.26913902164 -0.20084771514 -0.33864095807 -0.24603705108 -0.27347406745
-0.29760658741 -0.21622383595 -0.33864077926 -0.24603705108 -0.33864095807 0.27347406745 -0.21622383595 -0.29760658741 0.33864077926
-0.26913902164 -0.37043809891 0.20084771514 -0.2848995924 -0.39213064313 0.1227427423 -0.29288882017 -0.40312689543 0.041289672256
-0.29288882017 -0.40312689543 -0.041289672256 -0.2848995924 -0.39213064313 -0.1227427423 -0.26913902164 -0.37043809891 -0.20084771514
-0.24603705108 -0.33864095807 -0.27347406745 -0.21622383595 -0.29760658741 -0.33864077926 -0.12934933603 -0.39809632301 0.27347406745
-0.11367559433 -0.34985750914 0.33864077926 -0.14149476588 -0.43547609448 0.20084771514 -0.14978057146 -0.4609772265 0.1227427423
-0.15398077667 -0.47390407324 0.041289672256 -0.15398077667 -0.47390407324 -0.041289672256 -0.14978057146 -0.4609772265 -0.1227427423
-0.14149476588 -0.43547609448 -0.20084771514 -0.12934933603 -0.39809632301 -0.27347406745 -0.11367559433 -0.34985750914 -0.33864077926
-7.6892492899e-17 -0.41858324409 0.27347406745 -6.7575143714e-17 -0.36786195636 0.33864077926 -8.4112416453e-17 -0.45788666606 0.20084771514
-8.9037972598e-17 -0.48470014334 0.1227427423 -9.1534800733e-17 -0.49829223752 0.041289672256 -9.1534800733e-17 -0.49829223752 -0.041289672256
-8.9037972598e-17 -0.48470014334 -0.1227427423 -8.4112416453e-17 -0.45788666606 -0.20084771514 -7.6892492899e-17 -0.41858324409 -0.27347406745
-6.7575143714e-17 -0.36786195636 -0.33864077926 0.12934933603 -0.39809632301 0.27347406745 0.11367559433 -0.34985750914 0.33864077926
0.14149476588 -0.43547609448 0.20084771514 0.14978057146 -0.4609772265 0.1227427423 0.15398077667 -0.47390407324 0.041289672256
0.15398077667 -0.47390407324 -0.041289672256 0.14978057146 -0.4609772265 -0.1227427423 0.14149476588 -0.43547609448 -0.20084771514
0.12934933603 -0.39809632301 -0.27347406745 0.11367559433 -0.34985750914 -0.33864077926 0.24603705108 -0.33864095807 0.27347406745
0.21622383595 -0.29760658741 0.33864077926 0.26913902164 -0.37043809891 0.20084771514 0.2848995924 -0.39213064313 0.1227427423
0.29288882017 -0.40312689543 0.041289672256 0.29288882017 -0.40312689543 -0.041289672256 0.2848995924 -0.39213064313 -0.1227427423
0.26913902164 -0.37043809891 -0.20084771514 0.24603705108 -0.33864095807 -0.27347406745 0.21622383595 -0.29760658741 -0.33864077926
0.33864095807 -0.24603705108 0.27347406745 0.29760658741 -0.21622383595 0.33864077926 0.37043809891 -0.26913902164 0.20084771514
0.39213064313 -0.2848995924 0.1227427423 0.40312689543 -0.29288882017 0.041289672256 0.40312689543 -0.29288882017 -0.041289672256
0.39213064313 -0.2848995924 -0.1227427423 0.37043809891 -0.26913902164 -0.20084771514 0.33864095807 -0.24603705108 -0.27347406745
0.29760658741 -0.21622383595 -0.33864077926 0.39809632301 -0.12934933603 0.27347406745 0.34985750914 -0.11367559433 0.33864077926
0.43547609448 -0.14149476588 0.20084771514 0.4609772265 -0.14978057146 0.1227427423 0.47390407324 -0.15398077667 0.041289672256
0.47390407324 -0.15398077667 -0.041289672256 0.4609772265 -0.14978057146 -0.1227427423 0.43547609448 -0.14149476588 -0.20084771514
0.39809632301 -0.12934933603 -0.27347406745 0.34985750914 -0.11367559433 -0.33864077926 0.3283653157 -6.2943287406e-18 -0.375
0.32206539101 0.039776188896 -0.37500000495 0.3185939096 0.061694295065 -0.37500000495 0.31229398784 0.10147046551 -0.375
0.29401088955 0.13735306593 -0.37499999486 0.28393623568 0.15712568057 -0.37499999486 0.26565312857 0.1930082983 -0.375
0.23717652463 0.22148490223 -0.375 0.22148490223 0.23717652463 -0.375 0.1930082983 0.26565312857 -0.375
0.15712568057 0.28393623568 -0.37500000514 0.13735306593 0.29401088955 -0.37500000514 0.10147046551 0.31229398784 -0.375
0.061694295065 0.3185939096 -0.37499999505 0.039776188896 0.32206539101 -0.37499999505 2.5828452418e-17 0.3283653157 -0.375
-0.039776188896 0.32206539101 -0.37500000495 -0.061694295065 0.3185939096 -0.37500000495 -0.10147046551 0.31229398784 -0.375
-0.13735306593 0.29401088955 -0.37499999486 -0.15712568057 0.28393623568 -0.37499999486 -0.1930082983 0.26565312857 -0.375
-0.22148490223 0.23717652463 -0.375 -0.23717652463 0.22148490223 -0.375 -0.26565312857 0.1930082983 -0.375
-0.28393623568 0.15712568057 -0.37500000514 -0.29401088955 0.13735306593 -0.37500000514 -0.31229398784 0.10147046551 -0.375
-0.3185939096 0.061694295065 -0.37499999505 -0.32206539101 0.039776188896 -0.37499999505 -0.3283653157 4.1448352812e-17 -0.375
-0.32206539101 -0.039776188896 -0.37500000495 -0.3185939096 -0.061694295065 -0.37500000495 -0.31229398784 -0.10147046551 -0.375
-0.29401088955 -0.13735306593 -0.37499999486 -0.28393623568 -0.15712568057 -0.37499999486 -0.26565312857 -0.1930082983 -0.375
-0.23717652463 -0.22148490223 -0.375 -0.22148490223 -0.23717652463 -0.375 -0.1930082983 -0.26565312857 -0.375
-0.15712568057 -0.28393623568 -0.37500000514 -0.13735306593 -0.29401088955 -0.37500000514 -0.10147046551 -0.31229398784 -0.375
-0.061694295065 -0.3185939096 -0.37499999505 -0.039776188896 -0.32206539101 -0.37499999505 -6.1641014888e-17 -0.3283653157 -0.375
0.039776188896 -0.32206539101 -0.37500000495 0.061694295065 -0.3185939096 -0.37500000495 0.10147046551 -0.31229398784 -0.375
0.13735306593 -0.29401088955 -0.37499999486 0.15712568057 -0.28393623568 -0.37499999486 0.1930082983 -0.26565312857 -0.375
0.22148490223 -0.23717652463 -0.375 0.23717652463 -0.22148490223 -0.375 0.26565312857 -0.1930082983 -0.375
0.28393623568 -0.15712568057 -0.37500000514 0.29401088955 -0.13735306593 -0.37500000514 0.31229398784 -0.10147046551 -0.375
0.3185939096 -0.061694295065 -0.37499999505 0.32206539101 -0.039776188896 -0.37499999505 0.082297295332 0 -1.2431806326
0 0 -1.25 0.078269377351 0.025431262329 -1.2431806326 0.066579908133 0.048373136669 -1.2431806326
0.048373136669 0.066579908133 -1.2431806326 0.025431262329 0.078269377351 -1.2431806326 5.0392558428e-18 0.082297295332 -1.2431806326
-0.025431262329 0.078269377351 -1.2431806326 -0.048373136669 0.066579908133 -1.2431806326 -0.066579908133 0.048373136669 -1.2431806326
-0.078269377351 0.025431262329 -1.2431806326 -0.082297295332 1.0078511686e-17 -1.2431806326 -0.078269377351 -0.025431262329 -1.2431806326
-0.066579908133 -0.048373136669 -1.2431806326 -0.048373136669 -0.066579908133 -1.2431806326 -0.025431262329 -0.078269377351 -1.2431806326
-1.5117767942e-17 -0.082297295332 -1.2431806326 0.025431262329 -0.078269377351 -1.2431806326 0.048373136669 -0.066579908133 -1.2431806326
0.066579908133 -0.048373136669 -1.2431806326 0.078269377351 -0.025431262329 -1.2431806326 0.36786195636 0 -0.41135922074
0.41858324409 0 -0.47652593255 0.39809632301 0.12934933603 -0.47652593255 0.34985750914 0.11367559433 -0.41135922074
0.45788666606 0 -0.54915231466 0.43547609448 0.14149476588 -0.54915231466 0.48470014334 0 -0.6272572279
0.4609772265 0.14978057146 -0.6272572279 0.49829223752 0 -0.70871031284 0.47390407324 0.15398077667 -0.70871031284
0.49829223752 0 -0.79128968716 0.47390407324 0.15398077667 -0.79128968716 0.48470014334 0 -0.8727427721
0.4609772265 0.14978057146 -0.8727427721 0.45788666606 0 -0.95084768534 0.43547609448 0.14149476588 -0.95084768534
0.41858324409 0 -1.0234740973 0.39809632301 0.12934933603 -1.0234740973 0.36786195636 0 -1.0886408091
0.34985750914 0.11367559433 -1.0886408091 0.30710634589 0 -1.1445702314 0.29207551479 0.0949010849 -1.1445702314
0.23797369003 0 -1.1897368431 0.2263264358 0.073537915945 -1.1897368431 0.16234973073 0 -1.2229086161
0.15440377593 0.050168827176 -1.2229086161 0.33864095807 0.24603705108 -0.47652593255 0.29760658741 0.21622383595 -0.41135922074
0.37043809891 0.26913902164 -0.54915231466 0.39213064313 0.2848995924 -0.6272572279 0.40312689543 0.29288882017 -0.70871031284
0.40312689543 0.29288882017 -0.79128968716 0.39213064313 0.2848995924 -0.8727427721 0.37043809891 0.26913902164 -0.95084768534
0.33864095807 0.24603705108 -1.0234740973 0.29760658741 0.21622383595 -1.0886408091 0.24845425785 0.1805125922 -1.1445702314
0.19252476096 0.13987742364 -1.1897368431 0.13134369254 0.095426782966 -1.2229086161 0.24603705108 0.33864095807 -0.47652593255
0.21622383595 0.29760658741 -0.41135922074 0.26913902164 0.37043809891 -0.54915231466 0.2848995924 0.39213064313 -0.6272572279
0.29288882017 0.40312689543 -0.70871031284 0.29288882017 0.40312689543 -0.79128968716 0.2848995924 0.39213064313 -0.8727427721
0.26913902164 0.37043809891 -0.95084768534 0.24603705108 0.33864095807 -1.0234740973 0.21622383595 0.29760658741 -1.0886408091
0.1805125922 0.24845425785 -1.1445702314 0.13987742364 0.19252476096 -1.1897368431 0.095426782966 0.13134369254 -1.2229086161
0.12934933603 0.39809632301 -0.47652593255 0.11367559433 0.34985750914 -0.41135922074 0.14149476588 0.43547609448 -0.54915231466
0.14978057146 0.4609772265 -0.6272572279 0.15398077667 0.47390407324 -0.70871031284 0.15398077667 0.47390407324 -0.79128968716
0.14978057146 0.4609772265 -0.8727427721 0.14149476588 0.43547609448 -0.95084768534 0.12934933603 0.39809632301 -1.0234740973
0.11367559433 0.34985750914 -1.0886408091 0.0949010849 0.29207551479 -1.1445702314 0.073537915945 0.2263264358 -1.1897368431
0.050168827176 0.15440377593 -1.2229086161 2.5630831518e-17 0.41858324409 -0.47652593255 2.2525047905e-17 0.36786195636 -0.41135922074
2.8037472151e-17 0.45788666606 -0.54915231466 2.9679323096e-17 0.48470014334 -0.6272572279 3.0511599142e-17 0.49829223752 -0.70871031284
3.0511599142e-17 0.49829223752 -0.79128968716 2.9679323096e-17 0.48470014334 -0.8727427721 2.8037472151e-17 0.45788666606 -0.95084768534
2.5630831518e-17 0.41858324409 -1.0234740973 2.2525047905e-17 0.36786195636 -1.0886408091 1.880484115e-17 0.30710634589 -1.1445702314
1.4571686463e-17 0.23797369003 -1.1897368431 9.9410541201e-18 0.16234973073 -1.2229086161 -0.12934933603 0.39809632301 -0.47652593255
-0.11367559433 0.34985750914 -0.41135922074 -0.14149476588 0.43547609448 -0.54915231466 -0.14978057146 0.4609772265 -0.6272572279
-0.15398077667 0.47390407324 -0.70871031284 -0.15398077667 0.47390407324 -0.79128968716 -0.14978057146 0.4609772265 -0.8727427721
-0.14149476588 0.43547609448 -0.95084768534 -0.12934933603 0.39809632301 -1.0234740973 -0.11367559433 0.34985750914 -1.0886408091
-0.0949010849 0.29207551479 -1.1445702314 -0.073537915945 0.2263264358 -1.1897368431 -0.050168827176 0.15440377593 -1.2229086161
-0.24603705108 0.33864095807 -0.47652593255 -0.21622383595 0.29760658741 -0.41135922074 -0.26913902164 0.37043809891 -0.54915231466
-0.2848995924 0.39213064313 -0.6272572279 -0.29288882017 0.40312689543 -0.70871031284 -0.29288882017 0.40312689543 -0.79128968716
-0.2848995924 0.39213064313 -0.8727427721 -0.26913902164 0.37043809891 -0.95084768534 -0.24603705108 0.33864095807 -1.0234740973
-0.21622383595 0.29760658741 -1.0886408091 -0.1805125922 0.24845425785 -1.1445702314 -0.13987742364 0.19252476096 -1.1897368431
-0.095426782966 0.13134369254 -1.2229086161 -0.33864095807 0.24603705108 -0.47652593255 -0.29760658741 0.21622383595 -0.41135922074
-0.37043809891 0.26913902164 -0.54915231466 -0.39213064313 0.2848995924 -0.6272572279 -0.40312689543 0.29288882017 -0.70871031284
-0.40312689543 0.29288882017 -0.79128968716 -0.39213064313 0.2848995924 -0.8727427721 -0.37043809891 0.26913902164 -0.95084768534
-0.33864095807 0.24603705108 -1.0234740973 -0.29760658741 0.21622383595 -1.0886408091 -0.24845425785 0.1805125922 -1.1445702314
-0.19252476096 0.13987742364 -1.1897368431 -0.13134369254 0.095426782966 -1.2229086161 -0.39809632301 0.12934933603 -0.47652593255
-0.34985750914 0.11367559433 -0.41135922074 -0.43547609448 0.14149476588 -0.54915231466 -0.4609772265 0.14978057146 -0.6272572279
-0.47390407324 0.15398077667 -0.70871031284 -0.47390407324 0.15398077667 -0.79128968716 -0.4609772265 0.14978057146 -0.8727427721
-0.43547609448 0.14149476588 -0.95084768534 -0.39809632301 0.12934933603 -1.0234740973 -0.34985750914 0.11367559433 -1.0886408091
-0.29207551479 0.0949010849 -1.1445702314 -0.2263264358 0.073537915945 -1.1897368431 -0.15440377593 0.050168827176 -1.2229086161
-0.41858324409 5.1261663035e-17 -0.47652593255 -0.36786195636 4.5050095809e-17 -0.41135922074 -0.45788666606 5.6074944302e-17 -0.54915231466
-0.48470014334 5.9358646193e-17 -0.6272572279 -0.49829223752 6.1023198283e-17 -0.70871031284 -0.49829223752 6.1023198283e-17 -0.79128968716
-0.48470014334 5.9358646193e-17 -0.8727427721 -0.45788666606 5.6074944302e-17 -0.95084768534 -0.41858324409 5.1261663035e-17 -1.0234740973
-0.36786195636 4.5050095809e-17 -1.0886408091 -0.30710634589 3.76096823e-17 -1.1445702314 -0.23797369003 2.9143372925e-17 -1.1897368431
-0.16234973073 1.988210824e-17 -1.2229086161 -0.39809632301 -0.12934933603 -0.47652593255 -0.34985750914 -0.11367559433 -0.41135922074
-0.43547609448 -0.14149476588 -0.54915231466 -0.4609772265 -0.14978057146 -0.6272572279 -0.47390407324 -0.15398077667 -0.70871031284
-0.47390407324 -0.15398077667 -0.79128968716 -0.4609772265 -0.14978057146 -0.8727427721 -0.43547609448 -0.14149476588 -0.95084768534
-0.39809632301 -0.12934933603 -1.0234740973 -0.34985750914 -0.11367559433 -1.0886408091 -0.29207551479 -0.0949010849 -1.1445702314
-0.2263264358 -0.073537915945 -1.1897368431 -0.15440377593 -0.050168827176 -1.2229086161 -0.33864095807 -0.24603705108 -0.47652593255
-0.29760658741 -0.21622383595 -0.41135922074 -0.37043809891 -0.26913902164 -0.54915231466 -0.39213064313 -0.2848995924 -0.6272572279
-0.40312689543 -0.29288882017 -0.70871031284 -0.40312689543 -0.29288882017 -0.79128968716 -0.39213064313 -0.2848995924 -0.8727427721
-0.37043809891 -0.26913902164 -0.95084768534 -0.33864095807 -0.24603705108 -1.0234740973 -0.29760658741 -0.21622383595 -1.0886408091
-0.24845425785 -0.1805125922 -1.1445702314 -0.19252476096 -0.13987742364 -1.1897368431 -0.13134369254 -0.095426782966 -1.2229086161
-0.24603705108 -0.33864095807 -0.47652593255 -0.21622383595 -0.29760658741 -0.41135922074 -0.26913902164 -0.37043809891 -0.54915231466
-0.2848995924 -0.39213064313 -0.6272572279 -0.29288882017 -0.40312689543 -0.70871031284 -0.29288882017 -0.40312689543 -0.79128968716
-0.2848995924 -0.39213064313 -0.8727427721 -0.26913902164 -0.37043809891 -0.95084768534 -0.24603705108 -0.33864095807 -1.0234740973
-0.21622383595 -0.29760658741 -1.0886408091 -0.1805125922 -0.24845425785 -1.1445702314 -0.13987742364 -0.19252476096 -1.1897368431
-0.095426782966 -0.13134369254 -1.2229086161 -0.12934933603 -0.39809632301 -0.47652593255 -0.11367559433 -0.34985750914 -0.41135922074
-0.14149476588 -0.43547609448 -0.54915231466 -0.14978057146 -0.4609772265 -0.6272572279 -0.15398077667 -0.47390407324 -0.70871031284
-0.15398077667 -0.47390407324 -0.79128968716 -0.14978057146 -0.4609772265 -0.8727427721 -0.14149476588 -0.43547609448 -0.95084768534
-0.12934933603 -0.39809632301 -1.0234740973 -0.11367559433 -0.34985750914 -1.0886408091 -0.0949010849 -0.29207551479 -1.1445702314
-0.073537915945 -0.2263264358 -1.1897368431 -0.050168827176 -0.15440377593 -1.2229086161 -7.6892492899e-17 -0.41858324409 -0.47652593255
-6.7575143714e-17 -0.36786195636 -0.41135922074 -8.4112416453e-17 -0.45788666606 -0.54915231466 -8.9037972598e-17 -0.48470014334 -0.6272572279
-9.1534800733e-17 -0.49829223752 -0.70871031284 -9.1534800733e-17 -0.49829223752 -0.79128968716 -8.9037972598e-17 -0.48470014334 -0.8727427721
-8.4112416453e-17 -0.45788666606 -0.95084768534 -7.6892492899e-17 -0.41858324409 -1.0234740973 -6.7575143714e-17 -0.36786195636 -1.0886408091
-5.6414525104e-17 -0.30710634589 -1.1445702314 -4.3715059388e-17 -0.23797369003 -1.1897368431 -2.9823163188e-17 -0.16234973073 -1.2229086161
0.12934933603 -0.39809632301 -0.47652593255 0.11367559433 -0.34985750914 -0.41135922074 0.14149476588 -0.43547609448 -0.54915231466
0.14978057146 -0.4609772265 -0.6272572279 0.15398077667 -0.47390407324 -0.70871031284 0.15398077667 -0.47390407324 -0.79128968716
0.14978057146 -0.4609772265 -0.8727427721 0.14149476588 -0.43547609448 -0.95084768534 0.12934933603 -0.39809632301 -1.0234740973
0.11367559433 -0.34985750914 -1.0886408091 0.0949010849 -0.29207551479 -1.1445702314 0.073537915945 -0.2263264358 -1.1897368431
0.050168827176 -0.15440377593 -1.2229086161 0.24603705108 -0.33864095807 -0.47652593255 0.21622383595 -0.29760658741 -0.41135922074
0.26913902164 -0.37043809891 -0.54915231466 0.2848995924 -0.39213064313 -0.6272572279 0.29288882017 -0.40312689543 -0.70871031284
0.29288882017 -0.40312689543 -0.79128968716 0.2848995924 -0.39213064313 -0.8727427721 0.26913902164 -0.37043809891 -0.95084768534
0.24603705108 -0.33864095807 -1.0234740973 0.21622383595 -0.29760658741 -1.0886408091 0.1805125922 -0.24845425785 -1.1445702314
0.13987742364 -0.19252476096 -1.1897368431 0.095426782966 -0.13134369254 -1.2229086161 0.33864095807 -0.24603705108 -0.47652593255
0.29760658741 -0.21622383595 -0.41135922074 0.37043809891 -0.26913902164 -0.54915231466 0.39213064313 -0.2848995924 -0.6272572279
0.40312689543 -0.29288882017 -0.70871031284 0.40312689543 -0.29288882017 -0.79128968716 0.39213064313 -0.2848995924 -0.8727427721
0.37043809891 -0.26913902164 -0.95084768534 0.33864095807 -0.24603705108 -1.0234740973 0.29760658741 -0.21622383595 -1.0886408091
0.24845425785 -0.1805125922 -1.1445702314 0.19252476096 -0.13987742364 -1.1897368431 0.13134369254 -0.095426782966 -1.2229086161
0.39809632301 -0.12934933603 -0.47652593255 0.34985750914 -0.11367559433 -0.41135922074 0.43547609448 -0.14149476588 -0.54915231466
0.4609772265 -0.14978057146 -0.6272572279 0.47390407324 -0.15398077667 -0.70871031284 0.47390407324 -0.15398077667 -0.79128968716
0.4609772265 -0.14978057146 -0.8727427721 0.43547609448 -0.14149476588 -0.95084768534 0.39809632301 -0.12934933603 -1.0234740973
0.34985750914 -0.11367559433 -1.0886408091 0.29207551479 -0.0949010849 -1.1445702314 0.2263264358 -0.073537915945 -1.1897368431
0.15440377593 -0.050168827176 -1.2229086161 0.32206539101 0.039776188896 0.37499999505 0.3283653157 6.2943287406e-18 0.375
0.31229398784 0.10147046551 0.375 0.3185939096 0.061694295065 0.37499999505 0.29401088955 0.13735306593 0.37500000514
0.26565312857 0.1930082983 0.375 0.28393623568 0.15712568057 0.37500000514 0.23717652463 0.22148490223 0.375
0.1930082983 0.26565312857 0.375 0.22148490223 0.23717652463 0.375 0.15712568057 0.28393623568 0.37499999486
0.10147046551 0.31229398784 0.375 0.13735306593 0.29401088955 0.37499999486 0.061694295065 0.3185939096 0.37500000495
1.779775782e-17 0.3283653157 0.375 0.039776188896 0.32206539101 0.37500000495 -0.039776188896 0.32206539101 0.37499999505
-0.10147046551 0.31229398784 0.375 -0.061694295065 0.3185939096 0.37499999505 -0.13735306593 0.29401088955 0.37500000514
-0.1930082983 0.26565312857 0.375 -0.15712568057 0.28393623568 0.37500000514 -0.22148490223 0.23717652463 0.375
-0.26565312857 0.1930082983 0.375 -0.23717652463 0.22148490223 0.375 -0.28393623568 0.15712568057 0.37499999486
-0.31229398784 0.10147046551 0.375 -0.29401088955 0.13735306593 0.37499999486 -0.3185939096 0.061694295065 0.37500000495
-0.3283653157 3.7802275371e-17 0.375 -0.32206539101 0.039776188896 0.37500000495 -0.32206539101 -0.039776188896 0.37499999505
-0.31229398784 -0.10147046551 0.375 -0.3185939096 -0.061694295065 0.37499999505 -0.29401088955 -0.13735306593 0.37500000514
-0.26565312857 -0.1930082983 0.375 -0.28393623568 -0.15712568057 0.37500000514 -0.23717652463 -0.22148490223 0.375
-0.1930082983 -0.26565312857 0.375 -0.22148490223 -0.23717652463 0.375 -0.15712568057 -0.28393623568 0.37499999486
-0.10147046551 -0.31229398784 0.375 -0.13735306593 -0.29401088955 0.37499999486 -0.061694295065 -0.3185939096 0.37500000495
-5.7734190001e-17 -0.3283653157 0.375 -0.039776188896 -0.32206539101 0.37500000495 0.039776188896 -0.32206539101 0.37499999505
0.10147046551 -0.31229398784 0.375 0.061694295065 -0.3185939096 0.37499999505 0.13735306593 -0.29401088955 0.37500000514
0.1930082983 -0.26565312857 0.375 0.15712568057 -0.28393623568 0.37500000514 0.22148490223 -0.23717652463 0.375
0.26565312857 -0.1930082983 0.375 0.23717652463 -0.22148490223 0.375 0.28393623568 -0.15712568057 0.37499999486
0.31229398784 -0.10147046551 0.375 0.29401088955 -0.13735306593 0.37499999486 0.3185939096 -0.061694295065 0.37500000495
0.32206539101 -0.039776188896 0.37500000495 0.082297295332 0 1.2431806326 0.078269377351 0.025431262329 1.2431806326
0 0 1.25 0.066579908133 0.048373136669 1.2431806326 0.048373136669 0.066579908133 1.2431806326
0.025431262329 0.078269377351 1.2431806326 5.0392558428e-18 0.082297295332 1.2431806326 -0.025431262329 0.078269377351 1.2431806326
-0.048373136669 0.066579908133 1.2431806326 -0.066579908133 0.048373136669 1.2431806326 -0.078269377351 0.025431262329 1.2431806326
-0.082297295332 1.0078511686e-17 1.2431806326 -0.078269377351 -0.025431262329 1.2431806326 -0.066579908133 -0.048373136669 1.2431806326
-0.048373136669 -0.066579908133 1.2431806326 -0.025431262329 -0.078269377351 1.2431806326 -1.5117767942e-17 -0.082297295332 1.2431806326
0.025431262329 -0.078269377351 1.2431806326 0.048373136669 -0.066579908133 1.2431806326 0.066579908133 -0.048373136669 1.2431806326
0.078269377351 -0.025431262329 1.2431806326 0.16234973073 0 1.2229086161 0.15440377593 0.050168827176 1.2229086161
0.23797369003 0 1.1897368431 0.2263264358 0.073537915945 1.1897368431 0.30710634589 0 1.1445702314
0.29207551479 0.0949010849 1.1445702314 0.36786195636 0 1.0886408091 0.34985750914 0.11367559433 1.0886408091
0.41858324409 0 1.0234740973 0.39809632301 0.12934933603 1.0234740973 0.45788666606 0 0.95084768534
0.43547609448 0.14149476588 0.95084768534 0.48470014334 0 0.8727427721 0.4609772265 0.14978057146 0.8727427721
0.49829223752 0 0.79128968716 0.47390407324 0.15398077667 0.79128968716 0.49829223752 0 0.70871031284
0.47390407324 0.15398077667 0.70871031284 0.48470014334 0 0.6272572279 0.4609772265 0.14978057146 0.6272572279
0.45788666606 0 0.54915231466 0.43547609448 0.14149476588 0.54915231466 0.41858324409 0 0.47652593255
0.39809632301 0.12934933603 0.47652593255 0.36786195636 0 0.41135922074 0.34985750914 0.11367559433 0.41135922074
0.13134369254 0.0954
gitextract_hxnqu4v5/ ├── .github/ │ ├── FUNDING.yml │ └── workflows/ │ └── cmake.yml ├── CITATION.cff ├── CMakeLists.txt ├── Contact.cxx ├── Contact.h ├── LICENSE ├── Merger.cxx ├── Merger.h ├── Optimize.cxx ├── Optimize.h ├── README.md ├── Utilities.cxx ├── Utilities.h ├── module/ │ ├── CMakeLists.txt │ └── vtk.module ├── paraview/ │ ├── CMakeLists.txt │ ├── module/ │ │ ├── CMakeLists.txt │ │ ├── vtk.module │ │ └── vtkPolyDataBooleanFilter.xml │ └── paraview.plugin ├── run_some_tests.sh ├── testing/ │ ├── data/ │ │ ├── branched.vtk │ │ ├── branched3.vtk │ │ ├── branched4.vtk │ │ ├── branched6.vtk │ │ ├── cross.vtk │ │ ├── merger.vtk │ │ └── non-manifold.vtk │ ├── generate_frieze.py │ ├── pytest.ini │ ├── test_congruence.cxx │ ├── test_filter.py │ ├── test_merger.cxx │ └── test_python.py ├── vtkPolyDataBooleanFilter.cxx └── vtkPolyDataBooleanFilter.h
SYMBOL INDEX (135 symbols across 13 files)
FILE: Contact.cxx
function Clean (line 33) | vtkSmartPointer<vtkPolyData> Clean (vtkPolyData *pd) {
type Cmp (line 383) | struct Cmp {
FILE: Contact.h
type class (line 26) | enum class
type class (line 31) | enum class
function PointSrc (line 37) | enum class PointSrc {
type std (line 103) | typedef std::vector<InterPt> InterPtsType;
type std (line 104) | typedef std::vector<std::tuple<InterPt, InterPt>> OverlapsType;
type std (line 106) | typedef std::set<Pair> NonManifoldEdgesType;
type std (line 108) | typedef std::vector<std::pair<vtkIdType, vtkIdType>> PairsType;
function class (line 112) | class Contact {
FILE: Merger.h
type std (line 22) | typedef std::vector<std::size_t> GroupType;
type std (line 24) | typedef std::map<vtkIdType, std::size_t> SourcesType;
function class (line 26) | class Conn {
type ConnCmp (line 48) | struct ConnCmp {
type std (line 54) | typedef std::vector<Conn> ConnsType;
type std (line 55) | typedef std::map<std::size_t, ConnsType> PolyConnsType;
type std (line 57) | typedef std::set<Conn, ConnCmp> ConnsType2;
type Cmp (line 90) | struct Cmp {
type std (line 98) | typedef std::set<Prio, Cmp> PriosType;
type std (line 100) | typedef std::map<std::size_t, Prio> PolyPriosType;
function class (line 102) | class Merger {
FILE: Optimize.cxx
type Cmp (line 262) | struct Cmp {
function IdsType (line 378) | IdsType PreventEqualCaptPoints::TriangulateCell (vtkPolyData *pd, vtkIdT...
FILE: Optimize.h
type std (line 22) | typedef std::map<Pair, Points> Edges;
function class (line 24) | class SnapPoint {
function class (line 46) | class SnapEdge {
function class (line 70) | class PreventEqualCaptPoints {
FILE: Utilities.cxx
function ComputeNormal (line 30) | double ComputeNormal (vtkPoints *pts, double *n, vtkIdType num, const vt...
function FindPoints (line 52) | void FindPoints (vtkKdTreePointLocator *pl, const double *pt, vtkIdList ...
function WriteVTK (line 78) | void WriteVTK (const char *name, vtkPolyData *pd) {
function GetAngle (line 89) | double GetAngle (const double *vA, const double *vB, const double *n) {
function Transform (line 128) | void Transform (const double *in, double *out, const Base &base) {
function ComputeNormal (line 146) | double ComputeNormal (const Poly &poly, double *n) {
function PointInPoly (line 169) | bool PointInPoly (const Poly &poly, const Point3d &p) {
function WritePolys (line 199) | void WritePolys (const char *name, const PolysType &polys) {
function GetPolys (line 221) | void GetPolys (const ReferencedPointsType &pts, const IndexedPolysType &...
function GetPoly (line 233) | void GetPoly (vtkPoints *pts, vtkIdType num, const vtkIdType *poly, Poly...
function FlattenPoly (line 245) | void FlattenPoly (const Poly &poly, Poly &out, const Base &base) {
function FlattenPoly2 (line 261) | void FlattenPoly2 (const Poly &poly, Poly &out, const Base2 &base) {
function GetEdgeProj (line 275) | std::shared_ptr<Proj> GetEdgeProj (const Poly &poly, const Point3d &p) {
function ProjOnLine (line 300) | void ProjOnLine (const Point3d &a, const Point3d &b, const Point3d &p, d...
function ProjOnLine (line 317) | void ProjOnLine (vtkPolyData *pd, const Pair &line, const Point3d &p, st...
function CreatePolyData (line 331) | vtkSmartPointer<vtkPolyData> CreatePolyData (const PolysType &polys) {
function GetTriangleQuality (line 354) | double GetTriangleQuality (const Poly &poly) {
FILE: Utilities.h
function class (line 48) | class Point3d {
function operator (line 65) | bool operator== (const Point3d &other) const {
function GetVec (line 78) | static double GetVec (const Point3d &a, const Point3d &b, double *v) {
function GetDist (line 86) | static double GetDist (const Point3d &a, const Point3d &b) {
type std (line 96) | typedef std::vector<vtkIdType> IdsType;
type std (line 97) | typedef std::set<vtkIdType> _IdsType;
function class (line 99) | class Pair {
function operator (line 107) | bool operator== (const Pair &other) const {
function vtkIdType (line 110) | vtkIdType operator& (const Pair &other) const {
function class (line 122) | class Base {
function class (line 132) | class Base2 {
type std (line 184) | typedef std::vector<Point3d> Poly, Points;
type std (line 185) | typedef std::vector<Poly> PolysType;
type std (line 194) | typedef std::deque<vtkIdType> IndexedPoly;
type std (line 195) | typedef std::vector<IndexedPoly> IndexedPolysType;
type std (line 197) | typedef std::map<vtkIdType, std::reference_wrapper<const Point3d>> Refer...
function class (line 205) | class Proj {
FILE: testing/generate_frieze.py
function extrude (line 42) | def extrude(pts, h, z=0):
class Frieze (line 69) | class Frieze:
method __init__ (line 70) | def __init__ (self, usr_cfg):
method draw_bricks (line 88) | def draw_bricks(self, seq, end_seq):
method draw_zz_bricks (line 176) | def draw_zz_bricks(self):
method draw_spacer (line 207) | def draw_spacer(self):
method export (line 220) | def export(self, name):
FILE: testing/test_congruence.cxx
function main (line 19) | int main() {
FILE: testing/test_filter.py
function check_result (line 42) | def check_result(bf, expected_regs=None):
function write_result (line 258) | def write_result(bf, d):
function extrude_polygon (line 265) | def extrude_polygon(poly, z):
function create_polydata (line 289) | def create_polydata(pts, polys):
function test_simple (line 311) | def test_simple(tmp_path):
function test_simple_2 (line 330) | def test_simple_2(tmp_path):
function test_simple_3 (line 349) | def test_simple_3(tmp_path):
function test_simple_4 (line 367) | def test_simple_4(tmp_path):
function test_same (line 419) | def test_same(tmp_path):
function test_intersecting_strips (line 433) | def test_intersecting_strips():
function test_intersecting_strips_2 (line 470) | def test_intersecting_strips_2():
function test_touch (line 495) | def test_touch(tmp_path):
function test_merger (line 513) | def test_merger(tmp_path):
function test_merger_2 (line 529) | def test_merger_2(tmp_path):
function test_quads (line 545) | def test_quads(tmp_path):
function test_triangle_strips (line 564) | def test_triangle_strips(tmp_path):
function test_special (line 598) | def test_special(tmp_path):
function test_non_manifolds (line 632) | def test_non_manifolds():
function test_branched (line 650) | def test_branched(tmp_path):
function test_branched_2 (line 666) | def test_branched_2(tmp_path):
function test_branched_3 (line 683) | def test_branched_3():
function test_branched_4 (line 698) | def test_branched_4(tmp_path):
function test_branched_5 (line 714) | def test_branched_5(tmp_path):
function test_branched_6 (line 748) | def test_branched_6(tmp_path):
function test_bad_shaped (line 764) | def test_bad_shaped(tmp_path):
function test_self_intersecting_polys (line 805) | def test_self_intersecting_polys():
function test_equal_capt_pts (line 854) | def test_equal_capt_pts(tmp_path):
function test_equal_capt_pts_2 (line 879) | def test_equal_capt_pts_2(tmp_path):
function test_equal_capt_pts_3 (line 902) | def test_equal_capt_pts_3(tmp_path):
function test_transform_matrix (line 944) | def test_transform_matrix(tmp_path):
FILE: testing/test_merger.cxx
function Poly (line 26) | Poly CreateRegularPoly (double r, vtkIdType step, double x, double y, do...
function Test (line 52) | bool Test (vtkPolyData *pd, PolysType &polys, vtkIdType numCells, [[mayb...
function main (line 147) | int main() {
FILE: vtkPolyDataBooleanFilter.cxx
function ComputeNormal (line 1023) | void ComputeNormal (const StripPtsType &pts, const _RefsType &poly, doub...
function CleanPoly (line 1052) | void CleanPoly (vtkPolyData *pd, IdsType &poly) {
type Cmp (line 1912) | struct Cmp {
type Cmp (line 2129) | struct Cmp {
type Congr (line 2485) | enum class Congr {
class PolyAtEdge (line 2491) | class PolyAtEdge {
method PolyAtEdge (line 2495) | PolyAtEdge (vtkPolyData *_pd, vtkIdType _polyId, vtkIdType _ptIdA, vtk...
method Congr (line 2528) | Congr IsCongruent (const PolyAtEdge &p) const {
class PolyPair (line 2550) | class PolyPair {
method PolyPair (line 2552) | PolyPair (PolyAtEdge _pA, PolyAtEdge _pB) : pA(_pA), pB(_pB) {}
method GetLoc (line 2556) | void GetLoc (PolyAtEdge &pT, vtkIdType mode) {
function GetEdgePolys (line 2620) | std::shared_ptr<PolyPair> GetEdgePolys (vtkPolyData *pd, vtkIdList *ptsA...
function vtkMatrix4x4 (line 3127) | vtkMatrix4x4* vtkPolyDataBooleanFilter::GetMatrix (int i) {
function vtkMTimeType (line 3135) | vtkMTimeType vtkPolyDataBooleanFilter::GetMTime () {
FILE: vtkPolyDataBooleanFilter.h
type OperMode (line 38) | enum OperMode {
type class (line 46) | enum class
function std (line 60) | inline std::underlying_type_t<Capt> operator& (Capt lhs, Capt rhs) {
type class (line 65) | enum class
function Loc (line 71) | enum class Loc {
type std (line 131) | typedef std::map<vtkIdType, StripPt> StripPtsType;
type std (line 132) | typedef std::deque<StripPtR> StripType;
type std (line 133) | typedef std::vector<StripType> StripsType;
type std (line 135) | typedef std::vector<std::reference_wrapper<StripType>> _StripsType;
function class (line 137) | class PStrips {
type std (line 162) | typedef std::map<vtkIdType, PStrips> PolyStripsType;
type std (line 164) | typedef std::vector<std::reference_wrapper<StripPtR>> RefsType;
type std (line 165) | typedef std::vector<std::reference_wrapper<const StripPtR>> ConstRefsType;
function SetOperModeToNone (line 213) | void SetOperModeToNone () { OperMode = OPER_NONE; Modified(); }
function SetOperModeToUnion (line 214) | void SetOperModeToUnion () { OperMode = OPER_UNION; Modified(); }
function SetOperModeToIntersection (line 215) | void SetOperModeToIntersection () { OperMode = OPER_INTERSECTION; Modifi...
function SetOperModeToDifference (line 216) | void SetOperModeToDifference () { OperMode = OPER_DIFFERENCE; Modified(); }
function SetOperModeToDifference2 (line 217) | void SetOperModeToDifference2 () { OperMode = OPER_DIFFERENCE2; Modified...
function PrintSelf (line 230) | void PrintSelf (ostream&, vtkIndent) override {}
Condensed preview — 37 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (602K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 15,
"preview": "ko_fi: zippy84\n"
},
{
"path": ".github/workflows/cmake.yml",
"chars": 1849,
"preview": "name: CMake\n\non:\n push:\n branches:\n - '*'\n\njobs:\n Build:\n runs-on: ${{matrix.os}}\n strategy:\n matri"
},
{
"path": "CITATION.cff",
"chars": 319,
"preview": "cff-version: 1.2.0\ntitle: vtkbool\nmessage: 'If you use this software, please cite it as below.'\ntype: software\nauthors:\n"
},
{
"path": "CMakeLists.txt",
"chars": 4624,
"preview": "# Copyright 2012-2025 Ronald Römer\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use"
},
{
"path": "Contact.cxx",
"chars": 28690,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
},
{
"path": "Contact.h",
"chars": 3932,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
},
{
"path": "LICENSE",
"chars": 10175,
"preview": "\n Apache License\n Version 2.0, January 2004\n "
},
{
"path": "Merger.cxx",
"chars": 24424,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
},
{
"path": "Merger.h",
"chars": 3501,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
},
{
"path": "Optimize.cxx",
"chars": 13854,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
},
{
"path": "Optimize.h",
"chars": 2399,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
},
{
"path": "README.md",
"chars": 9538,
"preview": "# vtkbool [](https://github.com/zippy8"
},
{
"path": "Utilities.cxx",
"chars": 8851,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
},
{
"path": "Utilities.h",
"chars": 6617,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
},
{
"path": "module/CMakeLists.txt",
"chars": 250,
"preview": "set(srcs\n ../Utilities.cxx\n ../Optimize.cxx\n ../Contact.cxx\n ../Merger.cxx\n ../vtkPolyDataBooleanFilter.c"
},
{
"path": "module/vtk.module",
"chars": 243,
"preview": "NAME\n vtkbool\nDEPENDS\n VTK::CommonCore\n VTK::CommonExecutionModel\n VTK::FiltersPoints\n VTK::IOLegacy\n VTK::Filters"
},
{
"path": "paraview/CMakeLists.txt",
"chars": 155,
"preview": "paraview_add_plugin(PolyDataBooleanFilter\n VERSION \"${vtkbool_VERSION}\"\n MODULES vtkbool\n MODULE_FILES \"${CMAKE_CURRE"
},
{
"path": "paraview/module/CMakeLists.txt",
"chars": 360,
"preview": "set(srcs\n ../../Utilities.cxx\n ../../Optimize.cxx\n ../../Contact.cxx\n ../../Merger.cxx\n ../../vtkPolyData"
},
{
"path": "paraview/module/vtk.module",
"chars": 165,
"preview": "NAME\n vtkbool\nDEPENDS\n VTK::CommonCore\n VTK::CommonExecutionModel\n VTK::FiltersPoints\n VTK::IOLegacy\n VTK::Filters"
},
{
"path": "paraview/module/vtkPolyDataBooleanFilter.xml",
"chars": 2071,
"preview": "<ServerManagerConfiguration>\n <ProxyGroup name=\"filters\">\n <SourceProxy name=\"PolyDataBooleanFilter\" class=\"vt"
},
{
"path": "paraview/paraview.plugin",
"chars": 161,
"preview": "NAME\n PolyDataBooleanFilter\nREQUIRES_MODULES\n VTK::CommonCore\n VTK::FiltersCore\nDESCRIPTION\n This module contains a "
},
{
"path": "run_some_tests.sh",
"chars": 450,
"preview": "#!/bin/bash\nexport PYTHONPATH=/home/zippy/vtkbool/build/lib/python3.13/site-packages/vtkbool:$PYTHONPATH\npushd testing\n\n"
},
{
"path": "testing/data/branched.vtk",
"chars": 46722,
"preview": "# vtk DataFile Version 5.1\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS 622 double\n0.082297295332 0 0.86818063259 0.07826937"
},
{
"path": "testing/data/branched3.vtk",
"chars": 65344,
"preview": "# vtk DataFile Version 5.1\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS 882 double\n0.36786195636 0 0.33864077926 0.418583244"
},
{
"path": "testing/data/branched4.vtk",
"chars": 105616,
"preview": "# vtk DataFile Version 5.1\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS 1346 double\n0.082297295332 0 -0.86818063259 0 0 -0.8"
},
{
"path": "testing/data/branched6.vtk",
"chars": 92359,
"preview": "# vtk DataFile Version 5.1\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS 1232 double\n0.082297295332 -0.36765038967 0.86818063"
},
{
"path": "testing/data/cross.vtk",
"chars": 2748,
"preview": "# vtk DataFile Version 5.1\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS 70 double\n0.5 1 0 0.43301269412 1 -0.25 0.25 1 -0.43"
},
{
"path": "testing/data/merger.vtk",
"chars": 726,
"preview": "# vtk DataFile Version 5.1\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS 24 double\n-0.4 0 0.5 -0.4 0 -0.5 0 -0.4 0.5 \n0 -0.4 "
},
{
"path": "testing/data/non-manifold.vtk",
"chars": 2346,
"preview": "# vtk DataFile Version 5.1\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS 58 double\n-1 -0.5 -1 -1 0.5 -1 1 0.5 -1 \n1 -0.5 -1 -"
},
{
"path": "testing/generate_frieze.py",
"chars": 14106,
"preview": "#!/usr/bin/env python\n# *-* coding: UTF-8 *-*\n\n# Copyright 2012-2025 Ronald Römer\n#\n# Licensed under the Apache License,"
},
{
"path": "testing/pytest.ini",
"chars": 69,
"preview": "[pytest]\nlog_cli = True\naddopts = --basetemp=out\nxfail_strict = True\n"
},
{
"path": "testing/test_congruence.cxx",
"chars": 1153,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
},
{
"path": "testing/test_filter.py",
"chars": 25421,
"preview": "#!/usr/bin/env python\n# *-* coding: UTF-8 *-*\n\n# Copyright 2012-2025 Ronald Römer\n#\n# Licensed under the Apache License,"
},
{
"path": "testing/test_merger.cxx",
"chars": 4775,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
},
{
"path": "testing/test_python.py",
"chars": 1068,
"preview": "#!/usr/bin/env python\n# *-* coding: UTF-8 *-*\n\n# Copyright 2012-2025 Ronald Römer\n#\n# Licensed under the Apache License,"
},
{
"path": "vtkPolyDataBooleanFilter.cxx",
"chars": 93495,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
},
{
"path": "vtkPolyDataBooleanFilter.h",
"chars": 6480,
"preview": "/*\nCopyright 2012-2025 Ronald Römer\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use thi"
}
]
About this extraction
This page contains the full source code of the zippy84/vtkbool GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 37 files (571.4 KB), approximately 234.5k tokens, and a symbol index with 135 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.