diff --git a/README.md b/README.md index 3df8c00..0f99802 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,95 @@ [![CutCells CI](https://github.com/sclaus2/cutcells/actions/workflows/python-app.yml/badge.svg)](https://github.com/sclaus2/cutcells/actions/workflows/python-app.yml) -a library to compute intersections between mesh cells and implicit (level set) functions using marching cubes/tetrahedra algorithms. -The current version supports intervals, triangles and tetrahedra. Future versions will include quadrilaterals, hexahedra, pyramids and prisms. - -The library contains utility functions to cut through vtk meshes using pyvista. It is also used as a basis to generate run time quadrature rules in immersed boundary methods/cut finite element methods (see CutFEMx). - -The images below show a cut through a vtk mesh using pyvista and CutCells. -The corresponding demonstration code is located in `python/demo/cut_vtk_mesh`. - -

-Regular mesh cut by zero contour line of a circular level set function -Regular mesh cut by zero contour line of a popcorn level set function -

+**CutCells** is a lightweight **C++20 geometry kernel with Python bindings** to compute **cut-cell decompositions** of standard mesh elements by an **implicit surface / level set** `φ(x)`. + +Given one parent cell (or a whole mesh) and the level set values on its vertices, CutCells builds a **local sub-mesh** that describes: + +* the **inside** region `φ < 0`, +* the **outside** region `φ > 0`, +* and/or the **interface** `φ = 0` (as facets/segments embedded in the cell), + +with **explicit connectivity** and **element types**. + +It is designed as a building block for **unfitted / immersed FEM** workflows (e.g. **CutFEM**), where robust cut geometry and stable parent mappings are required for runtime quadrature. + +## Supported cell types + +Current parent cell support: + +* 1D: **interval** +* 2D: **triangle**, **quadrilateral** +* 3D: **tetrahedron**, **hexahedron**, **prism**, **pyramid** + +Higher-order (currently pragmatic) support: + +* **P2 triangle (6 nodes)** and **P2 tetrahedron (10 nodes)** via subdivision into linear sub-cells, cut, then merged back. + +## Performance and dependencies + +* **Few dependencies**: the computational core is plain C++. +* **Python bindings via nanobind**: CutCells exposes arrays in NumPy-friendly form and is designed to avoid unnecessary overhead. +* **Zero-copy where possible**: large buffers (coords, connectivity/offsets, parent IDs, provenance tags) are exposed as **views** when layout permits, minimizing memory traffic between C++ and Python. + +## Applications + +CutCells is intended as a reusable geometry backend for: + +* **CutFEM / unfitted FEM**: robust sub-cell and interface extraction for integration on `Ω∩K` and `Γ∩K` +* **runtime quadrature** generation +* general embedded geometry workflows where remeshing is undesirable + +## Example gallery + + +Below is a gallery of example outputs generated by CutCells and the provided Python demos. See `python/demo/` for scripts to reproduce these images. + + + + + + + + + + + + + + + + + +
+ 2D mesh cut by circle
+ 2D mesh cut by a circular level set +
+ Hybrid mesh flower cut
+ Hybrid mesh (quads+tris) cut by flower level set +
+ Quad cases with disambiguation
+ Quad cases with disambiguation panels +
+ Cut prism demo
+ Cut prism (wedge) demo +
+ Cut pyramid demo
+ Cut pyramid demo +
+ Cut pyramid demo + Cut pyramid demo
+ Cut tetrahedron demo +
+ 2D mesh cut by popcorn function
+ Tetrahedral mesh cut by a popcorn level set +
+ 3D hex mesh cut by popcorn
+ Hexahedral mesh cut by popcorn level set +
+ Hexahedron gyroid grid
+ Hexahedral mesh cut by gyroid level set +
# Installation @@ -64,6 +140,11 @@ in the corresponding demo folder, e.g. `cpp/demo/cut_triangle` The python demos are located in `python/demo`. +## Third-party notices + +Some generated clip/cut case tables (hexahedron/prism/pyramid) are derived from VTK's `vtkTableBasedClipCases.h`. +VTK's BSD-3-Clause license text is included in `third_party/VTK-Copyright.txt`. + ## Dependencies CutCells requires a C++20 compiler and depends on the C++ standard template library. diff --git a/cpp/src/CMakeLists.txt b/cpp/src/CMakeLists.txt index f33c25f..8885064 100644 --- a/cpp/src/CMakeLists.txt +++ b/cpp/src/CMakeLists.txt @@ -8,12 +8,22 @@ add_library(cutcells) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/version.h.in version.h) include_directories(${CMAKE_CURRENT_BINARY_DIR}) +# Make headers in this directory discoverable for generated table headers +# (e.g. generated/*_tables.h includes "cell_types.h"). +target_include_directories(cutcells PUBLIC + $ + $) + set(HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/cell_types.h ${CMAKE_CURRENT_SOURCE_DIR}/cell_flags.h ${CMAKE_CURRENT_SOURCE_DIR}/cell_subdivision.h ${CMAKE_CURRENT_SOURCE_DIR}/cut_triangle.h ${CMAKE_CURRENT_SOURCE_DIR}/cut_interval.h + ${CMAKE_CURRENT_SOURCE_DIR}/cut_quadrilateral.h + ${CMAKE_CURRENT_SOURCE_DIR}/cut_hexahedron.h + ${CMAKE_CURRENT_SOURCE_DIR}/cut_prism.h + ${CMAKE_CURRENT_SOURCE_DIR}/cut_pyramid.h ${CMAKE_CURRENT_SOURCE_DIR}/cut_tetrahedron.h ${CMAKE_CURRENT_SOURCE_DIR}/triangulation.h ${CMAKE_CURRENT_SOURCE_DIR}/cut_cell.h @@ -27,6 +37,10 @@ set(HEADERS target_sources(cutcells PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/cut_interval.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cut_triangle.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/cut_quadrilateral.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/cut_hexahedron.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/cut_prism.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/cut_pyramid.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cut_tetrahedron.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cut_cell.cpp ${CMAKE_CURRENT_SOURCE_DIR}/cut_mesh.cpp diff --git a/cpp/src/cell_topology.h b/cpp/src/cell_topology.h new file mode 100644 index 0000000..266cbff --- /dev/null +++ b/cpp/src/cell_topology.h @@ -0,0 +1,230 @@ +// Copyright (c) 2022 ONERA +// Authors: Susanne Claus +// This file is part of CutCells +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "cell_types.h" +#include +#include +#include + +namespace cutcells::cell +{ +/// @brief Cell topology data for edge-based clipping algorithms. +/// Edge and face numbering follows VTK conventions. + +//----------------------------------------------------------------------------- +// Edge definitions per cell type (VTK ordering) +//----------------------------------------------------------------------------- + +/// Interval: 1 edge (0-1) +inline constexpr std::array, 1> interval_edges = {{ + {0, 1} +}}; + +/// Triangle: 3 edges +/// VTK edge order: (0,1), (1,2), (2,0) +inline constexpr std::array, 3> triangle_edges = {{ + {0, 1}, {1, 2}, {2, 0} +}}; + +/// Quadrilateral: 4 edges +/// VTK edge order: (0,1), (1,2), (2,3), (3,0) +/// +/// 3 --- 2 +/// | | +/// 0 --- 1 +inline constexpr std::array, 4> quadrilateral_edges = {{ + {0, 1}, {1, 2}, {2, 3}, {3, 0} +}}; + +/// Tetrahedron: 6 edges +/// VTK edge order: (0,1), (1,2), (2,0), (0,3), (1,3), (2,3) +inline constexpr std::array, 6> tetrahedron_edges = {{ + {0, 1}, {1, 2}, {2, 0}, {0, 3}, {1, 3}, {2, 3} +}}; + +/// Hexahedron: 12 edges +/// VTK vertex numbering: +/// 7 -------- 6 +/// /| /| +/// / | / | +/// 4 -------- 5 | +/// | 3 ------|-- 2 +/// | / | / +/// |/ |/ +/// 0 -------- 1 +/// +/// VTK edge order: +/// Base: (0,1), (1,2), (2,3), (3,0) +/// Top: (4,5), (5,6), (6,7), (7,4) +/// Verticals: (0,4), (1,5), (2,6), (3,7) +inline constexpr std::array, 12> hexahedron_edges = {{ + // Base edges (0-3) + {0, 1}, {1, 2}, {2, 3}, {3, 0}, + // Top edges (4-7) + {4, 5}, {5, 6}, {6, 7}, {7, 4}, + // Vertical edges (8-11) + {0, 4}, {1, 5}, {2, 6}, {3, 7} +}}; + +/// Prism (Wedge): 9 edges +/// VTK vertex numbering: +/// 2 +/// /|\ +/// / | \ +/// 0-----1 +/// | | | +/// | 5 | +/// | /|\ | +/// |/ | \| +/// 3-----4 +/// +/// VTK edge order: +/// Bottom triangle: (0,1), (1,2), (2,0) +/// Top triangle: (3,4), (4,5), (5,3) +/// Verticals: (0,3), (1,4), (2,5) +inline constexpr std::array, 9> prism_edges = {{ + // Bottom triangle (0-2) + {0, 1}, {1, 2}, {2, 0}, + // Top triangle (3-5) + {3, 4}, {4, 5}, {5, 3}, + // Vertical edges (6-8) + {0, 3}, {1, 4}, {2, 5} +}}; + +/// Pyramid: 8 edges +/// VTK vertex numbering: +/// 4 +/// /|\ +/// / | \ +/// / | \ +/// / | \ +/// 3----|----2 +/// | | | +/// 0---------1 +/// +/// VTK edge order: +/// Base: (0,1), (1,2), (2,3), (3,0) +/// Apex connections: (0,4), (1,4), (2,4), (3,4) +inline constexpr std::array, 8> pyramid_edges = {{ + // Base edges (0-3) + {0, 1}, {1, 2}, {2, 3}, {3, 0}, + // Apex edges (4-7) + {0, 4}, {1, 4}, {2, 4}, {3, 4} +}}; + +//----------------------------------------------------------------------------- +// Edge count per cell type +//----------------------------------------------------------------------------- + +inline constexpr int num_edges(type cell_type) +{ + switch (cell_type) + { + case type::point: return 0; + case type::interval: return 1; + case type::triangle: return 3; + case type::quadrilateral: return 4; + case type::tetrahedron: return 6; + case type::hexahedron: return 12; + case type::prism: return 9; + case type::pyramid: return 8; + default: + throw std::invalid_argument("Unknown cell type in num_edges"); + } +} + +//----------------------------------------------------------------------------- +// Edge accessor (returns span to edge array for cell type) +//----------------------------------------------------------------------------- + +/// Get edges for a given cell type. +/// @param cell_type The cell type +/// @return Span of edge vertex pairs [v0, v1] for each edge +inline std::span> edges(type cell_type) +{ + switch (cell_type) + { + case type::interval: + return std::span(interval_edges); + case type::triangle: + return std::span(triangle_edges); + case type::quadrilateral: + return std::span(quadrilateral_edges); + case type::tetrahedron: + return std::span(tetrahedron_edges); + case type::hexahedron: + return std::span(hexahedron_edges); + case type::prism: + return std::span(prism_edges); + case type::pyramid: + return std::span(pyramid_edges); + default: + throw std::invalid_argument("Unknown cell type in edges()"); + } +} + +//----------------------------------------------------------------------------- +// Face definitions (for interface stitching, optional future use) +//----------------------------------------------------------------------------- + +/// Hexahedron: 6 faces (quads) +/// Face order: -X, +X, -Y, +Y, -Z, +Z (left, right, front, back, bottom, top) +inline constexpr std::array, 6> hexahedron_faces = {{ + {0, 3, 7, 4}, // -X (left) + {1, 2, 6, 5}, // +X (right) + {0, 1, 5, 4}, // -Y (front) + {3, 2, 6, 7}, // +Y (back) + {0, 1, 2, 3}, // -Z (bottom) + {4, 5, 6, 7} // +Z (top) +}}; + +/// Prism: 5 faces (2 triangles + 3 quads) +/// Represented as max 4 vertices per face, with -1 padding for triangles +inline constexpr std::array, 5> prism_faces = {{ + {0, 1, 2, -1}, // bottom triangle + {3, 4, 5, -1}, // top triangle + {0, 1, 4, 3}, // quad face + {1, 2, 5, 4}, // quad face + {2, 0, 3, 5} // quad face +}}; + +/// Pyramid: 5 faces (1 quad base + 4 triangles) +inline constexpr std::array, 5> pyramid_faces = {{ + {0, 1, 2, 3}, // base quad + {0, 1, 4, -1}, // triangle + {1, 2, 4, -1}, // triangle + {2, 3, 4, -1}, // triangle + {3, 0, 4, -1} // triangle +}}; + +//----------------------------------------------------------------------------- +// Face vertex count per face (for mixed cells) +//----------------------------------------------------------------------------- + +inline constexpr std::array hexahedron_face_sizes = {4, 4, 4, 4, 4, 4}; +inline constexpr std::array prism_face_sizes = {3, 3, 4, 4, 4}; +inline constexpr std::array pyramid_face_sizes = {4, 3, 3, 3, 3}; + +/// Get number of faces for a cell type +inline constexpr int num_faces(type cell_type) +{ + switch (cell_type) + { + case type::point: return 0; + case type::interval: return 0; + case type::triangle: return 1; + case type::quadrilateral: return 1; + case type::tetrahedron: return 4; + case type::hexahedron: return 6; + case type::prism: return 5; + case type::pyramid: return 5; + default: + throw std::invalid_argument("Unknown cell type in num_faces"); + } +} + +} // namespace cutcells::cell diff --git a/cpp/src/cell_types.h b/cpp/src/cell_types.h index e345a2f..71c9450 100644 --- a/cpp/src/cell_types.h +++ b/cpp/src/cell_types.h @@ -218,8 +218,18 @@ namespace cutcells cell_types[1]= type::quadrilateral; } break;} - case type::quadrilateral: {throw std::invalid_argument("quadrilateral yet not implemented"); - break;} + case type::quadrilateral: {if(ls_part=="phi=0") + { + cell_types.resize(1); + cell_types[0]= type::interval; + } + else + { + cell_types.resize(2); + cell_types[0]= type::triangle; + cell_types[1]= type::quadrilateral; + } + break;} case type::tetrahedron: {if(ls_part=="phi=0") { cell_types.resize(2); @@ -233,8 +243,19 @@ namespace cutcells cell_types[1]= type::prism; } break;} - case type::hexahedron: {throw std::invalid_argument("hexahedron yet not implemented"); - break;} + case type::hexahedron: {if(ls_part=="phi=0") + { + cell_types.resize(2); + cell_types[0]= type::triangle; + cell_types[1]= type::quadrilateral; + } + else + { + cell_types.resize(2); + cell_types[0]= type::tetrahedron; + cell_types[1]= type::prism; + } + break;} case type::prism: {throw std::invalid_argument("prism yet not implemented"); break;} case type::pyramid: {throw std::invalid_argument("pyramid yet not implemented"); diff --git a/cpp/src/cut_cell.cpp b/cpp/src/cut_cell.cpp index 007f1e8..01ba9de 100644 --- a/cpp/src/cut_cell.cpp +++ b/cpp/src/cut_cell.cpp @@ -7,6 +7,10 @@ #include "cut_cell.h" #include "cut_tetrahedron.h" #include "cut_triangle.h" +#include "cut_quadrilateral.h" +#include "cut_hexahedron.h" +#include "cut_prism.h" +#include "cut_pyramid.h" #include "cut_interval.h" #include "cell_flags.h" #include "cell_subdivision.h" @@ -16,6 +20,7 @@ #include #include #include +#include namespace cutcells::cell{ @@ -103,9 +108,11 @@ namespace cutcells::cell{ break; case type::triangle: vol +=triangle::volume(vertex_coordinates,gdim); break; + case type::quadrilateral: vol +=quadrilateral::volume(vertex_coordinates,gdim); + break; case type::tetrahedron: vol +=tetrahedron::volume(vertex_coordinates,gdim); break; - default: throw std::invalid_argument("Only intervals, triangles and tetrahedra are implemented for volume computations so far."); + default: throw std::invalid_argument("Only intervals, triangles, quadrilaterals and tetrahedra are implemented for volume computations so far."); break; } } @@ -126,9 +133,17 @@ namespace cutcells::cell{ break; case type::triangle: triangle::cut(vertex_coordinates, gdim, ls_values, cut_type_str, cut_cell, triangulate); break; + case type::quadrilateral: quadrilateral::cut(vertex_coordinates, gdim, ls_values, cut_type_str, cut_cell, triangulate); + break; case type::tetrahedron: tetrahedron::cut(vertex_coordinates, gdim, ls_values, cut_type_str, cut_cell, triangulate); break; - default: throw std::invalid_argument("Only intervals, triangles and tetrahedra are implemented for cutting so far."); + case type::hexahedron: hexahedron::cut(vertex_coordinates, gdim, ls_values, cut_type_str, cut_cell, triangulate); + break; + case type::prism: prism::cut(vertex_coordinates, gdim, ls_values, cut_type_str, cut_cell, triangulate); + break; + case type::pyramid: pyramid::cut(vertex_coordinates, gdim, ls_values, cut_type_str, cut_cell, triangulate); + break; + default: throw std::invalid_argument("Only intervals, triangles, quadrilaterals, tetrahedra, hexahedra, prisms and pyramids are implemented for cutting so far."); break; } } diff --git a/cpp/src/cut_cell.h b/cpp/src/cut_cell.h index 4e15e7d..98ac8f0 100644 --- a/cpp/src/cut_cell.h +++ b/cpp/src/cut_cell.h @@ -6,6 +6,7 @@ #pragma once #include +#include #include "cell_types.h" #include @@ -43,6 +44,18 @@ namespace cutcells /// these correspond to the local numbering of intersected facets or vertices /// vertices are indicated by a shift of 100 in the numbering vertex 1 -> 101 etc. std::vector _vertex_parent_entity; + + /// Parent cell index + int32_t _parent_cell_index; + + /// Parent cell type before cutting + type _parent_cell_type; + + /// Parent vertex coordinates (V*gdim) + std::vector _parent_vertex_coords; + + /// Parent vertex IDs (context-global ids) + std::vector _parent_vertex_ids; }; template diff --git a/cpp/src/cut_hexahedron.cpp b/cpp/src/cut_hexahedron.cpp new file mode 100644 index 0000000..8ba5c20 --- /dev/null +++ b/cpp/src/cut_hexahedron.cpp @@ -0,0 +1,332 @@ +// Copyright (c) 2025 ONERA +// Authors: Susanne Claus +// This file is part of CutCells +// +// SPDX-License-Identifier: MIT + +#include "cut_hexahedron.h" + +#include "cell_flags.h" +#include "cut_cell.h" +#include "cut_interval.h" +#include "generated/cut_hexahedron_inside_tables.h" +#include "generated/cut_hexahedron_interface_tables.h" +#include "generated/cut_hexahedron_outside_tables.h" +#include "utils.h" + +#include +#include +#include +#include +#include + +namespace cutcells::cell::hexahedron +{ + namespace + { + [[noreturn]] void throw_missing_token(const int flag, const int token, const char* where) + { + throw std::runtime_error(std::string(where) + ": missing token=" + std::to_string(token) + + " for flag=" + std::to_string(flag)); + } + + int lookup_token_or_throw(const std::unordered_map& vertex_case_map, + const int flag, + const int token, + const char* where) + { + const auto it = vertex_case_map.find(token); + if (it == vertex_case_map.end()) + throw_missing_token(flag, token, where); + return it->second; + } + + template + void compute_intersection_points(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const int flag, + std::vector& intersection_points, + std::unordered_map& vertex_case_map) + { + intersection_points.clear(); + vertex_case_map.clear(); + + std::vector v0(gdim); + std::vector v1(gdim); + std::vector ip(gdim); + + int ip_index = 0; + for (int e = 0; e < 12; ++e) + { + if (intersected_edges[flag][e] == 0) + continue; + + const int v0_id = edges[e][0]; + const int v1_id = edges[e][1]; + + for (int j = 0; j < gdim; ++j) + { + v0[j] = vertex_coordinates[v0_id * gdim + j]; + v1[j] = vertex_coordinates[v1_id * gdim + j]; + } + + const T ls0 = ls_values[v0_id]; + const T ls1 = ls_values[v1_id]; + + interval::compute_intersection_point(0.0, v0, v1, ls0, ls1, ip); + + for (int j = 0; j < gdim; ++j) + intersection_points.push_back(ip[j]); + + vertex_case_map[e] = ip_index; + ++ip_index; + } + } + + template + void ensure_vertex_token(const std::span vertex_coordinates, const int gdim, + const int token, + CutCell& cut_cell, + std::unordered_map& vertex_case_map) + { + if (vertex_case_map.find(token) != vertex_case_map.end()) + return; + + const int vid = token - 100; + const int local_idx = static_cast(cut_cell._vertex_coords.size() / gdim); + vertex_case_map[token] = local_idx; + cut_cell._vertex_coords.resize(cut_cell._vertex_coords.size() + gdim); + for (int j = 0; j < gdim; ++j) + cut_cell._vertex_coords[local_idx * gdim + j] = vertex_coordinates[vid * gdim + j]; + } + + template + void ensure_special_token(const std::span vertex_coordinates, const int gdim, + const int flag, const int token, + const int* special_point_count, + const int* special_point_offset, + const int* special_point_data, + CutCell& cut_cell, + std::unordered_map& vertex_case_map) + { + if (vertex_case_map.find(token) != vertex_case_map.end()) + return; + + const int sp_id = token - 200; + const int count = special_point_count[flag]; + if (sp_id < 0 || sp_id >= count) + throw std::runtime_error("Invalid special point id in table"); + + int idx = special_point_offset[flag]; + for (int sid = 0; sid < sp_id; ++sid) + { + const int nrefs = special_point_data[idx++]; + idx += nrefs; + } + + const int nrefs = special_point_data[idx++]; + if (nrefs <= 0) + throw std::runtime_error("Malformed special point definition"); + + std::vector coord(gdim, T(0)); + for (int r = 0; r < nrefs; ++r) + { + const int ref = special_point_data[idx++]; + + if (ref < 100) + { + // Edge intersection point (already stored in cut_cell at index vertex_case_map[edge_id]) + const int local = lookup_token_or_throw(vertex_case_map, flag, ref, "ensure_special_token(ref<100)"); + for (int j = 0; j < gdim; ++j) + coord[j] += cut_cell._vertex_coords[local * gdim + j]; + } + else if (ref < 200) + { + // Original vertex (not necessarily added yet) + const int vid = ref - 100; + for (int j = 0; j < gdim; ++j) + coord[j] += vertex_coordinates[vid * gdim + j]; + } + else + { + // Special point reference (rare): ensure and reuse + ensure_special_token(vertex_coordinates, gdim, flag, ref, + special_point_count, special_point_offset, special_point_data, + cut_cell, vertex_case_map); + const int local = lookup_token_or_throw(vertex_case_map, flag, ref, "ensure_special_token(ref>=200)"); + for (int j = 0; j < gdim; ++j) + coord[j] += cut_cell._vertex_coords[local * gdim + j]; + } + } + + for (int j = 0; j < gdim; ++j) + coord[j] /= static_cast(nrefs); + + const int local_idx = static_cast(cut_cell._vertex_coords.size() / gdim); + vertex_case_map[token] = local_idx; + cut_cell._vertex_coords.resize(cut_cell._vertex_coords.size() + gdim); + for (int j = 0; j < gdim; ++j) + cut_cell._vertex_coords[local_idx * gdim + j] = coord[j]; + } + + template + void decode_case(const std::span vertex_coordinates, const int gdim, + const int flag, + const int* case_offsets, + const type* cell_types, + const int (*subcell_verts)[MaxVerts], + const int* special_point_count, + const int* special_point_offset, + const int* special_point_data, + bool triangulate, + CutCell& cut_cell, + std::unordered_map& vertex_case_map) + { + const int cell_begin = case_offsets[flag]; + const int cell_end = case_offsets[flag + 1]; + + for (int cell_idx = cell_begin; cell_idx < cell_end; ++cell_idx) + { + const type sub_type = cell_types[cell_idx]; + const int* verts = subcell_verts[cell_idx]; + + std::vector verts_local; + verts_local.reserve(MaxVerts); + for (int i = 0; i < MaxVerts; ++i) + { + const int token = verts[i]; + if (token == -1) + break; + + if (token < 100) + { + // Edge intersection token: already present + } + else if (token < 200) + { + ensure_vertex_token(vertex_coordinates, gdim, token, cut_cell, vertex_case_map); + } + else + { + ensure_special_token(vertex_coordinates, gdim, flag, token, + special_point_count, special_point_offset, special_point_data, + cut_cell, vertex_case_map); + } + + verts_local.push_back(lookup_token_or_throw(vertex_case_map, flag, token, "decode_case")); + } + + if (triangulate && sub_type == type::quadrilateral && verts_local.size() == 4) + { + cut_cell._types.push_back(type::triangle); + cut_cell._connectivity.push_back({verts_local[0], verts_local[1], verts_local[2]}); + cut_cell._types.push_back(type::triangle); + cut_cell._connectivity.push_back({verts_local[0], verts_local[2], verts_local[3]}); + } + else + { + cut_cell._types.push_back(sub_type); + cut_cell._connectivity.push_back(std::move(verts_local)); + } + } + } + } + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate) + { + if (vertex_coordinates.size() != static_cast(8 * gdim)) + throw std::invalid_argument("hexahedron::cut expects 8 vertices"); + if (ls_values.size() != 8) + throw std::invalid_argument("hexahedron::cut expects 8 level set values"); + + // CutCells convention: case mask bit i is set when phi_i < 0. + const int flag_lt0 = get_entity_flag(ls_values, false); + if (flag_lt0 == 0 || flag_lt0 == 255) + { + throw std::invalid_argument("hexahedron is not intersected and therefore cannot be cut"); + } + + // Store parent geometry + cut_cell._parent_cell_type = type::hexahedron; + cut_cell._parent_vertex_coords.resize(8 * gdim); + cut_cell._parent_vertex_ids.resize(8); + for (int i = 0; i < 8; ++i) + { + for (int j = 0; j < gdim; ++j) + cut_cell._parent_vertex_coords[i * gdim + j] = vertex_coordinates[i * gdim + j]; + cut_cell._parent_vertex_ids[i] = i; + } + + // Compute intersections (shared for all parts) + std::vector intersection_points; + std::unordered_map vertex_case_map; + compute_intersection_points(vertex_coordinates, gdim, ls_values, flag_lt0, + intersection_points, vertex_case_map); + + cut_cell._gdim = gdim; + cut_cell._vertex_coords = std::move(intersection_points); + cut_cell._types.clear(); + cut_cell._connectivity.clear(); + + if (cut_type_str == "phi=0") + { + cut_cell._tdim = 2; + decode_case(vertex_coordinates, gdim, flag_lt0, + case_subcell_offset_interface, subcell_type_interface, subcell_verts_interface, + special_point_count_interface, special_point_offset_interface, special_point_data_interface, + triangulate, cut_cell, vertex_case_map); + } + else if (cut_type_str == "phi<0") + { + cut_cell._tdim = 3; + decode_case(vertex_coordinates, gdim, flag_lt0, + case_subcell_offset_inside, subcell_type_inside, subcell_verts_inside, + special_point_count_inside, special_point_offset_inside, special_point_data_inside, + triangulate, cut_cell, vertex_case_map); + } + else if (cut_type_str == "phi>0") + { + cut_cell._tdim = 3; + decode_case(vertex_coordinates, gdim, flag_lt0, + case_subcell_offset_outside, subcell_type_outside, subcell_verts_outside, + special_point_count_outside, special_point_offset_outside, special_point_data_outside, + triangulate, cut_cell, vertex_case_map); + } + else + { + throw std::invalid_argument("cutting type unknown"); + } + + cutcells::utils::create_vertex_parent_entity_map(vertex_case_map, cut_cell._vertex_parent_entity); + } + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate) + { + cut_cell.resize(cut_type_str.size()); + for (std::size_t i = 0; i < cut_type_str.size(); ++i) + { + cut(vertex_coordinates, gdim, ls_values, cut_type_str[i], cut_cell[i], triangulate); + } + } + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate); + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate); + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate); + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate); +} diff --git a/cpp/src/cut_hexahedron.h b/cpp/src/cut_hexahedron.h new file mode 100644 index 0000000..310dd74 --- /dev/null +++ b/cpp/src/cut_hexahedron.h @@ -0,0 +1,27 @@ +// Copyright (c) 2025 ONERA +// Authors: Susanne Claus +// This file is part of CutCells +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "cut_cell.h" +#include "cell_types.h" + +#include +#include +#include +#include + +namespace cutcells::cell::hexahedron +{ + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate = false); + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate = false); +} diff --git a/cpp/src/cut_mesh.cpp b/cpp/src/cut_mesh.cpp index 7719af5..daa0ac7 100644 --- a/cpp/src/cut_mesh.cpp +++ b/cpp/src/cut_mesh.cpp @@ -10,8 +10,49 @@ #include "utils.h" +#include "cell_topology.h" #include #include +#include + +namespace +{ + struct VertexKey + { + // 0: original vertex (global vertex id) + // 1: edge intersection (global vertex id pair) + // 2: special point (parent cell id + sid) + uint8_t kind = 0; + int32_t a = 0; + int32_t b = 0; + + bool operator==(const VertexKey& other) const noexcept + { + return kind == other.kind && a == other.a && b == other.b; + } + }; + + struct VertexKeyHash + { + std::size_t operator()(const VertexKey& k) const noexcept + { + // Basic mix; good enough for small integer keys. + const std::size_t h0 = std::hash{}(k.a); + const std::size_t h1 = std::hash{}(k.b); + const std::size_t hk = std::hash{}(k.kind); + return h0 ^ (h1 + 0x9e3779b97f4a7c15ULL + (h0 << 6) + (h0 >> 2)) ^ (hk << 1); + } + }; + + template + inline void append_vertex_coords(std::vector& out, const std::vector& in, + int local_vertex_id, int gdim) + { + const int base = local_vertex_id * gdim; + for (int j = 0; j < gdim; ++j) + out.push_back(in[base + j]); + } +} namespace cutcells::mesh { @@ -89,6 +130,15 @@ namespace cutcells::mesh { CutMesh cut_mesh; + if (cut_cells._cut_cells.empty()) + { + cut_mesh._gdim = 0; + cut_mesh._tdim = 0; + cut_mesh._num_cells = 0; + cut_mesh._num_vertices = 0; + return cut_mesh; + } + std::size_t gdim = cut_cells._cut_cells[0]._gdim; std::size_t tdim = cut_cells._cut_cells[0]._tdim; @@ -110,19 +160,26 @@ namespace cutcells::mesh cut_mesh._offset.resize(num_cells+1); cut_mesh._connectivity.resize(num_connectivity); - //either two or one - int num_parents = cut_cells._parent_map.size()/cut_cells._cut_cells.size(); + // either two or one; allow missing parent map + int num_parents = 0; + if (!cut_cells._parent_map.empty()) + num_parents = static_cast(cut_cells._parent_map.size() / cut_cells._cut_cells.size()); + if (num_parents <= 0) + num_parents = 1; cut_mesh._num_cells = num_cells; cut_mesh._types.resize(num_cells); - cut_mesh._parent_map.resize(num_cells*num_parents); + cut_mesh._parent_map.resize(num_cells * num_parents, -1); - int merged_vertex_id = 0; int sub_cell_offset = 0; - int vertex_counter = 0; int element_offset = 0; int cnt = 0; + // Fast global dedup: uses CutCell::_vertex_parent_entity tokens and CutCell::_parent_vertex_ids + // (which should be context-global vertex ids for the parent mesh). + std::unordered_map global_vertex_ids; + global_vertex_ids.reserve(static_cast(num_connectivity)); + //all cutcells in vector above should have the same gdim and tdim for(auto & cut_cell : cut_cells._cut_cells) { @@ -142,32 +199,103 @@ namespace cutcells::mesh int local_num_cells = cut_cell._connectivity.size(); - //Map from vertex id in current cutcell to merged cutmesh - std::map local_merged_vertex_ids; + // Map from vertex id in current cutcell to merged cutmesh + std::vector local_merged_vertex_ids(num_cut_cell_vertices, -1); - for(int local_id=0;local_id(cut_cell._vertex_parent_entity.size()) == num_cut_cell_vertices); + const int parent_vertices = cell::get_num_vertices(cut_cell._parent_cell_type); + const bool has_parent_ids = (static_cast(cut_cell._parent_vertex_ids.size()) == parent_vertices); + const int parent_cell_id = cut_cells._parent_map.empty() + ? -1 + : cut_cells._parent_map[cnt * num_parents + 0]; + const bool can_fast_dedup = has_tokens && has_parent_ids && (parent_cell_id >= 0); + + if (can_fast_dedup) { - //check if vertex already exists to avoid doubling of vertices - int id = cutcells::utils::vertex_exists(cut_mesh._vertex_coords, cut_cell._vertex_coords, local_id, gdim); + const auto parent_edges = cell::edges(cut_cell._parent_cell_type); - if(id==-1) //not found + for (int local_id = 0; local_id < num_cut_cell_vertices; ++local_id) { - //add vertex - merged_vertex_id=vertex_counter; - vertex_counter++; + const int32_t token = cut_cell._vertex_parent_entity[local_id]; + VertexKey key; - for(int j=0;j= 100 && token < 200) + { + const int ref_vid = static_cast(token - 100); + if (ref_vid < 0 || ref_vid >= parent_vertices) + { + // Fallback for unexpected token. + key.kind = 2; + key.a = parent_cell_id; + key.b = token; + } + else + { + key.kind = 0; + key.a = static_cast(cut_cell._parent_vertex_ids[ref_vid]); + key.b = 0; + } + } + else if (token >= 200) { - cut_mesh._vertex_coords.push_back(cut_cell._vertex_coords[local_id*gdim+j]); + key.kind = 2; + key.a = parent_cell_id; + key.b = static_cast(token - 200); + } + else + { + const int edge_id = static_cast(token); + if (edge_id < 0 || edge_id >= static_cast(parent_edges.size())) + { + key.kind = 2; + key.a = parent_cell_id; + key.b = token; + } + else + { + const int v0 = parent_edges[edge_id][0]; + const int v1 = parent_edges[edge_id][1]; + const int32_t gv0 = static_cast(cut_cell._parent_vertex_ids[v0]); + const int32_t gv1 = static_cast(cut_cell._parent_vertex_ids[v1]); + key.kind = 1; + key.a = std::min(gv0, gv1); + key.b = std::max(gv0, gv1); + } + } + + auto it = global_vertex_ids.find(key); + if (it == global_vertex_ids.end()) + { + const int merged_vertex_id = static_cast(cut_mesh._vertex_coords.size() / gdim); + append_vertex_coords(cut_mesh._vertex_coords, cut_cell._vertex_coords, local_id, static_cast(gdim)); + global_vertex_ids.emplace(key, merged_vertex_id); + local_merged_vertex_ids[local_id] = merged_vertex_id; + } + else + { + local_merged_vertex_ids[local_id] = it->second; } } - else //found + } + else + { + // Slow fallback: coordinate-based dedup (kept for compatibility). + for (int local_id = 0; local_id < num_cut_cell_vertices; ++local_id) { - //take already existing vertex for local mapping - merged_vertex_id = id; + const int id = cutcells::utils::vertex_exists(cut_mesh._vertex_coords, cut_cell._vertex_coords, + local_id, static_cast(gdim)); + if (id == -1) + { + const int merged_vertex_id = static_cast(cut_mesh._vertex_coords.size() / gdim); + append_vertex_coords(cut_mesh._vertex_coords, cut_cell._vertex_coords, local_id, static_cast(gdim)); + local_merged_vertex_ids[local_id] = merged_vertex_id; + } + else + { + local_merged_vertex_ids[local_id] = id; + } } - //offset is vertex_id - local_merged_vertex_ids[local_id] = merged_vertex_id; } for(int i=0;i(index)]; } cut_mesh._offset[sub_cell_offset+i] = element_offset; @@ -253,14 +381,26 @@ namespace cutcells::mesh std::span vtk_type, const std::string& cut_type_str) { - cutcells::mesh::CutCells cut_cells; + return cut_vtk_mesh(ls_vals, points, + connectivity, offset, + vtk_type, + cut_type_str, + true); + } - bool triangulate = true; + template + cutcells::mesh::CutMesh cut_vtk_mesh(std::span ls_vals, std::span points, + std::span connectivity, std::span offset, + std::span vtk_type, + const std::string& cut_type_str, + bool triangulate) + { + cutcells::mesh::CutCells cut_cells; auto intersected_cells = locate_cells(ls_vals, points, - connectivity, offset, - vtk_type, - cell::cut_type::phieq0); + connectivity, offset, + vtk_type, + cell::cut_type::phieq0); cut_cells._cut_cells.resize(intersected_cells.size()); cut_cells._parent_map.resize(intersected_cells.size()); @@ -289,6 +429,17 @@ namespace cutcells::mesh //cut the cell cell::cut(cell_type, vertex_coords,3,level_set_values,cut_type_str,cut_cell,triangulate); + + // Populate context-global parent vertex IDs to enable fast merging in create_cut_mesh. + // The cutters themselves default these IDs to 0..V-1. + cut_cell._parent_cell_type = cell_type; + cut_cell._parent_vertex_ids.resize(num_vertices); + for (int j = 0; j < num_vertices; ++j) + { + const int vertex_id = connectivity[cell_offset + j]; + cut_cell._parent_vertex_ids[j] = vertex_id; + } + cut_cells._cut_cells[i] = cut_cell; cut_cells._parent_map[i] = cell_index; @@ -329,5 +480,18 @@ namespace cutcells::mesh std::span vtk_type, const std::string& cut_type_str); + template + cutcells::mesh::CutMesh cut_vtk_mesh(std::span ls_vals, std::span points, + std::span connectivity, std::span offset, + std::span vtk_type, + const std::string& cut_type_str, + bool triangulate); + template + cutcells::mesh::CutMesh cut_vtk_mesh(std::span ls_vals, std::span points, + std::span connectivity, std::span offset, + std::span vtk_type, + const std::string& cut_type_str, + bool triangulate); + //----------------------------------------------------------------------------- } diff --git a/cpp/src/cut_mesh.h b/cpp/src/cut_mesh.h index 37241c9..913fa1a 100644 --- a/cpp/src/cut_mesh.h +++ b/cpp/src/cut_mesh.h @@ -94,4 +94,11 @@ namespace cutcells::mesh std::span connectivity, std::span offset, std::span vtk_type, const std::string& cut_type_str); + + template + cutcells::mesh::CutMesh cut_vtk_mesh(std::span ls_vals, std::span points, + std::span connectivity, std::span offset, + std::span vtk_type, + const std::string& cut_type_str, + bool triangulate); } \ No newline at end of file diff --git a/cpp/src/cut_prism.cpp b/cpp/src/cut_prism.cpp new file mode 100644 index 0000000..acc9faf --- /dev/null +++ b/cpp/src/cut_prism.cpp @@ -0,0 +1,336 @@ +// Copyright (c) 2025 ONERA +// Authors: Susanne Claus +// This file is part of CutCells +// +// SPDX-License-Identifier: MIT + +#include "cut_prism.h" + +#include "cell_flags.h" +#include "cut_cell.h" +#include "cut_interval.h" +#include "generated/cut_prism_inside_tables.h" +#include "generated/cut_prism_interface_tables.h" +#include "generated/cut_prism_outside_tables.h" +#include "utils.h" + +#include +#include +#include +#include +#include + +namespace cutcells::cell::prism +{ + namespace + { + // VTK_WEDGE / CutCells prism vertex ordering assumed: + // bottom tri: 0,1,2 ; top tri: 3,4,5. + // Edge ids must match the VTK TableBasedClip case stream. + constexpr int edges[9][2] = { + {0, 1}, {1, 2}, {2, 0}, // bottom triangle + {3, 4}, {4, 5}, {5, 3}, // top triangle + {0, 3}, {1, 4}, {2, 5} // vertical edges + }; + + [[noreturn]] void throw_missing_token(const int flag, const int token, const char* where) + { + throw std::runtime_error(std::string(where) + ": missing token=" + std::to_string(token) + + " for flag=" + std::to_string(flag)); + } + + int lookup_token_or_throw(const std::unordered_map& vertex_case_map, + const int flag, + const int token, + const char* where) + { + const auto it = vertex_case_map.find(token); + if (it == vertex_case_map.end()) + throw_missing_token(flag, token, where); + return it->second; + } + + template + void compute_intersection_points(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const int flag, + std::vector& intersection_points, + std::unordered_map& vertex_case_map) + { + intersection_points.clear(); + vertex_case_map.clear(); + + std::vector v0(gdim); + std::vector v1(gdim); + std::vector ip(gdim); + + int ip_index = 0; + for (int e = 0; e < 9; ++e) + { + if (intersected_edges[flag][e] == 0) + continue; + + const int v0_id = edges[e][0]; + const int v1_id = edges[e][1]; + + for (int j = 0; j < gdim; ++j) + { + v0[j] = vertex_coordinates[v0_id * gdim + j]; + v1[j] = vertex_coordinates[v1_id * gdim + j]; + } + + const T ls0 = ls_values[v0_id]; + const T ls1 = ls_values[v1_id]; + + interval::compute_intersection_point(0.0, v0, v1, ls0, ls1, ip); + + for (int j = 0; j < gdim; ++j) + intersection_points.push_back(ip[j]); + + vertex_case_map[e] = ip_index; + ++ip_index; + } + } + + template + void ensure_vertex_token(const std::span vertex_coordinates, const int gdim, + const int token, + CutCell& cut_cell, + std::unordered_map& vertex_case_map) + { + if (vertex_case_map.find(token) != vertex_case_map.end()) + return; + + const int vid = token - 100; + const int local_idx = static_cast(cut_cell._vertex_coords.size() / gdim); + vertex_case_map[token] = local_idx; + cut_cell._vertex_coords.resize(cut_cell._vertex_coords.size() + gdim); + for (int j = 0; j < gdim; ++j) + cut_cell._vertex_coords[local_idx * gdim + j] = vertex_coordinates[vid * gdim + j]; + } + + template + void ensure_special_token(const std::span vertex_coordinates, const int gdim, + const int flag, const int token, + const int* special_point_count, + const int* special_point_offset, + const int* special_point_data, + CutCell& cut_cell, + std::unordered_map& vertex_case_map) + { + if (vertex_case_map.find(token) != vertex_case_map.end()) + return; + + const int sp_id = token - 200; + const int count = special_point_count[flag]; + if (sp_id < 0 || sp_id >= count) + throw std::runtime_error("Invalid special point id in table"); + + int idx = special_point_offset[flag]; + for (int sid = 0; sid < sp_id; ++sid) + { + const int nrefs = special_point_data[idx++]; + idx += nrefs; + } + + const int nrefs = special_point_data[idx++]; + if (nrefs <= 0) + throw std::runtime_error("Malformed special point definition"); + + std::vector coord(gdim, T(0)); + for (int r = 0; r < nrefs; ++r) + { + const int ref = special_point_data[idx++]; + + if (ref < 100) + { + const int local = lookup_token_or_throw(vertex_case_map, flag, ref, + "ensure_special_token(ref<100)"); + for (int j = 0; j < gdim; ++j) + coord[j] += cut_cell._vertex_coords[local * gdim + j]; + } + else if (ref < 200) + { + const int vid = ref - 100; + for (int j = 0; j < gdim; ++j) + coord[j] += vertex_coordinates[vid * gdim + j]; + } + else + { + ensure_special_token(vertex_coordinates, gdim, flag, ref, + special_point_count, special_point_offset, special_point_data, + cut_cell, vertex_case_map); + const int local = lookup_token_or_throw(vertex_case_map, flag, ref, + "ensure_special_token(ref>=200)"); + for (int j = 0; j < gdim; ++j) + coord[j] += cut_cell._vertex_coords[local * gdim + j]; + } + } + + for (int j = 0; j < gdim; ++j) + coord[j] /= static_cast(nrefs); + + const int local_idx = static_cast(cut_cell._vertex_coords.size() / gdim); + vertex_case_map[token] = local_idx; + cut_cell._vertex_coords.resize(cut_cell._vertex_coords.size() + gdim); + for (int j = 0; j < gdim; ++j) + cut_cell._vertex_coords[local_idx * gdim + j] = coord[j]; + } + + template + void decode_case(const std::span vertex_coordinates, const int gdim, + const int flag, + const int* case_offsets, + const type* cell_types, + const int (*subcell_verts)[MaxVerts], + const int* special_point_count, + const int* special_point_offset, + const int* special_point_data, + bool triangulate, + CutCell& cut_cell, + std::unordered_map& vertex_case_map) + { + const int cell_begin = case_offsets[flag]; + const int cell_end = case_offsets[flag + 1]; + + for (int cell_idx = cell_begin; cell_idx < cell_end; ++cell_idx) + { + const type sub_type = cell_types[cell_idx]; + const int* verts = subcell_verts[cell_idx]; + + std::vector verts_local; + verts_local.reserve(MaxVerts); + for (int i = 0; i < MaxVerts; ++i) + { + const int token = verts[i]; + if (token == -1) + break; + + if (token < 100) + { + // Edge intersection token: already present + } + else if (token < 200) + { + ensure_vertex_token(vertex_coordinates, gdim, token, cut_cell, vertex_case_map); + } + else + { + ensure_special_token(vertex_coordinates, gdim, flag, token, + special_point_count, special_point_offset, special_point_data, + cut_cell, vertex_case_map); + } + + verts_local.push_back(lookup_token_or_throw(vertex_case_map, flag, token, "decode_case")); + } + + if (triangulate && sub_type == type::quadrilateral && verts_local.size() == 4) + { + cut_cell._types.push_back(type::triangle); + cut_cell._connectivity.push_back({verts_local[0], verts_local[1], verts_local[2]}); + cut_cell._types.push_back(type::triangle); + cut_cell._connectivity.push_back({verts_local[0], verts_local[2], verts_local[3]}); + } + else + { + cut_cell._types.push_back(sub_type); + cut_cell._connectivity.push_back(std::move(verts_local)); + } + } + } + } + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate) + { + if (vertex_coordinates.size() != static_cast(6 * gdim)) + throw std::invalid_argument("prism::cut expects 6 vertices"); + if (ls_values.size() != 6) + throw std::invalid_argument("prism::cut expects 6 level set values"); + + // CutCells convention: case mask bit i is set when phi_i < 0. + const int flag_lt0 = get_entity_flag(ls_values, false); + if (flag_lt0 == 0 || flag_lt0 == 63) + throw std::invalid_argument("prism is not intersected and therefore cannot be cut"); + + // Store parent geometry + cut_cell._parent_cell_type = type::prism; + cut_cell._parent_vertex_coords.resize(6 * gdim); + cut_cell._parent_vertex_ids.resize(6); + for (int i = 0; i < 6; ++i) + { + for (int j = 0; j < gdim; ++j) + cut_cell._parent_vertex_coords[i * gdim + j] = vertex_coordinates[i * gdim + j]; + cut_cell._parent_vertex_ids[i] = i; + } + + // Compute intersections (shared for all parts) + std::vector intersection_points; + std::unordered_map vertex_case_map; + compute_intersection_points(vertex_coordinates, gdim, ls_values, flag_lt0, + intersection_points, vertex_case_map); + + cut_cell._gdim = gdim; + cut_cell._vertex_coords = std::move(intersection_points); + cut_cell._types.clear(); + cut_cell._connectivity.clear(); + + if (cut_type_str == "phi=0") + { + cut_cell._tdim = 2; + decode_case(vertex_coordinates, gdim, flag_lt0, + case_subcell_offset_interface, subcell_type_interface, subcell_verts_interface, + special_point_count_interface, special_point_offset_interface, special_point_data_interface, + triangulate, cut_cell, vertex_case_map); + } + else if (cut_type_str == "phi<0") + { + cut_cell._tdim = 3; + decode_case(vertex_coordinates, gdim, flag_lt0, + case_subcell_offset_inside, subcell_type_inside, subcell_verts_inside, + special_point_count_inside, special_point_offset_inside, special_point_data_inside, + triangulate, cut_cell, vertex_case_map); + } + else if (cut_type_str == "phi>0") + { + cut_cell._tdim = 3; + decode_case(vertex_coordinates, gdim, flag_lt0, + case_subcell_offset_outside, subcell_type_outside, subcell_verts_outside, + special_point_count_outside, special_point_offset_outside, special_point_data_outside, + triangulate, cut_cell, vertex_case_map); + } + else + { + throw std::invalid_argument("cutting type unknown"); + } + + cutcells::utils::create_vertex_parent_entity_map(vertex_case_map, cut_cell._vertex_parent_entity); + } + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate) + { + cut_cell.resize(cut_type_str.size()); + for (std::size_t i = 0; i < cut_type_str.size(); ++i) + cut(vertex_coordinates, gdim, ls_values, cut_type_str[i], cut_cell[i], triangulate); + } + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate); + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate); + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate); + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate); +} diff --git a/cpp/src/cut_prism.h b/cpp/src/cut_prism.h new file mode 100644 index 0000000..4b2201c --- /dev/null +++ b/cpp/src/cut_prism.h @@ -0,0 +1,27 @@ +// Copyright (c) 2025 ONERA +// Authors: Susanne Claus +// This file is part of CutCells +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "cell_types.h" +#include "cut_cell.h" + +#include +#include +#include +#include + +namespace cutcells::cell::prism +{ + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate = false); + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate = false); +} diff --git a/cpp/src/cut_pyramid.cpp b/cpp/src/cut_pyramid.cpp new file mode 100644 index 0000000..3907a93 --- /dev/null +++ b/cpp/src/cut_pyramid.cpp @@ -0,0 +1,337 @@ +// Copyright (c) 2025 ONERA +// Authors: Susanne Claus +// This file is part of CutCells +// +// SPDX-License-Identifier: MIT + +#include "cut_pyramid.h" + +#include "cell_flags.h" +#include "cut_cell.h" +#include "cut_interval.h" +#include "generated/cut_pyramid_inside_tables.h" +#include "generated/cut_pyramid_interface_tables.h" +#include "generated/cut_pyramid_outside_tables.h" +#include "utils.h" + +#include +#include +#include +#include + +namespace cutcells::cell::pyramid +{ + namespace + { + // VTK_PYRAMID vertex ordering assumed: + // base quad: 0,1,2,3 and apex: 4. + // Edge ids must match the VTK TableBasedClip case stream. + constexpr int edges[8][2] = { + {0, 1}, {1, 2}, {2, 3}, {3, 0}, // base + {0, 4}, {1, 4}, {2, 4}, {3, 4} // sides + }; + + [[noreturn]] void throw_missing_token(const int flag, const int token, const char* where) + { + throw std::runtime_error(std::string(where) + ": missing token=" + std::to_string(token) + + " for flag=" + std::to_string(flag)); + } + + int lookup_token_or_throw(const std::unordered_map& vertex_case_map, + const int flag, + const int token, + const char* where) + { + const auto it = vertex_case_map.find(token); + if (it == vertex_case_map.end()) + throw_missing_token(flag, token, where); + return it->second; + } + + template + void compute_intersection_points(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const int flag, + std::vector& intersection_points, + std::unordered_map& vertex_case_map) + { + intersection_points.clear(); + vertex_case_map.clear(); + + std::vector v0(gdim); + std::vector v1(gdim); + std::vector ip(gdim); + + int ip_index = 0; + for (int e = 0; e < 8; ++e) + { + if (intersected_edges[flag][e] == 0) + continue; + + const int v0_id = edges[e][0]; + const int v1_id = edges[e][1]; + + for (int j = 0; j < gdim; ++j) + { + v0[j] = vertex_coordinates[v0_id * gdim + j]; + v1[j] = vertex_coordinates[v1_id * gdim + j]; + } + + const T ls0 = ls_values[v0_id]; + const T ls1 = ls_values[v1_id]; + + interval::compute_intersection_point(0.0, v0, v1, ls0, ls1, ip); + + for (int j = 0; j < gdim; ++j) + intersection_points.push_back(ip[j]); + + vertex_case_map[e] = ip_index; + ++ip_index; + } + } + + template + void ensure_vertex_token(const std::span vertex_coordinates, const int gdim, + const int token, + CutCell& cut_cell, + std::unordered_map& vertex_case_map) + { + if (vertex_case_map.find(token) != vertex_case_map.end()) + return; + + const int vid = token - 100; + const int local_idx = static_cast(cut_cell._vertex_coords.size() / gdim); + vertex_case_map[token] = local_idx; + cut_cell._vertex_coords.resize(cut_cell._vertex_coords.size() + gdim); + for (int j = 0; j < gdim; ++j) + cut_cell._vertex_coords[local_idx * gdim + j] = vertex_coordinates[vid * gdim + j]; + } + + template + void ensure_special_token(const std::span vertex_coordinates, const int gdim, + const int flag, const int token, + const int* special_point_count, + const int* special_point_offset, + const int* special_point_data, + CutCell& cut_cell, + std::unordered_map& vertex_case_map) + { + if (vertex_case_map.find(token) != vertex_case_map.end()) + return; + + if (special_point_count == nullptr || special_point_offset == nullptr || special_point_data == nullptr) + throw std::runtime_error("Special points referenced but not available for this table"); + + const int sp_id = token - 200; + const int count = special_point_count[flag]; + if (sp_id < 0 || sp_id >= count) + throw std::runtime_error("Invalid special point id in table"); + + int idx = special_point_offset[flag]; + for (int sid = 0; sid < sp_id; ++sid) + { + const int nrefs = special_point_data[idx++]; + idx += nrefs; + } + + const int nrefs = special_point_data[idx++]; + if (nrefs <= 0) + throw std::runtime_error("Malformed special point definition"); + + std::vector coord(gdim, T(0)); + for (int r = 0; r < nrefs; ++r) + { + const int ref = special_point_data[idx++]; + + if (ref < 100) + { + const int local = lookup_token_or_throw(vertex_case_map, flag, ref, + "ensure_special_token(ref<100)"); + for (int j = 0; j < gdim; ++j) + coord[j] += cut_cell._vertex_coords[local * gdim + j]; + } + else if (ref < 200) + { + const int vid = ref - 100; + for (int j = 0; j < gdim; ++j) + coord[j] += vertex_coordinates[vid * gdim + j]; + } + else + { + ensure_special_token(vertex_coordinates, gdim, flag, ref, + special_point_count, special_point_offset, special_point_data, + cut_cell, vertex_case_map); + const int local = lookup_token_or_throw(vertex_case_map, flag, ref, + "ensure_special_token(ref>=200)"); + for (int j = 0; j < gdim; ++j) + coord[j] += cut_cell._vertex_coords[local * gdim + j]; + } + } + + for (int j = 0; j < gdim; ++j) + coord[j] /= static_cast(nrefs); + + const int local_idx = static_cast(cut_cell._vertex_coords.size() / gdim); + vertex_case_map[token] = local_idx; + cut_cell._vertex_coords.resize(cut_cell._vertex_coords.size() + gdim); + for (int j = 0; j < gdim; ++j) + cut_cell._vertex_coords[local_idx * gdim + j] = coord[j]; + } + + template + void decode_case(const std::span vertex_coordinates, const int gdim, + const int flag, + const int* case_offsets, + const type* cell_types, + const int (*subcell_verts)[MaxVerts], + const int* special_point_count, + const int* special_point_offset, + const int* special_point_data, + bool triangulate, + CutCell& cut_cell, + std::unordered_map& vertex_case_map) + { + const int cell_begin = case_offsets[flag]; + const int cell_end = case_offsets[flag + 1]; + + for (int cell_idx = cell_begin; cell_idx < cell_end; ++cell_idx) + { + const type sub_type = cell_types[cell_idx]; + const int* verts = subcell_verts[cell_idx]; + + std::vector verts_local; + verts_local.reserve(MaxVerts); + for (int i = 0; i < MaxVerts; ++i) + { + const int token = verts[i]; + if (token == -1) + break; + + if (token < 100) + { + // Edge intersection token: already present + } + else if (token < 200) + { + ensure_vertex_token(vertex_coordinates, gdim, token, cut_cell, vertex_case_map); + } + else + { + ensure_special_token(vertex_coordinates, gdim, flag, token, + special_point_count, special_point_offset, special_point_data, + cut_cell, vertex_case_map); + } + + verts_local.push_back(lookup_token_or_throw(vertex_case_map, flag, token, "decode_case")); + } + + if (triangulate && sub_type == type::quadrilateral && verts_local.size() == 4) + { + cut_cell._types.push_back(type::triangle); + cut_cell._connectivity.push_back({verts_local[0], verts_local[1], verts_local[2]}); + cut_cell._types.push_back(type::triangle); + cut_cell._connectivity.push_back({verts_local[0], verts_local[2], verts_local[3]}); + } + else + { + cut_cell._types.push_back(sub_type); + cut_cell._connectivity.push_back(std::move(verts_local)); + } + } + } + } + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate) + { + if (vertex_coordinates.size() != static_cast(5 * gdim)) + throw std::invalid_argument("pyramid::cut expects 5 vertices"); + if (ls_values.size() != 5) + throw std::invalid_argument("pyramid::cut expects 5 level set values"); + + // CutCells convention: case mask bit i is set when phi_i < 0. + const int flag_lt0 = get_entity_flag(ls_values, false); + if (flag_lt0 == 0 || flag_lt0 == 31) + throw std::invalid_argument("pyramid is not intersected and therefore cannot be cut"); + + // Store parent geometry + cut_cell._parent_cell_type = type::pyramid; + cut_cell._parent_vertex_coords.resize(5 * gdim); + cut_cell._parent_vertex_ids.resize(5); + for (int i = 0; i < 5; ++i) + { + for (int j = 0; j < gdim; ++j) + cut_cell._parent_vertex_coords[i * gdim + j] = vertex_coordinates[i * gdim + j]; + cut_cell._parent_vertex_ids[i] = i; + } + + // Compute intersections (shared for all parts) + std::vector intersection_points; + std::unordered_map vertex_case_map; + compute_intersection_points(vertex_coordinates, gdim, ls_values, flag_lt0, + intersection_points, vertex_case_map); + + cut_cell._gdim = gdim; + cut_cell._vertex_coords = std::move(intersection_points); + cut_cell._types.clear(); + cut_cell._connectivity.clear(); + + if (cut_type_str == "phi=0") + { + cut_cell._tdim = 2; + decode_case(vertex_coordinates, gdim, flag_lt0, + case_subcell_offset_interface, subcell_type_interface, subcell_verts_interface, + nullptr, nullptr, nullptr, + triangulate, cut_cell, vertex_case_map); + } + else if (cut_type_str == "phi<0") + { + cut_cell._tdim = 3; + decode_case(vertex_coordinates, gdim, flag_lt0, + case_subcell_offset_inside, subcell_type_inside, subcell_verts_inside, + special_point_count_inside, special_point_offset_inside, special_point_data_inside, + triangulate, cut_cell, vertex_case_map); + } + else if (cut_type_str == "phi>0") + { + cut_cell._tdim = 3; + decode_case(vertex_coordinates, gdim, flag_lt0, + case_subcell_offset_outside, subcell_type_outside, subcell_verts_outside, + special_point_count_outside, special_point_offset_outside, special_point_data_outside, + triangulate, cut_cell, vertex_case_map); + } + else + { + throw std::invalid_argument("cutting type unknown"); + } + + cutcells::utils::create_vertex_parent_entity_map(vertex_case_map, cut_cell._vertex_parent_entity); + } + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate) + { + cut_cell.resize(cut_type_str.size()); + for (std::size_t i = 0; i < cut_type_str.size(); ++i) + cut(vertex_coordinates, gdim, ls_values, cut_type_str[i], cut_cell[i], triangulate); + } + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate); + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate); + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate); + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate); +} diff --git a/cpp/src/cut_pyramid.h b/cpp/src/cut_pyramid.h new file mode 100644 index 0000000..1bf2851 --- /dev/null +++ b/cpp/src/cut_pyramid.h @@ -0,0 +1,27 @@ +// Copyright (c) 2025 ONERA +// Authors: Susanne Claus +// This file is part of CutCells +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "cell_types.h" +#include "cut_cell.h" + +#include +#include +#include +#include + +namespace cutcells::cell::pyramid +{ + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate = false); + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate = false); +} diff --git a/cpp/src/cut_quadrilateral.cpp b/cpp/src/cut_quadrilateral.cpp new file mode 100644 index 0000000..9a720a3 --- /dev/null +++ b/cpp/src/cut_quadrilateral.cpp @@ -0,0 +1,372 @@ +// Copyright (c) 2022-2025 ONERA +// Authors: Susanne Claus +// This file is part of CutCells +// +// SPDX-License-Identifier: MIT + +#include "cut_quadrilateral.h" +#include "cell_flags.h" +#include "cell_topology.h" +#include "cut_interval.h" +#include "cut_triangle.h" +#include "generated/cut_quadrilateral_inside_tables.h" +#include "generated/cut_quadrilateral_outside_tables.h" +#include "generated/cut_quadrilateral_interface_tables.h" +#include "triangulation.h" +#include "utils.h" + +#include +#include +#include +#include + +namespace cutcells::cell::quadrilateral +{ + namespace + { + inline bool case_is_ambiguous(int flag) + { + // Opposite-corner patterns 0b0101 (5) and 0b1010 (10) + return flag == 5 || flag == 10; + } + + inline bool asymptotic_decider(double f0, double f1, double f2, double f3) + { + // Bilinear form for marching squares; true -> choose diagonal (0,2), false -> (1,3) + // This form is invariant to scaling of phi. + const double d = f0 * f2 - f1 * f3; + // Tie-break: when d==0 (center exactly on interface), prefer the alternate variant + // to keep the opposite-corners case disconnected. + return d > 0.0; + } + + template + void compute_intersection_points(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const int flag, + std::vector& intersection_points, + std::unordered_map& vertex_case_map) + { + const auto& intersected = intersected_edges[flag]; + + intersection_points.clear(); + vertex_case_map.clear(); + + std::vector v0(gdim); + std::vector v1(gdim); + std::vector ip(gdim); + + int ip_index = 0; + for (int e = 0; e < 4; ++e) + { + if (intersected[e] == 0) + continue; + + const int v0_id = edges[e][0]; + const int v1_id = edges[e][1]; + + for (int j = 0; j < gdim; ++j) + { + v0[j] = vertex_coordinates[v0_id * gdim + j]; + v1[j] = vertex_coordinates[v1_id * gdim + j]; + } + + const T ls0 = ls_values[v0_id]; + const T ls1 = ls_values[v1_id]; + + interval::compute_intersection_point(0.0, v0, v1, ls0, ls1, ip); + + for (int j = 0; j < gdim; ++j) + { + intersection_points.push_back(ip[j]); + } + + vertex_case_map[e] = ip_index; + ++ip_index; + } + } + template + void decode_range(const std::span vertex_coordinates, const int gdim, + const int cell_begin, const int cell_end, + const type* cell_types, + const int (*subcell_verts)[MaxVerts], + const std::span intersection_points, + bool triangulate, CutCell& cut_cell, + const std::unordered_map& edge_ip_map, + std::unordered_map& token_to_local_out) + { + // Map from token (edge id or 100+vid) to local vertex index in cut_cell._vertex_coords + std::unordered_map token_to_local; + + // Prefill edge intersections so they get stable indices + for (int e = 0; e < 4; ++e) + { + const auto it = edge_ip_map.find(e); + if (it == edge_ip_map.end()) + continue; + + const int token = it->first; // edge id + const int ip_idx = it->second; + const int local_idx = static_cast(cut_cell._vertex_coords.size() / gdim); + token_to_local[token] = local_idx; + cut_cell._vertex_coords.resize(cut_cell._vertex_coords.size() + gdim); + for (int j = 0; j < gdim; ++j) + cut_cell._vertex_coords[local_idx * gdim + j] = intersection_points[ip_idx * gdim + j]; + } + + auto get_local = [&](int token) -> int + { + auto it = token_to_local.find(token); + if (it != token_to_local.end()) + return it->second; + + const int local_idx = static_cast(cut_cell._vertex_coords.size() / gdim); + token_to_local[token] = local_idx; + cut_cell._vertex_coords.resize(cut_cell._vertex_coords.size() + gdim); + + if (token < 100) + { + // edge intersection point + const int ip_idx = edge_ip_map.at(token); + for (int j = 0; j < gdim; ++j) + cut_cell._vertex_coords[local_idx * gdim + j] = intersection_points[ip_idx * gdim + j]; + } + else + { + const int vid = token - 100; + for (int j = 0; j < gdim; ++j) + cut_cell._vertex_coords[local_idx * gdim + j] = vertex_coordinates[vid * gdim + j]; + } + return local_idx; + }; + + for (int cell_idx = cell_begin; cell_idx < cell_end; ++cell_idx) + { + const type sub_type = cell_types[cell_idx]; + const int* verts = subcell_verts[cell_idx]; + + std::vector verts_local; + for (int i = 0; i < MaxVerts; ++i) + { + const int token = verts[i]; + if (token == -1) + break; + verts_local.push_back(get_local(token)); + } + + if (triangulate && sub_type == type::quadrilateral && verts_local.size() == 4) + { + // split into two triangles (0,1,2) and (0,2,3) + cut_cell._types.push_back(type::triangle); + cut_cell._connectivity.push_back({verts_local[0], verts_local[1], verts_local[2]}); + cut_cell._types.push_back(type::triangle); + cut_cell._connectivity.push_back({verts_local[0], verts_local[2], verts_local[3]}); + } + else + { + cut_cell._types.push_back(sub_type); + cut_cell._connectivity.push_back(std::move(verts_local)); + } + } + + token_to_local_out = std::move(token_to_local); + } + + template + void decode_case(const std::span vertex_coordinates, const int gdim, int flag, + const int* case_offsets, const type* cell_types, + const int (*subcell_verts)[MaxVerts], + const std::span intersection_points, + bool triangulate, CutCell& cut_cell, + const std::unordered_map& edge_ip_map, + std::unordered_map& token_to_local_out) + { + decode_range(vertex_coordinates, gdim, + case_offsets[flag], case_offsets[flag + 1], + cell_types, subcell_verts, + intersection_points, triangulate, cut_cell, edge_ip_map, token_to_local_out); + } + } // namespace + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate) + { + const int flag_interior = get_entity_flag(ls_values, false); + + if (flag_interior == 0 || flag_interior == 15) + { + throw std::invalid_argument("quadrilateral is not intersected and therefore cannot be cut"); + } + + // Store parent geometry + cut_cell._parent_cell_type = type::quadrilateral; + cut_cell._parent_vertex_coords.resize(4 * gdim); + cut_cell._parent_vertex_ids.resize(4); + for (int i = 0; i < 4; ++i) + { + for (int j = 0; j < gdim; ++j) + { + cut_cell._parent_vertex_coords[i * gdim + j] = vertex_coordinates[i * gdim + j]; + } + cut_cell._parent_vertex_ids[i] = i; + } + + // Compute intersections (shared for all parts) + std::vector intersection_points; + std::unordered_map edge_ip_map; + compute_intersection_points(vertex_coordinates, gdim, ls_values, flag_interior, intersection_points, edge_ip_map); + + // Final token->local vertex index map used to populate CutCell::_vertex_parent_entity + std::unordered_map token_to_local; + + cut_cell._gdim = gdim; + cut_cell._vertex_coords.clear(); + cut_cell._types.clear(); + cut_cell._connectivity.clear(); + + const bool is_amb = case_is_ambiguous(flag_interior); + const int variant = asymptotic_decider(ls_values[0], ls_values[1], ls_values[2], ls_values[3]) ? 0 : 1; + + if (cut_type_str == "phi=0") + { + cut_cell._tdim = 1; + std::span ip_span(intersection_points.data(), intersection_points.size()); + if (is_amb) + { + const int amb_id = amb_case_id[flag_interior]; + const int begin = amb_range_interface[4 * amb_id + 2 * variant + 0]; + const int end = amb_range_interface[4 * amb_id + 2 * variant + 1]; + decode_range(vertex_coordinates, gdim, begin, end, + subcell_type_interface, subcell_verts_interface, + ip_span, triangulate, cut_cell, edge_ip_map, token_to_local); + } + else + { + decode_case(vertex_coordinates, gdim, flag_interior, + case_subcell_offset_interface, subcell_type_interface, + subcell_verts_interface, ip_span, triangulate, cut_cell, edge_ip_map, token_to_local); + } + } + else if (cut_type_str == "phi<0") + { + cut_cell._tdim = 2; + std::span ip_span(intersection_points.data(), intersection_points.size()); + if (is_amb) + { + const int amb_id = amb_case_id[flag_interior]; + const int begin = amb_range_inside[4 * amb_id + 2 * variant + 0]; + const int end = amb_range_inside[4 * amb_id + 2 * variant + 1]; + decode_range(vertex_coordinates, gdim, begin, end, + subcell_type_inside, subcell_verts_inside, + ip_span, triangulate, cut_cell, edge_ip_map, token_to_local); + } + else + { + decode_case(vertex_coordinates, gdim, flag_interior, + case_subcell_offset_inside, subcell_type_inside, + subcell_verts_inside, ip_span, triangulate, cut_cell, edge_ip_map, token_to_local); + } + } + else if (cut_type_str == "phi>0") + { + cut_cell._tdim = 2; + std::span ip_span(intersection_points.data(), intersection_points.size()); + // Note: the generated "outside" tables are keyed by the *interior* mask (phi<0), + // i.e. they already represent the complement region. + if (is_amb) + { + const int amb_id = amb_case_id[flag_interior]; + const int begin = amb_range_outside[4 * amb_id + 2 * variant + 0]; + const int end = amb_range_outside[4 * amb_id + 2 * variant + 1]; + decode_range(vertex_coordinates, gdim, begin, end, + subcell_type_outside, subcell_verts_outside, + ip_span, triangulate, cut_cell, edge_ip_map, token_to_local); + } + else + { + decode_case(vertex_coordinates, gdim, flag_interior, + case_subcell_offset_outside, subcell_type_outside, + subcell_verts_outside, ip_span, triangulate, cut_cell, edge_ip_map, token_to_local); + } + } + else + { + throw std::invalid_argument("cutting type unknown"); + } + + cutcells::utils::create_vertex_parent_entity_map(token_to_local, cut_cell._vertex_parent_entity); + } + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate) + { + const int flag_interior = get_entity_flag(ls_values, false); + if (flag_interior == 0 || flag_interior == 15) + { + throw std::invalid_argument("quadrilateral is not intersected and therefore cannot be cut"); + } + + cut_cell.resize(cut_type_str.size()); + for (std::size_t i = 0; i < cut_type_str.size(); ++i) + { + cut(vertex_coordinates, gdim, ls_values, cut_type_str[i], cut_cell[i], triangulate); + } + } + + template + T volume(const std::span vertex_coordinates, const int gdim) + { + // Split quad into two triangles (0-1-2) and (0-2-3) + std::vector t0; + t0.reserve(3 * gdim); + for (int j = 0; j < gdim; ++j) + { + t0.push_back(vertex_coordinates[0 * gdim + j]); + } + for (int j = 0; j < gdim; ++j) + { + t0.push_back(vertex_coordinates[1 * gdim + j]); + } + for (int j = 0; j < gdim; ++j) + { + t0.push_back(vertex_coordinates[2 * gdim + j]); + } + + std::vector t1; + t1.reserve(3 * gdim); + for (int j = 0; j < gdim; ++j) + { + t1.push_back(vertex_coordinates[0 * gdim + j]); + } + for (int j = 0; j < gdim; ++j) + { + t1.push_back(vertex_coordinates[2 * gdim + j]); + } + for (int j = 0; j < gdim; ++j) + { + t1.push_back(vertex_coordinates[3 * gdim + j]); + } + + return triangle::volume(t0, gdim) + triangle::volume(t1, gdim); + } + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate); + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate); + + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate); + template void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate); + + template double volume(const std::span vertex_coordinates, const int gdim); + template float volume(const std::span vertex_coordinates, const int gdim); +} diff --git a/cpp/src/cut_quadrilateral.h b/cpp/src/cut_quadrilateral.h new file mode 100644 index 0000000..c514845 --- /dev/null +++ b/cpp/src/cut_quadrilateral.h @@ -0,0 +1,30 @@ +// Copyright (c) 2022-2025 ONERA +// Authors: Susanne Claus +// This file is part of CutCells +// +// SPDX-License-Identifier: MIT +#pragma once + +#include "cut_cell.h" +#include "cell_types.h" + +#include +#include +#include +#include + +namespace cutcells::cell::quadrilateral +{ + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::string& cut_type_str, + CutCell& cut_cell, bool triangulate=false); + + template + void cut(const std::span vertex_coordinates, const int gdim, + const std::span ls_values, const std::vector& cut_type_str, + std::vector>& cut_cell, bool triangulate=false); + + template + T volume(const std::span vertex_coordinates, const int gdim); +} diff --git a/cpp/src/generated/cut_hexahedron_inside_tables.h b/cpp/src/generated/cut_hexahedron_inside_tables.h new file mode 100644 index 0000000..3c44567 --- /dev/null +++ b/cpp/src/generated/cut_hexahedron_inside_tables.h @@ -0,0 +1,1864 @@ +#ifndef CUT_CELLS_HEXAHEDRON_INSIDE_TABLES_H +#define CUT_CELLS_HEXAHEDRON_INSIDE_TABLES_H + +// ----------------------------------------------------------------------------- +// This file is generated by CutCells tablegen. +// +// It contains case tables derived from VTK's vtkTableBasedClipCases.h +// (Visualization Toolkit, TableBasedClip). +// +// VTK ref: master +// VTK header path override: (none) +// +// VTK is licensed under the BSD 3-Clause License. +// See third_party/VTK-Copyright.txt in this repository. +// ----------------------------------------------------------------------------- + +#include "cell_types.h" + +namespace cutcells::cell::hexahedron { + +// Topology +constexpr int edges[12][2] = { + {0,1}, {1,2}, {2,3}, {3,0}, // bottom face + {4,5}, {5,6}, {6,7}, {7,4}, // top face + {0,4}, {1,5}, {3,7}, {2,6} // vertical edges (VTK TableBasedClip ordering) +}; + +constexpr int faces[6][4] = { + {0,3,2,1}, {4,5,6,7}, // bottom, top + {0,1,5,4}, {1,2,6,5}, // front, right + {2,3,7,6}, {3,0,4,7} // back, left +}; + +// Intersected edges per case (1 = intersected, 0 = not intersected) +constexpr int intersected_edges[256][12] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0 }, + { 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, + { 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0 }, + { 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1 }, + { 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, + { 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1 }, + { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0 }, + { 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, + { 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0 }, + { 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0 }, + { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1 }, + { 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1 }, + { 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0 }, + { 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0 }, + { 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0 }, + { 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0 }, + { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1 }, + { 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1 }, + { 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0 }, + { 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0 }, + { 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0 }, + { 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0 }, + { 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1 }, + { 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 }, + { 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1 }, + { 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 }, + { 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0 }, + { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0 }, + { 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1 }, + { 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1 }, + { 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0 }, + { 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0 }, + { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0 }, + { 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0 }, + { 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1 }, + { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1 }, + { 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1 }, + { 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1 }, + { 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0 }, + { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 }, + { 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0 }, + { 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 }, + { 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1 }, + { 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1 }, + { 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1 }, + { 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0 }, + { 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0 }, + { 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0 }, + { 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0 }, + { 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1 }, + { 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1 }, + { 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1 }, + { 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1 }, + { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1 }, + { 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 }, + { 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1 }, + { 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 }, + { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0 }, + { 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0 }, + { 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0 }, + { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1 }, + { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1 }, + { 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1 }, + { 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1 }, + { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0 }, + { 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0 }, + { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0 }, + { 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0 }, + { 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1 }, + { 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1 }, + { 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1 }, + { 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1 }, + { 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, + { 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 }, + { 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0 }, + { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 }, + { 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 }, + { 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0 }, + { 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0 }, + { 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 }, + { 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0 }, + { 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1 }, + { 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1 }, + { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1 }, + { 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0 }, + { 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0 }, + { 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0 }, + { 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0 }, + { 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1 }, + { 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1 }, + { 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 }, + { 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0 }, + { 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0 }, + { 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0 }, + { 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0 }, + { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1 }, + { 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1 }, + { 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0 }, + { 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0 }, + { 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0 }, + { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0 }, + { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1 }, + { 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1 }, + { 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1 }, + { 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0 }, + { 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0 }, + { 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0 }, + { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 }, + { 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0 }, + { 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0 }, + { 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0 }, + { 0, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0 }, + { 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1 }, + { 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 1, 1 }, + { 1, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1 }, + { 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1 }, + { 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0 }, + { 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0 }, + { 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0 }, + { 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0 }, + { 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1 }, + { 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1 }, + { 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1 }, + { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1 }, + { 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0 }, + { 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0 }, + { 1, 1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0 }, + { 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0 }, + { 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1 }, + { 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 1, 1 }, + { 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1 }, + { 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1 }, + { 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0 }, + { 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0 }, + { 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0 }, + { 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0 }, + { 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1 }, + { 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1 }, + { 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1 }, + { 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1 }, + { 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0 }, + { 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0 }, + { 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 0 }, + { 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0 }, + { 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, + { 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1 }, + { 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1 }, + { 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0 }, + { 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0 }, + { 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, + { 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0 }, + { 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1 }, + { 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1 }, + { 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1 }, + { 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1 }, + { 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0 }, + { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0 }, + { 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0 }, + { 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0 }, + { 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1 }, + { 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1 }, + { 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1 }, + { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1 }, + { 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0 }, + { 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0 }, + { 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0 }, + { 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 }, + { 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1 }, + { 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1 }, + { 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1 }, + { 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1 }, + { 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1 }, + { 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1 }, + { 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1 }, + { 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1 }, + { 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0 }, + { 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0 }, + { 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0 }, + { 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0 }, + { 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1 }, + { 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1 }, + { 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1 }, + { 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0 }, + { 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0 }, + { 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 }, + { 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0 }, + { 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1 }, + { 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1 }, + { 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1 }, + { 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1 }, + { 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0 }, + { 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0 }, + { 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0 }, + { 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0 }, + { 0, 0, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1 }, + { 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1 }, + { 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0 }, + { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0 }, + { 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0 }, + { 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 1, 1 }, + { 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1 }, + { 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1 }, + { 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1 }, + { 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0 }, + { 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0 }, + { 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0 }, + { 0, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 0 }, + { 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1 }, + { 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1 }, + { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1 }, + { 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0 }, + { 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0 }, + { 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0 }, + { 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1 }, + { 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1 }, + { 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1 }, + { 0, 1, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0 }, + { 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 1, 0 }, + { 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0 }, + { 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0 }, + { 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1 }, + { 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1 }, + { 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1 }, + { 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0 }, + { 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }, + { 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +// Number of subcells produced for each case (inside volume) +constexpr int num_subcells_inside[256] = { 0, 1, 1, 1, 1, 6, 1, 6, 1, 1, 6, 6, 1, 6, 6, 1, 1, 1, 6, 6, 2, 7, 7, 8, 6, 6, 5, 5, 7, 8, 8, 8, 1, 6, 1, 6, 6, 5, 6, 5, 2, 7, 7, 8, 7, 8, 8, 8, 1, 6, 6, 1, 7, 8, 8, 8, 7, 8, 8, 8, 2, 10, 10, 2, 1, 2, 6, 7, 1, 7, 6, 8, 6, 7, 5, 8, 6, 8, 5, 8, 6, 7, 5, 8, 7, 2, 8, 10, 5, 8, 5, 5, 8, 10, 5, 5, 1, 7, 6, 8, 6, 8, 1, 8, 7, 2, 8, 10, 8, 10, 8, 2, 6, 8, 5, 8, 8, 10, 8, 2, 8, 10, 5, 5, 10, 6, 5, 8, 1, 6, 2, 7, 6, 5, 7, 8, 1, 6, 7, 8, 6, 5, 8, 8, 1, 6, 7, 8, 7, 8, 2, 10, 6, 1, 8, 8, 8, 8, 10, 2, 6, 5, 7, 8, 5, 5, 8, 5, 7, 8, 2, 10, 8, 5, 10, 5, 6, 5, 8, 8, 8, 5, 10, 5, 8, 8, 10, 2, 10, 5, 6, 8, 1, 7, 7, 2, 6, 8, 8, 10, 6, 8, 8, 10, 1, 8, 8, 2, 6, 8, 8, 10, 8, 10, 10, 6, 5, 8, 5, 5, 8, 2, 5, 8, 6, 8, 8, 10, 5, 5, 8, 5, 8, 10, 10, 6, 8, 5, 2, 8, 1, 8, 8, 2, 8, 5, 2, 8, 8, 2, 5, 8, 2, 8, 8, 1 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_inside[257] = { 0, 0, 1, 2, 3, 4, 10, 11, 17, 18, 19, 25, 31, 32, 38, 44, 45, 46, 47, 53, 59, 61, 68, 75, 83, 89, 95, 100, 105, 112, 120, 128, 136, 137, 143, 144, 150, 156, 161, 167, 172, 174, 181, 188, 196, 203, 211, 219, 227, 228, 234, 240, 241, 248, 256, 264, 272, 279, 287, 295, 303, 305, 315, 325, 327, 328, 330, 336, 343, 344, 351, 357, 365, 371, 378, 383, 391, 397, 405, 410, 418, 424, 431, 436, 444, 451, 453, 461, 471, 476, 484, 489, 494, 502, 512, 517, 522, 523, 530, 536, 544, 550, 558, 559, 567, 574, 576, 584, 594, 602, 612, 620, 622, 628, 636, 641, 649, 657, 667, 675, 677, 685, 695, 700, 705, 715, 721, 726, 734, 735, 741, 743, 750, 756, 761, 768, 776, 777, 783, 790, 798, 804, 809, 817, 825, 826, 832, 839, 847, 854, 862, 864, 874, 880, 881, 889, 897, 905, 913, 923, 925, 931, 936, 943, 951, 956, 961, 969, 974, 981, 989, 991, 1001, 1009, 1014, 1024, 1029, 1035, 1040, 1048, 1056, 1064, 1069, 1079, 1084, 1092, 1100, 1110, 1112, 1122, 1127, 1133, 1141, 1142, 1149, 1156, 1158, 1164, 1172, 1180, 1190, 1196, 1204, 1212, 1222, 1223, 1231, 1239, 1241, 1247, 1255, 1263, 1273, 1281, 1291, 1301, 1307, 1312, 1320, 1325, 1330, 1338, 1340, 1345, 1353, 1359, 1367, 1375, 1385, 1390, 1395, 1403, 1408, 1416, 1426, 1436, 1442, 1450, 1455, 1457, 1465, 1466, 1474, 1482, 1484, 1492, 1497, 1499, 1507, 1515, 1517, 1522, 1530, 1532, 1540, 1548, 1549 }; + +// Cell types for inside subcells +constexpr type subcell_type_inside[1549] = { cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::hexahedron, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::hexahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::hexahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::hexahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::hexahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron }; + +// Subcell vertices (max 8 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, 100..199 = 100+vertex_id, >=200 = 200+special_point_id +constexpr int subcell_verts_inside[1549][8] = { + { 100, 0, 3, 8, -1, -1, -1, -1 }, + { 101, 0, 9, 1, -1, -1, -1, -1 }, + { 101, 1, 9, 100, 3, 8, -1, -1 }, + { 102, 1, 11, 2, -1, -1, -1, -1 }, + { 100, 102, 2, 3, 200, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 1, 11, 102, 200, -1, -1, -1, -1 }, + { 102, 11, 2, 200, -1, -1, -1, -1 }, + { 0, 200, 100, 8, -1, -1, -1, -1 }, + { 3, 8, 100, 200, -1, -1, -1, -1 }, + { 102, 2, 11, 101, 0, 9, -1, -1 }, + { 9, 11, 102, 101, 200, -1, -1, -1 }, + { 8, 9, 101, 100, 200, -1, -1, -1 }, + { 3, 8, 100, 200, -1, -1, -1, -1 }, + { 100, 101, 102, 200, -1, -1, -1, -1 }, + { 3, 100, 102, 2, 200, -1, -1, -1 }, + { 102, 11, 2, 200, -1, -1, -1, -1 }, + { 103, 3, 2, 10, -1, -1, -1, -1 }, + { 103, 10, 2, 100, 8, 0, -1, -1 }, + { 103, 3, 0, 101, 200, -1, -1, -1 }, + { 2, 103, 101, 1, 200, -1, -1, -1 }, + { 1, 101, 9, 200, -1, -1, -1, -1 }, + { 101, 0, 9, 200, -1, -1, -1, -1 }, + { 2, 103, 200, 10, -1, -1, -1, -1 }, + { 3, 103, 10, 200, -1, -1, -1, -1 }, + { 8, 100, 103, 10, 200, -1, -1, -1 }, + { 9, 101, 100, 8, 200, -1, -1, -1 }, + { 1, 101, 9, 200, -1, -1, -1, -1 }, + { 101, 103, 100, 200, -1, -1, -1, -1 }, + { 1, 2, 103, 101, 200, -1, -1, -1 }, + { 103, 2, 10, 200, -1, -1, -1, -1 }, + { 103, 3, 10, 102, 1, 11, -1, -1 }, + { 10, 103, 102, 11, 200, -1, -1, -1 }, + { 8, 100, 103, 10, 200, -1, -1, -1 }, + { 0, 100, 8, 200, -1, -1, -1, -1 }, + { 100, 102, 103, 200, -1, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 102, 1, 11, 200, -1, -1, -1, -1 }, + { 11, 102, 101, 9, 200, -1, -1, -1 }, + { 10, 103, 102, 11, 200, -1, -1, -1 }, + { 3, 103, 10, 200, -1, -1, -1, -1 }, + { 103, 101, 102, 200, -1, -1, -1, -1 }, + { 3, 0, 101, 103, 200, -1, -1, -1 }, + { 101, 0, 9, 200, -1, -1, -1, -1 }, + { 100, 101, 102, 103, 8, 9, 11, 10 }, + { 104, 4, 8, 7, -1, -1, -1, -1 }, + { 100, 3, 0, 104, 7, 4, -1, -1 }, + { 104, 101, 0, 8, 200, -1, -1, -1 }, + { 4, 9, 101, 104, 200, -1, -1, -1 }, + { 9, 1, 101, 200, -1, -1, -1, -1 }, + { 101, 1, 0, 200, -1, -1, -1, -1 }, + { 4, 200, 104, 7, -1, -1, -1, -1 }, + { 8, 7, 104, 200, -1, -1, -1, -1 }, + { 3, 7, 104, 100, 200, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 9, 1, 101, 200, -1, -1, -1, -1 }, + { 101, 100, 104, 200, -1, -1, -1, -1 }, + { 9, 101, 104, 4, 200, -1, -1, -1 }, + { 104, 7, 4, 200, -1, -1, -1, -1 }, + { 104, 4, 8, 7, -1, -1, -1, -1 }, + { 102, 2, 1, 11, -1, -1, -1, -1 }, + { 102, 2, 3, 100, 200, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 102, 11, 2, 200, -1, -1, -1, -1 }, + { 1, 11, 102, 200, -1, -1, -1, -1 }, + { 3, 7, 104, 100, 200, -1, -1, -1 }, + { 100, 104, 4, 0, 200, -1, -1, -1 }, + { 4, 104, 7, 200, -1, -1, -1, -1 }, + { 104, 101, 0, 8, 200, -1, -1, -1 }, + { 9, 101, 104, 4, 200, -1, -1, -1 }, + { 104, 8, 7, 200, -1, -1, -1, -1 }, + { 4, 104, 7, 200, -1, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 101, 9, 11, 102, 200, -1, -1, -1 }, + { 11, 2, 102, 200, -1, -1, -1, -1 }, + { 100, 101, 102, 200, -1, -1, -1, -1 }, + { 3, 100, 102, 2, 200, -1, -1, -1 }, + { 3, 7, 104, 100, 200, -1, -1, -1 }, + { 104, 101, 100, 200, -1, -1, -1, -1 }, + { 104, 7, 4, 200, -1, -1, -1, -1 }, + { 104, 4, 9, 101, 200, -1, -1, -1 }, + { 9, 11, 102, 101, 200, -1, -1, -1 }, + { 11, 2, 102, 200, -1, -1, -1, -1 }, + { 103, 104, 8, 3, 200, -1, -1, -1 }, + { 10, 7, 104, 103, 200, -1, -1, -1 }, + { 7, 4, 104, 200, -1, -1, -1, -1 }, + { 104, 4, 8, 200, -1, -1, -1, -1 }, + { 10, 200, 103, 2, -1, -1, -1, -1 }, + { 3, 2, 103, 200, -1, -1, -1, -1 }, + { 0, 2, 103, 100, 200, -1, -1, -1 }, + { 4, 0, 100, 104, 200, -1, -1, -1 }, + { 7, 4, 104, 200, -1, -1, -1, -1 }, + { 104, 100, 103, 200, -1, -1, -1, -1 }, + { 7, 104, 103, 10, 200, -1, -1, -1 }, + { 103, 2, 10, 200, -1, -1, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 103, 10, 7, 104, 2, -1, -1, -1 }, + { 4, 9, 101, 104, 1, -1, -1, -1 }, + { 2, 103, 101, 1, 104, -1, -1, -1 }, + { 2, 1, 4, 7, 104, -1, -1, -1 }, + { 100, 101, 103, 104, -1, -1, -1, -1 }, + { 7, 104, 103, 10, 2, -1, -1, -1 }, + { 4, 9, 101, 104, 1, -1, -1, -1 }, + { 103, 101, 1, 2, 104, -1, -1, -1 }, + { 7, 2, 1, 4, 104, -1, -1, -1 }, + { 104, 8, 3, 103, 200, -1, -1, -1 }, + { 10, 7, 104, 103, 200, -1, -1, -1 }, + { 104, 4, 8, 200, -1, -1, -1, -1 }, + { 7, 4, 104, 200, -1, -1, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 103, 102, 11, 10, 200, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 100, 102, 103, 200, -1, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 0, 100, 104, 4, 200, -1, -1, -1 }, + { 104, 100, 103, 200, -1, -1, -1, -1 }, + { 104, 7, 4, 200, -1, -1, -1, -1 }, + { 104, 103, 10, 7, 200, -1, -1, -1 }, + { 10, 103, 102, 11, 200, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 101, 103, 104, 200, -1, -1, -1, -1 }, + { 103, 10, 7, 104, 200, -1, -1, -1 }, + { 102, 103, 101, 200, -1, -1, -1, -1 }, + { 9, 11, 102, 101, 200, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 104, 4, 9, 101, 200, -1, -1, -1 }, + { 7, 4, 104, 200, -1, -1, -1, -1 }, + { 100, 101, 102, 103, 200, -1, -1, -1 }, + { 103, 104, 100, 200, -1, -1, -1, -1 }, + { 104, 101, 100, 200, -1, -1, -1, -1 }, + { 104, 4, 9, 101, 200, -1, -1, -1 }, + { 9, 11, 102, 101, 200, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 10, 7, 104, 103, 200, -1, -1, -1 }, + { 4, 104, 7, 200, -1, -1, -1, -1 }, + { 105, 5, 9, 4, -1, -1, -1, -1 }, + { 100, 8, 4, 105, 200, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 9, 105, 5, 200, -1, -1, -1, -1 }, + { 105, 4, 5, 200, -1, -1, -1, -1 }, + { 0, 100, 200, 3, -1, -1, -1, -1 }, + { 8, 100, 3, 200, -1, -1, -1, -1 }, + { 101, 0, 1, 105, 4, 5, -1, -1 }, + { 1, 101, 105, 5, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 8, 100, 3, 200, -1, -1, -1, -1 }, + { 100, 105, 101, 200, -1, -1, -1, -1 }, + { 8, 4, 105, 100, 200, -1, -1, -1 }, + { 105, 4, 5, 200, -1, -1, -1, -1 }, + { 102, 1, 9, 105, 200, -1, -1, -1 }, + { 11, 102, 105, 5, 200, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 11, 102, 200, 2, -1, -1, -1, -1 }, + { 1, 102, 2, 200, -1, -1, -1, -1 }, + { 100, 105, 102, 0, 9, 1, -1, -1 }, + { 100, 102, 2, 3, 8, -1, -1, -1 }, + { 11, 102, 105, 5, 4, -1, -1, -1 }, + { 8, 4, 105, 100, 102, -1, -1, -1 }, + { 8, 2, 11, 4, 102, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 105, 102, 101, 200, -1, -1, -1, -1 }, + { 5, 11, 102, 105, 200, -1, -1, -1 }, + { 102, 11, 2, 200, -1, -1, -1, -1 }, + { 101, 100, 105, 102, -1, -1, -1, -1 }, + { 2, 3, 100, 102, 8, -1, -1, -1 }, + { 11, 102, 105, 5, 4, -1, -1, -1 }, + { 100, 8, 4, 105, 102, -1, -1, -1 }, + { 2, 11, 4, 8, 102, -1, -1, -1 }, + { 103, 3, 2, 10, -1, -1, -1, -1 }, + { 105, 9, 4, 5, -1, -1, -1, -1 }, + { 105, 100, 8, 4, 200, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 105, 4, 5, 200, -1, -1, -1, -1 }, + { 9, 105, 5, 200, -1, -1, -1, -1 }, + { 8, 100, 103, 10, 200, -1, -1, -1 }, + { 100, 0, 2, 103, 200, -1, -1, -1 }, + { 2, 10, 103, 200, -1, -1, -1, -1 }, + { 103, 3, 0, 101, 200, -1, -1, -1 }, + { 1, 2, 103, 101, 200, -1, -1, -1 }, + { 103, 10, 3, 200, -1, -1, -1, -1 }, + { 2, 10, 103, 200, -1, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 101, 105, 5, 1, 200, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 100, 105, 101, 200, -1, -1, -1, -1 }, + { 8, 4, 105, 100, 200, -1, -1, -1 }, + { 8, 100, 103, 10, 200, -1, -1, -1 }, + { 103, 100, 101, 200, -1, -1, -1, -1 }, + { 103, 2, 10, 200, -1, -1, -1, -1 }, + { 103, 101, 1, 2, 200, -1, -1, -1 }, + { 1, 101, 105, 5, 200, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 105, 102, 1, 9, 200, -1, -1, -1 }, + { 11, 102, 105, 5, 200, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 102, 11, 10, 103, 200, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 0, 1, 9, 100, 102, 105, -1, -1 }, + { 102, 100, 105, 200, -1, -1, -1, -1 }, + { 100, 8, 4, 105, 200, -1, -1, -1 }, + { 103, 100, 102, 200, -1, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 105, 5, 11, 102, 200, -1, -1, -1 }, + { 4, 5, 105, 200, -1, -1, -1, -1 }, + { 101, 102, 103, 200, -1, -1, -1, -1 }, + { 0, 101, 103, 3, 200, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 105, 102, 101, 200, -1, -1, -1, -1 }, + { 105, 4, 5, 200, -1, -1, -1, -1 }, + { 105, 5, 11, 102, 200, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 101, 102, 103, 100, 200, -1, -1, -1 }, + { 100, 105, 101, 200, -1, -1, -1, -1 }, + { 105, 102, 101, 200, -1, -1, -1, -1 }, + { 105, 5, 11, 102, 200, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 8, 4, 105, 100, 200, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 105, 9, 5, 104, 8, 7, -1, -1 }, + { 7, 5, 105, 104, 200, -1, -1, -1 }, + { 3, 7, 104, 100, 200, -1, -1, -1 }, + { 0, 3, 100, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 105, 5, 9, 200, -1, -1, -1, -1 }, + { 5, 1, 101, 105, 200, -1, -1, -1 }, + { 7, 5, 105, 104, 200, -1, -1, -1 }, + { 8, 7, 104, 200, -1, -1, -1, -1 }, + { 104, 105, 101, 200, -1, -1, -1, -1 }, + { 8, 104, 101, 0, 200, -1, -1, -1 }, + { 101, 1, 0, 200, -1, -1, -1, -1 }, + { 3, 1, 5, 7, 100, 101, 105, 104 }, + { 102, 1, 9, 105, 200, -1, -1, -1 }, + { 5, 11, 102, 105, 200, -1, -1, -1 }, + { 102, 2, 1, 200, -1, -1, -1, -1 }, + { 11, 2, 102, 200, -1, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 105, 104, 7, 5, 200, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 100, 105, 102, 0, 9, 1, -1, -1 }, + { 105, 102, 100, 200, -1, -1, -1, -1 }, + { 100, 102, 2, 3, 200, -1, -1, -1 }, + { 104, 105, 100, 200, -1, -1, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 102, 105, 5, 11, 200, -1, -1, -1 }, + { 2, 102, 11, 200, -1, -1, -1, -1 }, + { 101, 104, 105, 200, -1, -1, -1, -1 }, + { 0, 8, 104, 101, 200, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 102, 101, 105, 200, -1, -1, -1, -1 }, + { 102, 11, 2, 200, -1, -1, -1, -1 }, + { 102, 105, 5, 11, 200, -1, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 101, 100, 104, 105, 200, -1, -1, -1 }, + { 100, 101, 102, 200, -1, -1, -1, -1 }, + { 102, 101, 105, 200, -1, -1, -1, -1 }, + { 102, 105, 5, 11, 200, -1, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 3, 100, 102, 2, 200, -1, -1, -1 }, + { 11, 2, 102, 200, -1, -1, -1, -1 }, + { 103, 104, 8, 3, 200, -1, -1, -1 }, + { 7, 104, 103, 10, 200, -1, -1, -1 }, + { 103, 3, 2, 200, -1, -1, -1, -1 }, + { 10, 103, 2, 200, -1, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 104, 7, 5, 105, 200, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 0, 2, 103, 100, 200, -1, -1, -1 }, + { 103, 104, 100, 200, -1, -1, -1, -1 }, + { 103, 2, 10, 200, -1, -1, -1, -1 }, + { 103, 10, 7, 104, 200, -1, -1, -1 }, + { 7, 5, 105, 104, 200, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 104, 101, 103, 8, 0, 3, -1, -1 }, + { 101, 103, 104, 200, -1, -1, -1, -1 }, + { 104, 103, 10, 7, 200, -1, -1, -1 }, + { 105, 101, 104, 200, -1, -1, -1, -1 }, + { 1, 101, 105, 5, 200, -1, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 103, 101, 1, 2, 200, -1, -1, -1 }, + { 10, 103, 2, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 101, 200, -1, -1, -1 }, + { 104, 100, 103, 200, -1, -1, -1, -1 }, + { 103, 100, 101, 200, -1, -1, -1, -1 }, + { 103, 101, 1, 2, 200, -1, -1, -1 }, + { 1, 101, 105, 5, 200, -1, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 7, 104, 103, 10, 200, -1, -1, -1 }, + { 2, 10, 103, 200, -1, -1, -1, -1 }, + { 103, 104, 105, 102, 10, 7, 5, 11 }, + { 3, 8, 9, 1, 103, 104, 105, 102 }, + { 100, 105, 102, 0, 9, 1, -1, -1 }, + { 7, 5, 105, 104, 200, -1, -1, -1 }, + { 104, 105, 100, 200, -1, -1, -1, -1 }, + { 104, 100, 103, 200, -1, -1, -1, -1 }, + { 10, 7, 104, 103, 200, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 103, 100, 102, 200, -1, -1, -1, -1 }, + { 5, 7, 10, 11, 200, -1, -1, -1 }, + { 102, 100, 105, 200, -1, -1, -1, -1 }, + { 5, 11, 102, 105, 200, -1, -1, -1 }, + { 0, 8, 3, 101, 104, 103, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 105, 101, 104, 200, -1, -1, -1, -1 }, + { 105, 102, 101, 200, -1, -1, -1, -1 }, + { 11, 102, 105, 5, 200, -1, -1, -1 }, + { 10, 103, 102, 11, 200, -1, -1, -1 }, + { 102, 103, 101, 200, -1, -1, -1, -1 }, + { 7, 10, 11, 5, 200, -1, -1, -1 }, + { 103, 104, 101, 200, -1, -1, -1, -1 }, + { 7, 104, 103, 10, 200, -1, -1, -1 }, + { 103, 104, 105, 102, 10, 7, 5, 11 }, + { 101, 102, 105, 100, 103, 104, -1, -1 }, + { 106, 5, 6, 11, -1, -1, -1, -1 }, + { 100, 8, 0, 3, -1, -1, -1, -1 }, + { 106, 5, 6, 11, -1, -1, -1, -1 }, + { 101, 106, 11, 1, 200, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 5, 6, 106, 200, -1, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 9, 200, 101, 0, -1, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 106, 11, 1, 101, 200, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 5, 6, 106, 200, -1, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 101, 100, 8, 9, 200, -1, -1, -1 }, + { 8, 100, 3, 200, -1, -1, -1, -1 }, + { 102, 1, 2, 106, 5, 6, -1, -1 }, + { 100, 0, 1, 102, 200, -1, -1, -1 }, + { 2, 3, 100, 102, 200, -1, -1, -1 }, + { 100, 8, 0, 200, -1, -1, -1, -1 }, + { 3, 8, 100, 200, -1, -1, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 102, 106, 6, 2, 200, -1, -1, -1 }, + { 6, 106, 5, 200, -1, -1, -1, -1 }, + { 2, 102, 106, 6, 200, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 9, 101, 0, 200, -1, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 106, 5, 6, 200, -1, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 9, 101, 100, 8, 200, -1, -1, -1 }, + { 100, 101, 102, 200, -1, -1, -1, -1 }, + { 100, 3, 8, 200, -1, -1, -1, -1 }, + { 100, 102, 2, 3, 200, -1, -1, -1 }, + { 2, 102, 106, 6, 200, -1, -1, -1 }, + { 6, 106, 5, 200, -1, -1, -1, -1 }, + { 103, 106, 6, 10, 200, -1, -1, -1 }, + { 2, 11, 106, 103, 200, -1, -1, -1 }, + { 11, 5, 106, 200, -1, -1, -1, -1 }, + { 106, 5, 6, 200, -1, -1, -1, -1 }, + { 2, 200, 103, 3, -1, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 106, 6, 10, 103, 200, -1, -1, -1 }, + { 2, 11, 106, 103, 200, -1, -1, -1 }, + { 106, 5, 6, 200, -1, -1, -1, -1 }, + { 11, 5, 106, 200, -1, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 103, 100, 0, 2, 200, -1, -1, -1 }, + { 0, 100, 8, 200, -1, -1, -1, -1 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 101, 103, 3, 0, 9, -1, -1, -1 }, + { 10, 103, 106, 6, 5, -1, -1, -1 }, + { 9, 5, 106, 101, 103, -1, -1, -1 }, + { 9, 3, 10, 5, 103, -1, -1, -1 }, + { 1, 2, 11, 101, 103, 106, -1, -1 }, + { 103, 101, 106, 200, -1, -1, -1, -1 }, + { 101, 9, 5, 106, 200, -1, -1, -1 }, + { 100, 101, 103, 200, -1, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 8, 9, 101, 100, 200, -1, -1, -1 }, + { 106, 6, 10, 103, 200, -1, -1, -1 }, + { 5, 6, 106, 200, -1, -1, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 103, 102, 106, 200, -1, -1, -1, -1 }, + { 10, 103, 106, 6, 200, -1, -1, -1 }, + { 106, 5, 6, 200, -1, -1, -1, -1 }, + { 103, 102, 106, 200, -1, -1, -1, -1 }, + { 10, 103, 106, 6, 200, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 100, 102, 103, 200, -1, -1, -1, -1 }, + { 100, 8, 0, 200, -1, -1, -1, -1 }, + { 100, 0, 1, 102, 200, -1, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 5, 6, 106, 200, -1, -1, -1, -1 }, + { 102, 101, 106, 103, -1, -1, -1, -1 }, + { 3, 0, 101, 103, 9, -1, -1, -1 }, + { 10, 103, 106, 6, 5, -1, -1, -1 }, + { 101, 9, 5, 106, 103, -1, -1, -1 }, + { 3, 10, 5, 9, 103, -1, -1, -1 }, + { 102, 103, 100, 101, 200, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 106, 103, 102, 200, -1, -1, -1, -1 }, + { 106, 6, 10, 103, 200, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 8, 9, 101, 100, 200, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 6, 106, 5, 200, -1, -1, -1, -1 }, + { 104, 7, 6, 106, 200, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 5, 106, 11, 200, -1, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 4, 104, 200, 8, -1, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 106, 104, 7, 6, 200, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 5, 106, 11, 200, -1, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 104, 4, 0, 100, 200, -1, -1, -1 }, + { 0, 3, 100, 200, -1, -1, -1, -1 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 101, 0, 8, 104, 1, -1, -1, -1 }, + { 7, 6, 106, 104, 11, -1, -1, -1 }, + { 1, 101, 106, 11, 104, -1, -1, -1 }, + { 1, 11, 7, 8, 104, -1, -1, -1 }, + { 101, 104, 106, 9, 4, 5, -1, -1 }, + { 104, 106, 101, 200, -1, -1, -1, -1 }, + { 101, 106, 11, 1, 200, -1, -1, -1 }, + { 100, 104, 101, 200, -1, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 106, 104, 7, 6, 200, -1, -1, -1 }, + { 11, 106, 6, 200, -1, -1, -1, -1 }, + { 104, 106, 5, 4, 200, -1, -1, -1 }, + { 6, 106, 104, 7, 200, -1, -1, -1 }, + { 104, 4, 8, 200, -1, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 106, 6, 2, 102, 200, -1, -1, -1 }, + { 2, 1, 102, 200, -1, -1, -1, -1 }, + { 100, 102, 106, 104, 0, 1, 5, 4 }, + { 3, 2, 6, 7, 100, 102, 106, 104 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 106, 101, 104, 200, -1, -1, -1, -1 }, + { 101, 0, 8, 104, 200, -1, -1, -1 }, + { 102, 101, 106, 200, -1, -1, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 104, 7, 6, 106, 200, -1, -1, -1 }, + { 8, 7, 104, 200, -1, -1, -1, -1 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 2, 102, 106, 6, 200, -1, -1, -1 }, + { 102, 101, 106, 200, -1, -1, -1, -1 }, + { 102, 100, 101, 200, -1, -1, -1, -1 }, + { 3, 100, 102, 2, 200, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 100, 104, 101, 200, -1, -1, -1, -1 }, + { 6, 7, 3, 2, 200, -1, -1, -1 }, + { 104, 106, 101, 200, -1, -1, -1, -1 }, + { 6, 106, 104, 7, 200, -1, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 104, 8, 3, 103, 4, -1, -1, -1 }, + { 2, 11, 106, 103, 5, -1, -1, -1 }, + { 4, 104, 106, 5, 103, -1, -1, -1 }, + { 4, 5, 2, 3, 103, -1, -1, -1 }, + { 104, 103, 106, 7, 10, 6, -1, -1 }, + { 103, 106, 104, 200, -1, -1, -1, -1 }, + { 104, 106, 5, 4, 200, -1, -1, -1 }, + { 100, 103, 104, 200, -1, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 0, 100, 104, 4, 200, -1, -1, -1 }, + { 106, 103, 2, 11, 200, -1, -1, -1 }, + { 5, 106, 11, 200, -1, -1, -1, -1 }, + { 1, 2, 11, 101, 103, 106, -1, -1 }, + { 101, 106, 103, 104, -1, -1, -1, -1 }, + { 104, 106, 101, 4, 5, 9, -1, -1 }, + { 103, 104, 101, 3, 8, 0, -1, -1 }, + { 106, 104, 103, 6, 7, 10, -1, -1 }, + { 106, 103, 101, 11, 2, 1, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 104, 106, 101, 4, 5, 9, -1, -1 }, + { 106, 103, 101, 104, -1, -1, -1, -1 }, + { 104, 101, 100, 103, -1, -1, -1, -1 }, + { 103, 106, 104, 10, 6, 7, -1, -1 }, + { 106, 104, 103, 200, -1, -1, -1, -1 }, + { 103, 104, 8, 3, 200, -1, -1, -1 }, + { 102, 106, 103, 200, -1, -1, -1, -1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 104, 106, 5, 4, 200, -1, -1, -1 }, + { 8, 104, 4, 200, -1, -1, -1, -1 }, + { 103, 106, 104, 10, 6, 7, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 102, 106, 103, 200, -1, -1, -1, -1 }, + { 102, 103, 100, 200, -1, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 4, 0, 100, 104, 200, -1, -1, -1 }, + { 100, 103, 104, 200, -1, -1, -1, -1 }, + { 5, 1, 0, 4, 200, -1, -1, -1 }, + { 104, 103, 106, 200, -1, -1, -1, -1 }, + { 5, 4, 104, 106, 200, -1, -1, -1 }, + { 4, 9, 5, 104, 101, 106, -1, -1 }, + { 103, 104, 101, 3, 8, 0, -1, -1 }, + { 10, 7, 6, 103, 104, 106, -1, -1 }, + { 104, 106, 101, 103, -1, -1, -1, -1 }, + { 103, 102, 106, 101, -1, -1, -1, -1 }, + { 104, 106, 101, 4, 5, 9, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 100, 101, 102, 103, 104, -1, -1, -1 }, + { 106, 103, 102, 104, -1, -1, -1, -1 }, + { 106, 102, 101, 104, -1, -1, -1, -1 }, + { 106, 11, 6, 105, 9, 4, -1, -1 }, + { 100, 105, 9, 0, 200, -1, -1, -1 }, + { 4, 105, 100, 8, 200, -1, -1, -1 }, + { 100, 0, 3, 200, -1, -1, -1, -1 }, + { 8, 100, 3, 200, -1, -1, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 105, 4, 6, 106, 200, -1, -1, -1 }, + { 6, 11, 106, 200, -1, -1, -1, -1 }, + { 4, 6, 106, 105, 200, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 1, 101, 106, 11, 200, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 1, 101, 106, 11, 200, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 100, 105, 101, 200, -1, -1, -1, -1 }, + { 100, 3, 8, 200, -1, -1, -1, -1 }, + { 100, 8, 4, 105, 200, -1, -1, -1 }, + { 4, 6, 106, 105, 200, -1, -1, -1 }, + { 6, 11, 106, 200, -1, -1, -1, -1 }, + { 6, 106, 105, 4, 200, -1, -1, -1 }, + { 2, 102, 106, 6, 200, -1, -1, -1 }, + { 1, 102, 2, 200, -1, -1, -1, -1 }, + { 102, 105, 106, 200, -1, -1, -1, -1 }, + { 1, 9, 105, 102, 200, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 1, 9, 0, 102, 105, 100, -1, -1 }, + { 105, 102, 100, 200, -1, -1, -1, -1 }, + { 102, 2, 3, 100, 200, -1, -1, -1 }, + { 106, 102, 105, 200, -1, -1, -1, -1 }, + { 4, 6, 106, 105, 200, -1, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 100, 8, 4, 105, 200, -1, -1, -1 }, + { 3, 8, 100, 200, -1, -1, -1, -1 }, + { 101, 105, 106, 102, 0, 4, 6, 2 }, + { 101, 105, 106, 102, 200, -1, -1, -1 }, + { 102, 100, 101, 200, -1, -1, -1, -1 }, + { 100, 105, 101, 200, -1, -1, -1, -1 }, + { 100, 8, 4, 105, 200, -1, -1, -1 }, + { 4, 6, 106, 105, 200, -1, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 2, 3, 100, 102, 200, -1, -1, -1 }, + { 8, 100, 3, 200, -1, -1, -1, -1 }, + { 103, 2, 11, 106, 200, -1, -1, -1 }, + { 6, 10, 103, 106, 200, -1, -1, -1 }, + { 103, 3, 2, 200, -1, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 106, 105, 4, 6, 200, -1, -1, -1 }, + { 4, 105, 9, 200, -1, -1, -1, -1 }, + { 0, 9, 11, 2, 100, 105, 106, 103 }, + { 100, 105, 106, 103, 8, 4, 6, 10 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 106, 103, 101, 200, -1, -1, -1, -1 }, + { 101, 103, 3, 0, 200, -1, -1, -1 }, + { 105, 106, 101, 200, -1, -1, -1, -1 }, + { 6, 106, 105, 4, 200, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 103, 106, 6, 10, 200, -1, -1, -1 }, + { 3, 103, 10, 200, -1, -1, -1, -1 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 4, 6, 106, 105, 200, -1, -1, -1 }, + { 105, 106, 101, 200, -1, -1, -1, -1 }, + { 105, 101, 100, 200, -1, -1, -1, -1 }, + { 8, 4, 105, 100, 200, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 100, 101, 103, 200, -1, -1, -1, -1 }, + { 6, 4, 8, 10, 200, -1, -1, -1 }, + { 103, 101, 106, 200, -1, -1, -1, -1 }, + { 6, 10, 103, 106, 200, -1, -1, -1 }, + { 102, 105, 106, 200, -1, -1, -1, -1 }, + { 1, 9, 105, 102, 200, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 103, 102, 106, 200, -1, -1, -1, -1 }, + { 103, 10, 3, 200, -1, -1, -1, -1 }, + { 103, 106, 6, 10, 200, -1, -1, -1 }, + { 6, 106, 105, 4, 200, -1, -1, -1 }, + { 4, 105, 9, 200, -1, -1, -1, -1 }, + { 1, 9, 0, 102, 105, 100, -1, -1 }, + { 6, 106, 105, 4, 200, -1, -1, -1 }, + { 106, 102, 105, 200, -1, -1, -1, -1 }, + { 106, 103, 102, 200, -1, -1, -1, -1 }, + { 10, 103, 106, 6, 200, -1, -1, -1 }, + { 8, 100, 103, 10, 200, -1, -1, -1 }, + { 103, 100, 102, 200, -1, -1, -1, -1 }, + { 4, 8, 10, 6, 200, -1, -1, -1 }, + { 100, 105, 102, 200, -1, -1, -1, -1 }, + { 4, 105, 100, 8, 200, -1, -1, -1 }, + { 102, 101, 105, 106, 200, -1, -1, -1 }, + { 101, 102, 103, 200, -1, -1, -1, -1 }, + { 103, 102, 106, 200, -1, -1, -1, -1 }, + { 103, 106, 6, 10, 200, -1, -1, -1 }, + { 6, 106, 105, 4, 200, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 0, 101, 103, 3, 200, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 100, 105, 106, 103, 8, 4, 6, 10 }, + { 102, 103, 106, 101, 100, 105, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 104, 106, 105, 200, -1, -1, -1, -1 }, + { 7, 6, 106, 104, 200, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 104, 106, 105, 200, -1, -1, -1, -1 }, + { 7, 6, 106, 104, 200, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 100, 0, 3, 200, -1, -1, -1, -1 }, + { 100, 105, 9, 0, 200, -1, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 11, 106, 6, 200, -1, -1, -1, -1 }, + { 105, 106, 101, 104, -1, -1, -1, -1 }, + { 8, 104, 101, 0, 1, -1, -1, -1 }, + { 7, 6, 106, 104, 11, -1, -1, -1 }, + { 101, 106, 11, 1, 104, -1, -1, -1 }, + { 8, 1, 11, 7, 104, -1, -1, -1 }, + { 105, 101, 100, 104, 200, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 106, 105, 104, 200, -1, -1, -1, -1 }, + { 106, 104, 7, 6, 200, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 1, 101, 106, 11, 200, -1, -1, -1 }, + { 6, 11, 106, 200, -1, -1, -1, -1 }, + { 105, 106, 102, 200, -1, -1, -1, -1 }, + { 9, 105, 102, 1, 200, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 104, 106, 105, 200, -1, -1, -1, -1 }, + { 104, 8, 7, 200, -1, -1, -1, -1 }, + { 104, 7, 6, 106, 200, -1, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 2, 1, 102, 200, -1, -1, -1, -1 }, + { 105, 102, 100, 9, 1, 0, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 106, 102, 105, 200, -1, -1, -1, -1 }, + { 106, 105, 104, 200, -1, -1, -1, -1 }, + { 7, 6, 106, 104, 200, -1, -1, -1 }, + { 3, 7, 104, 100, 200, -1, -1, -1 }, + { 104, 105, 100, 200, -1, -1, -1, -1 }, + { 2, 6, 7, 3, 200, -1, -1, -1 }, + { 100, 105, 102, 200, -1, -1, -1, -1 }, + { 2, 3, 100, 102, 200, -1, -1, -1 }, + { 105, 106, 102, 101, 200, -1, -1, -1 }, + { 101, 104, 105, 200, -1, -1, -1, -1 }, + { 104, 106, 105, 200, -1, -1, -1, -1 }, + { 104, 7, 6, 106, 200, -1, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 0, 8, 104, 101, 200, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 3, 2, 6, 7, 100, 102, 106, 104 }, + { 101, 100, 102, 105, 104, 106, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 106, 104, 103, 200, -1, -1, -1, -1 }, + { 104, 8, 3, 103, 200, -1, -1, -1 }, + { 105, 104, 106, 200, -1, -1, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 103, 2, 11, 106, 200, -1, -1, -1 }, + { 3, 2, 103, 200, -1, -1, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 105, 104, 106, 200, -1, -1, -1, -1 }, + { 105, 100, 104, 200, -1, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 100, 103, 104, 200, -1, -1, -1, -1 }, + { 11, 2, 0, 9, 200, -1, -1, -1 }, + { 103, 106, 104, 200, -1, -1, -1, -1 }, + { 11, 106, 103, 2, 200, -1, -1, -1 }, + { 103, 101, 106, 2, 1, 11, -1, -1 }, + { 8, 3, 0, 104, 103, 101, -1, -1 }, + { 104, 103, 106, 7, 10, 6, -1, -1 }, + { 103, 101, 106, 104, -1, -1, -1, -1 }, + { 104, 106, 105, 101, -1, -1, -1, -1 }, + { 2, 11, 1, 103, 106, 101, -1, -1 }, + { 103, 106, 104, 10, 6, 7, -1, -1 }, + { 100, 104, 105, 101, 103, -1, -1, -1 }, + { 106, 105, 104, 103, -1, -1, -1, -1 }, + { 106, 101, 105, 103, -1, -1, -1, -1 }, + { 6, 10, 7, 106, 103, 104, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 102, 106, 103, 200, -1, -1, -1, -1 }, + { 102, 105, 106, 200, -1, -1, -1, -1 }, + { 9, 105, 102, 1, 200, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 105, 104, 106, 200, -1, -1, -1, -1 }, + { 3, 8, 9, 1, 200, -1, -1, -1 }, + { 104, 103, 106, 200, -1, -1, -1, -1 }, + { 3, 103, 104, 8, 200, -1, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 9, 0, 1, 105, 100, 102, -1, -1 }, + { 102, 103, 100, 105, -1, -1, -1, -1 }, + { 105, 104, 106, 103, -1, -1, -1, -1 }, + { 104, 105, 100, 103, -1, -1, -1, -1 }, + { 105, 106, 102, 103, -1, -1, -1, -1 }, + { 10, 7, 6, 103, 104, 106, -1, -1 }, + { 103, 104, 101, 3, 8, 0, -1, -1 }, + { 102, 101, 105, 106, 103, -1, -1, -1 }, + { 104, 105, 101, 103, -1, -1, -1, -1 }, + { 104, 106, 105, 103, -1, -1, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 104, 103, 106, 200, -1, -1, -1, -1 }, + { 105, 106, 102, 101, 200, -1, -1, -1 }, + { 106, 103, 102, 200, -1, -1, -1, -1 }, + { 100, 101, 102, 103, 200, -1, -1, -1 }, + { 100, 103, 104, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 101, 200, -1, -1, -1 }, + { 104, 106, 105, 200, -1, -1, -1, -1 }, + { 107, 6, 7, 10, -1, -1, -1, -1 }, + { 100, 3, 10, 107, 200, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 7, 107, 6, 200, -1, -1, -1, -1 }, + { 107, 10, 6, 200, -1, -1, -1, -1 }, + { 8, 100, 200, 0, -1, -1, -1, -1 }, + { 3, 100, 0, 200, -1, -1, -1, -1 }, + { 101, 0, 9, 1, -1, -1, -1, -1 }, + { 107, 7, 10, 6, -1, -1, -1, -1 }, + { 107, 100, 3, 10, 200, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 107, 10, 6, 200, -1, -1, -1, -1 }, + { 7, 107, 6, 200, -1, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 100, 8, 9, 101, 200, -1, -1, -1 }, + { 9, 1, 101, 200, -1, -1, -1, -1 }, + { 107, 10, 2, 102, 200, -1, -1, -1 }, + { 6, 107, 102, 11, 200, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 102, 2, 1, 200, -1, -1, -1, -1 }, + { 6, 107, 200, 7, -1, -1, -1, -1 }, + { 10, 107, 7, 200, -1, -1, -1, -1 }, + { 100, 102, 107, 3, 2, 10, -1, -1 }, + { 100, 107, 7, 8, 0, -1, -1, -1 }, + { 6, 107, 102, 11, 1, -1, -1, -1 }, + { 0, 1, 102, 100, 107, -1, -1, -1 }, + { 0, 7, 6, 1, 107, -1, -1, -1 }, + { 107, 10, 2, 102, 200, -1, -1, -1 }, + { 11, 6, 107, 102, 200, -1, -1, -1 }, + { 107, 7, 10, 200, -1, -1, -1, -1 }, + { 6, 7, 107, 200, -1, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 102, 101, 9, 11, 200, -1, -1, -1 }, + { 9, 101, 0, 200, -1, -1, -1, -1 }, + { 100, 102, 107, 3, 2, 10, -1, -1 }, + { 102, 107, 100, 200, -1, -1, -1, -1 }, + { 100, 107, 7, 8, 200, -1, -1, -1 }, + { 101, 102, 100, 200, -1, -1, -1, -1 }, + { 11, 102, 101, 9, 200, -1, -1, -1 }, + { 9, 101, 100, 8, 200, -1, -1, -1 }, + { 107, 102, 11, 6, 200, -1, -1, -1 }, + { 7, 107, 6, 200, -1, -1, -1, -1 }, + { 107, 7, 6, 103, 3, 2, -1, -1 }, + { 2, 6, 107, 103, 200, -1, -1, -1 }, + { 0, 2, 103, 100, 200, -1, -1, -1 }, + { 8, 0, 100, 200, -1, -1, -1, -1 }, + { 100, 103, 107, 200, -1, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 107, 6, 7, 200, -1, -1, -1, -1 }, + { 101, 103, 3, 0, 200, -1, -1, -1 }, + { 2, 103, 101, 1, 200, -1, -1, -1 }, + { 101, 0, 9, 200, -1, -1, -1, -1 }, + { 1, 101, 9, 200, -1, -1, -1, -1 }, + { 3, 103, 107, 7, 200, -1, -1, -1 }, + { 103, 2, 6, 107, 200, -1, -1, -1 }, + { 6, 7, 107, 200, -1, -1, -1, -1 }, + { 100, 103, 107, 200, -1, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 8, 9, 101, 100, 200, -1, -1, -1 }, + { 101, 103, 100, 200, -1, -1, -1, -1 }, + { 101, 9, 1, 200, -1, -1, -1, -1 }, + { 101, 1, 2, 103, 200, -1, -1, -1 }, + { 2, 6, 107, 103, 200, -1, -1, -1 }, + { 6, 7, 107, 200, -1, -1, -1, -1 }, + { 3, 103, 107, 7, 200, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 102, 107, 103, 200, -1, -1, -1, -1 }, + { 11, 6, 107, 102, 200, -1, -1, -1 }, + { 107, 6, 7, 200, -1, -1, -1, -1 }, + { 103, 100, 102, 107, -1, -1, -1, -1 }, + { 7, 8, 100, 107, 0, -1, -1, -1 }, + { 6, 107, 102, 11, 1, -1, -1, -1 }, + { 100, 0, 1, 102, 107, -1, -1, -1 }, + { 7, 6, 1, 0, 107, -1, -1, -1 }, + { 103, 101, 102, 200, -1, -1, -1, -1 }, + { 3, 0, 101, 103, 200, -1, -1, -1 }, + { 3, 103, 107, 7, 200, -1, -1, -1 }, + { 107, 103, 102, 200, -1, -1, -1, -1 }, + { 107, 6, 7, 200, -1, -1, -1, -1 }, + { 107, 102, 11, 6, 200, -1, -1, -1 }, + { 11, 102, 101, 9, 200, -1, -1, -1 }, + { 9, 101, 0, 200, -1, -1, -1, -1 }, + { 103, 100, 101, 102, 200, -1, -1, -1 }, + { 100, 103, 107, 200, -1, -1, -1, -1 }, + { 107, 103, 102, 200, -1, -1, -1, -1 }, + { 107, 102, 11, 6, 200, -1, -1, -1 }, + { 11, 102, 101, 9, 200, -1, -1, -1 }, + { 9, 101, 100, 8, 200, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 6, 7, 107, 200, -1, -1, -1, -1 }, + { 104, 8, 4, 107, 10, 6, -1, -1 }, + { 4, 104, 107, 6, 200, -1, -1, -1 }, + { 0, 100, 104, 4, 200, -1, -1, -1 }, + { 3, 100, 0, 200, -1, -1, -1, -1 }, + { 100, 107, 104, 200, -1, -1, -1, -1 }, + { 3, 10, 107, 100, 200, -1, -1, -1 }, + { 107, 10, 6, 200, -1, -1, -1, -1 }, + { 101, 0, 8, 104, 200, -1, -1, -1 }, + { 4, 9, 101, 104, 200, -1, -1, -1 }, + { 101, 1, 0, 200, -1, -1, -1, -1 }, + { 9, 1, 101, 200, -1, -1, -1, -1 }, + { 8, 10, 107, 104, 200, -1, -1, -1 }, + { 104, 107, 6, 4, 200, -1, -1, -1 }, + { 6, 107, 10, 200, -1, -1, -1, -1 }, + { 100, 107, 104, 200, -1, -1, -1, -1 }, + { 3, 10, 107, 100, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 101, 100, 104, 200, -1, -1, -1, -1 }, + { 101, 9, 1, 200, -1, -1, -1, -1 }, + { 101, 104, 4, 9, 200, -1, -1, -1 }, + { 4, 104, 107, 6, 200, -1, -1, -1 }, + { 6, 107, 10, 200, -1, -1, -1, -1 }, + { 102, 107, 10, 2, 200, -1, -1, -1 }, + { 6, 107, 102, 11, 200, -1, -1, -1 }, + { 102, 2, 1, 200, -1, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 107, 6, 4, 104, 200, -1, -1, -1 }, + { 4, 8, 104, 200, -1, -1, -1, -1 }, + { 3, 10, 2, 100, 107, 102, -1, -1 }, + { 107, 100, 102, 200, -1, -1, -1, -1 }, + { 100, 0, 1, 102, 200, -1, -1, -1 }, + { 104, 100, 107, 200, -1, -1, -1, -1 }, + { 6, 4, 104, 107, 200, -1, -1, -1 }, + { 4, 0, 100, 104, 200, -1, -1, -1 }, + { 102, 11, 6, 107, 200, -1, -1, -1 }, + { 1, 11, 102, 200, -1, -1, -1, -1 }, + { 104, 101, 102, 107, 4, 9, 11, 6 }, + { 8, 0, 2, 10, 104, 101, 102, 107 }, + { 100, 102, 107, 3, 2, 10, -1, -1 }, + { 9, 11, 102, 101, 200, -1, -1, -1 }, + { 101, 102, 100, 200, -1, -1, -1, -1 }, + { 101, 100, 104, 200, -1, -1, -1, -1 }, + { 4, 9, 101, 104, 200, -1, -1, -1 }, + { 6, 4, 104, 107, 200, -1, -1, -1 }, + { 104, 100, 107, 200, -1, -1, -1, -1 }, + { 11, 9, 4, 6, 200, -1, -1, -1 }, + { 107, 100, 102, 200, -1, -1, -1, -1 }, + { 11, 6, 107, 102, 200, -1, -1, -1 }, + { 6, 4, 104, 107, 200, -1, -1, -1 }, + { 2, 6, 107, 103, 200, -1, -1, -1 }, + { 3, 2, 103, 200, -1, -1, -1, -1 }, + { 103, 107, 104, 200, -1, -1, -1, -1 }, + { 3, 103, 104, 8, 200, -1, -1, -1 }, + { 104, 4, 8, 200, -1, -1, -1, -1 }, + { 0, 4, 6, 2, 100, 104, 107, 103 }, + { 103, 104, 101, 3, 8, 0, -1, -1 }, + { 104, 101, 103, 200, -1, -1, -1, -1 }, + { 103, 101, 1, 2, 200, -1, -1, -1 }, + { 107, 104, 103, 200, -1, -1, -1, -1 }, + { 4, 104, 107, 6, 200, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 101, 104, 4, 9, 200, -1, -1, -1 }, + { 1, 101, 9, 200, -1, -1, -1, -1 }, + { 100, 103, 107, 104, 200, -1, -1, -1 }, + { 103, 100, 101, 200, -1, -1, -1, -1 }, + { 101, 100, 104, 200, -1, -1, -1, -1 }, + { 101, 104, 4, 9, 200, -1, -1, -1 }, + { 4, 104, 107, 6, 200, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 2, 103, 101, 1, 200, -1, -1, -1 }, + { 9, 1, 101, 200, -1, -1, -1, -1 }, + { 103, 107, 104, 200, -1, -1, -1, -1 }, + { 3, 103, 104, 8, 200, -1, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 102, 107, 103, 200, -1, -1, -1, -1 }, + { 102, 1, 11, 200, -1, -1, -1, -1 }, + { 102, 11, 6, 107, 200, -1, -1, -1 }, + { 6, 4, 104, 107, 200, -1, -1, -1 }, + { 4, 8, 104, 200, -1, -1, -1, -1 }, + { 103, 107, 104, 100, 200, -1, -1, -1 }, + { 100, 102, 103, 200, -1, -1, -1, -1 }, + { 102, 107, 103, 200, -1, -1, -1, -1 }, + { 102, 11, 6, 107, 200, -1, -1, -1 }, + { 6, 4, 104, 107, 200, -1, -1, -1 }, + { 4, 0, 100, 104, 200, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 11, 102, 101, 9, 200, -1, -1, -1 }, + { 102, 103, 101, 200, -1, -1, -1, -1 }, + { 102, 107, 103, 200, -1, -1, -1, -1 }, + { 6, 107, 102, 11, 200, -1, -1, -1 }, + { 4, 104, 107, 6, 200, -1, -1, -1 }, + { 107, 104, 103, 200, -1, -1, -1, -1 }, + { 9, 4, 6, 11, 200, -1, -1, -1 }, + { 104, 101, 103, 200, -1, -1, -1, -1 }, + { 9, 101, 104, 4, 200, -1, -1, -1 }, + { 104, 101, 102, 107, 4, 9, 11, 6 }, + { 103, 107, 102, 100, 104, 101, -1, -1 }, + { 107, 105, 4, 7, 200, -1, -1, -1 }, + { 6, 5, 105, 107, 200, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 6, 200, 107, 10, -1, -1, -1, -1 }, + { 7, 10, 107, 200, -1, -1, -1, -1 }, + { 8, 4, 7, 100, 105, 107, -1, -1 }, + { 100, 3, 10, 107, 0, -1, -1, -1 }, + { 6, 5, 105, 107, 9, -1, -1, -1 }, + { 0, 100, 105, 9, 107, -1, -1, -1 }, + { 0, 9, 6, 10, 107, -1, -1, -1 }, + { 107, 105, 4, 7, 200, -1, -1, -1 }, + { 5, 105, 107, 6, 200, -1, -1, -1 }, + { 107, 7, 10, 200, -1, -1, -1, -1 }, + { 6, 107, 10, 200, -1, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 105, 5, 1, 101, 200, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 8, 4, 7, 100, 105, 107, -1, -1 }, + { 105, 100, 107, 200, -1, -1, -1, -1 }, + { 100, 3, 10, 107, 200, -1, -1, -1 }, + { 101, 100, 105, 200, -1, -1, -1, -1 }, + { 5, 1, 101, 105, 200, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 107, 6, 5, 105, 200, -1, -1, -1 }, + { 10, 6, 107, 200, -1, -1, -1, -1 }, + { 105, 107, 102, 5, 6, 11, -1, -1 }, + { 105, 102, 1, 9, 4, -1, -1, -1 }, + { 2, 102, 107, 10, 7, -1, -1, -1 }, + { 4, 7, 107, 105, 102, -1, -1, -1 }, + { 4, 1, 2, 7, 102, -1, -1, -1 }, + { 102, 100, 105, 1, 0, 9, -1, -1 }, + { 102, 100, 105, 107, -1, -1, -1, -1 }, + { 6, 5, 11, 107, 105, 102, -1, -1 }, + { 3, 10, 2, 100, 107, 102, -1, -1 }, + { 4, 7, 8, 105, 107, 100, -1, -1 }, + { 5, 11, 6, 105, 102, 107, -1, -1 }, + { 102, 105, 107, 200, -1, -1, -1, -1 }, + { 105, 4, 7, 107, 200, -1, -1, -1 }, + { 101, 105, 102, 200, -1, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 107, 10, 2, 102, 200, -1, -1, -1 }, + { 7, 10, 107, 200, -1, -1, -1, -1 }, + { 7, 8, 4, 107, 100, 105, -1, -1 }, + { 102, 107, 100, 2, 10, 3, -1, -1 }, + { 11, 6, 5, 102, 107, 105, -1, -1 }, + { 107, 105, 100, 102, -1, -1, -1, -1 }, + { 102, 101, 105, 100, -1, -1, -1, -1 }, + { 105, 4, 7, 107, 200, -1, -1, -1 }, + { 6, 5, 105, 107, 200, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 107, 103, 2, 6, 200, -1, -1, -1 }, + { 2, 103, 3, 200, -1, -1, -1, -1 }, + { 100, 107, 105, 8, 7, 4, -1, -1 }, + { 107, 105, 100, 200, -1, -1, -1, -1 }, + { 100, 105, 9, 0, 200, -1, -1, -1 }, + { 103, 107, 100, 200, -1, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 105, 107, 6, 5, 200, -1, -1, -1 }, + { 9, 105, 5, 200, -1, -1, -1, -1 }, + { 2, 1, 5, 6, 103, 101, 105, 107 }, + { 103, 101, 105, 107, 3, 0, 4, 7 }, + { 8, 4, 7, 100, 105, 107, -1, -1 }, + { 1, 101, 105, 5, 200, -1, -1, -1 }, + { 101, 100, 105, 200, -1, -1, -1, -1 }, + { 101, 103, 100, 200, -1, -1, -1, -1 }, + { 2, 103, 101, 1, 200, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 103, 107, 100, 200, -1, -1, -1, -1 }, + { 5, 6, 2, 1, 200, -1, -1, -1 }, + { 107, 105, 100, 200, -1, -1, -1, -1 }, + { 5, 105, 107, 6, 200, -1, -1, -1 }, + { 11, 6, 5, 102, 107, 105, -1, -1 }, + { 107, 102, 105, 200, -1, -1, -1, -1 }, + { 102, 1, 9, 105, 200, -1, -1, -1 }, + { 103, 102, 107, 200, -1, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 105, 4, 7, 107, 200, -1, -1, -1 }, + { 9, 4, 105, 200, -1, -1, -1, -1 }, + { 9, 0, 1, 105, 100, 102, -1, -1 }, + { 107, 105, 100, 7, 4, 8, -1, -1 }, + { 6, 5, 11, 107, 105, 102, -1, -1 }, + { 105, 102, 100, 107, -1, -1, -1, -1 }, + { 107, 103, 102, 100, -1, -1, -1, -1 }, + { 11, 6, 5, 102, 107, 105, -1, -1 }, + { 3, 103, 107, 7, 200, -1, -1, -1 }, + { 103, 102, 107, 200, -1, -1, -1, -1 }, + { 103, 101, 102, 200, -1, -1, -1, -1 }, + { 0, 101, 103, 3, 200, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 101, 105, 102, 200, -1, -1, -1, -1 }, + { 7, 4, 0, 3, 200, -1, -1, -1 }, + { 105, 107, 102, 200, -1, -1, -1, -1 }, + { 7, 107, 105, 4, 200, -1, -1, -1 }, + { 6, 5, 11, 107, 105, 102, -1, -1 }, + { 107, 105, 100, 7, 4, 8, -1, -1 }, + { 103, 100, 101, 102, 107, -1, -1, -1 }, + { 105, 101, 100, 107, -1, -1, -1, -1 }, + { 105, 102, 101, 107, -1, -1, -1, -1 }, + { 8, 10, 107, 104, 200, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 105, 104, 107, 200, -1, -1, -1, -1 }, + { 5, 105, 107, 6, 200, -1, -1, -1 }, + { 107, 10, 6, 200, -1, -1, -1, -1 }, + { 104, 105, 100, 107, -1, -1, -1, -1 }, + { 10, 107, 100, 3, 0, -1, -1, -1 }, + { 6, 5, 105, 107, 9, -1, -1, -1 }, + { 100, 105, 9, 0, 107, -1, -1, -1 }, + { 10, 0, 9, 6, 107, -1, -1, -1 }, + { 104, 105, 101, 200, -1, -1, -1, -1 }, + { 8, 104, 101, 0, 200, -1, -1, -1 }, + { 8, 10, 107, 104, 200, -1, -1, -1 }, + { 107, 105, 104, 200, -1, -1, -1, -1 }, + { 107, 10, 6, 200, -1, -1, -1, -1 }, + { 107, 6, 5, 105, 200, -1, -1, -1 }, + { 5, 1, 101, 105, 200, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 104, 105, 101, 100, 200, -1, -1, -1 }, + { 100, 107, 104, 200, -1, -1, -1, -1 }, + { 107, 105, 104, 200, -1, -1, -1, -1 }, + { 107, 6, 5, 105, 200, -1, -1, -1 }, + { 5, 1, 101, 105, 200, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 3, 10, 107, 100, 200, -1, -1, -1 }, + { 6, 107, 10, 200, -1, -1, -1, -1 }, + { 105, 107, 102, 5, 6, 11, -1, -1 }, + { 107, 102, 105, 200, -1, -1, -1, -1 }, + { 105, 102, 1, 9, 200, -1, -1, -1 }, + { 104, 107, 105, 200, -1, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 102, 107, 10, 2, 200, -1, -1, -1 }, + { 1, 102, 2, 200, -1, -1, -1, -1 }, + { 102, 100, 105, 1, 0, 9, -1, -1 }, + { 10, 2, 3, 107, 102, 100, -1, -1 }, + { 107, 102, 105, 6, 11, 5, -1, -1 }, + { 102, 100, 105, 107, -1, -1, -1, -1 }, + { 107, 105, 104, 100, -1, -1, -1, -1 }, + { 105, 107, 102, 5, 6, 11, -1, -1 }, + { 8, 10, 107, 104, 200, -1, -1, -1 }, + { 104, 107, 105, 200, -1, -1, -1, -1 }, + { 104, 105, 101, 200, -1, -1, -1, -1 }, + { 0, 8, 104, 101, 200, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 101, 105, 102, 200, -1, -1, -1, -1 }, + { 10, 8, 0, 2, 200, -1, -1, -1 }, + { 102, 105, 107, 200, -1, -1, -1, -1 }, + { 10, 2, 102, 107, 200, -1, -1, -1 }, + { 107, 102, 105, 6, 11, 5, -1, -1 }, + { 10, 2, 3, 107, 102, 100, -1, -1 }, + { 104, 105, 101, 100, 107, -1, -1, -1 }, + { 102, 100, 101, 107, -1, -1, -1, -1 }, + { 102, 101, 105, 107, -1, -1, -1, -1 }, + { 104, 103, 107, 200, -1, -1, -1, -1 }, + { 8, 3, 103, 104, 200, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 105, 104, 107, 200, -1, -1, -1, -1 }, + { 105, 5, 9, 200, -1, -1, -1, -1 }, + { 105, 107, 6, 5, 200, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 2, 103, 3, 200, -1, -1, -1, -1 }, + { 104, 100, 103, 107, 200, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 105, 104, 107, 200, -1, -1, -1, -1 }, + { 105, 107, 6, 5, 200, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 104, 101, 103, 8, 0, 3, -1, -1 }, + { 5, 1, 101, 105, 200, -1, -1, -1 }, + { 105, 101, 104, 200, -1, -1, -1, -1 }, + { 105, 104, 107, 200, -1, -1, -1, -1 }, + { 6, 5, 105, 107, 200, -1, -1, -1 }, + { 2, 6, 107, 103, 200, -1, -1, -1 }, + { 107, 104, 103, 200, -1, -1, -1, -1 }, + { 1, 5, 6, 2, 200, -1, -1, -1 }, + { 103, 104, 101, 200, -1, -1, -1, -1 }, + { 1, 2, 103, 101, 200, -1, -1, -1 }, + { 2, 1, 5, 6, 103, 101, 105, 107 }, + { 100, 103, 101, 104, 107, 105, -1, -1 }, + { 107, 102, 105, 6, 11, 5, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 103, 102, 107, 200, -1, -1, -1, -1 }, + { 103, 107, 104, 200, -1, -1, -1, -1 }, + { 8, 3, 103, 104, 200, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 104, 107, 105, 200, -1, -1, -1, -1 }, + { 1, 3, 8, 9, 200, -1, -1, -1 }, + { 105, 107, 102, 200, -1, -1, -1, -1 }, + { 1, 9, 105, 102, 200, -1, -1, -1 }, + { 102, 105, 107, 11, 5, 6, -1, -1 }, + { 1, 9, 0, 102, 105, 100, -1, -1 }, + { 103, 107, 104, 100, 102, -1, -1, -1 }, + { 105, 100, 104, 102, -1, -1, -1, -1 }, + { 105, 104, 107, 102, -1, -1, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 11, 6, 5, 102, 107, 105, -1, -1 }, + { 105, 104, 107, 102, -1, -1, -1, -1 }, + { 102, 103, 101, 104, -1, -1, -1, -1 }, + { 103, 102, 107, 104, -1, -1, -1, -1 }, + { 102, 101, 105, 104, -1, -1, -1, -1 }, + { 105, 107, 102, 5, 6, 11, -1, -1 }, + { 105, 107, 102, 200, -1, -1, -1, -1 }, + { 104, 100, 103, 107, 200, -1, -1, -1 }, + { 107, 103, 102, 200, -1, -1, -1, -1 }, + { 101, 102, 103, 100, 200, -1, -1, -1 }, + { 101, 105, 102, 200, -1, -1, -1, -1 }, + { 101, 100, 104, 105, 200, -1, -1, -1 }, + { 105, 104, 107, 200, -1, -1, -1, -1 }, + { 106, 5, 11, 107, 7, 10, -1, -1 }, + { 100, 107, 7, 8, 200, -1, -1, -1 }, + { 10, 107, 100, 3, 200, -1, -1, -1 }, + { 100, 8, 0, 200, -1, -1, -1, -1 }, + { 3, 100, 0, 200, -1, -1, -1, -1 }, + { 7, 107, 106, 5, 200, -1, -1, -1 }, + { 107, 10, 11, 106, 200, -1, -1, -1 }, + { 11, 5, 106, 200, -1, -1, -1, -1 }, + { 101, 9, 5, 106, 200, -1, -1, -1 }, + { 11, 1, 101, 106, 200, -1, -1, -1 }, + { 101, 0, 9, 200, -1, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 106, 107, 10, 11, 200, -1, -1, -1 }, + { 10, 107, 7, 200, -1, -1, -1, -1 }, + { 8, 7, 5, 9, 100, 107, 106, 101 }, + { 100, 107, 106, 101, 3, 10, 11, 1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 7, 107, 106, 5, 200, -1, -1, -1 }, + { 10, 107, 7, 200, -1, -1, -1, -1 }, + { 107, 102, 106, 200, -1, -1, -1, -1 }, + { 10, 2, 102, 107, 200, -1, -1, -1 }, + { 102, 2, 1, 200, -1, -1, -1, -1 }, + { 10, 2, 3, 107, 102, 100, -1, -1 }, + { 102, 107, 100, 200, -1, -1, -1, -1 }, + { 107, 7, 8, 100, 200, -1, -1, -1 }, + { 106, 107, 102, 200, -1, -1, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 100, 0, 1, 102, 200, -1, -1, -1 }, + { 8, 0, 100, 200, -1, -1, -1, -1 }, + { 102, 106, 107, 200, -1, -1, -1, -1 }, + { 2, 102, 107, 10, 200, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 101, 0, 9, 200, -1, -1, -1, -1 }, + { 101, 9, 5, 106, 200, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 7, 10, 107, 200, -1, -1, -1, -1 }, + { 102, 107, 100, 2, 10, 3, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 106, 107, 102, 200, -1, -1, -1, -1 }, + { 106, 102, 101, 200, -1, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 8, 9, 101, 100, 200, -1, -1, -1 }, + { 101, 102, 100, 200, -1, -1, -1, -1 }, + { 7, 5, 9, 8, 200, -1, -1, -1 }, + { 100, 102, 107, 200, -1, -1, -1, -1 }, + { 7, 8, 100, 107, 200, -1, -1, -1 }, + { 7, 107, 106, 5, 200, -1, -1, -1 }, + { 3, 103, 107, 7, 200, -1, -1, -1 }, + { 2, 103, 3, 200, -1, -1, -1, -1 }, + { 103, 106, 107, 200, -1, -1, -1, -1 }, + { 2, 11, 106, 103, 200, -1, -1, -1 }, + { 106, 11, 5, 200, -1, -1, -1, -1 }, + { 103, 106, 107, 200, -1, -1, -1, -1 }, + { 2, 11, 106, 103, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 100, 103, 107, 200, -1, -1, -1, -1 }, + { 100, 8, 0, 200, -1, -1, -1, -1 }, + { 100, 107, 7, 8, 200, -1, -1, -1 }, + { 7, 107, 106, 5, 200, -1, -1, -1 }, + { 5, 106, 11, 200, -1, -1, -1, -1 }, + { 2, 11, 1, 103, 106, 101, -1, -1 }, + { 106, 103, 101, 200, -1, -1, -1, -1 }, + { 103, 3, 0, 101, 200, -1, -1, -1 }, + { 107, 103, 106, 200, -1, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 101, 9, 5, 106, 200, -1, -1, -1 }, + { 0, 9, 101, 200, -1, -1, -1, -1 }, + { 2, 11, 1, 103, 106, 101, -1, -1 }, + { 7, 107, 106, 5, 200, -1, -1, -1 }, + { 107, 103, 106, 200, -1, -1, -1, -1 }, + { 107, 100, 103, 200, -1, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 9, 101, 100, 8, 200, -1, -1, -1 }, + { 100, 101, 103, 200, -1, -1, -1, -1 }, + { 5, 9, 8, 7, 200, -1, -1, -1 }, + { 101, 106, 103, 200, -1, -1, -1, -1 }, + { 5, 106, 101, 9, 200, -1, -1, -1 }, + { 103, 102, 106, 107, 3, 1, 5, 7 }, + { 103, 102, 106, 107, 200, -1, -1, -1 }, + { 107, 100, 103, 200, -1, -1, -1, -1 }, + { 100, 102, 103, 200, -1, -1, -1, -1 }, + { 100, 0, 1, 102, 200, -1, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 7, 8, 100, 107, 200, -1, -1, -1 }, + { 0, 100, 8, 200, -1, -1, -1, -1 }, + { 102, 106, 107, 103, 200, -1, -1, -1 }, + { 103, 101, 102, 200, -1, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 101, 9, 5, 106, 200, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 3, 0, 101, 103, 200, -1, -1, -1 }, + { 9, 101, 0, 200, -1, -1, -1, -1 }, + { 8, 7, 5, 9, 100, 107, 106, 101 }, + { 103, 100, 107, 102, 101, 106, -1, -1 }, + { 10, 11, 106, 107, 200, -1, -1, -1 }, + { 8, 10, 107, 104, 200, -1, -1, -1 }, + { 4, 8, 104, 200, -1, -1, -1, -1 }, + { 104, 107, 106, 200, -1, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 106, 11, 5, 200, -1, -1, -1, -1 }, + { 104, 107, 106, 200, -1, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 4, 0, 100, 104, 200, -1, -1, -1 }, + { 100, 107, 104, 200, -1, -1, -1, -1 }, + { 100, 0, 3, 200, -1, -1, -1, -1 }, + { 100, 3, 10, 107, 200, -1, -1, -1 }, + { 10, 11, 106, 107, 200, -1, -1, -1 }, + { 11, 5, 106, 200, -1, -1, -1, -1 }, + { 104, 106, 101, 4, 5, 9, -1, -1 }, + { 106, 101, 104, 200, -1, -1, -1, -1 }, + { 104, 101, 0, 8, 200, -1, -1, -1 }, + { 107, 106, 104, 200, -1, -1, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 101, 106, 11, 1, 200, -1, -1, -1 }, + { 0, 101, 1, 200, -1, -1, -1, -1 }, + { 104, 106, 101, 4, 5, 9, -1, -1 }, + { 10, 11, 106, 107, 200, -1, -1, -1 }, + { 107, 106, 104, 200, -1, -1, -1, -1 }, + { 107, 104, 100, 200, -1, -1, -1, -1 }, + { 3, 10, 107, 100, 200, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 100, 104, 101, 200, -1, -1, -1, -1 }, + { 11, 10, 3, 1, 200, -1, -1, -1 }, + { 101, 104, 106, 200, -1, -1, -1, -1 }, + { 11, 1, 101, 106, 200, -1, -1, -1 }, + { 107, 102, 106, 200, -1, -1, -1, -1 }, + { 10, 2, 102, 107, 200, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 104, 107, 106, 200, -1, -1, -1, -1 }, + { 104, 4, 8, 200, -1, -1, -1, -1 }, + { 104, 106, 5, 4, 200, -1, -1, -1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 1, 102, 2, 200, -1, -1, -1, -1 }, + { 10, 2, 3, 107, 102, 100, -1, -1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 106, 107, 102, 200, -1, -1, -1, -1 }, + { 106, 104, 107, 200, -1, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 0, 100, 104, 4, 200, -1, -1, -1 }, + { 104, 100, 107, 200, -1, -1, -1, -1 }, + { 1, 0, 4, 5, 200, -1, -1, -1 }, + { 100, 102, 107, 200, -1, -1, -1, -1 }, + { 1, 102, 100, 0, 200, -1, -1, -1 }, + { 5, 4, 9, 106, 104, 101, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 107, 106, 104, 200, -1, -1, -1, -1 }, + { 107, 102, 106, 200, -1, -1, -1, -1 }, + { 2, 102, 107, 10, 200, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 102, 101, 106, 200, -1, -1, -1, -1 }, + { 8, 0, 2, 10, 200, -1, -1, -1 }, + { 101, 104, 106, 200, -1, -1, -1, -1 }, + { 8, 104, 101, 0, 200, -1, -1, -1 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 2, 3, 10, 102, 100, 107, -1, -1 }, + { 107, 104, 100, 102, -1, -1, -1, -1 }, + { 102, 101, 106, 104, -1, -1, -1, -1 }, + { 101, 102, 100, 104, -1, -1, -1, -1 }, + { 102, 106, 107, 104, -1, -1, -1, -1 }, + { 107, 106, 104, 103, -1, -1, -1, -1 }, + { 3, 103, 104, 8, 4, -1, -1, -1 }, + { 2, 11, 106, 103, 5, -1, -1, -1 }, + { 104, 106, 5, 4, 103, -1, -1, -1 }, + { 3, 4, 5, 2, 103, -1, -1, -1 }, + { 107, 104, 100, 103, 200, -1, -1, -1 }, + { 104, 107, 106, 200, -1, -1, -1, -1 }, + { 106, 107, 103, 200, -1, -1, -1, -1 }, + { 106, 103, 2, 11, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 0, 100, 104, 4, 200, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 11, 5, 106, 200, -1, -1, -1, -1 }, + { 101, 104, 106, 9, 4, 5, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 103, 101, 106, 2, 1, 11, -1, -1 }, + { 101, 104, 106, 103, -1, -1, -1, -1 }, + { 103, 106, 107, 104, -1, -1, -1, -1 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 100, 103, 107, 104, 101, -1, -1, -1 }, + { 106, 107, 103, 101, -1, -1, -1, -1 }, + { 106, 104, 107, 101, -1, -1, -1, -1 }, + { 107, 103, 102, 106, 200, -1, -1, -1 }, + { 103, 107, 104, 200, -1, -1, -1, -1 }, + { 104, 107, 106, 200, -1, -1, -1, -1 }, + { 104, 106, 5, 4, 200, -1, -1, -1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 3, 103, 104, 8, 200, -1, -1, -1 }, + { 4, 8, 104, 200, -1, -1, -1, -1 }, + { 100, 102, 106, 104, 0, 1, 5, 4 }, + { 107, 104, 106, 103, 100, 102, -1, -1 }, + { 4, 9, 5, 104, 101, 106, -1, -1 }, + { 104, 101, 103, 8, 0, 3, -1, -1 }, + { 107, 103, 102, 106, 104, -1, -1, -1 }, + { 101, 102, 103, 104, -1, -1, -1, -1 }, + { 101, 106, 102, 104, -1, -1, -1, -1 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 101, 104, 106, 200, -1, -1, -1, -1 }, + { 102, 106, 107, 103, 200, -1, -1, -1 }, + { 106, 104, 107, 200, -1, -1, -1, -1 }, + { 100, 103, 107, 104, 200, -1, -1, -1 }, + { 100, 104, 101, 200, -1, -1, -1, -1 }, + { 100, 101, 102, 103, 200, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 10, 11, 106, 107, 200, -1, -1, -1 }, + { 7, 10, 107, 200, -1, -1, -1, -1 }, + { 107, 106, 105, 200, -1, -1, -1, -1 }, + { 7, 107, 105, 4, 200, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 107, 105, 100, 7, 4, 8, -1, -1 }, + { 105, 100, 107, 200, -1, -1, -1, -1 }, + { 107, 100, 3, 10, 200, -1, -1, -1 }, + { 106, 105, 107, 200, -1, -1, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 100, 105, 9, 0, 200, -1, -1, -1 }, + { 3, 100, 0, 200, -1, -1, -1, -1 }, + { 105, 107, 106, 200, -1, -1, -1, -1 }, + { 4, 7, 107, 105, 200, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 101, 1, 0, 200, -1, -1, -1, -1 }, + { 101, 106, 11, 1, 200, -1, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 10, 107, 7, 200, -1, -1, -1, -1 }, + { 4, 7, 8, 105, 107, 100, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 106, 105, 107, 200, -1, -1, -1, -1 }, + { 106, 101, 105, 200, -1, -1, -1, -1 }, + { 1, 101, 106, 11, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 101, 100, 105, 200, -1, -1, -1, -1 }, + { 10, 3, 1, 11, 200, -1, -1, -1 }, + { 100, 107, 105, 200, -1, -1, -1, -1 }, + { 10, 107, 100, 3, 200, -1, -1, -1 }, + { 106, 105, 107, 102, -1, -1, -1, -1 }, + { 1, 9, 105, 102, 4, -1, -1, -1 }, + { 2, 102, 107, 10, 7, -1, -1, -1 }, + { 105, 4, 7, 107, 102, -1, -1, -1 }, + { 1, 2, 7, 4, 102, -1, -1, -1 }, + { 8, 4, 7, 100, 105, 107, -1, -1 }, + { 102, 100, 105, 1, 0, 9, -1, -1 }, + { 2, 3, 10, 102, 100, 107, -1, -1 }, + { 100, 107, 105, 102, -1, -1, -1, -1 }, + { 102, 106, 107, 105, -1, -1, -1, -1 }, + { 106, 102, 101, 105, 200, -1, -1, -1 }, + { 105, 107, 106, 200, -1, -1, -1, -1 }, + { 107, 102, 106, 200, -1, -1, -1, -1 }, + { 107, 10, 2, 102, 200, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 4, 7, 107, 105, 200, -1, -1, -1 }, + { 10, 107, 7, 200, -1, -1, -1, -1 }, + { 100, 107, 105, 8, 7, 4, -1, -1 }, + { 3, 10, 2, 100, 107, 102, -1, -1 }, + { 101, 105, 106, 102, 100, -1, -1, -1 }, + { 107, 102, 106, 100, -1, -1, -1, -1 }, + { 107, 106, 105, 100, -1, -1, -1, -1 }, + { 107, 106, 105, 200, -1, -1, -1, -1 }, + { 7, 107, 105, 4, 200, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 103, 106, 107, 200, -1, -1, -1, -1 }, + { 103, 3, 2, 200, -1, -1, -1, -1 }, + { 103, 2, 11, 106, 200, -1, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 9, 4, 105, 200, -1, -1, -1, -1 }, + { 107, 105, 100, 7, 4, 8, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 106, 105, 107, 200, -1, -1, -1, -1 }, + { 106, 107, 103, 200, -1, -1, -1, -1 }, + { 2, 11, 106, 103, 200, -1, -1, -1 }, + { 0, 2, 103, 100, 200, -1, -1, -1 }, + { 103, 107, 100, 200, -1, -1, -1, -1 }, + { 9, 11, 2, 0, 200, -1, -1, -1 }, + { 100, 107, 105, 200, -1, -1, -1, -1 }, + { 9, 0, 100, 105, 200, -1, -1, -1 }, + { 106, 103, 101, 11, 2, 1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 107, 103, 106, 200, -1, -1, -1, -1 }, + { 107, 106, 105, 200, -1, -1, -1, -1 }, + { 4, 7, 107, 105, 200, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 105, 106, 101, 200, -1, -1, -1, -1 }, + { 3, 7, 4, 0, 200, -1, -1, -1 }, + { 101, 106, 103, 200, -1, -1, -1, -1 }, + { 3, 0, 101, 103, 200, -1, -1, -1 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 105, 100, 107, 4, 8, 7, -1, -1 }, + { 107, 100, 103, 105, -1, -1, -1, -1 }, + { 105, 106, 101, 103, -1, -1, -1, -1 }, + { 101, 100, 105, 103, -1, -1, -1, -1 }, + { 105, 107, 106, 103, -1, -1, -1, -1 }, + { 106, 107, 103, 102, 200, -1, -1, -1 }, + { 102, 105, 106, 200, -1, -1, -1, -1 }, + { 105, 107, 106, 200, -1, -1, -1, -1 }, + { 105, 4, 7, 107, 200, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 1, 9, 105, 102, 200, -1, -1, -1 }, + { 4, 105, 9, 200, -1, -1, -1, -1 }, + { 100, 105, 102, 0, 9, 1, -1, -1 }, + { 8, 4, 7, 100, 105, 107, -1, -1 }, + { 103, 102, 106, 107, 100, -1, -1, -1 }, + { 105, 107, 106, 100, -1, -1, -1, -1 }, + { 105, 106, 102, 100, -1, -1, -1, -1 }, + { 0, 3, 7, 4, 101, 103, 107, 105 }, + { 102, 101, 103, 106, 105, 107, -1, -1 }, + { 107, 105, 100, 7, 4, 8, -1, -1 }, + { 107, 105, 100, 200, -1, -1, -1, -1 }, + { 106, 102, 101, 105, 200, -1, -1, -1 }, + { 105, 101, 100, 200, -1, -1, -1, -1 }, + { 103, 100, 101, 102, 200, -1, -1, -1 }, + { 103, 107, 100, 200, -1, -1, -1, -1 }, + { 103, 102, 106, 107, 200, -1, -1, -1 }, + { 107, 106, 105, 200, -1, -1, -1, -1 }, + { 8, 9, 11, 10, 104, 105, 106, 107 }, + { 104, 107, 106, 105, 200, -1, -1, -1 }, + { 107, 104, 100, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 100, 105, 9, 0, 200, -1, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 10, 107, 100, 3, 200, -1, -1, -1 }, + { 0, 3, 100, 200, -1, -1, -1, -1 }, + { 105, 104, 107, 106, 200, -1, -1, -1 }, + { 104, 105, 101, 200, -1, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 101, 106, 11, 1, 200, -1, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 8, 104, 101, 0, 200, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 100, 107, 106, 101, 3, 10, 11, 1 }, + { 105, 101, 106, 104, 100, 107, -1, -1 }, + { 106, 105, 104, 107, 200, -1, -1, -1 }, + { 105, 106, 102, 200, -1, -1, -1, -1 }, + { 102, 106, 107, 200, -1, -1, -1, -1 }, + { 102, 107, 10, 2, 200, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 9, 105, 102, 1, 200, -1, -1, -1 }, + { 2, 1, 102, 200, -1, -1, -1, -1 }, + { 0, 1, 9, 100, 102, 105, -1, -1 }, + { 100, 102, 107, 3, 2, 10, -1, -1 }, + { 104, 107, 106, 105, 100, -1, -1, -1 }, + { 102, 106, 107, 100, -1, -1, -1, -1 }, + { 102, 105, 106, 100, -1, -1, -1, -1 }, + { 101, 104, 107, 102, 0, 8, 10, 2 }, + { 106, 102, 107, 105, 101, 104, -1, -1 }, + { 10, 2, 3, 107, 102, 100, -1, -1 }, + { 107, 100, 102, 200, -1, -1, -1, -1 }, + { 106, 102, 101, 105, 200, -1, -1, -1 }, + { 102, 100, 101, 200, -1, -1, -1, -1 }, + { 104, 105, 101, 100, 200, -1, -1, -1 }, + { 104, 100, 107, 200, -1, -1, -1, -1 }, + { 104, 107, 106, 105, 200, -1, -1, -1 }, + { 107, 102, 106, 200, -1, -1, -1, -1 }, + { 107, 106, 105, 104, 200, -1, -1, -1 }, + { 104, 103, 107, 200, -1, -1, -1, -1 }, + { 103, 106, 107, 200, -1, -1, -1, -1 }, + { 103, 2, 11, 106, 200, -1, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 8, 3, 103, 104, 200, -1, -1, -1 }, + { 2, 103, 3, 200, -1, -1, -1, -1 }, + { 0, 9, 11, 2, 100, 105, 106, 103 }, + { 104, 100, 105, 107, 103, 106, -1, -1 }, + { 103, 101, 106, 2, 1, 11, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 107, 106, 105, 104, 103, -1, -1, -1 }, + { 101, 104, 105, 103, -1, -1, -1, -1 }, + { 101, 105, 106, 103, -1, -1, -1, -1 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 101, 106, 103, 200, -1, -1, -1, -1 }, + { 105, 104, 107, 106, 200, -1, -1, -1 }, + { 106, 107, 103, 200, -1, -1, -1, -1 }, + { 100, 103, 107, 104, 200, -1, -1, -1 }, + { 100, 101, 103, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 101, 200, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 104, 103, 102, 105, 8, 3, 1, 9 }, + { 106, 105, 102, 107, 104, 103, -1, -1 }, + { 1, 9, 0, 102, 105, 100, -1, -1 }, + { 102, 100, 105, 200, -1, -1, -1, -1 }, + { 106, 105, 104, 107, 200, -1, -1, -1 }, + { 105, 100, 104, 200, -1, -1, -1, -1 }, + { 103, 107, 104, 100, 200, -1, -1, -1 }, + { 103, 100, 102, 200, -1, -1, -1, -1 }, + { 103, 102, 106, 107, 200, -1, -1, -1 }, + { 102, 105, 106, 200, -1, -1, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 103, 104, 101, 200, -1, -1, -1, -1 }, + { 102, 101, 105, 106, 200, -1, -1, -1 }, + { 101, 104, 105, 200, -1, -1, -1, -1 }, + { 107, 106, 105, 104, 200, -1, -1, -1 }, + { 107, 104, 103, 200, -1, -1, -1, -1 }, + { 107, 103, 102, 106, 200, -1, -1, -1 }, + { 103, 101, 102, 200, -1, -1, -1, -1 }, + { 100, 101, 102, 103, 104, 105, 106, 107 } +}; + +// Special points (e.g. centroid): per-case definition streams +constexpr int special_point_count_inside[256] = { 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; +constexpr int special_point_offset_inside[257] = { 0, 0, 0, 0, 0, 0, 3, 3, 9, 9, 9, 12, 18, 18, 24, 30, 30, 30, 30, 33, 39, 39, 44, 49, 56, 59, 65, 65, 65, 70, 77, 83, 89, 89, 92, 92, 98, 101, 101, 107, 107, 107, 112, 117, 124, 129, 135, 142, 148, 148, 154, 160, 160, 165, 171, 178, 184, 189, 196, 202, 208, 208, 215, 222, 222, 222, 222, 225, 230, 230, 235, 241, 248, 251, 256, 256, 262, 268, 275, 275, 281, 284, 289, 289, 295, 300, 300, 306, 313, 313, 319, 319, 319, 325, 332, 332, 332, 332, 337, 343, 350, 356, 362, 362, 368, 373, 373, 379, 386, 393, 400, 406, 406, 412, 419, 419, 425, 432, 439, 445, 445, 451, 458, 458, 458, 465, 465, 465, 473, 473, 476, 476, 481, 484, 484, 489, 495, 495, 501, 506, 513, 519, 519, 526, 532, 532, 538, 543, 550, 555, 561, 561, 568, 574, 574, 580, 586, 593, 599, 606, 606, 609, 609, 614, 620, 620, 620, 626, 626, 631, 637, 637, 644, 650, 650, 657, 657, 663, 663, 670, 676, 682, 682, 689, 689, 696, 702, 709, 709, 716, 716, 716, 724, 724, 729, 734, 734, 740, 746, 753, 760, 766, 773, 779, 786, 786, 792, 798, 798, 804, 811, 817, 824, 831, 838, 845, 845, 845, 851, 851, 851, 857, 857, 857, 865, 871, 877, 884, 891, 891, 891, 897, 897, 904, 911, 918, 918, 924, 924, 924, 932, 932, 938, 944, 944, 950, 950, 950, 958, 964, 964, 964, 972, 972, 980, 988, 988 }; +constexpr int special_point_data_inside[988] = { 2, 8, 11, 5, 8, 9, 3, 2, 11, 2, 10, 9, 5, 9, 8, 1, 2, 10, 5, 8, 10, 0, 1, 11, 5, 10, 11, 3, 0, 9, 2, 7, 1, 5, 1, 3, 9, 4, 7, 4, 4, 7, 11, 11, 4, 11, 2, 7, 7, 6, 3, 2, 11, 9, 4, 7, 2, 2, 4, 5, 4, 0, 7, 10, 2, 4, 11, 1, 4, 4, 6, 0, 1, 11, 10, 7, 4, 5, 11, 9, 10, 7, 4, 5, 9, 11, 10, 4, 7, 2, 3, 5, 5, 3, 1, 8, 4, 5, 2, 2, 4, 5, 4, 0, 5, 11, 2, 4, 2, 10, 5, 5, 4, 5, 4, 10, 10, 6, 8, 4, 5, 1, 2, 10, 4, 10, 3, 4, 4, 5, 10, 11, 8, 4, 5, 6, 0, 3, 10, 11, 5, 4, 5, 11, 10, 8, 5, 4, 5, 3, 7, 0, 9, 5, 5, 7, 5, 8, 0, 1, 4, 7, 8, 2, 2, 5, 7, 5, 3, 2, 11, 6, 0, 8, 7, 5, 11, 2, 5, 5, 7, 3, 11, 2, 4, 5, 9, 2, 2, 6, 0, 9, 5, 7, 10, 2, 5, 5, 1, 7, 10, 2, 5, 1, 5, 7, 2, 10, 6, 100, 102, 103, 104, 5, 7, 6, 101, 103, 102, 105, 7, 5, 2, 0, 6, 4, 8, 3, 6, 6, 4, 6, 5, 8, 8, 5, 0, 2, 9, 5, 6, 6, 9, 5, 6, 2, 3, 8, 2, 3, 5, 4, 0, 8, 5, 5, 5, 8, 10, 9, 5, 6, 5, 3, 1, 10, 6, 5, 6, 10, 6, 5, 1, 0, 8, 5, 10, 8, 9, 6, 5, 2, 8, 11, 4, 0, 3, 11, 11, 5, 3, 7, 1, 11, 6, 4, 2, 1, 8, 8, 5, 2, 6, 0, 8, 7, 6, 101, 104, 100, 102, 6, 2, 5, 0, 2, 4, 5, 11, 5, 1, 5, 3, 8, 4, 6, 103, 104, 100, 102, 5, 1, 4, 6, 11, 3, 3, 5, 0, 4, 1, 11, 6, 6, 1, 11, 6, 4, 8, 3, 5, 2, 6, 1, 9, 4, 5, 6, 4, 2, 3, 8, 5, 4, 6, 2, 8, 3, 4, 4, 9, 3, 3, 5, 4, 6, 0, 3, 10, 6, 101, 103, 100, 105, 6, 4, 6, 1, 9, 4, 6, 10, 3, 6, 102, 100, 103, 106, 4, 6, 5, 6, 4, 0, 10, 3, 5, 8, 9, 7, 6, 11, 6, 7, 6, 11, 9, 0, 3, 5, 7, 3, 1, 6, 11, 6, 9, 1, 2, 6, 7, 8, 6, 105, 100, 104, 106, 2, 6, 5, 6, 2, 0, 7, 8, 5, 9, 11, 8, 3, 2, 6, 104, 103, 100, 105, 11, 9, 6, 106, 104, 105, 102, 3, 1, 7, 100, 101, 102, 103, 104, 105, 106, 2, 0, 6, 4, 9, 1, 6, 6, 2, 7, 1, 4, 9, 0, 7, 7, 5, 9, 11, 8, 7, 6, 5, 0, 2, 8, 7, 6, 4, 6, 7, 9, 9, 6, 8, 7, 6, 2, 1, 9, 5, 1, 3, 11, 6, 7, 6, 3, 0, 9, 11, 6, 7, 5, 11, 9, 8, 6, 7, 5, 0, 4, 3, 10, 6, 4, 6, 10, 1, 1, 6, 3, 10, 6, 4, 9, 1, 4, 4, 8, 1, 1, 5, 4, 6, 0, 1, 11, 6, 100, 107, 104, 101, 11, 9, 5, 2, 6, 3, 8, 4, 5, 6, 4, 2, 1, 9, 5, 4, 6, 2, 9, 1, 6, 3, 8, 4, 6, 11, 1, 5, 6, 4, 0, 11, 1, 6, 103, 104, 107, 102, 9, 11, 2, 10, 9, 4, 1, 0, 10, 10, 5, 1, 5, 3, 10, 6, 5, 0, 2, 4, 7, 10, 4, 2, 3, 9, 9, 5, 2, 6, 0, 9, 5, 6, 100, 107, 103, 101, 5, 1, 5, 3, 7, 1, 9, 4, 6, 102, 105, 101, 103, 7, 3, 5, 9, 8, 5, 6, 10, 6, 8, 0, 1, 5, 6, 10, 5, 5, 1, 3, 6, 10, 5, 8, 10, 9, 1, 2, 6, 105, 102, 101, 104, 10, 8, 6, 8, 3, 2, 6, 5, 9, 5, 6, 2, 0, 5, 9, 6, 104, 103, 107, 105, 1, 5, 6, 107, 105, 104, 103, 1, 3, 7, 101, 100, 103, 102, 105, 104, 107, 4, 11, 5, 0, 0, 4, 10, 7, 0, 0, 5, 7, 5, 10, 2, 1, 5, 5, 1, 7, 8, 0, 6, 2, 10, 7, 5, 9, 0, 6, 102, 100, 101, 106, 7, 5, 5, 3, 7, 2, 11, 5, 6, 2, 11, 5, 7, 8, 0, 5, 7, 5, 3, 0, 9, 6, 103, 101, 100, 107, 5, 7, 5, 1, 5, 7, 0, 8, 5, 5, 7, 3, 9, 0, 5, 8, 10, 4, 5, 11, 6, 4, 5, 11, 10, 3, 0, 5, 10, 11, 8, 0, 1, 6, 104, 101, 100, 107, 11, 10, 6, 10, 2, 1, 5, 4, 8, 6, 107, 100, 104, 106, 1, 5, 6, 106, 101, 102, 107, 8, 10, 5, 2, 0, 4, 11, 5, 5, 5, 1, 3, 4, 8, 7, 100, 103, 107, 104, 101, 102, 106, 5, 10, 11, 7, 4, 9, 5, 11, 9, 10, 3, 0, 6, 4, 7, 10, 11, 1, 0, 6, 105, 100, 101, 106, 10, 11, 5, 2, 0, 4, 10, 7, 6, 7, 4, 9, 11, 2, 3, 6, 107, 100, 103, 106, 9, 11, 6, 106, 101, 105, 107, 3, 7, 5, 7, 3, 1, 4, 9, 7, 103, 102, 101, 100, 107, 106, 105, 5, 9, 11, 10, 0, 3, 5, 11, 10, 8, 1, 0, 5, 10, 8, 9, 2, 1, 7, 104, 105, 101, 100, 107, 106, 102, 5, 11, 9, 8, 2, 3, 7, 100, 104, 107, 103, 101, 105, 106, 7, 103, 107, 104, 100, 102, 106, 105, 7, 107, 106, 105, 104, 103, 102, 101 }; + +} // namespace cutcells::cell::hexahedron + +#endif // CUT_CELLS_HEXAHEDRON_INSIDE_TABLES_H \ No newline at end of file diff --git a/cpp/src/generated/cut_hexahedron_interface_tables.h b/cpp/src/generated/cut_hexahedron_interface_tables.h new file mode 100644 index 0000000..c39ac9c --- /dev/null +++ b/cpp/src/generated/cut_hexahedron_interface_tables.h @@ -0,0 +1,1044 @@ +#ifndef CUT_CELLS_HEXAHEDRON_INTERFACE_TABLES_H +#define CUT_CELLS_HEXAHEDRON_INTERFACE_TABLES_H + +// ----------------------------------------------------------------------------- +// This file is generated by CutCells tablegen. +// +// It contains case tables derived from VTK's vtkTableBasedClipCases.h +// (Visualization Toolkit, TableBasedClip). +// +// VTK ref: master +// VTK header path override: (none) +// +// VTK is licensed under the BSD 3-Clause License. +// See third_party/VTK-Copyright.txt in this repository. +// ----------------------------------------------------------------------------- + +#include "cell_types.h" + +namespace cutcells::cell::hexahedron { + +// Number of subcells produced for each case (interface volume) +constexpr int num_subcells_interface[256] = { 0, 1, 1, 1, 1, 6, 1, 5, 1, 1, 6, 5, 1, 5, 5, 1, 1, 1, 6, 5, 2, 7, 7, 6, 6, 5, 4, 3, 7, 6, 6, 5, 1, 6, 1, 5, 6, 4, 5, 3, 2, 7, 7, 6, 7, 6, 6, 5, 1, 5, 5, 1, 7, 6, 6, 5, 7, 6, 6, 5, 2, 2, 2, 1, 1, 2, 6, 7, 1, 7, 5, 6, 6, 7, 4, 6, 5, 6, 3, 5, 6, 7, 4, 6, 7, 2, 6, 2, 4, 6, 4, 3, 6, 2, 3, 2, 1, 7, 5, 6, 5, 6, 1, 5, 7, 2, 6, 2, 6, 2, 5, 1, 5, 6, 3, 5, 6, 2, 5, 1, 6, 2, 3, 2, 2, 2, 2, 1, 1, 6, 2, 7, 6, 4, 7, 6, 1, 5, 7, 6, 5, 3, 6, 5, 1, 5, 7, 6, 7, 6, 2, 2, 5, 1, 6, 5, 6, 5, 2, 1, 6, 4, 7, 6, 4, 4, 6, 3, 7, 6, 2, 2, 6, 3, 2, 2, 5, 3, 6, 5, 6, 3, 2, 2, 6, 5, 2, 1, 2, 2, 2, 1, 1, 7, 7, 2, 5, 6, 6, 2, 5, 6, 6, 2, 1, 5, 5, 1, 5, 6, 6, 2, 6, 2, 2, 2, 3, 5, 3, 2, 5, 1, 2, 1, 5, 6, 6, 2, 3, 3, 5, 2, 6, 2, 2, 2, 5, 2, 1, 1, 1, 5, 5, 1, 5, 2, 1, 1, 5, 1, 2, 1, 1, 1, 1, 0 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_interface[257] = { 0, 0, 1, 2, 3, 4, 10, 11, 16, 17, 18, 24, 29, 30, 35, 40, 41, 42, 43, 49, 54, 56, 63, 70, 76, 82, 87, 91, 94, 101, 107, 113, 118, 119, 125, 126, 131, 137, 141, 146, 149, 151, 158, 165, 171, 178, 184, 190, 195, 196, 201, 206, 207, 214, 220, 226, 231, 238, 244, 250, 255, 257, 259, 261, 262, 263, 265, 271, 278, 279, 286, 291, 297, 303, 310, 314, 320, 325, 331, 334, 339, 345, 352, 356, 362, 369, 371, 377, 379, 383, 389, 393, 396, 402, 404, 407, 409, 410, 417, 422, 428, 433, 439, 440, 445, 452, 454, 460, 462, 468, 470, 475, 476, 481, 487, 490, 495, 501, 503, 508, 509, 515, 517, 520, 522, 524, 526, 528, 529, 530, 536, 538, 545, 551, 555, 562, 568, 569, 574, 581, 587, 592, 595, 601, 606, 607, 612, 619, 625, 632, 638, 640, 642, 647, 648, 654, 659, 665, 670, 672, 673, 679, 683, 690, 696, 700, 704, 710, 713, 720, 726, 728, 730, 736, 739, 741, 743, 748, 751, 757, 762, 768, 771, 773, 775, 781, 786, 788, 789, 791, 793, 795, 796, 797, 804, 811, 813, 818, 824, 830, 832, 837, 843, 849, 851, 852, 857, 862, 863, 868, 874, 880, 882, 888, 890, 892, 894, 897, 902, 905, 907, 912, 913, 915, 916, 921, 927, 933, 935, 938, 941, 946, 948, 954, 956, 958, 960, 965, 967, 968, 969, 970, 975, 980, 981, 986, 988, 989, 990, 995, 996, 998, 999, 1000, 1001, 1002, 1002 }; + +// Cell types for interface subcells +constexpr type subcell_type_interface[1002] = { cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle }; + +// Subcell vertices (max 4 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, 100..199 = 100+vertex_id, >=200 = 200+special_point_id +constexpr int subcell_verts_interface[1002][4] = { + { 0, 8, 3, -1 }, + { 0, 1, 9, -1 }, + { 1, 3, 8, 9 }, + { 1, 2, 11, -1 }, + { 2, 200, 3, -1 }, + { 0, 200, 1, -1 }, + { 1, 200, 11, -1 }, + { 11, 200, 2, -1 }, + { 0, 8, 200, -1 }, + { 3, 200, 8, -1 }, + { 2, 0, 9, 11 }, + { 9, 200, 11, -1 }, + { 8, 200, 9, -1 }, + { 3, 200, 8, -1 }, + { 2, 200, 3, -1 }, + { 11, 200, 2, -1 }, + { 3, 10, 2, -1 }, + { 10, 8, 0, 2 }, + { 3, 200, 0, -1 }, + { 1, 200, 2, -1 }, + { 1, 9, 200, -1 }, + { 0, 200, 9, -1 }, + { 2, 200, 10, -1 }, + { 3, 10, 200, -1 }, + { 10, 200, 8, -1 }, + { 8, 200, 9, -1 }, + { 1, 9, 200, -1 }, + { 1, 200, 2, -1 }, + { 2, 200, 10, -1 }, + { 3, 1, 11, 10 }, + { 11, 200, 10, -1 }, + { 10, 200, 8, -1 }, + { 0, 8, 200, -1 }, + { 0, 200, 1, -1 }, + { 1, 200, 11, -1 }, + { 9, 200, 11, -1 }, + { 11, 200, 10, -1 }, + { 3, 10, 200, -1 }, + { 3, 200, 0, -1 }, + { 0, 200, 9, -1 }, + { 8, 10, 11, 9 }, + { 4, 7, 8, -1 }, + { 3, 7, 4, 0 }, + { 0, 200, 8, -1 }, + { 4, 200, 9, -1 }, + { 9, 200, 1, -1 }, + { 1, 200, 0, -1 }, + { 4, 7, 200, -1 }, + { 8, 200, 7, -1 }, + { 3, 200, 7, -1 }, + { 1, 200, 3, -1 }, + { 9, 200, 1, -1 }, + { 4, 200, 9, -1 }, + { 7, 200, 4, -1 }, + { 4, 7, 8, -1 }, + { 2, 11, 1, -1 }, + { 2, 200, 3, -1 }, + { 0, 200, 1, -1 }, + { 11, 200, 2, -1 }, + { 1, 200, 11, -1 }, + { 3, 200, 7, -1 }, + { 4, 200, 0, -1 }, + { 4, 7, 200, -1 }, + { 0, 200, 8, -1 }, + { 4, 200, 9, -1 }, + { 8, 200, 7, -1 }, + { 4, 7, 200, -1 }, + { 2, 200, 0, -1 }, + { 9, 200, 11, -1 }, + { 11, 200, 2, -1 }, + { 2, 200, 3, -1 }, + { 3, 200, 7, -1 }, + { 7, 200, 4, -1 }, + { 4, 200, 9, -1 }, + { 9, 200, 11, -1 }, + { 11, 200, 2, -1 }, + { 8, 200, 3, -1 }, + { 10, 200, 7, -1 }, + { 7, 200, 4, -1 }, + { 4, 200, 8, -1 }, + { 10, 2, 200, -1 }, + { 3, 200, 2, -1 }, + { 0, 200, 2, -1 }, + { 4, 200, 0, -1 }, + { 7, 200, 4, -1 }, + { 10, 200, 7, -1 }, + { 2, 200, 10, -1 }, + { 3, 0, 8, -1 }, + { 10, 2, 7, -1 }, + { 4, 1, 9, -1 }, + { 2, 1, 4, 7 }, + { 10, 2, 7, -1 }, + { 4, 1, 9, -1 }, + { 7, 2, 1, 4 }, + { 8, 200, 3, -1 }, + { 10, 200, 7, -1 }, + { 4, 200, 8, -1 }, + { 7, 200, 4, -1 }, + { 3, 200, 1, -1 }, + { 11, 200, 10, -1 }, + { 11, 1, 200, -1 }, + { 0, 200, 1, -1 }, + { 4, 200, 0, -1 }, + { 7, 200, 4, -1 }, + { 10, 200, 7, -1 }, + { 11, 200, 10, -1 }, + { 11, 1, 200, -1 }, + { 3, 0, 8, -1 }, + { 10, 200, 7, -1 }, + { 9, 200, 11, -1 }, + { 11, 200, 10, -1 }, + { 4, 200, 9, -1 }, + { 7, 200, 4, -1 }, + { 4, 200, 9, -1 }, + { 9, 200, 11, -1 }, + { 11, 200, 10, -1 }, + { 10, 200, 7, -1 }, + { 4, 7, 200, -1 }, + { 5, 4, 9, -1 }, + { 8, 200, 4, -1 }, + { 9, 200, 0, -1 }, + { 9, 5, 200, -1 }, + { 4, 200, 5, -1 }, + { 0, 200, 3, -1 }, + { 8, 3, 200, -1 }, + { 0, 4, 5, 1 }, + { 5, 200, 1, -1 }, + { 1, 200, 3, -1 }, + { 8, 3, 200, -1 }, + { 8, 200, 4, -1 }, + { 4, 200, 5, -1 }, + { 1, 200, 9, -1 }, + { 5, 200, 11, -1 }, + { 5, 4, 200, -1 }, + { 9, 200, 4, -1 }, + { 11, 200, 2, -1 }, + { 1, 2, 200, -1 }, + { 0, 1, 9, -1 }, + { 2, 8, 3, -1 }, + { 5, 4, 11, -1 }, + { 8, 2, 11, 4 }, + { 2, 200, 0, -1 }, + { 0, 200, 4, -1 }, + { 5, 4, 200, -1 }, + { 5, 200, 11, -1 }, + { 11, 200, 2, -1 }, + { 2, 8, 3, -1 }, + { 5, 4, 11, -1 }, + { 2, 11, 4, 8 }, + { 3, 10, 2, -1 }, + { 9, 5, 4, -1 }, + { 8, 200, 4, -1 }, + { 9, 200, 0, -1 }, + { 4, 200, 5, -1 }, + { 9, 5, 200, -1 }, + { 10, 200, 8, -1 }, + { 0, 200, 2, -1 }, + { 2, 200, 10, -1 }, + { 3, 200, 0, -1 }, + { 1, 200, 2, -1 }, + { 10, 200, 3, -1 }, + { 2, 200, 10, -1 }, + { 0, 200, 4, -1 }, + { 5, 200, 1, -1 }, + { 5, 4, 200, -1 }, + { 8, 200, 4, -1 }, + { 10, 200, 8, -1 }, + { 2, 200, 10, -1 }, + { 1, 200, 2, -1 }, + { 5, 200, 1, -1 }, + { 5, 4, 200, -1 }, + { 1, 200, 9, -1 }, + { 5, 200, 11, -1 }, + { 9, 200, 4, -1 }, + { 5, 4, 200, -1 }, + { 3, 200, 1, -1 }, + { 11, 200, 10, -1 }, + { 10, 200, 3, -1 }, + { 0, 1, 9, -1 }, + { 8, 200, 4, -1 }, + { 11, 200, 10, -1 }, + { 10, 200, 8, -1 }, + { 5, 200, 11, -1 }, + { 4, 200, 5, -1 }, + { 3, 200, 0, -1 }, + { 0, 200, 4, -1 }, + { 4, 200, 5, -1 }, + { 5, 200, 11, -1 }, + { 11, 200, 10, -1 }, + { 10, 200, 3, -1 }, + { 5, 200, 11, -1 }, + { 11, 200, 10, -1 }, + { 10, 200, 8, -1 }, + { 8, 200, 4, -1 }, + { 5, 4, 200, -1 }, + { 9, 8, 7, 5 }, + { 7, 200, 5, -1 }, + { 3, 200, 7, -1 }, + { 0, 200, 3, -1 }, + { 9, 200, 0, -1 }, + { 5, 200, 9, -1 }, + { 5, 200, 1, -1 }, + { 7, 200, 5, -1 }, + { 8, 200, 7, -1 }, + { 0, 200, 8, -1 }, + { 1, 200, 0, -1 }, + { 3, 1, 5, 7 }, + { 1, 200, 9, -1 }, + { 5, 200, 11, -1 }, + { 2, 200, 1, -1 }, + { 11, 200, 2, -1 }, + { 9, 200, 8, -1 }, + { 7, 200, 5, -1 }, + { 7, 8, 200, -1 }, + { 0, 1, 9, -1 }, + { 2, 200, 3, -1 }, + { 7, 200, 5, -1 }, + { 3, 200, 7, -1 }, + { 5, 200, 11, -1 }, + { 2, 11, 200, -1 }, + { 0, 200, 8, -1 }, + { 2, 200, 0, -1 }, + { 11, 200, 2, -1 }, + { 5, 200, 11, -1 }, + { 7, 200, 5, -1 }, + { 7, 8, 200, -1 }, + { 5, 200, 11, -1 }, + { 7, 200, 5, -1 }, + { 3, 200, 7, -1 }, + { 2, 200, 3, -1 }, + { 11, 200, 2, -1 }, + { 8, 200, 3, -1 }, + { 10, 200, 7, -1 }, + { 3, 200, 2, -1 }, + { 10, 2, 200, -1 }, + { 9, 200, 8, -1 }, + { 7, 200, 5, -1 }, + { 5, 200, 9, -1 }, + { 9, 200, 0, -1 }, + { 0, 200, 2, -1 }, + { 2, 200, 10, -1 }, + { 10, 200, 7, -1 }, + { 7, 200, 5, -1 }, + { 5, 200, 9, -1 }, + { 8, 3, 0, -1 }, + { 10, 200, 7, -1 }, + { 5, 200, 1, -1 }, + { 7, 200, 5, -1 }, + { 1, 200, 2, -1 }, + { 10, 2, 200, -1 }, + { 1, 200, 2, -1 }, + { 5, 200, 1, -1 }, + { 7, 200, 5, -1 }, + { 10, 200, 7, -1 }, + { 2, 200, 10, -1 }, + { 10, 11, 5, 7 }, + { 3, 8, 9, 1 }, + { 0, 1, 9, -1 }, + { 5, 7, 10, 11 }, + { 0, 8, 3, -1 }, + { 7, 10, 11, 5 }, + { 10, 11, 5, 7 }, + { 5, 11, 6, -1 }, + { 8, 3, 0, -1 }, + { 5, 11, 6, -1 }, + { 11, 200, 1, -1 }, + { 9, 200, 5, -1 }, + { 5, 200, 6, -1 }, + { 6, 200, 11, -1 }, + { 9, 0, 200, -1 }, + { 1, 200, 0, -1 }, + { 11, 200, 1, -1 }, + { 9, 200, 5, -1 }, + { 6, 200, 11, -1 }, + { 5, 200, 6, -1 }, + { 1, 200, 3, -1 }, + { 8, 200, 9, -1 }, + { 8, 3, 200, -1 }, + { 1, 5, 6, 2 }, + { 0, 200, 1, -1 }, + { 2, 200, 3, -1 }, + { 8, 200, 0, -1 }, + { 3, 200, 8, -1 }, + { 1, 200, 5, -1 }, + { 6, 200, 2, -1 }, + { 6, 5, 200, -1 }, + { 6, 200, 2, -1 }, + { 2, 200, 0, -1 }, + { 9, 0, 200, -1 }, + { 9, 200, 5, -1 }, + { 5, 200, 6, -1 }, + { 9, 200, 5, -1 }, + { 8, 200, 9, -1 }, + { 3, 200, 8, -1 }, + { 2, 200, 3, -1 }, + { 6, 200, 2, -1 }, + { 6, 5, 200, -1 }, + { 6, 200, 10, -1 }, + { 2, 200, 11, -1 }, + { 11, 200, 5, -1 }, + { 5, 200, 6, -1 }, + { 2, 3, 200, -1 }, + { 10, 200, 3, -1 }, + { 6, 200, 10, -1 }, + { 2, 200, 11, -1 }, + { 5, 200, 6, -1 }, + { 11, 200, 5, -1 }, + { 10, 200, 8, -1 }, + { 0, 200, 2, -1 }, + { 0, 8, 200, -1 }, + { 1, 2, 11, -1 }, + { 3, 9, 0, -1 }, + { 6, 5, 10, -1 }, + { 9, 3, 10, 5 }, + { 1, 2, 11, -1 }, + { 9, 200, 5, -1 }, + { 10, 200, 8, -1 }, + { 8, 200, 9, -1 }, + { 6, 200, 10, -1 }, + { 5, 200, 6, -1 }, + { 1, 200, 5, -1 }, + { 3, 200, 1, -1 }, + { 10, 200, 3, -1 }, + { 6, 200, 10, -1 }, + { 5, 200, 6, -1 }, + { 6, 200, 10, -1 }, + { 10, 200, 8, -1 }, + { 8, 200, 0, -1 }, + { 0, 200, 1, -1 }, + { 1, 200, 5, -1 }, + { 5, 200, 6, -1 }, + { 3, 9, 0, -1 }, + { 6, 5, 10, -1 }, + { 3, 10, 5, 9 }, + { 6, 200, 10, -1 }, + { 10, 200, 8, -1 }, + { 8, 200, 9, -1 }, + { 9, 200, 5, -1 }, + { 6, 5, 200, -1 }, + { 7, 200, 6, -1 }, + { 5, 200, 4, -1 }, + { 5, 11, 200, -1 }, + { 6, 200, 11, -1 }, + { 4, 200, 8, -1 }, + { 7, 8, 200, -1 }, + { 7, 200, 6, -1 }, + { 5, 200, 4, -1 }, + { 6, 200, 11, -1 }, + { 5, 11, 200, -1 }, + { 3, 200, 7, -1 }, + { 4, 200, 0, -1 }, + { 0, 200, 3, -1 }, + { 9, 5, 4, -1 }, + { 0, 1, 8, -1 }, + { 7, 11, 6, -1 }, + { 1, 11, 7, 8 }, + { 9, 5, 4, -1 }, + { 11, 200, 1, -1 }, + { 3, 200, 7, -1 }, + { 1, 200, 3, -1 }, + { 7, 200, 6, -1 }, + { 11, 6, 200, -1 }, + { 5, 200, 4, -1 }, + { 7, 200, 6, -1 }, + { 4, 200, 8, -1 }, + { 7, 8, 200, -1 }, + { 1, 200, 5, -1 }, + { 6, 200, 2, -1 }, + { 2, 200, 1, -1 }, + { 0, 4, 5, 1 }, + { 3, 2, 6, 7 }, + { 9, 5, 4, -1 }, + { 0, 200, 8, -1 }, + { 6, 200, 2, -1 }, + { 2, 200, 0, -1 }, + { 7, 200, 6, -1 }, + { 8, 200, 7, -1 }, + { 9, 5, 4, -1 }, + { 6, 7, 3, 2 }, + { 7, 6, 10, -1 }, + { 8, 4, 3, -1 }, + { 2, 5, 11, -1 }, + { 4, 5, 2, 3 }, + { 7, 6, 10, -1 }, + { 5, 200, 4, -1 }, + { 0, 200, 2, -1 }, + { 4, 200, 0, -1 }, + { 2, 200, 11, -1 }, + { 5, 11, 200, -1 }, + { 1, 2, 11, -1 }, + { 4, 9, 5, -1 }, + { 3, 0, 8, -1 }, + { 6, 10, 7, -1 }, + { 11, 1, 2, -1 }, + { 7, 6, 10, -1 }, + { 4, 9, 5, -1 }, + { 10, 7, 6, -1 }, + { 8, 200, 3, -1 }, + { 1, 200, 5, -1 }, + { 3, 200, 1, -1 }, + { 5, 200, 4, -1 }, + { 8, 4, 200, -1 }, + { 10, 7, 6, -1 }, + { 5, 1, 0, 4 }, + { 4, 9, 5, -1 }, + { 3, 0, 8, -1 }, + { 10, 7, 6, -1 }, + { 4, 9, 5, -1 }, + { 7, 6, 10, -1 }, + { 11, 9, 4, 6 }, + { 9, 200, 0, -1 }, + { 8, 200, 4, -1 }, + { 0, 200, 3, -1 }, + { 8, 3, 200, -1 }, + { 11, 200, 9, -1 }, + { 4, 200, 6, -1 }, + { 6, 200, 11, -1 }, + { 4, 200, 6, -1 }, + { 0, 200, 4, -1 }, + { 1, 200, 0, -1 }, + { 11, 200, 1, -1 }, + { 6, 200, 11, -1 }, + { 11, 200, 1, -1 }, + { 1, 200, 3, -1 }, + { 3, 200, 8, -1 }, + { 8, 200, 4, -1 }, + { 4, 200, 6, -1 }, + { 6, 200, 11, -1 }, + { 4, 200, 6, -1 }, + { 6, 200, 2, -1 }, + { 1, 2, 200, -1 }, + { 1, 200, 9, -1 }, + { 9, 200, 4, -1 }, + { 1, 9, 0, -1 }, + { 2, 200, 3, -1 }, + { 4, 200, 6, -1 }, + { 6, 200, 2, -1 }, + { 8, 200, 4, -1 }, + { 3, 200, 8, -1 }, + { 0, 2, 6, 4 }, + { 8, 200, 4, -1 }, + { 4, 200, 6, -1 }, + { 6, 200, 2, -1 }, + { 2, 200, 3, -1 }, + { 8, 3, 200, -1 }, + { 2, 200, 11, -1 }, + { 6, 200, 10, -1 }, + { 3, 200, 2, -1 }, + { 10, 200, 3, -1 }, + { 11, 200, 9, -1 }, + { 4, 200, 6, -1 }, + { 4, 9, 200, -1 }, + { 0, 9, 11, 2 }, + { 8, 10, 6, 4 }, + { 1, 2, 11, -1 }, + { 3, 200, 0, -1 }, + { 4, 200, 6, -1 }, + { 0, 200, 4, -1 }, + { 6, 200, 10, -1 }, + { 3, 10, 200, -1 }, + { 1, 2, 11, -1 }, + { 6, 4, 8, 10 }, + { 1, 200, 9, -1 }, + { 3, 200, 1, -1 }, + { 10, 200, 3, -1 }, + { 6, 200, 10, -1 }, + { 4, 200, 6, -1 }, + { 4, 9, 200, -1 }, + { 1, 9, 0, -1 }, + { 4, 8, 10, 6 }, + { 6, 200, 10, -1 }, + { 4, 200, 6, -1 }, + { 0, 200, 4, -1 }, + { 3, 200, 0, -1 }, + { 10, 200, 3, -1 }, + { 8, 10, 6, 4 }, + { 11, 200, 9, -1 }, + { 9, 200, 8, -1 }, + { 7, 8, 200, -1 }, + { 7, 200, 6, -1 }, + { 6, 200, 11, -1 }, + { 7, 200, 6, -1 }, + { 3, 200, 7, -1 }, + { 0, 200, 3, -1 }, + { 9, 200, 0, -1 }, + { 11, 200, 9, -1 }, + { 11, 6, 200, -1 }, + { 0, 1, 8, -1 }, + { 7, 11, 6, -1 }, + { 8, 1, 11, 7 }, + { 7, 200, 6, -1 }, + { 3, 200, 7, -1 }, + { 1, 200, 3, -1 }, + { 11, 200, 1, -1 }, + { 6, 200, 11, -1 }, + { 1, 200, 9, -1 }, + { 9, 200, 8, -1 }, + { 8, 200, 7, -1 }, + { 7, 200, 6, -1 }, + { 6, 200, 2, -1 }, + { 2, 200, 1, -1 }, + { 9, 0, 1, -1 }, + { 2, 6, 7, 3 }, + { 7, 200, 6, -1 }, + { 6, 200, 2, -1 }, + { 2, 200, 0, -1 }, + { 0, 200, 8, -1 }, + { 7, 8, 200, -1 }, + { 3, 2, 6, 7 }, + { 7, 6, 10, -1 }, + { 8, 200, 3, -1 }, + { 11, 200, 9, -1 }, + { 9, 200, 8, -1 }, + { 2, 200, 11, -1 }, + { 3, 200, 2, -1 }, + { 7, 6, 10, -1 }, + { 11, 2, 0, 9 }, + { 2, 11, 1, -1 }, + { 8, 3, 0, -1 }, + { 7, 6, 10, -1 }, + { 2, 11, 1, -1 }, + { 10, 7, 6, -1 }, + { 6, 10, 7, -1 }, + { 3, 8, 9, 1 }, + { 7, 6, 10, -1 }, + { 9, 0, 1, -1 }, + { 10, 7, 6, -1 }, + { 3, 0, 8, -1 }, + { 7, 6, 10, -1 }, + { 6, 10, 7, -1 }, + { 3, 200, 10, -1 }, + { 7, 200, 8, -1 }, + { 7, 6, 200, -1 }, + { 10, 200, 6, -1 }, + { 8, 200, 0, -1 }, + { 3, 0, 200, -1 }, + { 0, 1, 9, -1 }, + { 7, 6, 10, -1 }, + { 3, 200, 10, -1 }, + { 7, 200, 8, -1 }, + { 10, 200, 6, -1 }, + { 7, 6, 200, -1 }, + { 1, 200, 3, -1 }, + { 8, 200, 9, -1 }, + { 9, 200, 1, -1 }, + { 10, 200, 2, -1 }, + { 11, 200, 6, -1 }, + { 11, 1, 200, -1 }, + { 2, 200, 1, -1 }, + { 6, 200, 7, -1 }, + { 10, 7, 200, -1 }, + { 3, 10, 2, -1 }, + { 7, 0, 8, -1 }, + { 11, 1, 6, -1 }, + { 0, 7, 6, 1 }, + { 10, 200, 2, -1 }, + { 11, 200, 6, -1 }, + { 7, 200, 10, -1 }, + { 6, 200, 7, -1 }, + { 2, 200, 0, -1 }, + { 9, 200, 11, -1 }, + { 9, 0, 200, -1 }, + { 3, 10, 2, -1 }, + { 7, 200, 8, -1 }, + { 9, 200, 11, -1 }, + { 8, 200, 9, -1 }, + { 11, 200, 6, -1 }, + { 7, 6, 200, -1 }, + { 7, 3, 2, 6 }, + { 2, 200, 6, -1 }, + { 0, 200, 2, -1 }, + { 8, 200, 0, -1 }, + { 7, 200, 8, -1 }, + { 6, 200, 7, -1 }, + { 3, 200, 0, -1 }, + { 1, 200, 2, -1 }, + { 0, 200, 9, -1 }, + { 1, 9, 200, -1 }, + { 7, 200, 3, -1 }, + { 2, 200, 6, -1 }, + { 6, 200, 7, -1 }, + { 7, 200, 8, -1 }, + { 8, 200, 9, -1 }, + { 9, 200, 1, -1 }, + { 1, 200, 2, -1 }, + { 2, 200, 6, -1 }, + { 6, 200, 7, -1 }, + { 7, 200, 3, -1 }, + { 3, 200, 1, -1 }, + { 11, 1, 200, -1 }, + { 11, 200, 6, -1 }, + { 6, 200, 7, -1 }, + { 7, 0, 8, -1 }, + { 11, 1, 6, -1 }, + { 7, 6, 1, 0 }, + { 3, 200, 0, -1 }, + { 7, 200, 3, -1 }, + { 6, 200, 7, -1 }, + { 11, 200, 6, -1 }, + { 9, 200, 11, -1 }, + { 9, 0, 200, -1 }, + { 11, 200, 6, -1 }, + { 9, 200, 11, -1 }, + { 8, 200, 9, -1 }, + { 7, 200, 8, -1 }, + { 6, 200, 7, -1 }, + { 8, 10, 6, 4 }, + { 6, 200, 4, -1 }, + { 4, 200, 0, -1 }, + { 3, 0, 200, -1 }, + { 3, 200, 10, -1 }, + { 10, 200, 6, -1 }, + { 0, 200, 8, -1 }, + { 4, 200, 9, -1 }, + { 1, 200, 0, -1 }, + { 9, 200, 1, -1 }, + { 8, 200, 10, -1 }, + { 6, 200, 4, -1 }, + { 6, 10, 200, -1 }, + { 3, 200, 10, -1 }, + { 1, 200, 3, -1 }, + { 9, 200, 1, -1 }, + { 4, 200, 9, -1 }, + { 6, 200, 4, -1 }, + { 6, 10, 200, -1 }, + { 10, 200, 2, -1 }, + { 11, 200, 6, -1 }, + { 2, 200, 1, -1 }, + { 11, 1, 200, -1 }, + { 8, 200, 10, -1 }, + { 6, 200, 4, -1 }, + { 4, 200, 8, -1 }, + { 3, 10, 2, -1 }, + { 0, 200, 1, -1 }, + { 6, 200, 4, -1 }, + { 4, 200, 0, -1 }, + { 11, 200, 6, -1 }, + { 1, 200, 11, -1 }, + { 4, 6, 11, 9 }, + { 8, 0, 2, 10 }, + { 3, 10, 2, -1 }, + { 11, 9, 4, 6 }, + { 6, 200, 4, -1 }, + { 2, 200, 6, -1 }, + { 3, 200, 2, -1 }, + { 8, 200, 3, -1 }, + { 4, 200, 8, -1 }, + { 0, 4, 6, 2 }, + { 3, 0, 8, -1 }, + { 1, 200, 2, -1 }, + { 6, 200, 4, -1 }, + { 2, 200, 6, -1 }, + { 4, 200, 9, -1 }, + { 1, 9, 200, -1 }, + { 4, 200, 9, -1 }, + { 6, 200, 4, -1 }, + { 2, 200, 6, -1 }, + { 1, 200, 2, -1 }, + { 9, 200, 1, -1 }, + { 8, 200, 3, -1 }, + { 3, 200, 1, -1 }, + { 1, 200, 11, -1 }, + { 11, 200, 6, -1 }, + { 6, 200, 4, -1 }, + { 4, 200, 8, -1 }, + { 11, 200, 6, -1 }, + { 6, 200, 4, -1 }, + { 4, 200, 0, -1 }, + { 0, 200, 1, -1 }, + { 11, 1, 200, -1 }, + { 3, 0, 8, -1 }, + { 9, 4, 6, 11 }, + { 4, 6, 11, 9 }, + { 4, 200, 7, -1 }, + { 6, 200, 5, -1 }, + { 5, 200, 9, -1 }, + { 9, 200, 4, -1 }, + { 6, 10, 200, -1 }, + { 7, 200, 10, -1 }, + { 8, 4, 7, -1 }, + { 3, 0, 10, -1 }, + { 6, 9, 5, -1 }, + { 0, 9, 6, 10 }, + { 4, 200, 7, -1 }, + { 6, 200, 5, -1 }, + { 7, 200, 10, -1 }, + { 6, 10, 200, -1 }, + { 0, 200, 4, -1 }, + { 5, 200, 1, -1 }, + { 1, 200, 0, -1 }, + { 8, 4, 7, -1 }, + { 3, 200, 10, -1 }, + { 5, 200, 1, -1 }, + { 1, 200, 3, -1 }, + { 6, 200, 5, -1 }, + { 10, 200, 6, -1 }, + { 5, 11, 6, -1 }, + { 1, 4, 9, -1 }, + { 10, 7, 2, -1 }, + { 4, 1, 2, 7 }, + { 1, 9, 0, -1 }, + { 6, 5, 11, -1 }, + { 3, 10, 2, -1 }, + { 4, 7, 8, -1 }, + { 5, 11, 6, -1 }, + { 4, 200, 7, -1 }, + { 2, 200, 0, -1 }, + { 0, 200, 4, -1 }, + { 10, 200, 2, -1 }, + { 7, 200, 10, -1 }, + { 7, 8, 4, -1 }, + { 2, 3, 10, -1 }, + { 11, 6, 5, -1 }, + { 4, 200, 7, -1 }, + { 6, 200, 5, -1 }, + { 9, 200, 4, -1 }, + { 5, 200, 9, -1 }, + { 7, 200, 3, -1 }, + { 2, 200, 6, -1 }, + { 2, 3, 200, -1 }, + { 8, 4, 7, -1 }, + { 9, 200, 0, -1 }, + { 2, 200, 6, -1 }, + { 0, 200, 2, -1 }, + { 6, 200, 5, -1 }, + { 9, 5, 200, -1 }, + { 2, 1, 5, 6 }, + { 3, 7, 4, 0 }, + { 8, 4, 7, -1 }, + { 5, 6, 2, 1 }, + { 11, 6, 5, -1 }, + { 1, 200, 9, -1 }, + { 7, 200, 3, -1 }, + { 3, 200, 1, -1 }, + { 4, 200, 7, -1 }, + { 9, 200, 4, -1 }, + { 9, 0, 1, -1 }, + { 7, 8, 4, -1 }, + { 6, 5, 11, -1 }, + { 11, 6, 5, -1 }, + { 7, 4, 0, 3 }, + { 6, 5, 11, -1 }, + { 7, 8, 4, -1 }, + { 8, 200, 10, -1 }, + { 9, 200, 8, -1 }, + { 5, 200, 9, -1 }, + { 6, 200, 5, -1 }, + { 10, 200, 6, -1 }, + { 3, 0, 10, -1 }, + { 6, 9, 5, -1 }, + { 10, 0, 9, 6 }, + { 0, 200, 8, -1 }, + { 8, 200, 10, -1 }, + { 10, 200, 6, -1 }, + { 6, 200, 5, -1 }, + { 5, 200, 1, -1 }, + { 1, 200, 0, -1 }, + { 6, 200, 5, -1 }, + { 5, 200, 1, -1 }, + { 1, 200, 3, -1 }, + { 3, 200, 10, -1 }, + { 6, 10, 200, -1 }, + { 5, 11, 6, -1 }, + { 1, 200, 9, -1 }, + { 8, 200, 10, -1 }, + { 9, 200, 8, -1 }, + { 10, 200, 2, -1 }, + { 1, 2, 200, -1 }, + { 1, 9, 0, -1 }, + { 10, 2, 3, -1 }, + { 6, 5, 11, -1 }, + { 5, 11, 6, -1 }, + { 10, 8, 0, 2 }, + { 6, 5, 11, -1 }, + { 10, 2, 3, -1 }, + { 8, 200, 3, -1 }, + { 9, 200, 8, -1 }, + { 5, 200, 9, -1 }, + { 6, 200, 5, -1 }, + { 2, 200, 6, -1 }, + { 2, 3, 200, -1 }, + { 6, 200, 5, -1 }, + { 2, 200, 6, -1 }, + { 0, 200, 2, -1 }, + { 9, 200, 0, -1 }, + { 5, 200, 9, -1 }, + { 8, 3, 0, -1 }, + { 1, 5, 6, 2 }, + { 2, 1, 5, 6 }, + { 6, 5, 11, -1 }, + { 1, 3, 8, 9 }, + { 11, 6, 5, -1 }, + { 1, 9, 0, -1 }, + { 3, 0, 8, -1 }, + { 11, 6, 5, -1 }, + { 5, 11, 6, -1 }, + { 5, 7, 10, 11 }, + { 7, 200, 8, -1 }, + { 3, 200, 10, -1 }, + { 8, 200, 0, -1 }, + { 3, 0, 200, -1 }, + { 5, 200, 7, -1 }, + { 10, 200, 11, -1 }, + { 11, 200, 5, -1 }, + { 9, 200, 5, -1 }, + { 11, 200, 1, -1 }, + { 0, 200, 9, -1 }, + { 1, 200, 0, -1 }, + { 5, 200, 7, -1 }, + { 10, 200, 11, -1 }, + { 10, 7, 200, -1 }, + { 8, 7, 5, 9 }, + { 3, 1, 11, 10 }, + { 1, 200, 5, -1 }, + { 5, 200, 7, -1 }, + { 10, 7, 200, -1 }, + { 10, 200, 2, -1 }, + { 2, 200, 1, -1 }, + { 10, 2, 3, -1 }, + { 7, 200, 8, -1 }, + { 1, 200, 5, -1 }, + { 5, 200, 7, -1 }, + { 0, 200, 1, -1 }, + { 8, 200, 0, -1 }, + { 10, 200, 2, -1 }, + { 2, 200, 0, -1 }, + { 0, 200, 9, -1 }, + { 9, 200, 5, -1 }, + { 5, 200, 7, -1 }, + { 7, 200, 10, -1 }, + { 2, 3, 10, -1 }, + { 7, 5, 9, 8 }, + { 5, 200, 7, -1 }, + { 7, 200, 3, -1 }, + { 2, 3, 200, -1 }, + { 2, 200, 11, -1 }, + { 11, 200, 5, -1 }, + { 2, 200, 11, -1 }, + { 0, 200, 2, -1 }, + { 8, 200, 0, -1 }, + { 7, 200, 8, -1 }, + { 5, 200, 7, -1 }, + { 5, 11, 200, -1 }, + { 2, 11, 1, -1 }, + { 3, 200, 0, -1 }, + { 5, 200, 7, -1 }, + { 7, 200, 3, -1 }, + { 9, 200, 5, -1 }, + { 0, 200, 9, -1 }, + { 2, 11, 1, -1 }, + { 5, 9, 8, 7 }, + { 3, 7, 5, 1 }, + { 0, 200, 1, -1 }, + { 1, 200, 5, -1 }, + { 5, 200, 7, -1 }, + { 7, 200, 8, -1 }, + { 0, 8, 200, -1 }, + { 9, 200, 5, -1 }, + { 5, 200, 7, -1 }, + { 7, 200, 3, -1 }, + { 3, 200, 0, -1 }, + { 9, 0, 200, -1 }, + { 8, 7, 5, 9 }, + { 10, 200, 11, -1 }, + { 8, 200, 10, -1 }, + { 4, 200, 8, -1 }, + { 5, 200, 4, -1 }, + { 11, 200, 5, -1 }, + { 5, 200, 4, -1 }, + { 4, 200, 0, -1 }, + { 0, 200, 3, -1 }, + { 3, 200, 10, -1 }, + { 10, 200, 11, -1 }, + { 11, 200, 5, -1 }, + { 4, 9, 5, -1 }, + { 0, 200, 8, -1 }, + { 10, 200, 11, -1 }, + { 8, 200, 10, -1 }, + { 11, 200, 1, -1 }, + { 0, 1, 200, -1 }, + { 4, 9, 5, -1 }, + { 11, 10, 3, 1 }, + { 10, 200, 2, -1 }, + { 8, 200, 10, -1 }, + { 4, 200, 8, -1 }, + { 5, 200, 4, -1 }, + { 1, 200, 5, -1 }, + { 1, 2, 200, -1 }, + { 10, 2, 3, -1 }, + { 1, 0, 4, 5 }, + { 5, 4, 9, -1 }, + { 8, 0, 2, 10 }, + { 9, 5, 4, -1 }, + { 2, 3, 10, -1 }, + { 8, 4, 3, -1 }, + { 2, 5, 11, -1 }, + { 3, 4, 5, 2 }, + { 2, 200, 11, -1 }, + { 0, 200, 2, -1 }, + { 4, 200, 0, -1 }, + { 5, 200, 4, -1 }, + { 11, 200, 5, -1 }, + { 9, 5, 4, -1 }, + { 3, 0, 8, -1 }, + { 2, 11, 1, -1 }, + { 9, 5, 4, -1 }, + { 1, 2, 11, -1 }, + { 5, 200, 4, -1 }, + { 1, 200, 5, -1 }, + { 3, 200, 1, -1 }, + { 8, 200, 3, -1 }, + { 4, 200, 8, -1 }, + { 0, 4, 5, 1 }, + { 4, 9, 5, -1 }, + { 8, 3, 0, -1 }, + { 9, 5, 4, -1 }, + { 11, 200, 9, -1 }, + { 10, 200, 11, -1 }, + { 7, 200, 10, -1 }, + { 4, 200, 7, -1 }, + { 9, 200, 4, -1 }, + { 7, 8, 4, -1 }, + { 3, 200, 10, -1 }, + { 11, 200, 9, -1 }, + { 10, 200, 11, -1 }, + { 9, 200, 0, -1 }, + { 3, 0, 200, -1 }, + { 4, 200, 7, -1 }, + { 0, 200, 4, -1 }, + { 1, 200, 0, -1 }, + { 11, 200, 1, -1 }, + { 10, 200, 11, -1 }, + { 10, 7, 200, -1 }, + { 4, 7, 8, -1 }, + { 10, 3, 1, 11 }, + { 1, 4, 9, -1 }, + { 10, 7, 2, -1 }, + { 1, 2, 7, 4 }, + { 8, 4, 7, -1 }, + { 1, 9, 0, -1 }, + { 2, 3, 10, -1 }, + { 10, 200, 2, -1 }, + { 2, 200, 0, -1 }, + { 0, 200, 4, -1 }, + { 4, 200, 7, -1 }, + { 10, 7, 200, -1 }, + { 8, 4, 7, -1 }, + { 3, 10, 2, -1 }, + { 4, 200, 7, -1 }, + { 7, 200, 3, -1 }, + { 3, 200, 2, -1 }, + { 2, 200, 11, -1 }, + { 11, 200, 9, -1 }, + { 9, 200, 4, -1 }, + { 7, 8, 4, -1 }, + { 9, 11, 2, 0 }, + { 11, 1, 2, -1 }, + { 3, 7, 4, 0 }, + { 1, 2, 11, -1 }, + { 4, 7, 8, -1 }, + { 4, 200, 7, -1 }, + { 7, 200, 3, -1 }, + { 3, 200, 1, -1 }, + { 1, 200, 9, -1 }, + { 4, 9, 200, -1 }, + { 0, 1, 9, -1 }, + { 8, 4, 7, -1 }, + { 0, 3, 7, 4 }, + { 7, 8, 4, -1 }, + { 8, 9, 11, 10 }, + { 9, 200, 0, -1 }, + { 11, 200, 9, -1 }, + { 10, 200, 11, -1 }, + { 3, 200, 10, -1 }, + { 0, 200, 3, -1 }, + { 11, 200, 1, -1 }, + { 10, 200, 11, -1 }, + { 8, 200, 10, -1 }, + { 0, 200, 8, -1 }, + { 1, 200, 0, -1 }, + { 3, 1, 11, 10 }, + { 10, 200, 2, -1 }, + { 8, 200, 10, -1 }, + { 9, 200, 8, -1 }, + { 1, 200, 9, -1 }, + { 2, 200, 1, -1 }, + { 0, 1, 9, -1 }, + { 3, 10, 2, -1 }, + { 0, 2, 10, 8 }, + { 10, 2, 3, -1 }, + { 2, 200, 11, -1 }, + { 11, 200, 9, -1 }, + { 9, 200, 8, -1 }, + { 8, 200, 3, -1 }, + { 2, 3, 200, -1 }, + { 0, 9, 11, 2 }, + { 2, 11, 1, -1 }, + { 3, 0, 8, -1 }, + { 1, 2, 11, -1 }, + { 8, 9, 1, 3 }, + { 1, 9, 0, -1 }, + { 3, 0, 8, -1 } +}; + +// Special points (e.g. centroid): per-case definition streams +constexpr int special_point_count_interface[256] = { 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 }; +constexpr int special_point_offset_interface[257] = { 0, 0, 0, 0, 0, 0, 3, 3, 9, 9, 9, 12, 18, 18, 24, 30, 30, 30, 30, 33, 39, 39, 44, 49, 56, 59, 65, 65, 65, 70, 77, 83, 89, 89, 92, 92, 98, 101, 101, 107, 107, 107, 112, 117, 124, 129, 135, 142, 148, 148, 154, 160, 160, 165, 171, 178, 184, 189, 196, 202, 208, 208, 208, 208, 208, 208, 208, 211, 216, 216, 221, 227, 234, 237, 242, 242, 248, 254, 261, 261, 267, 270, 275, 275, 281, 286, 286, 292, 292, 292, 298, 298, 298, 304, 304, 304, 304, 304, 309, 315, 322, 328, 334, 334, 340, 345, 345, 351, 351, 358, 358, 364, 364, 370, 377, 377, 383, 390, 390, 396, 396, 402, 402, 402, 402, 402, 402, 402, 402, 402, 405, 405, 410, 413, 413, 418, 424, 424, 430, 435, 442, 448, 448, 455, 461, 461, 467, 472, 479, 484, 490, 490, 490, 496, 496, 502, 508, 515, 521, 521, 521, 524, 524, 529, 535, 535, 535, 541, 541, 546, 552, 552, 552, 558, 558, 558, 558, 564, 564, 571, 577, 583, 583, 583, 583, 590, 596, 596, 596, 596, 596, 596, 596, 596, 601, 606, 606, 612, 618, 625, 625, 631, 638, 644, 644, 644, 650, 656, 656, 662, 669, 675, 675, 682, 682, 682, 682, 682, 688, 688, 688, 694, 694, 694, 694, 700, 706, 713, 713, 713, 713, 719, 719, 726, 726, 726, 726, 732, 732, 732, 732, 732, 738, 744, 744, 750, 750, 750, 750, 756, 756, 756, 756, 756, 756, 756, 756 }; +constexpr int special_point_data_interface[756] = { 2, 8, 11, 5, 8, 9, 3, 2, 11, 2, 10, 9, 5, 9, 8, 1, 2, 10, 5, 8, 10, 0, 1, 11, 5, 10, 11, 3, 0, 9, 2, 7, 1, 5, 1, 3, 9, 4, 7, 4, 4, 7, 11, 11, 4, 11, 2, 7, 7, 6, 3, 2, 11, 9, 4, 7, 2, 2, 4, 5, 4, 0, 7, 10, 2, 4, 11, 1, 4, 4, 6, 0, 1, 11, 10, 7, 4, 5, 11, 9, 10, 7, 4, 5, 9, 11, 10, 4, 7, 2, 3, 5, 5, 3, 1, 8, 4, 5, 2, 2, 4, 5, 4, 0, 5, 11, 2, 4, 2, 10, 5, 5, 4, 5, 4, 10, 10, 6, 8, 4, 5, 1, 2, 10, 4, 10, 3, 4, 4, 5, 10, 11, 8, 4, 5, 6, 0, 3, 10, 11, 5, 4, 5, 11, 10, 8, 5, 4, 5, 3, 7, 0, 9, 5, 5, 7, 5, 8, 0, 1, 4, 7, 8, 2, 2, 5, 7, 5, 3, 2, 11, 6, 0, 8, 7, 5, 11, 2, 5, 5, 7, 3, 11, 2, 4, 5, 9, 2, 2, 6, 0, 9, 5, 7, 10, 2, 5, 5, 1, 7, 10, 2, 5, 1, 5, 7, 2, 10, 2, 0, 6, 4, 8, 3, 6, 6, 4, 6, 5, 8, 8, 5, 0, 2, 9, 5, 6, 6, 9, 5, 6, 2, 3, 8, 2, 3, 5, 4, 0, 8, 5, 5, 5, 8, 10, 9, 5, 6, 5, 3, 1, 10, 6, 5, 6, 10, 6, 5, 1, 0, 8, 5, 10, 8, 9, 6, 5, 2, 8, 11, 4, 0, 3, 11, 11, 5, 3, 7, 1, 11, 6, 4, 2, 1, 8, 8, 5, 2, 6, 0, 8, 7, 5, 0, 2, 4, 5, 11, 5, 1, 5, 3, 8, 4, 4, 6, 11, 3, 3, 5, 0, 4, 1, 11, 6, 6, 1, 11, 6, 4, 8, 3, 5, 2, 6, 1, 9, 4, 5, 6, 4, 2, 3, 8, 5, 4, 6, 2, 8, 3, 4, 4, 9, 3, 3, 5, 4, 6, 0, 3, 10, 6, 1, 9, 4, 6, 10, 3, 5, 6, 4, 0, 10, 3, 5, 8, 9, 7, 6, 11, 6, 7, 6, 11, 9, 0, 3, 5, 7, 3, 1, 6, 11, 6, 9, 1, 2, 6, 7, 8, 5, 6, 2, 0, 7, 8, 5, 9, 11, 8, 3, 2, 2, 0, 6, 4, 9, 1, 6, 6, 2, 7, 1, 4, 9, 0, 7, 7, 5, 9, 11, 8, 7, 6, 5, 0, 2, 8, 7, 6, 4, 6, 7, 9, 9, 6, 8, 7, 6, 2, 1, 9, 5, 1, 3, 11, 6, 7, 6, 3, 0, 9, 11, 6, 7, 5, 11, 9, 8, 6, 7, 5, 0, 4, 3, 10, 6, 4, 6, 10, 1, 1, 6, 3, 10, 6, 4, 9, 1, 4, 4, 8, 1, 1, 5, 4, 6, 0, 1, 11, 5, 2, 6, 3, 8, 4, 5, 6, 4, 2, 1, 9, 5, 4, 6, 2, 9, 1, 6, 3, 8, 4, 6, 11, 1, 5, 6, 4, 0, 11, 1, 2, 10, 9, 4, 1, 0, 10, 10, 5, 1, 5, 3, 10, 6, 5, 0, 2, 4, 7, 10, 4, 2, 3, 9, 9, 5, 2, 6, 0, 9, 5, 5, 3, 7, 1, 9, 4, 5, 9, 8, 5, 6, 10, 6, 8, 0, 1, 5, 6, 10, 5, 5, 1, 3, 6, 10, 5, 8, 10, 9, 1, 2, 6, 8, 3, 2, 6, 5, 9, 5, 6, 2, 0, 5, 9, 4, 11, 5, 0, 0, 4, 10, 7, 0, 0, 5, 7, 5, 10, 2, 1, 5, 5, 1, 7, 8, 0, 6, 2, 10, 7, 5, 9, 0, 5, 3, 7, 2, 11, 5, 6, 2, 11, 5, 7, 8, 0, 5, 7, 5, 3, 0, 9, 5, 1, 5, 7, 0, 8, 5, 5, 7, 3, 9, 0, 5, 8, 10, 4, 5, 11, 6, 4, 5, 11, 10, 3, 0, 5, 10, 11, 8, 0, 1, 6, 10, 2, 1, 5, 4, 8, 5, 2, 0, 4, 11, 5, 5, 5, 1, 3, 4, 8, 5, 10, 11, 7, 4, 9, 5, 11, 9, 10, 3, 0, 6, 4, 7, 10, 11, 1, 0, 5, 2, 0, 4, 10, 7, 6, 7, 4, 9, 11, 2, 3, 5, 7, 3, 1, 4, 9, 5, 9, 11, 10, 0, 3, 5, 11, 10, 8, 1, 0, 5, 10, 8, 9, 2, 1, 5, 11, 9, 8, 2, 3 }; + +} // namespace cutcells::cell::hexahedron + +#endif // CUT_CELLS_HEXAHEDRON_INTERFACE_TABLES_H \ No newline at end of file diff --git a/cpp/src/generated/cut_hexahedron_outside_tables.h b/cpp/src/generated/cut_hexahedron_outside_tables.h new file mode 100644 index 0000000..c31412d --- /dev/null +++ b/cpp/src/generated/cut_hexahedron_outside_tables.h @@ -0,0 +1,1591 @@ +#ifndef CUT_CELLS_HEXAHEDRON_OUTSIDE_TABLES_H +#define CUT_CELLS_HEXAHEDRON_OUTSIDE_TABLES_H + +// ----------------------------------------------------------------------------- +// This file is generated by CutCells tablegen. +// +// It contains case tables derived from VTK's vtkTableBasedClipCases.h +// (Visualization Toolkit, TableBasedClip). +// +// VTK ref: master +// VTK header path override: (none) +// +// VTK is licensed under the BSD 3-Clause License. +// See third_party/VTK-Copyright.txt in this repository. +// ----------------------------------------------------------------------------- + +#include "cell_types.h" + +namespace cutcells::cell::hexahedron { + +// Number of subcells produced for each case (outside volume) +constexpr int num_subcells_outside[256] = { 1, 8, 8, 2, 8, 5, 2, 8, 8, 2, 5, 8, 2, 8, 8, 1, 8, 2, 5, 8, 6, 10, 10, 8, 5, 8, 5, 5, 10, 8, 8, 6, 8, 5, 2, 8, 5, 5, 8, 5, 6, 10, 10, 8, 10, 8, 8, 6, 2, 8, 8, 1, 10, 8, 8, 6, 10, 8, 8, 6, 2, 7, 7, 1, 8, 6, 5, 10, 2, 10, 8, 8, 5, 10, 5, 8, 8, 8, 5, 6, 5, 10, 5, 8, 10, 2, 8, 7, 5, 8, 5, 5, 8, 7, 5, 6, 2, 10, 8, 8, 8, 8, 1, 6, 10, 2, 8, 7, 8, 7, 6, 1, 8, 8, 5, 6, 8, 7, 6, 1, 8, 7, 5, 6, 7, 2, 6, 1, 8, 5, 6, 10, 5, 5, 10, 8, 2, 8, 10, 8, 8, 5, 8, 6, 2, 8, 10, 8, 10, 8, 2, 7, 8, 1, 8, 6, 8, 6, 7, 1, 5, 5, 10, 8, 5, 5, 8, 5, 10, 8, 2, 7, 8, 5, 7, 6, 8, 5, 8, 6, 8, 5, 7, 6, 8, 6, 7, 1, 7, 6, 2, 1, 2, 10, 10, 2, 8, 8, 8, 7, 8, 8, 8, 7, 1, 6, 6, 1, 8, 8, 8, 7, 8, 7, 7, 2, 5, 6, 5, 6, 6, 1, 6, 1, 8, 8, 8, 7, 5, 5, 6, 6, 8, 7, 7, 2, 6, 6, 1, 1, 1, 6, 6, 1, 6, 6, 1, 1, 6, 1, 6, 1, 1, 1, 1, 0 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_outside[257] = { 0, 1, 9, 17, 19, 27, 32, 34, 42, 50, 52, 57, 65, 67, 75, 83, 84, 92, 94, 99, 107, 113, 123, 133, 141, 146, 154, 159, 164, 174, 182, 190, 196, 204, 209, 211, 219, 224, 229, 237, 242, 248, 258, 268, 276, 286, 294, 302, 308, 310, 318, 326, 327, 337, 345, 353, 359, 369, 377, 385, 391, 393, 400, 407, 408, 416, 422, 427, 437, 439, 449, 457, 465, 470, 480, 485, 493, 501, 509, 514, 520, 525, 535, 540, 548, 558, 560, 568, 575, 580, 588, 593, 598, 606, 613, 618, 624, 626, 636, 644, 652, 660, 668, 669, 675, 685, 687, 695, 702, 710, 717, 723, 724, 732, 740, 745, 751, 759, 766, 772, 773, 781, 788, 793, 799, 806, 808, 814, 815, 823, 828, 834, 844, 849, 854, 864, 872, 874, 882, 892, 900, 908, 913, 921, 927, 929, 937, 947, 955, 965, 973, 975, 982, 990, 991, 999, 1005, 1013, 1019, 1026, 1027, 1032, 1037, 1047, 1055, 1060, 1065, 1073, 1078, 1088, 1096, 1098, 1105, 1113, 1118, 1125, 1131, 1139, 1144, 1152, 1158, 1166, 1171, 1178, 1184, 1192, 1198, 1205, 1206, 1213, 1219, 1221, 1222, 1224, 1234, 1244, 1246, 1254, 1262, 1270, 1277, 1285, 1293, 1301, 1308, 1309, 1315, 1321, 1322, 1330, 1338, 1346, 1353, 1361, 1368, 1375, 1377, 1382, 1388, 1393, 1399, 1405, 1406, 1412, 1413, 1421, 1429, 1437, 1444, 1449, 1454, 1460, 1466, 1474, 1481, 1488, 1490, 1496, 1502, 1503, 1504, 1505, 1511, 1517, 1518, 1524, 1530, 1531, 1532, 1538, 1539, 1545, 1546, 1547, 1548, 1549, 1549 }; + +// Cell types for outside subcells +constexpr type subcell_type_outside[1549] = { cell::type::hexahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::hexahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::hexahedron, cell::type::hexahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::hexahedron, cell::type::hexahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::hexahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::hexahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::hexahedron, cell::type::hexahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::hexahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron }; + +// Subcell vertices (max 8 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, 100..199 = 100+vertex_id, >=200 = 200+special_point_id +constexpr int subcell_verts_outside[1549][8] = { + { 100, 101, 102, 103, 104, 105, 106, 107 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 103, 104, 101, 200, -1, -1, -1, -1 }, + { 102, 101, 105, 106, 200, -1, -1, -1 }, + { 101, 104, 105, 200, -1, -1, -1, -1 }, + { 107, 106, 105, 104, 200, -1, -1, -1 }, + { 107, 104, 103, 200, -1, -1, -1, -1 }, + { 107, 103, 102, 106, 200, -1, -1, -1 }, + { 103, 101, 102, 200, -1, -1, -1, -1 }, + { 1, 9, 0, 102, 105, 100, -1, -1 }, + { 102, 100, 105, 200, -1, -1, -1, -1 }, + { 106, 105, 104, 107, 200, -1, -1, -1 }, + { 105, 100, 104, 200, -1, -1, -1, -1 }, + { 103, 107, 104, 100, 200, -1, -1, -1 }, + { 103, 100, 102, 200, -1, -1, -1, -1 }, + { 103, 102, 106, 107, 200, -1, -1, -1 }, + { 102, 105, 106, 200, -1, -1, -1, -1 }, + { 104, 103, 102, 105, 8, 3, 1, 9 }, + { 106, 105, 102, 107, 104, 103, -1, -1 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 101, 106, 103, 200, -1, -1, -1, -1 }, + { 105, 104, 107, 106, 200, -1, -1, -1 }, + { 106, 107, 103, 200, -1, -1, -1, -1 }, + { 100, 103, 107, 104, 200, -1, -1, -1 }, + { 100, 101, 103, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 101, 200, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 103, 101, 106, 2, 1, 11, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 107, 106, 105, 104, 103, -1, -1, -1 }, + { 101, 104, 105, 103, -1, -1, -1, -1 }, + { 101, 105, 106, 103, -1, -1, -1, -1 }, + { 0, 9, 11, 2, 100, 105, 106, 103 }, + { 104, 100, 105, 107, 103, 106, -1, -1 }, + { 107, 106, 105, 104, 200, -1, -1, -1 }, + { 104, 103, 107, 200, -1, -1, -1, -1 }, + { 103, 106, 107, 200, -1, -1, -1, -1 }, + { 103, 2, 11, 106, 200, -1, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 8, 3, 103, 104, 200, -1, -1, -1 }, + { 2, 103, 3, 200, -1, -1, -1, -1 }, + { 10, 2, 3, 107, 102, 100, -1, -1 }, + { 107, 100, 102, 200, -1, -1, -1, -1 }, + { 106, 102, 101, 105, 200, -1, -1, -1 }, + { 102, 100, 101, 200, -1, -1, -1, -1 }, + { 104, 105, 101, 100, 200, -1, -1, -1 }, + { 104, 100, 107, 200, -1, -1, -1, -1 }, + { 104, 107, 106, 105, 200, -1, -1, -1 }, + { 107, 102, 106, 200, -1, -1, -1, -1 }, + { 101, 104, 107, 102, 0, 8, 10, 2 }, + { 106, 102, 107, 105, 101, 104, -1, -1 }, + { 0, 1, 9, 100, 102, 105, -1, -1 }, + { 100, 102, 107, 3, 2, 10, -1, -1 }, + { 104, 107, 106, 105, 100, -1, -1, -1 }, + { 102, 106, 107, 100, -1, -1, -1, -1 }, + { 102, 105, 106, 100, -1, -1, -1, -1 }, + { 106, 105, 104, 107, 200, -1, -1, -1 }, + { 105, 106, 102, 200, -1, -1, -1, -1 }, + { 102, 106, 107, 200, -1, -1, -1, -1 }, + { 102, 107, 10, 2, 200, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 9, 105, 102, 1, 200, -1, -1, -1 }, + { 2, 1, 102, 200, -1, -1, -1, -1 }, + { 100, 107, 106, 101, 3, 10, 11, 1 }, + { 105, 101, 106, 104, 100, 107, -1, -1 }, + { 105, 104, 107, 106, 200, -1, -1, -1 }, + { 104, 105, 101, 200, -1, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 101, 106, 11, 1, 200, -1, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 8, 104, 101, 0, 200, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 104, 107, 106, 105, 200, -1, -1, -1 }, + { 107, 104, 100, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 100, 105, 9, 0, 200, -1, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 10, 107, 100, 3, 200, -1, -1, -1 }, + { 0, 3, 100, 200, -1, -1, -1, -1 }, + { 8, 9, 11, 10, 104, 105, 106, 107 }, + { 107, 105, 100, 7, 4, 8, -1, -1 }, + { 107, 105, 100, 200, -1, -1, -1, -1 }, + { 106, 102, 101, 105, 200, -1, -1, -1 }, + { 105, 101, 100, 200, -1, -1, -1, -1 }, + { 103, 100, 101, 102, 200, -1, -1, -1 }, + { 103, 107, 100, 200, -1, -1, -1, -1 }, + { 103, 102, 106, 107, 200, -1, -1, -1 }, + { 107, 106, 105, 200, -1, -1, -1, -1 }, + { 0, 3, 7, 4, 101, 103, 107, 105 }, + { 102, 101, 103, 106, 105, 107, -1, -1 }, + { 100, 105, 102, 0, 9, 1, -1, -1 }, + { 8, 4, 7, 100, 105, 107, -1, -1 }, + { 103, 102, 106, 107, 100, -1, -1, -1 }, + { 105, 107, 106, 100, -1, -1, -1, -1 }, + { 105, 106, 102, 100, -1, -1, -1, -1 }, + { 106, 107, 103, 102, 200, -1, -1, -1 }, + { 102, 105, 106, 200, -1, -1, -1, -1 }, + { 105, 107, 106, 200, -1, -1, -1, -1 }, + { 105, 4, 7, 107, 200, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 1, 9, 105, 102, 200, -1, -1, -1 }, + { 4, 105, 9, 200, -1, -1, -1, -1 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 105, 100, 107, 4, 8, 7, -1, -1 }, + { 107, 100, 103, 105, -1, -1, -1, -1 }, + { 105, 106, 101, 103, -1, -1, -1, -1 }, + { 101, 100, 105, 103, -1, -1, -1, -1 }, + { 105, 107, 106, 103, -1, -1, -1, -1 }, + { 106, 103, 101, 11, 2, 1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 107, 103, 106, 200, -1, -1, -1, -1 }, + { 107, 106, 105, 200, -1, -1, -1, -1 }, + { 4, 7, 107, 105, 200, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 105, 106, 101, 200, -1, -1, -1, -1 }, + { 3, 7, 4, 0, 200, -1, -1, -1 }, + { 101, 106, 103, 200, -1, -1, -1, -1 }, + { 3, 0, 101, 103, 200, -1, -1, -1 }, + { 107, 105, 100, 7, 4, 8, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 106, 105, 107, 200, -1, -1, -1, -1 }, + { 106, 107, 103, 200, -1, -1, -1, -1 }, + { 2, 11, 106, 103, 200, -1, -1, -1 }, + { 0, 2, 103, 100, 200, -1, -1, -1 }, + { 103, 107, 100, 200, -1, -1, -1, -1 }, + { 9, 11, 2, 0, 200, -1, -1, -1 }, + { 100, 107, 105, 200, -1, -1, -1, -1 }, + { 9, 0, 100, 105, 200, -1, -1, -1 }, + { 107, 106, 105, 200, -1, -1, -1, -1 }, + { 7, 107, 105, 4, 200, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 103, 106, 107, 200, -1, -1, -1, -1 }, + { 103, 3, 2, 200, -1, -1, -1, -1 }, + { 103, 2, 11, 106, 200, -1, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 9, 4, 105, 200, -1, -1, -1, -1 }, + { 100, 107, 105, 8, 7, 4, -1, -1 }, + { 3, 10, 2, 100, 107, 102, -1, -1 }, + { 101, 105, 106, 102, 100, -1, -1, -1 }, + { 107, 102, 106, 100, -1, -1, -1, -1 }, + { 107, 106, 105, 100, -1, -1, -1, -1 }, + { 106, 102, 101, 105, 200, -1, -1, -1 }, + { 105, 107, 106, 200, -1, -1, -1, -1 }, + { 107, 102, 106, 200, -1, -1, -1, -1 }, + { 107, 10, 2, 102, 200, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 4, 7, 107, 105, 200, -1, -1, -1 }, + { 10, 107, 7, 200, -1, -1, -1, -1 }, + { 8, 4, 7, 100, 105, 107, -1, -1 }, + { 102, 100, 105, 1, 0, 9, -1, -1 }, + { 2, 3, 10, 102, 100, 107, -1, -1 }, + { 100, 107, 105, 102, -1, -1, -1, -1 }, + { 102, 106, 107, 105, -1, -1, -1, -1 }, + { 106, 105, 107, 102, -1, -1, -1, -1 }, + { 1, 9, 105, 102, 4, -1, -1, -1 }, + { 2, 102, 107, 10, 7, -1, -1, -1 }, + { 105, 4, 7, 107, 102, -1, -1, -1 }, + { 1, 2, 7, 4, 102, -1, -1, -1 }, + { 4, 7, 8, 105, 107, 100, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 106, 105, 107, 200, -1, -1, -1, -1 }, + { 106, 101, 105, 200, -1, -1, -1, -1 }, + { 1, 101, 106, 11, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 101, 100, 105, 200, -1, -1, -1, -1 }, + { 10, 3, 1, 11, 200, -1, -1, -1 }, + { 100, 107, 105, 200, -1, -1, -1, -1 }, + { 10, 107, 100, 3, 200, -1, -1, -1 }, + { 105, 107, 106, 200, -1, -1, -1, -1 }, + { 4, 7, 107, 105, 200, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 101, 1, 0, 200, -1, -1, -1, -1 }, + { 101, 106, 11, 1, 200, -1, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 10, 107, 7, 200, -1, -1, -1, -1 }, + { 107, 105, 100, 7, 4, 8, -1, -1 }, + { 105, 100, 107, 200, -1, -1, -1, -1 }, + { 107, 100, 3, 10, 200, -1, -1, -1 }, + { 106, 105, 107, 200, -1, -1, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 100, 105, 9, 0, 200, -1, -1, -1 }, + { 3, 100, 0, 200, -1, -1, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 10, 11, 106, 107, 200, -1, -1, -1 }, + { 7, 10, 107, 200, -1, -1, -1, -1 }, + { 107, 106, 105, 200, -1, -1, -1, -1 }, + { 7, 107, 105, 4, 200, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 101, 104, 106, 200, -1, -1, -1, -1 }, + { 102, 106, 107, 103, 200, -1, -1, -1 }, + { 106, 104, 107, 200, -1, -1, -1, -1 }, + { 100, 103, 107, 104, 200, -1, -1, -1 }, + { 100, 104, 101, 200, -1, -1, -1, -1 }, + { 100, 101, 102, 103, 200, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 4, 9, 5, 104, 101, 106, -1, -1 }, + { 104, 101, 103, 8, 0, 3, -1, -1 }, + { 107, 103, 102, 106, 104, -1, -1, -1 }, + { 101, 102, 103, 104, -1, -1, -1, -1 }, + { 101, 106, 102, 104, -1, -1, -1, -1 }, + { 100, 102, 106, 104, 0, 1, 5, 4 }, + { 107, 104, 106, 103, 100, 102, -1, -1 }, + { 107, 103, 102, 106, 200, -1, -1, -1 }, + { 103, 107, 104, 200, -1, -1, -1, -1 }, + { 104, 107, 106, 200, -1, -1, -1, -1 }, + { 104, 106, 5, 4, 200, -1, -1, -1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 3, 103, 104, 8, 200, -1, -1, -1 }, + { 4, 8, 104, 200, -1, -1, -1, -1 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 100, 103, 107, 104, 101, -1, -1, -1 }, + { 106, 107, 103, 101, -1, -1, -1, -1 }, + { 106, 104, 107, 101, -1, -1, -1, -1 }, + { 101, 104, 106, 9, 4, 5, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 103, 101, 106, 2, 1, 11, -1, -1 }, + { 101, 104, 106, 103, -1, -1, -1, -1 }, + { 103, 106, 107, 104, -1, -1, -1, -1 }, + { 107, 104, 100, 103, 200, -1, -1, -1 }, + { 104, 107, 106, 200, -1, -1, -1, -1 }, + { 106, 107, 103, 200, -1, -1, -1, -1 }, + { 106, 103, 2, 11, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 0, 100, 104, 4, 200, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 11, 5, 106, 200, -1, -1, -1, -1 }, + { 107, 106, 104, 103, -1, -1, -1, -1 }, + { 3, 103, 104, 8, 4, -1, -1, -1 }, + { 2, 11, 106, 103, 5, -1, -1, -1 }, + { 104, 106, 5, 4, 103, -1, -1, -1 }, + { 3, 4, 5, 2, 103, -1, -1, -1 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 2, 3, 10, 102, 100, 107, -1, -1 }, + { 107, 104, 100, 102, -1, -1, -1, -1 }, + { 102, 101, 106, 104, -1, -1, -1, -1 }, + { 101, 102, 100, 104, -1, -1, -1, -1 }, + { 102, 106, 107, 104, -1, -1, -1, -1 }, + { 5, 4, 9, 106, 104, 101, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 107, 106, 104, 200, -1, -1, -1, -1 }, + { 107, 102, 106, 200, -1, -1, -1, -1 }, + { 2, 102, 107, 10, 200, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 102, 101, 106, 200, -1, -1, -1, -1 }, + { 8, 0, 2, 10, 200, -1, -1, -1 }, + { 101, 104, 106, 200, -1, -1, -1, -1 }, + { 8, 104, 101, 0, 200, -1, -1, -1 }, + { 10, 2, 3, 107, 102, 100, -1, -1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 106, 107, 102, 200, -1, -1, -1, -1 }, + { 106, 104, 107, 200, -1, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 0, 100, 104, 4, 200, -1, -1, -1 }, + { 104, 100, 107, 200, -1, -1, -1, -1 }, + { 1, 0, 4, 5, 200, -1, -1, -1 }, + { 100, 102, 107, 200, -1, -1, -1, -1 }, + { 1, 102, 100, 0, 200, -1, -1, -1 }, + { 107, 102, 106, 200, -1, -1, -1, -1 }, + { 10, 2, 102, 107, 200, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 104, 107, 106, 200, -1, -1, -1, -1 }, + { 104, 4, 8, 200, -1, -1, -1, -1 }, + { 104, 106, 5, 4, 200, -1, -1, -1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 1, 102, 2, 200, -1, -1, -1, -1 }, + { 104, 106, 101, 4, 5, 9, -1, -1 }, + { 10, 11, 106, 107, 200, -1, -1, -1 }, + { 107, 106, 104, 200, -1, -1, -1, -1 }, + { 107, 104, 100, 200, -1, -1, -1, -1 }, + { 3, 10, 107, 100, 200, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 100, 104, 101, 200, -1, -1, -1, -1 }, + { 11, 10, 3, 1, 200, -1, -1, -1 }, + { 101, 104, 106, 200, -1, -1, -1, -1 }, + { 11, 1, 101, 106, 200, -1, -1, -1 }, + { 104, 106, 101, 4, 5, 9, -1, -1 }, + { 106, 101, 104, 200, -1, -1, -1, -1 }, + { 104, 101, 0, 8, 200, -1, -1, -1 }, + { 107, 106, 104, 200, -1, -1, -1, -1 }, + { 11, 106, 107, 10, 200, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 101, 106, 11, 1, 200, -1, -1, -1 }, + { 0, 101, 1, 200, -1, -1, -1, -1 }, + { 104, 107, 106, 200, -1, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 4, 0, 100, 104, 200, -1, -1, -1 }, + { 100, 107, 104, 200, -1, -1, -1, -1 }, + { 100, 0, 3, 200, -1, -1, -1, -1 }, + { 100, 3, 10, 107, 200, -1, -1, -1 }, + { 10, 11, 106, 107, 200, -1, -1, -1 }, + { 11, 5, 106, 200, -1, -1, -1, -1 }, + { 10, 11, 106, 107, 200, -1, -1, -1 }, + { 8, 10, 107, 104, 200, -1, -1, -1 }, + { 4, 8, 104, 200, -1, -1, -1, -1 }, + { 104, 107, 106, 200, -1, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 106, 11, 5, 200, -1, -1, -1, -1 }, + { 8, 7, 5, 9, 100, 107, 106, 101 }, + { 103, 100, 107, 102, 101, 106, -1, -1 }, + { 102, 106, 107, 103, 200, -1, -1, -1 }, + { 103, 101, 102, 200, -1, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 101, 9, 5, 106, 200, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 3, 0, 101, 103, 200, -1, -1, -1 }, + { 9, 101, 0, 200, -1, -1, -1, -1 }, + { 103, 102, 106, 107, 200, -1, -1, -1 }, + { 107, 100, 103, 200, -1, -1, -1, -1 }, + { 100, 102, 103, 200, -1, -1, -1, -1 }, + { 100, 0, 1, 102, 200, -1, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 7, 8, 100, 107, 200, -1, -1, -1 }, + { 0, 100, 8, 200, -1, -1, -1, -1 }, + { 103, 102, 106, 107, 3, 1, 5, 7 }, + { 2, 11, 1, 103, 106, 101, -1, -1 }, + { 7, 107, 106, 5, 200, -1, -1, -1 }, + { 107, 103, 106, 200, -1, -1, -1, -1 }, + { 107, 100, 103, 200, -1, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 9, 101, 100, 8, 200, -1, -1, -1 }, + { 100, 101, 103, 200, -1, -1, -1, -1 }, + { 5, 9, 8, 7, 200, -1, -1, -1 }, + { 101, 106, 103, 200, -1, -1, -1, -1 }, + { 5, 106, 101, 9, 200, -1, -1, -1 }, + { 2, 11, 1, 103, 106, 101, -1, -1 }, + { 106, 103, 101, 200, -1, -1, -1, -1 }, + { 103, 3, 0, 101, 200, -1, -1, -1 }, + { 107, 103, 106, 200, -1, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 101, 9, 5, 106, 200, -1, -1, -1 }, + { 0, 9, 101, 200, -1, -1, -1, -1 }, + { 103, 106, 107, 200, -1, -1, -1, -1 }, + { 2, 11, 106, 103, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 100, 103, 107, 200, -1, -1, -1, -1 }, + { 100, 8, 0, 200, -1, -1, -1, -1 }, + { 100, 107, 7, 8, 200, -1, -1, -1 }, + { 7, 107, 106, 5, 200, -1, -1, -1 }, + { 5, 106, 11, 200, -1, -1, -1, -1 }, + { 7, 107, 106, 5, 200, -1, -1, -1 }, + { 3, 103, 107, 7, 200, -1, -1, -1 }, + { 2, 103, 3, 200, -1, -1, -1, -1 }, + { 103, 106, 107, 200, -1, -1, -1, -1 }, + { 2, 11, 106, 103, 200, -1, -1, -1 }, + { 106, 11, 5, 200, -1, -1, -1, -1 }, + { 102, 107, 100, 2, 10, 3, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 106, 107, 102, 200, -1, -1, -1, -1 }, + { 106, 102, 101, 200, -1, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 8, 9, 101, 100, 200, -1, -1, -1 }, + { 101, 102, 100, 200, -1, -1, -1, -1 }, + { 7, 5, 9, 8, 200, -1, -1, -1 }, + { 100, 102, 107, 200, -1, -1, -1, -1 }, + { 7, 8, 100, 107, 200, -1, -1, -1 }, + { 102, 106, 107, 200, -1, -1, -1, -1 }, + { 2, 102, 107, 10, 200, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 101, 0, 9, 200, -1, -1, -1, -1 }, + { 101, 9, 5, 106, 200, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 7, 10, 107, 200, -1, -1, -1, -1 }, + { 10, 2, 3, 107, 102, 100, -1, -1 }, + { 102, 107, 100, 200, -1, -1, -1, -1 }, + { 107, 7, 8, 100, 200, -1, -1, -1 }, + { 106, 107, 102, 200, -1, -1, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 100, 0, 1, 102, 200, -1, -1, -1 }, + { 8, 0, 100, 200, -1, -1, -1, -1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 7, 107, 106, 5, 200, -1, -1, -1 }, + { 10, 107, 7, 200, -1, -1, -1, -1 }, + { 107, 102, 106, 200, -1, -1, -1, -1 }, + { 10, 2, 102, 107, 200, -1, -1, -1 }, + { 102, 2, 1, 200, -1, -1, -1, -1 }, + { 8, 7, 5, 9, 100, 107, 106, 101 }, + { 100, 107, 106, 101, 3, 10, 11, 1 }, + { 101, 9, 5, 106, 200, -1, -1, -1 }, + { 11, 1, 101, 106, 200, -1, -1, -1 }, + { 101, 0, 9, 200, -1, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 5, 7, 107, 106, 200, -1, -1, -1 }, + { 106, 107, 10, 11, 200, -1, -1, -1 }, + { 10, 107, 7, 200, -1, -1, -1, -1 }, + { 100, 107, 7, 8, 200, -1, -1, -1 }, + { 10, 107, 100, 3, 200, -1, -1, -1 }, + { 100, 8, 0, 200, -1, -1, -1, -1 }, + { 3, 100, 0, 200, -1, -1, -1, -1 }, + { 7, 107, 106, 5, 200, -1, -1, -1 }, + { 107, 10, 11, 106, 200, -1, -1, -1 }, + { 11, 5, 106, 200, -1, -1, -1, -1 }, + { 106, 5, 11, 107, 7, 10, -1, -1 }, + { 105, 107, 102, 5, 6, 11, -1, -1 }, + { 105, 107, 102, 200, -1, -1, -1, -1 }, + { 104, 100, 103, 107, 200, -1, -1, -1 }, + { 107, 103, 102, 200, -1, -1, -1, -1 }, + { 101, 102, 103, 100, 200, -1, -1, -1 }, + { 101, 105, 102, 200, -1, -1, -1, -1 }, + { 101, 100, 104, 105, 200, -1, -1, -1 }, + { 105, 104, 107, 200, -1, -1, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 11, 6, 5, 102, 107, 105, -1, -1 }, + { 105, 104, 107, 102, -1, -1, -1, -1 }, + { 102, 103, 101, 104, -1, -1, -1, -1 }, + { 103, 102, 107, 104, -1, -1, -1, -1 }, + { 102, 101, 105, 104, -1, -1, -1, -1 }, + { 102, 105, 107, 11, 5, 6, -1, -1 }, + { 1, 9, 0, 102, 105, 100, -1, -1 }, + { 103, 107, 104, 100, 102, -1, -1, -1 }, + { 105, 100, 104, 102, -1, -1, -1, -1 }, + { 105, 104, 107, 102, -1, -1, -1, -1 }, + { 107, 102, 105, 6, 11, 5, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 103, 102, 107, 200, -1, -1, -1, -1 }, + { 103, 107, 104, 200, -1, -1, -1, -1 }, + { 8, 3, 103, 104, 200, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 104, 107, 105, 200, -1, -1, -1, -1 }, + { 1, 3, 8, 9, 200, -1, -1, -1 }, + { 105, 107, 102, 200, -1, -1, -1, -1 }, + { 1, 9, 105, 102, 200, -1, -1, -1 }, + { 2, 1, 5, 6, 103, 101, 105, 107 }, + { 100, 103, 101, 104, 107, 105, -1, -1 }, + { 104, 101, 103, 8, 0, 3, -1, -1 }, + { 5, 1, 101, 105, 200, -1, -1, -1 }, + { 105, 101, 104, 200, -1, -1, -1, -1 }, + { 105, 104, 107, 200, -1, -1, -1, -1 }, + { 6, 5, 105, 107, 200, -1, -1, -1 }, + { 2, 6, 107, 103, 200, -1, -1, -1 }, + { 107, 104, 103, 200, -1, -1, -1, -1 }, + { 1, 5, 6, 2, 200, -1, -1, -1 }, + { 103, 104, 101, 200, -1, -1, -1, -1 }, + { 1, 2, 103, 101, 200, -1, -1, -1 }, + { 104, 100, 103, 107, 200, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 105, 104, 107, 200, -1, -1, -1, -1 }, + { 105, 107, 6, 5, 200, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 104, 103, 107, 200, -1, -1, -1, -1 }, + { 8, 3, 103, 104, 200, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 105, 104, 107, 200, -1, -1, -1, -1 }, + { 105, 5, 9, 200, -1, -1, -1, -1 }, + { 105, 107, 6, 5, 200, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 2, 103, 3, 200, -1, -1, -1, -1 }, + { 107, 102, 105, 6, 11, 5, -1, -1 }, + { 10, 2, 3, 107, 102, 100, -1, -1 }, + { 104, 105, 101, 100, 107, -1, -1, -1 }, + { 102, 100, 101, 107, -1, -1, -1, -1 }, + { 102, 101, 105, 107, -1, -1, -1, -1 }, + { 105, 107, 102, 5, 6, 11, -1, -1 }, + { 8, 10, 107, 104, 200, -1, -1, -1 }, + { 104, 107, 105, 200, -1, -1, -1, -1 }, + { 104, 105, 101, 200, -1, -1, -1, -1 }, + { 0, 8, 104, 101, 200, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 101, 105, 102, 200, -1, -1, -1, -1 }, + { 10, 8, 0, 2, 200, -1, -1, -1 }, + { 102, 105, 107, 200, -1, -1, -1, -1 }, + { 10, 2, 102, 107, 200, -1, -1, -1 }, + { 102, 100, 105, 1, 0, 9, -1, -1 }, + { 10, 2, 3, 107, 102, 100, -1, -1 }, + { 107, 102, 105, 6, 11, 5, -1, -1 }, + { 102, 100, 105, 107, -1, -1, -1, -1 }, + { 107, 105, 104, 100, -1, -1, -1, -1 }, + { 105, 107, 102, 5, 6, 11, -1, -1 }, + { 107, 102, 105, 200, -1, -1, -1, -1 }, + { 105, 102, 1, 9, 200, -1, -1, -1 }, + { 104, 107, 105, 200, -1, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 102, 107, 10, 2, 200, -1, -1, -1 }, + { 1, 102, 2, 200, -1, -1, -1, -1 }, + { 104, 105, 101, 100, 200, -1, -1, -1 }, + { 100, 107, 104, 200, -1, -1, -1, -1 }, + { 107, 105, 104, 200, -1, -1, -1, -1 }, + { 107, 6, 5, 105, 200, -1, -1, -1 }, + { 5, 1, 101, 105, 200, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 3, 10, 107, 100, 200, -1, -1, -1 }, + { 6, 107, 10, 200, -1, -1, -1, -1 }, + { 104, 105, 101, 200, -1, -1, -1, -1 }, + { 8, 104, 101, 0, 200, -1, -1, -1 }, + { 8, 10, 107, 104, 200, -1, -1, -1 }, + { 107, 105, 104, 200, -1, -1, -1, -1 }, + { 107, 10, 6, 200, -1, -1, -1, -1 }, + { 107, 6, 5, 105, 200, -1, -1, -1 }, + { 5, 1, 101, 105, 200, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 104, 105, 100, 107, -1, -1, -1, -1 }, + { 10, 107, 100, 3, 0, -1, -1, -1 }, + { 6, 5, 105, 107, 9, -1, -1, -1 }, + { 100, 105, 9, 0, 107, -1, -1, -1 }, + { 10, 0, 9, 6, 107, -1, -1, -1 }, + { 8, 10, 107, 104, 200, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 105, 104, 107, 200, -1, -1, -1, -1 }, + { 5, 105, 107, 6, 200, -1, -1, -1 }, + { 107, 10, 6, 200, -1, -1, -1, -1 }, + { 6, 5, 11, 107, 105, 102, -1, -1 }, + { 107, 105, 100, 7, 4, 8, -1, -1 }, + { 103, 100, 101, 102, 107, -1, -1, -1 }, + { 105, 101, 100, 107, -1, -1, -1, -1 }, + { 105, 102, 101, 107, -1, -1, -1, -1 }, + { 11, 6, 5, 102, 107, 105, -1, -1 }, + { 3, 103, 107, 7, 200, -1, -1, -1 }, + { 103, 102, 107, 200, -1, -1, -1, -1 }, + { 103, 101, 102, 200, -1, -1, -1, -1 }, + { 0, 101, 103, 3, 200, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 101, 105, 102, 200, -1, -1, -1, -1 }, + { 7, 4, 0, 3, 200, -1, -1, -1 }, + { 105, 107, 102, 200, -1, -1, -1, -1 }, + { 7, 107, 105, 4, 200, -1, -1, -1 }, + { 9, 0, 1, 105, 100, 102, -1, -1 }, + { 107, 105, 100, 7, 4, 8, -1, -1 }, + { 6, 5, 11, 107, 105, 102, -1, -1 }, + { 105, 102, 100, 107, -1, -1, -1, -1 }, + { 107, 103, 102, 100, -1, -1, -1, -1 }, + { 11, 6, 5, 102, 107, 105, -1, -1 }, + { 107, 102, 105, 200, -1, -1, -1, -1 }, + { 102, 1, 9, 105, 200, -1, -1, -1 }, + { 103, 102, 107, 200, -1, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 105, 4, 7, 107, 200, -1, -1, -1 }, + { 9, 4, 105, 200, -1, -1, -1, -1 }, + { 8, 4, 7, 100, 105, 107, -1, -1 }, + { 1, 101, 105, 5, 200, -1, -1, -1 }, + { 101, 100, 105, 200, -1, -1, -1, -1 }, + { 101, 103, 100, 200, -1, -1, -1, -1 }, + { 2, 103, 101, 1, 200, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 103, 107, 100, 200, -1, -1, -1, -1 }, + { 5, 6, 2, 1, 200, -1, -1, -1 }, + { 107, 105, 100, 200, -1, -1, -1, -1 }, + { 5, 105, 107, 6, 200, -1, -1, -1 }, + { 2, 1, 5, 6, 103, 101, 105, 107 }, + { 103, 101, 105, 107, 3, 0, 4, 7 }, + { 100, 107, 105, 8, 7, 4, -1, -1 }, + { 107, 105, 100, 200, -1, -1, -1, -1 }, + { 100, 105, 9, 0, 200, -1, -1, -1 }, + { 103, 107, 100, 200, -1, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 105, 107, 6, 5, 200, -1, -1, -1 }, + { 9, 105, 5, 200, -1, -1, -1, -1 }, + { 105, 4, 7, 107, 200, -1, -1, -1 }, + { 6, 5, 105, 107, 200, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 7, 3, 103, 107, 200, -1, -1, -1 }, + { 107, 103, 2, 6, 200, -1, -1, -1 }, + { 2, 103, 3, 200, -1, -1, -1, -1 }, + { 7, 8, 4, 107, 100, 105, -1, -1 }, + { 102, 107, 100, 2, 10, 3, -1, -1 }, + { 11, 6, 5, 102, 107, 105, -1, -1 }, + { 107, 105, 100, 102, -1, -1, -1, -1 }, + { 102, 101, 105, 100, -1, -1, -1, -1 }, + { 5, 11, 6, 105, 102, 107, -1, -1 }, + { 102, 105, 107, 200, -1, -1, -1, -1 }, + { 105, 4, 7, 107, 200, -1, -1, -1 }, + { 101, 105, 102, 200, -1, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 107, 10, 2, 102, 200, -1, -1, -1 }, + { 7, 10, 107, 200, -1, -1, -1, -1 }, + { 102, 100, 105, 1, 0, 9, -1, -1 }, + { 102, 100, 105, 107, -1, -1, -1, -1 }, + { 6, 5, 11, 107, 105, 102, -1, -1 }, + { 3, 10, 2, 100, 107, 102, -1, -1 }, + { 4, 7, 8, 105, 107, 100, -1, -1 }, + { 105, 107, 102, 5, 6, 11, -1, -1 }, + { 105, 102, 1, 9, 4, -1, -1, -1 }, + { 2, 102, 107, 10, 7, -1, -1, -1 }, + { 4, 7, 107, 105, 102, -1, -1, -1 }, + { 4, 1, 2, 7, 102, -1, -1, -1 }, + { 8, 4, 7, 100, 105, 107, -1, -1 }, + { 105, 100, 107, 200, -1, -1, -1, -1 }, + { 100, 3, 10, 107, 200, -1, -1, -1 }, + { 101, 100, 105, 200, -1, -1, -1, -1 }, + { 5, 1, 101, 105, 200, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 107, 6, 5, 105, 200, -1, -1, -1 }, + { 10, 6, 107, 200, -1, -1, -1, -1 }, + { 107, 105, 4, 7, 200, -1, -1, -1 }, + { 5, 105, 107, 6, 200, -1, -1, -1 }, + { 107, 7, 10, 200, -1, -1, -1, -1 }, + { 6, 107, 10, 200, -1, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 105, 5, 1, 101, 200, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 8, 4, 7, 100, 105, 107, -1, -1 }, + { 100, 3, 10, 107, 0, -1, -1, -1 }, + { 6, 5, 105, 107, 9, -1, -1, -1 }, + { 0, 100, 105, 9, 107, -1, -1, -1 }, + { 0, 9, 6, 10, 107, -1, -1, -1 }, + { 107, 105, 4, 7, 200, -1, -1, -1 }, + { 6, 5, 105, 107, 200, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 6, 200, 107, 10, -1, -1, -1, -1 }, + { 7, 10, 107, 200, -1, -1, -1, -1 }, + { 104, 101, 102, 107, 4, 9, 11, 6 }, + { 103, 107, 102, 100, 104, 101, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 11, 102, 101, 9, 200, -1, -1, -1 }, + { 102, 103, 101, 200, -1, -1, -1, -1 }, + { 102, 107, 103, 200, -1, -1, -1, -1 }, + { 6, 107, 102, 11, 200, -1, -1, -1 }, + { 4, 104, 107, 6, 200, -1, -1, -1 }, + { 107, 104, 103, 200, -1, -1, -1, -1 }, + { 9, 4, 6, 11, 200, -1, -1, -1 }, + { 104, 101, 103, 200, -1, -1, -1, -1 }, + { 9, 101, 104, 4, 200, -1, -1, -1 }, + { 103, 107, 104, 100, 200, -1, -1, -1 }, + { 100, 102, 103, 200, -1, -1, -1, -1 }, + { 102, 107, 103, 200, -1, -1, -1, -1 }, + { 102, 11, 6, 107, 200, -1, -1, -1 }, + { 6, 4, 104, 107, 200, -1, -1, -1 }, + { 4, 0, 100, 104, 200, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 103, 107, 104, 200, -1, -1, -1, -1 }, + { 3, 103, 104, 8, 200, -1, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 102, 107, 103, 200, -1, -1, -1, -1 }, + { 102, 1, 11, 200, -1, -1, -1, -1 }, + { 102, 11, 6, 107, 200, -1, -1, -1 }, + { 6, 4, 104, 107, 200, -1, -1, -1 }, + { 4, 8, 104, 200, -1, -1, -1, -1 }, + { 100, 103, 107, 104, 200, -1, -1, -1 }, + { 103, 100, 101, 200, -1, -1, -1, -1 }, + { 101, 100, 104, 200, -1, -1, -1, -1 }, + { 101, 104, 4, 9, 200, -1, -1, -1 }, + { 4, 104, 107, 6, 200, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 2, 103, 101, 1, 200, -1, -1, -1 }, + { 9, 1, 101, 200, -1, -1, -1, -1 }, + { 103, 104, 101, 3, 8, 0, -1, -1 }, + { 104, 101, 103, 200, -1, -1, -1, -1 }, + { 103, 101, 1, 2, 200, -1, -1, -1 }, + { 107, 104, 103, 200, -1, -1, -1, -1 }, + { 4, 104, 107, 6, 200, -1, -1, -1 }, + { 6, 107, 103, 2, 200, -1, -1, -1 }, + { 101, 104, 4, 9, 200, -1, -1, -1 }, + { 1, 101, 9, 200, -1, -1, -1, -1 }, + { 0, 4, 6, 2, 100, 104, 107, 103 }, + { 6, 4, 104, 107, 200, -1, -1, -1 }, + { 2, 6, 107, 103, 200, -1, -1, -1 }, + { 3, 2, 103, 200, -1, -1, -1, -1 }, + { 103, 107, 104, 200, -1, -1, -1, -1 }, + { 3, 103, 104, 8, 200, -1, -1, -1 }, + { 104, 4, 8, 200, -1, -1, -1, -1 }, + { 100, 102, 107, 3, 2, 10, -1, -1 }, + { 9, 11, 102, 101, 200, -1, -1, -1 }, + { 101, 102, 100, 200, -1, -1, -1, -1 }, + { 101, 100, 104, 200, -1, -1, -1, -1 }, + { 4, 9, 101, 104, 200, -1, -1, -1 }, + { 6, 4, 104, 107, 200, -1, -1, -1 }, + { 104, 100, 107, 200, -1, -1, -1, -1 }, + { 11, 9, 4, 6, 200, -1, -1, -1 }, + { 107, 100, 102, 200, -1, -1, -1, -1 }, + { 11, 6, 107, 102, 200, -1, -1, -1 }, + { 104, 101, 102, 107, 4, 9, 11, 6 }, + { 8, 0, 2, 10, 104, 101, 102, 107 }, + { 3, 10, 2, 100, 107, 102, -1, -1 }, + { 107, 100, 102, 200, -1, -1, -1, -1 }, + { 100, 0, 1, 102, 200, -1, -1, -1 }, + { 104, 100, 107, 200, -1, -1, -1, -1 }, + { 6, 4, 104, 107, 200, -1, -1, -1 }, + { 4, 0, 100, 104, 200, -1, -1, -1 }, + { 102, 11, 6, 107, 200, -1, -1, -1 }, + { 1, 11, 102, 200, -1, -1, -1, -1 }, + { 102, 107, 10, 2, 200, -1, -1, -1 }, + { 6, 107, 102, 11, 200, -1, -1, -1 }, + { 102, 2, 1, 200, -1, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 10, 107, 104, 8, 200, -1, -1, -1 }, + { 107, 6, 4, 104, 200, -1, -1, -1 }, + { 4, 8, 104, 200, -1, -1, -1, -1 }, + { 100, 107, 104, 200, -1, -1, -1, -1 }, + { 3, 10, 107, 100, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 101, 100, 104, 200, -1, -1, -1, -1 }, + { 101, 9, 1, 200, -1, -1, -1, -1 }, + { 101, 104, 4, 9, 200, -1, -1, -1 }, + { 4, 104, 107, 6, 200, -1, -1, -1 }, + { 6, 107, 10, 200, -1, -1, -1, -1 }, + { 101, 0, 8, 104, 200, -1, -1, -1 }, + { 4, 9, 101, 104, 200, -1, -1, -1 }, + { 101, 1, 0, 200, -1, -1, -1, -1 }, + { 9, 1, 101, 200, -1, -1, -1, -1 }, + { 8, 10, 107, 104, 200, -1, -1, -1 }, + { 104, 107, 6, 4, 200, -1, -1, -1 }, + { 6, 107, 10, 200, -1, -1, -1, -1 }, + { 4, 104, 107, 6, 200, -1, -1, -1 }, + { 0, 100, 104, 4, 200, -1, -1, -1 }, + { 3, 100, 0, 200, -1, -1, -1, -1 }, + { 100, 107, 104, 200, -1, -1, -1, -1 }, + { 3, 10, 107, 100, 200, -1, -1, -1 }, + { 107, 10, 6, 200, -1, -1, -1, -1 }, + { 104, 8, 4, 107, 10, 6, -1, -1 }, + { 103, 100, 101, 102, 200, -1, -1, -1 }, + { 100, 103, 107, 200, -1, -1, -1, -1 }, + { 107, 103, 102, 200, -1, -1, -1, -1 }, + { 107, 102, 11, 6, 200, -1, -1, -1 }, + { 11, 102, 101, 9, 200, -1, -1, -1 }, + { 9, 101, 100, 8, 200, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 6, 7, 107, 200, -1, -1, -1, -1 }, + { 103, 101, 102, 200, -1, -1, -1, -1 }, + { 3, 0, 101, 103, 200, -1, -1, -1 }, + { 3, 103, 107, 7, 200, -1, -1, -1 }, + { 107, 103, 102, 200, -1, -1, -1, -1 }, + { 107, 6, 7, 200, -1, -1, -1, -1 }, + { 107, 102, 11, 6, 200, -1, -1, -1 }, + { 11, 102, 101, 9, 200, -1, -1, -1 }, + { 9, 101, 0, 200, -1, -1, -1, -1 }, + { 103, 100, 102, 107, -1, -1, -1, -1 }, + { 7, 8, 100, 107, 0, -1, -1, -1 }, + { 6, 107, 102, 11, 1, -1, -1, -1 }, + { 100, 0, 1, 102, 107, -1, -1, -1 }, + { 7, 6, 1, 0, 107, -1, -1, -1 }, + { 3, 103, 107, 7, 200, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 102, 107, 103, 200, -1, -1, -1, -1 }, + { 11, 6, 107, 102, 200, -1, -1, -1 }, + { 107, 6, 7, 200, -1, -1, -1, -1 }, + { 100, 103, 107, 200, -1, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 8, 9, 101, 100, 200, -1, -1, -1 }, + { 101, 103, 100, 200, -1, -1, -1, -1 }, + { 101, 9, 1, 200, -1, -1, -1, -1 }, + { 101, 1, 2, 103, 200, -1, -1, -1 }, + { 2, 6, 107, 103, 200, -1, -1, -1 }, + { 6, 7, 107, 200, -1, -1, -1, -1 }, + { 101, 103, 3, 0, 200, -1, -1, -1 }, + { 2, 103, 101, 1, 200, -1, -1, -1 }, + { 101, 0, 9, 200, -1, -1, -1, -1 }, + { 1, 101, 9, 200, -1, -1, -1, -1 }, + { 3, 103, 107, 7, 200, -1, -1, -1 }, + { 103, 2, 6, 107, 200, -1, -1, -1 }, + { 6, 7, 107, 200, -1, -1, -1, -1 }, + { 2, 6, 107, 103, 200, -1, -1, -1 }, + { 0, 2, 103, 100, 200, -1, -1, -1 }, + { 8, 0, 100, 200, -1, -1, -1, -1 }, + { 100, 103, 107, 200, -1, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 107, 6, 7, 200, -1, -1, -1, -1 }, + { 107, 7, 6, 103, 3, 2, -1, -1 }, + { 100, 102, 107, 3, 2, 10, -1, -1 }, + { 102, 107, 100, 200, -1, -1, -1, -1 }, + { 100, 107, 7, 8, 200, -1, -1, -1 }, + { 101, 102, 100, 200, -1, -1, -1, -1 }, + { 11, 102, 101, 9, 200, -1, -1, -1 }, + { 9, 101, 100, 8, 200, -1, -1, -1 }, + { 107, 102, 11, 6, 200, -1, -1, -1 }, + { 7, 107, 6, 200, -1, -1, -1, -1 }, + { 107, 10, 2, 102, 200, -1, -1, -1 }, + { 11, 6, 107, 102, 200, -1, -1, -1 }, + { 107, 7, 10, 200, -1, -1, -1, -1 }, + { 6, 7, 107, 200, -1, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 102, 101, 9, 11, 200, -1, -1, -1 }, + { 9, 101, 0, 200, -1, -1, -1, -1 }, + { 100, 102, 107, 3, 2, 10, -1, -1 }, + { 100, 107, 7, 8, 0, -1, -1, -1 }, + { 6, 107, 102, 11, 1, -1, -1, -1 }, + { 0, 1, 102, 100, 107, -1, -1, -1 }, + { 0, 7, 6, 1, 107, -1, -1, -1 }, + { 107, 10, 2, 102, 200, -1, -1, -1 }, + { 6, 107, 102, 11, 200, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 102, 2, 1, 200, -1, -1, -1, -1 }, + { 6, 107, 200, 7, -1, -1, -1, -1 }, + { 10, 107, 7, 200, -1, -1, -1, -1 }, + { 107, 100, 3, 10, 200, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 107, 10, 6, 200, -1, -1, -1, -1 }, + { 7, 107, 6, 200, -1, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 100, 8, 9, 101, 200, -1, -1, -1 }, + { 9, 1, 101, 200, -1, -1, -1, -1 }, + { 101, 0, 9, 1, -1, -1, -1, -1 }, + { 107, 7, 10, 6, -1, -1, -1, -1 }, + { 100, 3, 10, 107, 200, -1, -1, -1 }, + { 8, 100, 107, 7, 200, -1, -1, -1 }, + { 7, 107, 6, 200, -1, -1, -1, -1 }, + { 107, 10, 6, 200, -1, -1, -1, -1 }, + { 8, 100, 200, 0, -1, -1, -1, -1 }, + { 3, 100, 0, 200, -1, -1, -1, -1 }, + { 107, 6, 7, 10, -1, -1, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 104, 103, 106, 200, -1, -1, -1, -1 }, + { 105, 106, 102, 101, 200, -1, -1, -1 }, + { 106, 103, 102, 200, -1, -1, -1, -1 }, + { 100, 101, 102, 103, 200, -1, -1, -1 }, + { 100, 103, 104, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 101, 200, -1, -1, -1 }, + { 104, 106, 105, 200, -1, -1, -1, -1 }, + { 10, 7, 6, 103, 104, 106, -1, -1 }, + { 103, 104, 101, 3, 8, 0, -1, -1 }, + { 102, 101, 105, 106, 103, -1, -1, -1 }, + { 104, 105, 101, 103, -1, -1, -1, -1 }, + { 104, 106, 105, 103, -1, -1, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 9, 0, 1, 105, 100, 102, -1, -1 }, + { 102, 103, 100, 105, -1, -1, -1, -1 }, + { 105, 104, 106, 103, -1, -1, -1, -1 }, + { 104, 105, 100, 103, -1, -1, -1, -1 }, + { 105, 106, 102, 103, -1, -1, -1, -1 }, + { 6, 10, 7, 106, 103, 104, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 102, 106, 103, 200, -1, -1, -1, -1 }, + { 102, 105, 106, 200, -1, -1, -1, -1 }, + { 9, 105, 102, 1, 200, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 105, 104, 106, 200, -1, -1, -1, -1 }, + { 3, 8, 9, 1, 200, -1, -1, -1 }, + { 104, 103, 106, 200, -1, -1, -1, -1 }, + { 3, 103, 104, 8, 200, -1, -1, -1 }, + { 2, 11, 1, 103, 106, 101, -1, -1 }, + { 103, 106, 104, 10, 6, 7, -1, -1 }, + { 100, 104, 105, 101, 103, -1, -1, -1 }, + { 106, 105, 104, 103, -1, -1, -1, -1 }, + { 106, 101, 105, 103, -1, -1, -1, -1 }, + { 103, 101, 106, 2, 1, 11, -1, -1 }, + { 8, 3, 0, 104, 103, 101, -1, -1 }, + { 104, 103, 106, 7, 10, 6, -1, -1 }, + { 103, 101, 106, 104, -1, -1, -1, -1 }, + { 104, 106, 105, 101, -1, -1, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 105, 104, 106, 200, -1, -1, -1, -1 }, + { 105, 100, 104, 200, -1, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 100, 103, 104, 200, -1, -1, -1, -1 }, + { 11, 2, 0, 9, 200, -1, -1, -1 }, + { 103, 106, 104, 200, -1, -1, -1, -1 }, + { 11, 106, 103, 2, 200, -1, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 106, 104, 103, 200, -1, -1, -1, -1 }, + { 104, 8, 3, 103, 200, -1, -1, -1 }, + { 105, 104, 106, 200, -1, -1, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 103, 2, 11, 106, 200, -1, -1, -1 }, + { 3, 2, 103, 200, -1, -1, -1, -1 }, + { 3, 2, 6, 7, 100, 102, 106, 104 }, + { 101, 100, 102, 105, 104, 106, -1, -1 }, + { 105, 106, 102, 101, 200, -1, -1, -1 }, + { 101, 104, 105, 200, -1, -1, -1, -1 }, + { 104, 106, 105, 200, -1, -1, -1, -1 }, + { 104, 7, 6, 106, 200, -1, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 0, 8, 104, 101, 200, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 105, 102, 100, 9, 1, 0, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 106, 102, 105, 200, -1, -1, -1, -1 }, + { 106, 105, 104, 200, -1, -1, -1, -1 }, + { 7, 6, 106, 104, 200, -1, -1, -1 }, + { 3, 7, 104, 100, 200, -1, -1, -1 }, + { 104, 105, 100, 200, -1, -1, -1, -1 }, + { 2, 6, 7, 3, 200, -1, -1, -1 }, + { 100, 105, 102, 200, -1, -1, -1, -1 }, + { 2, 3, 100, 102, 200, -1, -1, -1 }, + { 105, 106, 102, 200, -1, -1, -1, -1 }, + { 9, 105, 102, 1, 200, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 104, 106, 105, 200, -1, -1, -1, -1 }, + { 104, 8, 7, 200, -1, -1, -1, -1 }, + { 104, 7, 6, 106, 200, -1, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 2, 1, 102, 200, -1, -1, -1, -1 }, + { 105, 101, 100, 104, 200, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 106, 105, 104, 200, -1, -1, -1, -1 }, + { 106, 104, 7, 6, 200, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 1, 101, 106, 11, 200, -1, -1, -1 }, + { 6, 11, 106, 200, -1, -1, -1, -1 }, + { 105, 106, 101, 104, -1, -1, -1, -1 }, + { 8, 104, 101, 0, 1, -1, -1, -1 }, + { 7, 6, 106, 104, 11, -1, -1, -1 }, + { 101, 106, 11, 1, 104, -1, -1, -1 }, + { 8, 1, 11, 7, 104, -1, -1, -1 }, + { 104, 106, 105, 200, -1, -1, -1, -1 }, + { 7, 6, 106, 104, 200, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 100, 0, 3, 200, -1, -1, -1, -1 }, + { 100, 105, 9, 0, 200, -1, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 11, 106, 6, 200, -1, -1, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 104, 106, 105, 200, -1, -1, -1, -1 }, + { 7, 6, 106, 104, 200, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 100, 105, 106, 103, 8, 4, 6, 10 }, + { 102, 103, 106, 101, 100, 105, -1, -1 }, + { 102, 101, 105, 106, 200, -1, -1, -1 }, + { 101, 102, 103, 200, -1, -1, -1, -1 }, + { 103, 102, 106, 200, -1, -1, -1, -1 }, + { 103, 106, 6, 10, 200, -1, -1, -1 }, + { 6, 106, 105, 4, 200, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 0, 101, 103, 3, 200, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 1, 9, 0, 102, 105, 100, -1, -1 }, + { 6, 106, 105, 4, 200, -1, -1, -1 }, + { 106, 102, 105, 200, -1, -1, -1, -1 }, + { 106, 103, 102, 200, -1, -1, -1, -1 }, + { 10, 103, 106, 6, 200, -1, -1, -1 }, + { 8, 100, 103, 10, 200, -1, -1, -1 }, + { 103, 100, 102, 200, -1, -1, -1, -1 }, + { 4, 8, 10, 6, 200, -1, -1, -1 }, + { 100, 105, 102, 200, -1, -1, -1, -1 }, + { 4, 105, 100, 8, 200, -1, -1, -1 }, + { 102, 105, 106, 200, -1, -1, -1, -1 }, + { 1, 9, 105, 102, 200, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 103, 102, 106, 200, -1, -1, -1, -1 }, + { 103, 10, 3, 200, -1, -1, -1, -1 }, + { 103, 106, 6, 10, 200, -1, -1, -1 }, + { 6, 106, 105, 4, 200, -1, -1, -1 }, + { 4, 105, 9, 200, -1, -1, -1, -1 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 4, 6, 106, 105, 200, -1, -1, -1 }, + { 105, 106, 101, 200, -1, -1, -1, -1 }, + { 105, 101, 100, 200, -1, -1, -1, -1 }, + { 8, 4, 105, 100, 200, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 100, 101, 103, 200, -1, -1, -1, -1 }, + { 6, 4, 8, 10, 200, -1, -1, -1 }, + { 103, 101, 106, 200, -1, -1, -1, -1 }, + { 6, 10, 103, 106, 200, -1, -1, -1 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 106, 103, 101, 200, -1, -1, -1, -1 }, + { 101, 103, 3, 0, 200, -1, -1, -1 }, + { 105, 106, 101, 200, -1, -1, -1, -1 }, + { 6, 106, 105, 4, 200, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 103, 106, 6, 10, 200, -1, -1, -1 }, + { 3, 103, 10, 200, -1, -1, -1, -1 }, + { 0, 9, 11, 2, 100, 105, 106, 103 }, + { 100, 105, 106, 103, 8, 4, 6, 10 }, + { 103, 2, 11, 106, 200, -1, -1, -1 }, + { 6, 10, 103, 106, 200, -1, -1, -1 }, + { 103, 3, 2, 200, -1, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 11, 9, 105, 106, 200, -1, -1, -1 }, + { 106, 105, 4, 6, 200, -1, -1, -1 }, + { 4, 105, 9, 200, -1, -1, -1, -1 }, + { 101, 105, 106, 102, 200, -1, -1, -1 }, + { 102, 100, 101, 200, -1, -1, -1, -1 }, + { 100, 105, 101, 200, -1, -1, -1, -1 }, + { 100, 8, 4, 105, 200, -1, -1, -1 }, + { 4, 6, 106, 105, 200, -1, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 2, 3, 100, 102, 200, -1, -1, -1 }, + { 8, 100, 3, 200, -1, -1, -1, -1 }, + { 101, 105, 106, 102, 0, 4, 6, 2 }, + { 1, 9, 0, 102, 105, 100, -1, -1 }, + { 105, 102, 100, 200, -1, -1, -1, -1 }, + { 102, 2, 3, 100, 200, -1, -1, -1 }, + { 106, 102, 105, 200, -1, -1, -1, -1 }, + { 4, 6, 106, 105, 200, -1, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 100, 8, 4, 105, 200, -1, -1, -1 }, + { 3, 8, 100, 200, -1, -1, -1, -1 }, + { 6, 106, 105, 4, 200, -1, -1, -1 }, + { 2, 102, 106, 6, 200, -1, -1, -1 }, + { 1, 102, 2, 200, -1, -1, -1, -1 }, + { 102, 105, 106, 200, -1, -1, -1, -1 }, + { 1, 9, 105, 102, 200, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 1, 101, 106, 11, 200, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 100, 105, 101, 200, -1, -1, -1, -1 }, + { 100, 3, 8, 200, -1, -1, -1, -1 }, + { 100, 8, 4, 105, 200, -1, -1, -1 }, + { 4, 6, 106, 105, 200, -1, -1, -1 }, + { 6, 11, 106, 200, -1, -1, -1, -1 }, + { 4, 6, 106, 105, 200, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 101, 105, 106, 200, -1, -1, -1, -1 }, + { 1, 101, 106, 11, 200, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 100, 105, 9, 0, 200, -1, -1, -1 }, + { 4, 105, 100, 8, 200, -1, -1, -1 }, + { 100, 0, 3, 200, -1, -1, -1, -1 }, + { 8, 100, 3, 200, -1, -1, -1, -1 }, + { 9, 105, 106, 11, 200, -1, -1, -1 }, + { 105, 4, 6, 106, 200, -1, -1, -1 }, + { 6, 11, 106, 200, -1, -1, -1, -1 }, + { 106, 11, 6, 105, 9, 4, -1, -1 }, + { 104, 106, 101, 4, 5, 9, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 100, 101, 102, 103, 104, -1, -1, -1 }, + { 106, 103, 102, 104, -1, -1, -1, -1 }, + { 106, 102, 101, 104, -1, -1, -1, -1 }, + { 4, 9, 5, 104, 101, 106, -1, -1 }, + { 103, 104, 101, 3, 8, 0, -1, -1 }, + { 10, 7, 6, 103, 104, 106, -1, -1 }, + { 104, 106, 101, 103, -1, -1, -1, -1 }, + { 103, 102, 106, 101, -1, -1, -1, -1 }, + { 103, 106, 104, 10, 6, 7, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 102, 106, 103, 200, -1, -1, -1, -1 }, + { 102, 103, 100, 200, -1, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 4, 0, 100, 104, 200, -1, -1, -1 }, + { 100, 103, 104, 200, -1, -1, -1, -1 }, + { 5, 1, 0, 4, 200, -1, -1, -1 }, + { 104, 103, 106, 200, -1, -1, -1, -1 }, + { 5, 4, 104, 106, 200, -1, -1, -1 }, + { 103, 106, 104, 10, 6, 7, -1, -1 }, + { 106, 104, 103, 200, -1, -1, -1, -1 }, + { 103, 104, 8, 3, 200, -1, -1, -1 }, + { 102, 106, 103, 200, -1, -1, -1, -1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 104, 106, 5, 4, 200, -1, -1, -1 }, + { 8, 104, 4, 200, -1, -1, -1, -1 }, + { 106, 103, 101, 11, 2, 1, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 104, 106, 101, 4, 5, 9, -1, -1 }, + { 106, 103, 101, 104, -1, -1, -1, -1 }, + { 104, 101, 100, 103, -1, -1, -1, -1 }, + { 1, 2, 11, 101, 103, 106, -1, -1 }, + { 101, 106, 103, 104, -1, -1, -1, -1 }, + { 104, 106, 101, 4, 5, 9, -1, -1 }, + { 103, 104, 101, 3, 8, 0, -1, -1 }, + { 106, 104, 103, 6, 7, 10, -1, -1 }, + { 104, 103, 106, 7, 10, 6, -1, -1 }, + { 103, 106, 104, 200, -1, -1, -1, -1 }, + { 104, 106, 5, 4, 200, -1, -1, -1 }, + { 100, 103, 104, 200, -1, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 0, 100, 104, 4, 200, -1, -1, -1 }, + { 106, 103, 2, 11, 200, -1, -1, -1 }, + { 5, 106, 11, 200, -1, -1, -1, -1 }, + { 7, 6, 10, 104, 106, 103, -1, -1 }, + { 104, 8, 3, 103, 4, -1, -1, -1 }, + { 2, 11, 106, 103, 5, -1, -1, -1 }, + { 4, 104, 106, 5, 103, -1, -1, -1 }, + { 4, 5, 2, 3, 103, -1, -1, -1 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 2, 102, 106, 6, 200, -1, -1, -1 }, + { 102, 101, 106, 200, -1, -1, -1, -1 }, + { 102, 100, 101, 200, -1, -1, -1, -1 }, + { 3, 100, 102, 2, 200, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 100, 104, 101, 200, -1, -1, -1, -1 }, + { 6, 7, 3, 2, 200, -1, -1, -1 }, + { 104, 106, 101, 200, -1, -1, -1, -1 }, + { 6, 106, 104, 7, 200, -1, -1, -1 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 106, 101, 104, 200, -1, -1, -1, -1 }, + { 101, 0, 8, 104, 200, -1, -1, -1 }, + { 102, 101, 106, 200, -1, -1, -1, -1 }, + { 6, 2, 102, 106, 200, -1, -1, -1 }, + { 2, 0, 101, 102, 200, -1, -1, -1 }, + { 104, 7, 6, 106, 200, -1, -1, -1 }, + { 8, 7, 104, 200, -1, -1, -1, -1 }, + { 100, 102, 106, 104, 0, 1, 5, 4 }, + { 3, 2, 6, 7, 100, 102, 106, 104 }, + { 104, 106, 5, 4, 200, -1, -1, -1 }, + { 6, 106, 104, 7, 200, -1, -1, -1 }, + { 104, 4, 8, 200, -1, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 5, 106, 102, 1, 200, -1, -1, -1 }, + { 106, 6, 2, 102, 200, -1, -1, -1 }, + { 2, 1, 102, 200, -1, -1, -1, -1 }, + { 101, 104, 106, 9, 4, 5, -1, -1 }, + { 104, 106, 101, 200, -1, -1, -1, -1 }, + { 101, 106, 11, 1, 200, -1, -1, -1 }, + { 100, 104, 101, 200, -1, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 106, 104, 7, 6, 200, -1, -1, -1 }, + { 11, 106, 6, 200, -1, -1, -1, -1 }, + { 9, 5, 4, 101, 106, 104, -1, -1 }, + { 101, 0, 8, 104, 1, -1, -1, -1 }, + { 7, 6, 106, 104, 11, -1, -1, -1 }, + { 1, 101, 106, 11, 104, -1, -1, -1 }, + { 1, 11, 7, 8, 104, -1, -1, -1 }, + { 106, 104, 7, 6, 200, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 5, 106, 11, 200, -1, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 104, 4, 0, 100, 200, -1, -1, -1 }, + { 0, 3, 100, 200, -1, -1, -1, -1 }, + { 104, 7, 6, 106, 200, -1, -1, -1 }, + { 4, 104, 106, 5, 200, -1, -1, -1 }, + { 5, 106, 11, 200, -1, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 4, 104, 200, 8, -1, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 102, 103, 100, 101, 200, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 106, 103, 102, 200, -1, -1, -1, -1 }, + { 106, 6, 10, 103, 200, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 8, 9, 101, 100, 200, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 6, 106, 5, 200, -1, -1, -1, -1 }, + { 102, 101, 106, 103, -1, -1, -1, -1 }, + { 3, 0, 101, 103, 9, -1, -1, -1 }, + { 10, 103, 106, 6, 5, -1, -1, -1 }, + { 101, 9, 5, 106, 103, -1, -1, -1 }, + { 3, 10, 5, 9, 103, -1, -1, -1 }, + { 103, 102, 106, 200, -1, -1, -1, -1 }, + { 10, 103, 106, 6, 200, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 100, 102, 103, 200, -1, -1, -1, -1 }, + { 100, 8, 0, 200, -1, -1, -1, -1 }, + { 100, 0, 1, 102, 200, -1, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 5, 6, 106, 200, -1, -1, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 103, 102, 106, 200, -1, -1, -1, -1 }, + { 10, 103, 106, 6, 200, -1, -1, -1 }, + { 106, 5, 6, 200, -1, -1, -1, -1 }, + { 1, 2, 11, 101, 103, 106, -1, -1 }, + { 103, 101, 106, 200, -1, -1, -1, -1 }, + { 101, 9, 5, 106, 200, -1, -1, -1 }, + { 100, 101, 103, 200, -1, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 8, 9, 101, 100, 200, -1, -1, -1 }, + { 106, 6, 10, 103, 200, -1, -1, -1 }, + { 5, 6, 106, 200, -1, -1, -1, -1 }, + { 101, 106, 103, 1, 11, 2, -1, -1 }, + { 101, 103, 3, 0, 9, -1, -1, -1 }, + { 10, 103, 106, 6, 5, -1, -1, -1 }, + { 9, 5, 106, 101, 103, -1, -1, -1 }, + { 9, 3, 10, 5, 103, -1, -1, -1 }, + { 106, 6, 10, 103, 200, -1, -1, -1 }, + { 2, 11, 106, 103, 200, -1, -1, -1 }, + { 106, 5, 6, 200, -1, -1, -1, -1 }, + { 11, 5, 106, 200, -1, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 103, 100, 0, 2, 200, -1, -1, -1 }, + { 0, 100, 8, 200, -1, -1, -1, -1 }, + { 103, 106, 6, 10, 200, -1, -1, -1 }, + { 2, 11, 106, 103, 200, -1, -1, -1 }, + { 11, 5, 106, 200, -1, -1, -1, -1 }, + { 106, 5, 6, 200, -1, -1, -1, -1 }, + { 2, 200, 103, 3, -1, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 9, 101, 100, 8, 200, -1, -1, -1 }, + { 100, 101, 102, 200, -1, -1, -1, -1 }, + { 100, 3, 8, 200, -1, -1, -1, -1 }, + { 100, 102, 2, 3, 200, -1, -1, -1 }, + { 2, 102, 106, 6, 200, -1, -1, -1 }, + { 6, 106, 5, 200, -1, -1, -1, -1 }, + { 2, 102, 106, 6, 200, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 9, 101, 0, 200, -1, -1, -1, -1 }, + { 101, 106, 102, 200, -1, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 106, 5, 6, 200, -1, -1, -1, -1 }, + { 100, 0, 1, 102, 200, -1, -1, -1 }, + { 2, 3, 100, 102, 200, -1, -1, -1 }, + { 100, 8, 0, 200, -1, -1, -1, -1 }, + { 3, 8, 100, 200, -1, -1, -1, -1 }, + { 1, 5, 106, 102, 200, -1, -1, -1 }, + { 102, 106, 6, 2, 200, -1, -1, -1 }, + { 6, 106, 5, 200, -1, -1, -1, -1 }, + { 102, 1, 2, 106, 5, 6, -1, -1 }, + { 106, 11, 1, 101, 200, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 5, 6, 106, 200, -1, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 101, 100, 8, 9, 200, -1, -1, -1 }, + { 8, 100, 3, 200, -1, -1, -1, -1 }, + { 101, 106, 11, 1, 200, -1, -1, -1 }, + { 9, 5, 106, 101, 200, -1, -1, -1 }, + { 5, 6, 106, 200, -1, -1, -1, -1 }, + { 106, 6, 11, 200, -1, -1, -1, -1 }, + { 9, 200, 101, 0, -1, -1, -1, -1 }, + { 1, 0, 101, 200, -1, -1, -1, -1 }, + { 100, 8, 0, 3, -1, -1, -1, -1 }, + { 106, 5, 6, 11, -1, -1, -1, -1 }, + { 106, 5, 6, 11, -1, -1, -1, -1 }, + { 103, 104, 105, 102, 10, 7, 5, 11 }, + { 101, 102, 105, 100, 103, 104, -1, -1 }, + { 0, 8, 3, 101, 104, 103, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 105, 101, 104, 200, -1, -1, -1, -1 }, + { 105, 102, 101, 200, -1, -1, -1, -1 }, + { 11, 102, 105, 5, 200, -1, -1, -1 }, + { 10, 103, 102, 11, 200, -1, -1, -1 }, + { 102, 103, 101, 200, -1, -1, -1, -1 }, + { 7, 10, 11, 5, 200, -1, -1, -1 }, + { 103, 104, 101, 200, -1, -1, -1, -1 }, + { 7, 104, 103, 10, 200, -1, -1, -1 }, + { 100, 105, 102, 0, 9, 1, -1, -1 }, + { 7, 5, 105, 104, 200, -1, -1, -1 }, + { 104, 105, 100, 200, -1, -1, -1, -1 }, + { 104, 100, 103, 200, -1, -1, -1, -1 }, + { 10, 7, 104, 103, 200, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 103, 100, 102, 200, -1, -1, -1, -1 }, + { 5, 7, 10, 11, 200, -1, -1, -1 }, + { 102, 100, 105, 200, -1, -1, -1, -1 }, + { 5, 11, 102, 105, 200, -1, -1, -1 }, + { 103, 104, 105, 102, 10, 7, 5, 11 }, + { 3, 8, 9, 1, 103, 104, 105, 102 }, + { 100, 104, 105, 101, 200, -1, -1, -1 }, + { 104, 100, 103, 200, -1, -1, -1, -1 }, + { 103, 100, 101, 200, -1, -1, -1, -1 }, + { 103, 101, 1, 2, 200, -1, -1, -1 }, + { 1, 101, 105, 5, 200, -1, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 7, 104, 103, 10, 200, -1, -1, -1 }, + { 2, 10, 103, 200, -1, -1, -1, -1 }, + { 104, 101, 103, 8, 0, 3, -1, -1 }, + { 101, 103, 104, 200, -1, -1, -1, -1 }, + { 104, 103, 10, 7, 200, -1, -1, -1 }, + { 105, 101, 104, 200, -1, -1, -1, -1 }, + { 1, 101, 105, 5, 200, -1, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 103, 101, 1, 2, 200, -1, -1, -1 }, + { 10, 103, 2, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 0, 2, 103, 100, 200, -1, -1, -1 }, + { 103, 104, 100, 200, -1, -1, -1, -1 }, + { 103, 2, 10, 200, -1, -1, -1, -1 }, + { 103, 10, 7, 104, 200, -1, -1, -1 }, + { 7, 5, 105, 104, 200, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 103, 104, 8, 3, 200, -1, -1, -1 }, + { 7, 104, 103, 10, 200, -1, -1, -1 }, + { 103, 3, 2, 200, -1, -1, -1, -1 }, + { 10, 103, 2, 200, -1, -1, -1, -1 }, + { 8, 104, 105, 9, 200, -1, -1, -1 }, + { 104, 7, 5, 105, 200, -1, -1, -1 }, + { 5, 9, 105, 200, -1, -1, -1, -1 }, + { 101, 100, 104, 105, 200, -1, -1, -1 }, + { 100, 101, 102, 200, -1, -1, -1, -1 }, + { 102, 101, 105, 200, -1, -1, -1, -1 }, + { 102, 105, 5, 11, 200, -1, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 3, 100, 102, 2, 200, -1, -1, -1 }, + { 11, 2, 102, 200, -1, -1, -1, -1 }, + { 101, 104, 105, 200, -1, -1, -1, -1 }, + { 0, 8, 104, 101, 200, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 102, 101, 105, 200, -1, -1, -1, -1 }, + { 102, 11, 2, 200, -1, -1, -1, -1 }, + { 102, 105, 5, 11, 200, -1, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 100, 105, 102, 0, 9, 1, -1, -1 }, + { 105, 102, 100, 200, -1, -1, -1, -1 }, + { 100, 102, 2, 3, 200, -1, -1, -1 }, + { 104, 105, 100, 200, -1, -1, -1, -1 }, + { 5, 105, 104, 7, 200, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 102, 105, 5, 11, 200, -1, -1, -1 }, + { 2, 102, 11, 200, -1, -1, -1, -1 }, + { 102, 1, 9, 105, 200, -1, -1, -1 }, + { 5, 11, 102, 105, 200, -1, -1, -1 }, + { 102, 2, 1, 200, -1, -1, -1, -1 }, + { 11, 2, 102, 200, -1, -1, -1, -1 }, + { 9, 8, 104, 105, 200, -1, -1, -1 }, + { 105, 104, 7, 5, 200, -1, -1, -1 }, + { 7, 104, 8, 200, -1, -1, -1, -1 }, + { 3, 1, 5, 7, 100, 101, 105, 104 }, + { 5, 1, 101, 105, 200, -1, -1, -1 }, + { 7, 5, 105, 104, 200, -1, -1, -1 }, + { 8, 7, 104, 200, -1, -1, -1, -1 }, + { 104, 105, 101, 200, -1, -1, -1, -1 }, + { 8, 104, 101, 0, 200, -1, -1, -1 }, + { 101, 1, 0, 200, -1, -1, -1, -1 }, + { 7, 5, 105, 104, 200, -1, -1, -1 }, + { 3, 7, 104, 100, 200, -1, -1, -1 }, + { 0, 3, 100, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 105, 5, 9, 200, -1, -1, -1, -1 }, + { 105, 9, 5, 104, 8, 7, -1, -1 }, + { 101, 102, 103, 100, 200, -1, -1, -1 }, + { 100, 105, 101, 200, -1, -1, -1, -1 }, + { 105, 102, 101, 200, -1, -1, -1, -1 }, + { 105, 5, 11, 102, 200, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 8, 4, 105, 100, 200, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 101, 102, 103, 200, -1, -1, -1, -1 }, + { 0, 101, 103, 3, 200, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 105, 102, 101, 200, -1, -1, -1, -1 }, + { 105, 4, 5, 200, -1, -1, -1, -1 }, + { 105, 5, 11, 102, 200, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 0, 1, 9, 100, 102, 105, -1, -1 }, + { 102, 100, 105, 200, -1, -1, -1, -1 }, + { 100, 8, 4, 105, 200, -1, -1, -1 }, + { 103, 100, 102, 200, -1, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 10, 8, 100, 103, 200, -1, -1, -1 }, + { 105, 5, 11, 102, 200, -1, -1, -1 }, + { 4, 5, 105, 200, -1, -1, -1, -1 }, + { 105, 102, 1, 9, 200, -1, -1, -1 }, + { 11, 102, 105, 5, 200, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 102, 11, 10, 103, 200, -1, -1, -1 }, + { 10, 3, 103, 200, -1, -1, -1, -1 }, + { 100, 105, 101, 200, -1, -1, -1, -1 }, + { 8, 4, 105, 100, 200, -1, -1, -1 }, + { 8, 100, 103, 10, 200, -1, -1, -1 }, + { 103, 100, 101, 200, -1, -1, -1, -1 }, + { 103, 2, 10, 200, -1, -1, -1, -1 }, + { 103, 101, 1, 2, 200, -1, -1, -1 }, + { 1, 101, 105, 5, 200, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 103, 3, 0, 101, 200, -1, -1, -1 }, + { 1, 2, 103, 101, 200, -1, -1, -1 }, + { 103, 10, 3, 200, -1, -1, -1, -1 }, + { 2, 10, 103, 200, -1, -1, -1, -1 }, + { 0, 4, 105, 101, 200, -1, -1, -1 }, + { 101, 105, 5, 1, 200, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 105, 100, 8, 4, 200, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 105, 4, 5, 200, -1, -1, -1, -1 }, + { 9, 105, 5, 200, -1, -1, -1, -1 }, + { 8, 100, 103, 10, 200, -1, -1, -1 }, + { 100, 0, 2, 103, 200, -1, -1, -1 }, + { 2, 10, 103, 200, -1, -1, -1, -1 }, + { 103, 3, 2, 10, -1, -1, -1, -1 }, + { 105, 9, 4, 5, -1, -1, -1, -1 }, + { 101, 100, 105, 102, -1, -1, -1, -1 }, + { 2, 3, 100, 102, 8, -1, -1, -1 }, + { 11, 102, 105, 5, 4, -1, -1, -1 }, + { 100, 8, 4, 105, 102, -1, -1, -1 }, + { 2, 11, 4, 8, 102, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 4, 105, 101, 0, 200, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 105, 102, 101, 200, -1, -1, -1, -1 }, + { 5, 11, 102, 105, 200, -1, -1, -1 }, + { 102, 11, 2, 200, -1, -1, -1, -1 }, + { 100, 105, 102, 0, 9, 1, -1, -1 }, + { 100, 102, 2, 3, 8, -1, -1, -1 }, + { 11, 102, 105, 5, 4, -1, -1, -1 }, + { 8, 4, 105, 100, 102, -1, -1, -1 }, + { 8, 2, 11, 4, 102, -1, -1, -1 }, + { 102, 1, 9, 105, 200, -1, -1, -1 }, + { 11, 102, 105, 5, 200, -1, -1, -1 }, + { 5, 105, 4, 200, -1, -1, -1, -1 }, + { 105, 9, 4, 200, -1, -1, -1, -1 }, + { 11, 102, 200, 2, -1, -1, -1, -1 }, + { 1, 102, 2, 200, -1, -1, -1, -1 }, + { 1, 101, 105, 5, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 8, 100, 3, 200, -1, -1, -1, -1 }, + { 100, 105, 101, 200, -1, -1, -1, -1 }, + { 8, 4, 105, 100, 200, -1, -1, -1 }, + { 105, 4, 5, 200, -1, -1, -1, -1 }, + { 101, 0, 1, 105, 4, 5, -1, -1 }, + { 100, 8, 4, 105, 200, -1, -1, -1 }, + { 0, 100, 105, 9, 200, -1, -1, -1 }, + { 9, 105, 5, 200, -1, -1, -1, -1 }, + { 105, 4, 5, 200, -1, -1, -1, -1 }, + { 0, 100, 200, 3, -1, -1, -1, -1 }, + { 8, 100, 3, 200, -1, -1, -1, -1 }, + { 105, 5, 9, 4, -1, -1, -1, -1 }, + { 100, 101, 102, 103, 200, -1, -1, -1 }, + { 103, 104, 100, 200, -1, -1, -1, -1 }, + { 104, 101, 100, 200, -1, -1, -1, -1 }, + { 104, 4, 9, 101, 200, -1, -1, -1 }, + { 9, 11, 102, 101, 200, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 10, 7, 104, 103, 200, -1, -1, -1 }, + { 4, 104, 7, 200, -1, -1, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 101, 103, 104, 200, -1, -1, -1, -1 }, + { 103, 10, 7, 104, 200, -1, -1, -1 }, + { 102, 103, 101, 200, -1, -1, -1, -1 }, + { 9, 11, 102, 101, 200, -1, -1, -1 }, + { 11, 10, 103, 102, 200, -1, -1, -1 }, + { 104, 4, 9, 101, 200, -1, -1, -1 }, + { 7, 4, 104, 200, -1, -1, -1, -1 }, + { 100, 102, 103, 200, -1, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 0, 100, 104, 4, 200, -1, -1, -1 }, + { 104, 100, 103, 200, -1, -1, -1, -1 }, + { 104, 7, 4, 200, -1, -1, -1, -1 }, + { 104, 103, 10, 7, 200, -1, -1, -1 }, + { 10, 103, 102, 11, 200, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 104, 8, 3, 103, 200, -1, -1, -1 }, + { 10, 7, 104, 103, 200, -1, -1, -1 }, + { 104, 4, 8, 200, -1, -1, -1, -1 }, + { 7, 4, 104, 200, -1, -1, -1, -1 }, + { 3, 1, 102, 103, 200, -1, -1, -1 }, + { 103, 102, 11, 10, 200, -1, -1, -1 }, + { 11, 102, 1, 200, -1, -1, -1, -1 }, + { 100, 101, 103, 104, -1, -1, -1, -1 }, + { 7, 104, 103, 10, 2, -1, -1, -1 }, + { 4, 9, 101, 104, 1, -1, -1, -1 }, + { 103, 101, 1, 2, 104, -1, -1, -1 }, + { 7, 2, 1, 4, 104, -1, -1, -1 }, + { 3, 0, 8, 103, 101, 104, -1, -1 }, + { 103, 10, 7, 104, 2, -1, -1, -1 }, + { 4, 9, 101, 104, 1, -1, -1, -1 }, + { 2, 103, 101, 1, 104, -1, -1, -1 }, + { 2, 1, 4, 7, 104, -1, -1, -1 }, + { 0, 2, 103, 100, 200, -1, -1, -1 }, + { 4, 0, 100, 104, 200, -1, -1, -1 }, + { 7, 4, 104, 200, -1, -1, -1, -1 }, + { 104, 100, 103, 200, -1, -1, -1, -1 }, + { 7, 104, 103, 10, 200, -1, -1, -1 }, + { 103, 2, 10, 200, -1, -1, -1, -1 }, + { 103, 104, 8, 3, 200, -1, -1, -1 }, + { 10, 7, 104, 103, 200, -1, -1, -1 }, + { 7, 4, 104, 200, -1, -1, -1, -1 }, + { 104, 4, 8, 200, -1, -1, -1, -1 }, + { 10, 200, 103, 2, -1, -1, -1, -1 }, + { 3, 2, 103, 200, -1, -1, -1, -1 }, + { 100, 101, 102, 200, -1, -1, -1, -1 }, + { 3, 100, 102, 2, 200, -1, -1, -1 }, + { 3, 7, 104, 100, 200, -1, -1, -1 }, + { 104, 101, 100, 200, -1, -1, -1, -1 }, + { 104, 7, 4, 200, -1, -1, -1, -1 }, + { 104, 4, 9, 101, 200, -1, -1, -1 }, + { 9, 11, 102, 101, 200, -1, -1, -1 }, + { 11, 2, 102, 200, -1, -1, -1, -1 }, + { 104, 101, 0, 8, 200, -1, -1, -1 }, + { 9, 101, 104, 4, 200, -1, -1, -1 }, + { 104, 8, 7, 200, -1, -1, -1, -1 }, + { 4, 104, 7, 200, -1, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 101, 9, 11, 102, 200, -1, -1, -1 }, + { 11, 2, 102, 200, -1, -1, -1, -1 }, + { 102, 2, 3, 100, 200, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 102, 11, 2, 200, -1, -1, -1, -1 }, + { 1, 11, 102, 200, -1, -1, -1, -1 }, + { 3, 7, 104, 100, 200, -1, -1, -1 }, + { 100, 104, 4, 0, 200, -1, -1, -1 }, + { 4, 104, 7, 200, -1, -1, -1, -1 }, + { 104, 4, 8, 7, -1, -1, -1, -1 }, + { 102, 2, 1, 11, -1, -1, -1, -1 }, + { 3, 7, 104, 100, 200, -1, -1, -1 }, + { 1, 3, 100, 101, 200, -1, -1, -1 }, + { 9, 1, 101, 200, -1, -1, -1, -1 }, + { 101, 100, 104, 200, -1, -1, -1, -1 }, + { 9, 101, 104, 4, 200, -1, -1, -1 }, + { 104, 7, 4, 200, -1, -1, -1, -1 }, + { 104, 101, 0, 8, 200, -1, -1, -1 }, + { 4, 9, 101, 104, 200, -1, -1, -1 }, + { 9, 1, 101, 200, -1, -1, -1, -1 }, + { 101, 1, 0, 200, -1, -1, -1, -1 }, + { 4, 200, 104, 7, -1, -1, -1, -1 }, + { 8, 7, 104, 200, -1, -1, -1, -1 }, + { 100, 3, 0, 104, 7, 4, -1, -1 }, + { 104, 4, 8, 7, -1, -1, -1, -1 }, + { 100, 101, 102, 103, 8, 9, 11, 10 }, + { 11, 102, 101, 9, 200, -1, -1, -1 }, + { 10, 103, 102, 11, 200, -1, -1, -1 }, + { 3, 103, 10, 200, -1, -1, -1, -1 }, + { 103, 101, 102, 200, -1, -1, -1, -1 }, + { 3, 0, 101, 103, 200, -1, -1, -1 }, + { 101, 0, 9, 200, -1, -1, -1, -1 }, + { 10, 103, 102, 11, 200, -1, -1, -1 }, + { 8, 100, 103, 10, 200, -1, -1, -1 }, + { 0, 100, 8, 200, -1, -1, -1, -1 }, + { 100, 102, 103, 200, -1, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 102, 1, 11, 200, -1, -1, -1, -1 }, + { 103, 3, 10, 102, 1, 11, -1, -1 }, + { 8, 100, 103, 10, 200, -1, -1, -1 }, + { 9, 101, 100, 8, 200, -1, -1, -1 }, + { 1, 101, 9, 200, -1, -1, -1, -1 }, + { 101, 103, 100, 200, -1, -1, -1, -1 }, + { 1, 2, 103, 101, 200, -1, -1, -1 }, + { 103, 2, 10, 200, -1, -1, -1, -1 }, + { 103, 3, 0, 101, 200, -1, -1, -1 }, + { 2, 103, 101, 1, 200, -1, -1, -1 }, + { 1, 101, 9, 200, -1, -1, -1, -1 }, + { 101, 0, 9, 200, -1, -1, -1, -1 }, + { 2, 103, 200, 10, -1, -1, -1, -1 }, + { 3, 103, 10, 200, -1, -1, -1, -1 }, + { 103, 10, 2, 100, 8, 0, -1, -1 }, + { 103, 3, 2, 10, -1, -1, -1, -1 }, + { 9, 11, 102, 101, 200, -1, -1, -1 }, + { 8, 9, 101, 100, 200, -1, -1, -1 }, + { 3, 8, 100, 200, -1, -1, -1, -1 }, + { 100, 101, 102, 200, -1, -1, -1, -1 }, + { 3, 100, 102, 2, 200, -1, -1, -1 }, + { 102, 11, 2, 200, -1, -1, -1, -1 }, + { 102, 2, 11, 101, 0, 9, -1, -1 }, + { 100, 102, 2, 3, 200, -1, -1, -1 }, + { 0, 1, 102, 100, 200, -1, -1, -1 }, + { 1, 11, 102, 200, -1, -1, -1, -1 }, + { 102, 11, 2, 200, -1, -1, -1, -1 }, + { 0, 200, 100, 8, -1, -1, -1, -1 }, + { 3, 8, 100, 200, -1, -1, -1, -1 }, + { 102, 1, 11, 2, -1, -1, -1, -1 }, + { 101, 1, 9, 100, 3, 8, -1, -1 }, + { 101, 0, 9, 1, -1, -1, -1, -1 }, + { 100, 0, 3, 8, -1, -1, -1, -1 } +}; + +// Special points (e.g. centroid): per-case definition streams +constexpr int special_point_count_outside[256] = { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0 }; +constexpr int special_point_offset_outside[257] = { 0, 0, 8, 16, 16, 24, 24, 24, 30, 38, 38, 38, 44, 44, 50, 56, 56, 64, 64, 64, 70, 70, 77, 84, 91, 91, 97, 97, 97, 104, 111, 117, 123, 131, 131, 131, 137, 137, 137, 143, 143, 143, 150, 157, 164, 171, 177, 184, 190, 190, 196, 202, 202, 209, 215, 222, 228, 235, 242, 248, 254, 254, 259, 264, 264, 272, 272, 272, 279, 279, 286, 292, 299, 299, 306, 306, 312, 318, 325, 325, 331, 331, 338, 338, 344, 351, 351, 357, 362, 362, 368, 368, 368, 374, 379, 379, 382, 382, 389, 395, 402, 408, 414, 414, 420, 427, 427, 433, 438, 445, 450, 456, 456, 462, 469, 469, 475, 482, 487, 493, 493, 499, 504, 504, 507, 512, 512, 515, 515, 523, 523, 523, 530, 530, 530, 537, 543, 543, 549, 556, 563, 569, 569, 576, 582, 582, 588, 595, 602, 609, 615, 615, 620, 626, 626, 632, 638, 645, 651, 656, 656, 656, 656, 663, 669, 669, 669, 675, 675, 682, 688, 688, 693, 699, 699, 704, 707, 713, 713, 720, 726, 732, 732, 737, 740, 747, 753, 758, 758, 763, 766, 766, 766, 766, 773, 780, 780, 786, 792, 799, 804, 810, 817, 823, 828, 828, 834, 840, 840, 846, 853, 859, 864, 871, 876, 881, 881, 881, 887, 887, 890, 896, 896, 899, 899, 905, 911, 918, 923, 923, 923, 929, 932, 939, 944, 949, 949, 955, 958, 958, 958, 958, 964, 970, 970, 976, 979, 979, 979, 985, 985, 988, 988, 988, 988, 988, 988 }; +constexpr int special_point_data_outside[988] = { 7, 107, 106, 105, 104, 103, 102, 101, 7, 103, 107, 104, 100, 102, 106, 105, 7, 100, 104, 107, 103, 101, 105, 106, 5, 11, 9, 8, 2, 3, 7, 104, 105, 101, 100, 107, 106, 102, 5, 10, 8, 9, 2, 1, 5, 11, 10, 8, 1, 0, 5, 9, 11, 10, 0, 3, 7, 103, 102, 101, 100, 107, 106, 105, 5, 7, 3, 1, 4, 9, 6, 106, 101, 105, 107, 3, 7, 6, 107, 100, 103, 106, 9, 11, 6, 7, 4, 9, 11, 2, 3, 5, 2, 0, 4, 10, 7, 6, 105, 100, 101, 106, 10, 11, 6, 4, 7, 10, 11, 1, 0, 5, 11, 9, 10, 3, 0, 5, 10, 11, 7, 4, 9, 7, 100, 103, 107, 104, 101, 102, 106, 5, 5, 1, 3, 4, 8, 5, 2, 0, 4, 11, 5, 6, 106, 101, 102, 107, 8, 10, 6, 107, 100, 104, 106, 1, 5, 6, 10, 2, 1, 5, 4, 8, 6, 104, 101, 100, 107, 11, 10, 5, 10, 11, 8, 0, 1, 6, 4, 5, 11, 10, 3, 0, 5, 8, 10, 4, 5, 11, 5, 5, 7, 3, 9, 0, 5, 1, 5, 7, 0, 8, 6, 103, 101, 100, 107, 5, 7, 5, 7, 5, 3, 0, 9, 6, 2, 11, 5, 7, 8, 0, 5, 3, 7, 2, 11, 5, 6, 102, 100, 101, 106, 7, 5, 6, 2, 10, 7, 5, 9, 0, 5, 5, 1, 7, 8, 0, 5, 7, 5, 10, 2, 1, 4, 10, 7, 0, 0, 4, 11, 5, 0, 0, 7, 101, 100, 103, 102, 105, 104, 107, 6, 107, 105, 104, 103, 1, 3, 6, 104, 103, 107, 105, 1, 5, 5, 6, 2, 0, 5, 9, 6, 8, 3, 2, 6, 5, 9, 6, 105, 102, 101, 104, 10, 8, 5, 8, 10, 9, 1, 2, 5, 5, 1, 3, 6, 10, 6, 8, 0, 1, 5, 6, 10, 5, 9, 8, 5, 6, 10, 6, 102, 105, 101, 103, 7, 3, 5, 3, 7, 1, 9, 4, 6, 100, 107, 103, 101, 5, 1, 5, 2, 6, 0, 9, 5, 4, 2, 3, 9, 9, 5, 0, 2, 4, 7, 10, 5, 1, 5, 3, 10, 6, 4, 1, 0, 10, 10, 2, 10, 9, 6, 103, 104, 107, 102, 9, 11, 5, 6, 4, 0, 11, 1, 6, 3, 8, 4, 6, 11, 1, 5, 4, 6, 2, 9, 1, 5, 6, 4, 2, 1, 9, 5, 2, 6, 3, 8, 4, 6, 100, 107, 104, 101, 11, 9, 5, 4, 6, 0, 1, 11, 4, 4, 8, 1, 1, 6, 3, 10, 6, 4, 9, 1, 4, 6, 10, 1, 1, 5, 0, 4, 3, 10, 6, 5, 11, 9, 8, 6, 7, 6, 3, 0, 9, 11, 6, 7, 5, 1, 3, 11, 6, 7, 6, 8, 7, 6, 2, 1, 9, 4, 6, 7, 9, 9, 5, 0, 2, 8, 7, 6, 5, 9, 11, 8, 7, 6, 4, 9, 0, 7, 7, 2, 7, 1, 4, 9, 1, 6, 6, 2, 0, 6, 7, 100, 101, 102, 103, 104, 105, 106, 6, 106, 104, 105, 102, 3, 1, 6, 104, 103, 100, 105, 11, 9, 5, 9, 11, 8, 3, 2, 5, 6, 2, 0, 7, 8, 6, 105, 100, 104, 106, 2, 6, 6, 9, 1, 2, 6, 7, 8, 5, 7, 3, 1, 6, 11, 6, 7, 6, 11, 9, 0, 3, 5, 8, 9, 7, 6, 11, 5, 6, 4, 0, 10, 3, 6, 102, 100, 103, 106, 4, 6, 6, 1, 9, 4, 6, 10, 3, 6, 101, 103, 100, 105, 6, 4, 5, 4, 6, 0, 3, 10, 4, 4, 9, 3, 3, 5, 4, 6, 2, 8, 3, 5, 6, 4, 2, 3, 8, 5, 2, 6, 1, 9, 4, 6, 1, 11, 6, 4, 8, 3, 5, 0, 4, 1, 11, 6, 4, 6, 11, 3, 3, 6, 103, 104, 100, 102, 5, 1, 5, 1, 5, 3, 8, 4, 5, 0, 2, 4, 5, 11, 6, 101, 104, 100, 102, 6, 2, 5, 2, 6, 0, 8, 7, 4, 2, 1, 8, 8, 5, 3, 7, 1, 11, 6, 4, 0, 3, 11, 11, 2, 8, 11, 5, 10, 8, 9, 6, 5, 6, 10, 6, 5, 1, 0, 8, 5, 3, 1, 10, 6, 5, 5, 8, 10, 9, 5, 6, 4, 0, 8, 5, 5, 2, 3, 5, 6, 9, 5, 6, 2, 3, 8, 5, 0, 2, 9, 5, 6, 4, 6, 5, 8, 8, 4, 8, 3, 6, 6, 2, 0, 6, 6, 101, 103, 102, 105, 7, 5, 6, 100, 102, 103, 104, 5, 7, 5, 1, 5, 7, 2, 10, 5, 5, 1, 7, 10, 2, 6, 0, 9, 5, 7, 10, 2, 4, 5, 9, 2, 2, 5, 5, 7, 3, 11, 2, 6, 0, 8, 7, 5, 11, 2, 5, 7, 5, 3, 2, 11, 4, 7, 8, 2, 2, 5, 7, 5, 8, 0, 1, 5, 3, 7, 0, 9, 5, 5, 11, 10, 8, 5, 4, 6, 0, 3, 10, 11, 5, 4, 5, 10, 11, 8, 4, 5, 4, 10, 3, 4, 4, 6, 8, 4, 5, 1, 2, 10, 4, 5, 4, 10, 10, 4, 2, 10, 5, 5, 5, 4, 0, 5, 11, 2, 2, 2, 4, 5, 3, 1, 8, 4, 5, 2, 3, 5, 5, 9, 11, 10, 4, 7, 5, 11, 9, 10, 7, 4, 6, 0, 1, 11, 10, 7, 4, 4, 11, 1, 4, 4, 5, 4, 0, 7, 10, 2, 2, 2, 4, 6, 3, 2, 11, 9, 4, 7, 4, 11, 2, 7, 7, 4, 4, 7, 11, 11, 5, 1, 3, 9, 4, 7, 2, 7, 1, 5, 10, 11, 3, 0, 9, 5, 8, 10, 0, 1, 11, 5, 9, 8, 1, 2, 10, 2, 10, 9, 5, 8, 9, 3, 2, 11, 2, 8, 11 }; + +} // namespace cutcells::cell::hexahedron + +#endif // CUT_CELLS_HEXAHEDRON_OUTSIDE_TABLES_H \ No newline at end of file diff --git a/cpp/src/generated/cut_prism_inside_tables.h b/cpp/src/generated/cut_prism_inside_tables.h new file mode 100644 index 0000000..b02877b --- /dev/null +++ b/cpp/src/generated/cut_prism_inside_tables.h @@ -0,0 +1,350 @@ +#ifndef CUT_CELLS_PRISM_INSIDE_TABLES_H +#define CUT_CELLS_PRISM_INSIDE_TABLES_H + +// ----------------------------------------------------------------------------- +// This file is generated by CutCells tablegen. +// +// It contains case tables derived from VTK's vtkTableBasedClipCases.h +// (Visualization Toolkit, TableBasedClip). +// +// VTK is licensed under the BSD 3-Clause License. +// See third_party/VTK-Copyright.txt in this repository. +// ----------------------------------------------------------------------------- + +#include "cell_types.h" + +namespace cutcells::cell::prism { + +// Intersected edges per case (1 = intersected, 0 = not intersected) +constexpr int intersected_edges[64][9] = { + { 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 1, 0, 0, 0, 1, 0, 0 }, + { 1, 1, 0, 0, 0, 0, 0, 1, 0 }, + { 0, 1, 1, 0, 0, 0, 1, 1, 0 }, + { 0, 1, 1, 0, 0, 0, 0, 0, 1 }, + { 1, 1, 0, 0, 0, 0, 1, 0, 1 }, + { 1, 0, 1, 0, 0, 0, 0, 1, 1 }, + { 0, 0, 0, 0, 0, 0, 1, 1, 1 }, + { 0, 0, 0, 1, 0, 1, 1, 0, 0 }, + { 1, 0, 1, 1, 0, 1, 0, 0, 0 }, + { 1, 1, 0, 1, 0, 1, 1, 1, 0 }, + { 0, 1, 1, 1, 0, 1, 0, 1, 0 }, + { 0, 1, 1, 1, 0, 1, 1, 0, 1 }, + { 1, 1, 0, 1, 0, 1, 0, 0, 1 }, + { 1, 0, 1, 1, 0, 1, 1, 1, 1 }, + { 0, 0, 0, 1, 0, 1, 0, 1, 1 }, + { 0, 0, 0, 1, 1, 0, 0, 1, 0 }, + { 1, 0, 1, 1, 1, 0, 1, 1, 0 }, + { 1, 1, 0, 1, 1, 0, 0, 0, 0 }, + { 0, 1, 1, 1, 1, 0, 1, 0, 0 }, + { 0, 1, 1, 1, 1, 0, 0, 1, 1 }, + { 1, 1, 0, 1, 1, 0, 1, 1, 1 }, + { 1, 0, 1, 1, 1, 0, 0, 0, 1 }, + { 0, 0, 0, 1, 1, 0, 1, 0, 1 }, + { 0, 0, 0, 0, 1, 1, 1, 1, 0 }, + { 1, 0, 1, 0, 1, 1, 0, 1, 0 }, + { 1, 1, 0, 0, 1, 1, 1, 0, 0 }, + { 0, 1, 1, 0, 1, 1, 0, 0, 0 }, + { 0, 1, 1, 0, 1, 1, 1, 1, 1 }, + { 1, 1, 0, 0, 1, 1, 0, 1, 1 }, + { 1, 0, 1, 0, 1, 1, 1, 0, 1 }, + { 0, 0, 0, 0, 1, 1, 0, 0, 1 }, + { 0, 0, 0, 0, 1, 1, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 1, 1, 0, 1 }, + { 1, 1, 0, 0, 1, 1, 0, 1, 1 }, + { 0, 1, 1, 0, 1, 1, 1, 1, 1 }, + { 0, 1, 1, 0, 1, 1, 0, 0, 0 }, + { 1, 1, 0, 0, 1, 1, 1, 0, 0 }, + { 1, 0, 1, 0, 1, 1, 0, 1, 0 }, + { 0, 0, 0, 0, 1, 1, 1, 1, 0 }, + { 0, 0, 0, 1, 1, 0, 1, 0, 1 }, + { 1, 0, 1, 1, 1, 0, 0, 0, 1 }, + { 1, 1, 0, 1, 1, 0, 1, 1, 1 }, + { 0, 1, 1, 1, 1, 0, 0, 1, 1 }, + { 0, 1, 1, 1, 1, 0, 1, 0, 0 }, + { 1, 1, 0, 1, 1, 0, 0, 0, 0 }, + { 1, 0, 1, 1, 1, 0, 1, 1, 0 }, + { 0, 0, 0, 1, 1, 0, 0, 1, 0 }, + { 0, 0, 0, 1, 0, 1, 0, 1, 1 }, + { 1, 0, 1, 1, 0, 1, 1, 1, 1 }, + { 1, 1, 0, 1, 0, 1, 0, 0, 1 }, + { 0, 1, 1, 1, 0, 1, 1, 0, 1 }, + { 0, 1, 1, 1, 0, 1, 0, 1, 0 }, + { 1, 1, 0, 1, 0, 1, 1, 1, 0 }, + { 1, 0, 1, 1, 0, 1, 0, 0, 0 }, + { 0, 0, 0, 1, 0, 1, 1, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 1, 1, 1 }, + { 1, 0, 1, 0, 0, 0, 0, 1, 1 }, + { 1, 1, 0, 0, 0, 0, 1, 0, 1 }, + { 0, 1, 1, 0, 0, 0, 0, 0, 1 }, + { 0, 1, 1, 0, 0, 0, 1, 1, 0 }, + { 1, 1, 0, 0, 0, 0, 0, 1, 0 }, + { 1, 0, 1, 0, 0, 0, 1, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +// Number of subcells produced for each case (inside volume) +constexpr int num_subcells_inside[64] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 6, 6, 6, 7, 7, 1, 6, 1, 6, 6, 7, 6, 7, 1, 6, 6, 1, 7, 3, 3, 2, 1, 6, 6, 7, 1, 6, 6, 7, 1, 6, 7, 3, 6, 1, 3, 2, 1, 7, 6, 3, 6, 3, 1, 2, 1, 7, 7, 2, 7, 2, 2, 1 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_inside[65] = { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 21, 27, 33, 40, 47, 48, 54, 55, 61, 67, 74, 80, 87, 88, 94, 100, 101, 108, 111, 114, 116, 117, 123, 129, 136, 137, 143, 149, 156, 157, 163, 170, 173, 179, 180, 183, 185, 186, 193, 199, 202, 208, 211, 212, 214, 215, 222, 229, 231, 238, 240, 242, 243 }; + +// Cell types for inside subcells +constexpr type subcell_type_inside[243] = { cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::hexahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::hexahedron, cell::type::prism, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::prism }; + +// Subcell vertices (max 8 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, 100..199 = 100+vertex_id, >=200 = 200+special_point_id +constexpr int subcell_verts_inside[243][8] = { + { 6, 0, 2, 100, -1, -1, -1, -1 }, + { 7, 1, 0, 101, -1, -1, -1, -1 }, + { 2, 6, 100, 1, 7, 101, -1, -1 }, + { 8, 2, 1, 102, -1, -1, -1, -1 }, + { 1, 8, 102, 0, 6, 100, -1, -1 }, + { 0, 7, 101, 2, 8, 102, -1, -1 }, + { 100, 101, 102, 6, 7, 8, -1, -1 }, + { 6, 5, 3, 103, -1, -1, -1, -1 }, + { 100, 0, 2, 103, 3, 5, -1, -1 }, + { 6, 0, 101, 103, 200, -1, -1, -1 }, + { 103, 101, 7, 3, 200, -1, -1, -1 }, + { 103, 3, 5, 200, -1, -1, -1, -1 }, + { 5, 6, 103, 200, -1, -1, -1, -1 }, + { 101, 1, 7, 200, -1, -1, -1, -1 }, + { 101, 0, 1, 200, -1, -1, -1, -1 }, + { 100, 101, 103, 200, -1, -1, -1, -1 }, + { 2, 1, 101, 100, 200, -1, -1, -1 }, + { 2, 100, 103, 5, 200, -1, -1, -1 }, + { 5, 103, 3, 200, -1, -1, -1, -1 }, + { 103, 101, 7, 3, 200, -1, -1, -1 }, + { 101, 1, 7, 200, -1, -1, -1, -1 }, + { 8, 102, 103, 5, 200, -1, -1, -1 }, + { 102, 2, 6, 103, 200, -1, -1, -1 }, + { 102, 1, 2, 200, -1, -1, -1, -1 }, + { 1, 102, 8, 200, -1, -1, -1, -1 }, + { 103, 6, 3, 200, -1, -1, -1, -1 }, + { 103, 3, 5, 200, -1, -1, -1, -1 }, + { 100, 103, 102, 200, -1, -1, -1, -1 }, + { 0, 100, 102, 1, 200, -1, -1, -1 }, + { 0, 3, 103, 100, 200, -1, -1, -1 }, + { 3, 5, 103, 200, -1, -1, -1, -1 }, + { 103, 5, 8, 102, 200, -1, -1, -1 }, + { 102, 8, 1, 200, -1, -1, -1, -1 }, + { 102, 101, 103, 2, 0, 6, -1, -1 }, + { 5, 3, 7, 8, 200, -1, -1, -1 }, + { 7, 101, 102, 8, 200, -1, -1, -1 }, + { 103, 102, 101, 200, -1, -1, -1, -1 }, + { 103, 3, 5, 200, -1, -1, -1, -1 }, + { 3, 103, 101, 7, 200, -1, -1, -1 }, + { 8, 102, 103, 5, 200, -1, -1, -1 }, + { 100, 102, 101, 103, -1, -1, -1, -1 }, + { 5, 3, 7, 8, 200, -1, -1, -1 }, + { 8, 7, 101, 102, 200, -1, -1, -1 }, + { 103, 102, 101, 200, -1, -1, -1, -1 }, + { 103, 3, 5, 200, -1, -1, -1, -1 }, + { 103, 101, 7, 3, 200, -1, -1, -1 }, + { 102, 103, 5, 8, 200, -1, -1, -1 }, + { 7, 3, 4, 104, -1, -1, -1, -1 }, + { 6, 100, 104, 3, 200, -1, -1, -1 }, + { 100, 0, 7, 104, 200, -1, -1, -1 }, + { 100, 2, 0, 200, -1, -1, -1, -1 }, + { 2, 100, 6, 200, -1, -1, -1, -1 }, + { 104, 7, 4, 200, -1, -1, -1, -1 }, + { 104, 4, 3, 200, -1, -1, -1, -1 }, + { 101, 1, 0, 104, 4, 3, -1, -1 }, + { 101, 104, 100, 200, -1, -1, -1, -1 }, + { 1, 101, 100, 2, 200, -1, -1, -1 }, + { 1, 4, 104, 101, 200, -1, -1, -1 }, + { 4, 3, 104, 200, -1, -1, -1, -1 }, + { 104, 3, 6, 100, 200, -1, -1, -1 }, + { 100, 6, 2, 200, -1, -1, -1, -1 }, + { 7, 1, 102, 104, 200, -1, -1, -1 }, + { 104, 102, 8, 4, 200, -1, -1, -1 }, + { 104, 4, 3, 200, -1, -1, -1, -1 }, + { 3, 7, 104, 200, -1, -1, -1, -1 }, + { 102, 2, 8, 200, -1, -1, -1, -1 }, + { 102, 1, 2, 200, -1, -1, -1, -1 }, + { 100, 102, 104, 0, 1, 7, -1, -1 }, + { 3, 4, 8, 6, 200, -1, -1, -1 }, + { 8, 102, 100, 6, 200, -1, -1, -1 }, + { 104, 100, 102, 200, -1, -1, -1, -1 }, + { 104, 4, 3, 200, -1, -1, -1, -1 }, + { 4, 104, 102, 8, 200, -1, -1, -1 }, + { 6, 100, 104, 3, 200, -1, -1, -1 }, + { 101, 102, 104, 200, -1, -1, -1, -1 }, + { 0, 2, 102, 101, 200, -1, -1, -1 }, + { 0, 101, 104, 3, 200, -1, -1, -1 }, + { 3, 104, 4, 200, -1, -1, -1, -1 }, + { 104, 102, 8, 4, 200, -1, -1, -1 }, + { 102, 2, 8, 200, -1, -1, -1, -1 }, + { 101, 100, 102, 104, -1, -1, -1, -1 }, + { 3, 4, 8, 6, 200, -1, -1, -1 }, + { 6, 8, 102, 100, 200, -1, -1, -1 }, + { 104, 100, 102, 200, -1, -1, -1, -1 }, + { 104, 4, 3, 200, -1, -1, -1, -1 }, + { 104, 102, 8, 4, 200, -1, -1, -1 }, + { 100, 104, 3, 6, 200, -1, -1, -1 }, + { 4, 7, 104, 5, 6, 103, -1, -1 }, + { 103, 100, 104, 200, -1, -1, -1, -1 }, + { 5, 103, 104, 4, 200, -1, -1, -1 }, + { 5, 2, 100, 103, 200, -1, -1, -1 }, + { 2, 0, 100, 200, -1, -1, -1, -1 }, + { 100, 0, 7, 104, 200, -1, -1, -1 }, + { 104, 7, 4, 200, -1, -1, -1, -1 }, + { 104, 103, 101, 200, -1, -1, -1, -1 }, + { 4, 5, 103, 104, 200, -1, -1, -1 }, + { 4, 104, 101, 1, 200, -1, -1, -1 }, + { 1, 101, 0, 200, -1, -1, -1, -1 }, + { 101, 103, 6, 0, 200, -1, -1, -1 }, + { 103, 5, 6, 200, -1, -1, -1, -1 }, + { 103, 104, 4, 5, 100, 101, 1, 2 }, + { 4, 5, 8, 104, 103, 102, -1, -1 }, + { 1, 7, 6, 2, 200, -1, -1, -1 }, + { 6, 7, 104, 103, 200, -1, -1, -1 }, + { 102, 103, 104, 200, -1, -1, -1, -1 }, + { 102, 1, 2, 200, -1, -1, -1, -1 }, + { 2, 6, 103, 102, 200, -1, -1, -1 }, + { 7, 1, 102, 104, 200, -1, -1, -1 }, + { 102, 103, 104, 8, 5, 4, -1, -1 }, + { 102, 103, 104, 100, -1, -1, -1, -1 }, + { 102, 104, 100, 1, 7, 0, -1, -1 }, + { 6, 0, 2, 103, 101, 102, -1, -1 }, + { 103, 102, 101, 104, -1, -1, -1, -1 }, + { 5, 8, 4, 103, 102, 104, -1, -1 }, + { 8, 4, 5, 102, 104, 103, -1, -1 }, + { 100, 101, 104, 103, 102, -1, -1, -1 }, + { 8, 4, 5, 105, -1, -1, -1, -1 }, + { 8, 2, 100, 105, 200, -1, -1, -1 }, + { 105, 100, 6, 5, 200, -1, -1, -1 }, + { 105, 5, 4, 200, -1, -1, -1, -1 }, + { 4, 8, 105, 200, -1, -1, -1, -1 }, + { 100, 0, 6, 200, -1, -1, -1, -1 }, + { 100, 2, 0, 200, -1, -1, -1, -1 }, + { 7, 101, 105, 4, 200, -1, -1, -1 }, + { 101, 1, 8, 105, 200, -1, -1, -1 }, + { 101, 0, 1, 200, -1, -1, -1, -1 }, + { 0, 101, 7, 200, -1, -1, -1, -1 }, + { 105, 8, 5, 200, -1, -1, -1, -1 }, + { 105, 5, 4, 200, -1, -1, -1, -1 }, + { 101, 100, 105, 1, 2, 8, -1, -1 }, + { 4, 5, 6, 7, 200, -1, -1, -1 }, + { 6, 100, 101, 7, 200, -1, -1, -1 }, + { 105, 101, 100, 200, -1, -1, -1, -1 }, + { 105, 5, 4, 200, -1, -1, -1, -1 }, + { 5, 105, 100, 6, 200, -1, -1, -1 }, + { 7, 101, 105, 4, 200, -1, -1, -1 }, + { 102, 2, 1, 105, 5, 4, -1, -1 }, + { 102, 100, 105, 200, -1, -1, -1, -1 }, + { 1, 0, 100, 102, 200, -1, -1, -1 }, + { 1, 102, 105, 4, 200, -1, -1, -1 }, + { 4, 105, 5, 200, -1, -1, -1, -1 }, + { 105, 100, 6, 5, 200, -1, -1, -1 }, + { 100, 0, 6, 200, -1, -1, -1, -1 }, + { 102, 105, 101, 200, -1, -1, -1, -1 }, + { 2, 102, 101, 0, 200, -1, -1, -1 }, + { 2, 5, 105, 102, 200, -1, -1, -1 }, + { 5, 4, 105, 200, -1, -1, -1, -1 }, + { 105, 4, 7, 101, 200, -1, -1, -1 }, + { 101, 7, 0, 200, -1, -1, -1, -1 }, + { 102, 101, 100, 105, -1, -1, -1, -1 }, + { 4, 5, 6, 7, 200, -1, -1, -1 }, + { 7, 6, 100, 101, 200, -1, -1, -1 }, + { 105, 101, 100, 200, -1, -1, -1, -1 }, + { 105, 5, 4, 200, -1, -1, -1, -1 }, + { 105, 100, 6, 5, 200, -1, -1, -1 }, + { 101, 105, 4, 7, 200, -1, -1, -1 }, + { 3, 6, 103, 4, 8, 105, -1, -1 }, + { 103, 105, 100, 200, -1, -1, -1, -1 }, + { 3, 4, 105, 103, 200, -1, -1, -1 }, + { 3, 103, 100, 0, 200, -1, -1, -1 }, + { 0, 100, 2, 200, -1, -1, -1, -1 }, + { 100, 105, 8, 2, 200, -1, -1, -1 }, + { 105, 4, 8, 200, -1, -1, -1, -1 }, + { 3, 4, 7, 103, 105, 101, -1, -1 }, + { 0, 6, 8, 1, 200, -1, -1, -1 }, + { 8, 6, 103, 105, 200, -1, -1, -1 }, + { 101, 105, 103, 200, -1, -1, -1, -1 }, + { 101, 0, 1, 200, -1, -1, -1, -1 }, + { 1, 8, 105, 101, 200, -1, -1, -1 }, + { 6, 0, 101, 103, 200, -1, -1, -1 }, + { 8, 2, 1, 105, 100, 101, -1, -1 }, + { 105, 101, 100, 103, -1, -1, -1, -1 }, + { 4, 7, 3, 105, 101, 103, -1, -1 }, + { 105, 102, 103, 200, -1, -1, -1, -1 }, + { 4, 105, 103, 3, 200, -1, -1, -1 }, + { 4, 1, 102, 105, 200, -1, -1, -1 }, + { 1, 2, 102, 200, -1, -1, -1, -1 }, + { 102, 2, 6, 103, 200, -1, -1, -1 }, + { 103, 6, 3, 200, -1, -1, -1, -1 }, + { 105, 103, 3, 4, 102, 100, 0, 1 }, + { 101, 105, 103, 7, 4, 3, -1, -1 }, + { 101, 105, 103, 102, -1, -1, -1, -1 }, + { 101, 103, 102, 0, 6, 2, -1, -1 }, + { 7, 3, 4, 101, 103, 105, -1, -1 }, + { 102, 100, 103, 105, 101, -1, -1, -1 }, + { 5, 8, 105, 3, 7, 104, -1, -1 }, + { 5, 3, 6, 105, 104, 100, -1, -1 }, + { 2, 8, 7, 0, 200, -1, -1, -1 }, + { 7, 8, 105, 104, 200, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 100, 2, 0, 200, -1, -1, -1, -1 }, + { 0, 7, 104, 100, 200, -1, -1, -1 }, + { 8, 2, 100, 105, 200, -1, -1, -1 }, + { 104, 101, 105, 200, -1, -1, -1, -1 }, + { 3, 104, 105, 5, 200, -1, -1, -1 }, + { 3, 0, 101, 104, 200, -1, -1, -1 }, + { 0, 1, 101, 200, -1, -1, -1, -1 }, + { 101, 1, 8, 105, 200, -1, -1, -1 }, + { 105, 8, 5, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 6, 3, 5, -1, -1 }, + { 100, 104, 105, 101, -1, -1, -1, -1 }, + { 100, 105, 101, 2, 8, 1, -1, -1 }, + { 105, 104, 102, 200, -1, -1, -1, -1 }, + { 5, 3, 104, 105, 200, -1, -1, -1 }, + { 5, 105, 102, 2, 200, -1, -1, -1 }, + { 2, 102, 1, 200, -1, -1, -1, -1 }, + { 102, 104, 7, 1, 200, -1, -1, -1 }, + { 104, 3, 7, 200, -1, -1, -1, -1 }, + { 7, 1, 0, 104, 102, 100, -1, -1 }, + { 104, 100, 102, 105, -1, -1, -1, -1 }, + { 3, 6, 5, 104, 100, 105, -1, -1 }, + { 104, 105, 5, 3, 101, 102, 2, 0 }, + { 6, 5, 3, 100, 105, 104, -1, -1 }, + { 101, 102, 105, 104, 100, -1, -1, -1 }, + { 6, 7, 8, 103, 104, 105, -1, -1 }, + { 103, 104, 105, 100, -1, -1, -1, -1 }, + { 2, 8, 7, 0, 200, -1, -1, -1 }, + { 8, 105, 104, 7, 200, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 100, 2, 0, 200, -1, -1, -1, -1 }, + { 100, 0, 7, 104, 200, -1, -1, -1 }, + { 105, 8, 2, 100, 200, -1, -1, -1 }, + { 104, 105, 103, 101, -1, -1, -1, -1 }, + { 0, 6, 8, 1, 200, -1, -1, -1 }, + { 6, 103, 105, 8, 200, -1, -1, -1 }, + { 101, 105, 103, 200, -1, -1, -1, -1 }, + { 101, 0, 1, 200, -1, -1, -1, -1 }, + { 101, 1, 8, 105, 200, -1, -1, -1 }, + { 103, 6, 0, 101, 200, -1, -1, -1 }, + { 105, 101, 100, 8, 1, 2, -1, -1 }, + { 103, 100, 101, 104, 105, -1, -1, -1 }, + { 105, 103, 104, 102, -1, -1, -1, -1 }, + { 1, 7, 6, 2, 200, -1, -1, -1 }, + { 7, 104, 103, 6, 200, -1, -1, -1 }, + { 102, 103, 104, 200, -1, -1, -1, -1 }, + { 102, 1, 2, 200, -1, -1, -1, -1 }, + { 102, 2, 6, 103, 200, -1, -1, -1 }, + { 104, 7, 1, 102, 200, -1, -1, -1 }, + { 104, 100, 102, 7, 0, 1, -1, -1 }, + { 105, 102, 100, 103, 104, -1, -1, -1 }, + { 103, 102, 101, 6, 2, 0, -1, -1 }, + { 104, 101, 102, 105, 103, -1, -1, -1 }, + { 100, 101, 102, 103, 104, 105, -1, -1 } +}; + +// Special points (e.g. centroid): per-case definition streams +constexpr int special_point_count_inside[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0 }; +constexpr int special_point_offset_inside[65] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 13, 20, 26, 34, 42, 42, 49, 49, 55, 62, 70, 76, 84, 84, 90, 96, 96, 104, 104, 104, 104, 104, 111, 118, 126, 126, 132, 138, 146, 146, 152, 160, 160, 166, 166, 166, 166, 166, 174, 180, 180, 186, 186, 186, 186, 186, 194, 202, 202, 210, 210, 210, 210 }; +constexpr int special_point_data_inside[210] = { 6, 0, 1, 7, 3, 5, 6, 5, 1, 2, 5, 3, 7, 6, 5, 3, 6, 2, 1, 8, 5, 1, 0, 3, 5, 8, 7, 3, 5, 8, 7, 103, 102, 101, 7, 101, 102, 103, 5, 3, 7, 8, 6, 3, 4, 7, 0, 2, 6, 5, 2, 1, 4, 3, 6, 6, 1, 2, 8, 4, 3, 7, 7, 4, 3, 6, 8, 104, 100, 102, 5, 2, 0, 3, 4, 8, 7, 102, 100, 104, 3, 4, 8, 6, 5, 4, 5, 2, 0, 7, 5, 5, 4, 1, 0, 6, 7, 2, 1, 7, 6, 102, 104, 103, 6, 2, 0, 6, 5, 4, 8, 6, 4, 5, 8, 1, 0, 7, 7, 5, 4, 7, 6, 105, 101, 100, 5, 0, 1, 4, 5, 6, 5, 0, 2, 5, 4, 7, 7, 100, 101, 105, 4, 5, 6, 7, 5, 4, 3, 0, 2, 8, 7, 1, 0, 6, 8, 101, 103, 105, 5, 3, 4, 1, 2, 6, 7, 0, 2, 8, 7, 100, 105, 104, 5, 5, 3, 0, 1, 8, 5, 3, 5, 2, 1, 7, 7, 104, 105, 100, 2, 0, 7, 8, 7, 105, 103, 101, 0, 1, 8, 6, 7, 103, 104, 102, 1, 2, 6, 7 }; + +} // namespace cutcells::cell::prism + +#endif // CUT_CELLS_PRISM_INSIDE_TABLES_H \ No newline at end of file diff --git a/cpp/src/generated/cut_prism_interface_tables.h b/cpp/src/generated/cut_prism_interface_tables.h new file mode 100644 index 0000000..d44e4a5 --- /dev/null +++ b/cpp/src/generated/cut_prism_interface_tables.h @@ -0,0 +1,191 @@ +#ifndef CUT_CELLS_PRISM_INTERFACE_TABLES_H +#define CUT_CELLS_PRISM_INTERFACE_TABLES_H + +// ----------------------------------------------------------------------------- +// This file is generated by CutCells tablegen. +// +// It contains case tables derived from VTK's vtkTableBasedClipCases.h +// (Visualization Toolkit, TableBasedClip). +// +// VTK is licensed under the BSD 3-Clause License. +// See third_party/VTK-Copyright.txt in this repository. +// ----------------------------------------------------------------------------- + +#include "cell_types.h" + +namespace cutcells::cell::prism { + +// Number of subcells produced for each case (interface volume) +constexpr int num_subcells_interface[64] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 6, 5, 6, 5, 2, 1, 1, 6, 1, 5, 6, 2, 5, 1, 1, 5, 5, 1, 2, 2, 2, 1, 1, 6, 6, 2, 1, 5, 5, 1, 1, 5, 2, 2, 5, 1, 2, 1, 1, 2, 5, 2, 5, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_interface[65] = { 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 15, 20, 26, 31, 33, 34, 35, 41, 42, 47, 53, 55, 60, 61, 62, 67, 72, 73, 75, 77, 79, 80, 81, 87, 93, 95, 96, 101, 106, 107, 108, 113, 115, 117, 122, 123, 125, 126, 127, 129, 134, 136, 141, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 152 }; + +// Cell types for interface subcells +constexpr type subcell_type_interface[152] = { cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle }; + +// Subcell vertices (max 4 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, 100..199 = 100+vertex_id, >=200 = 200+special_point_id +constexpr int subcell_verts_interface[152][4] = { + { 6, 0, 2, -1 }, + { 7, 1, 0, -1 }, + { 2, 1, 7, 6 }, + { 8, 2, 1, -1 }, + { 1, 0, 6, 8 }, + { 0, 2, 8, 7 }, + { 6, 8, 7, -1 }, + { 6, 5, 3, -1 }, + { 0, 3, 5, 2 }, + { 6, 200, 0, -1 }, + { 7, 200, 3, -1 }, + { 3, 200, 5, -1 }, + { 5, 200, 6, -1 }, + { 1, 200, 7, -1 }, + { 0, 200, 1, -1 }, + { 2, 200, 1, -1 }, + { 5, 200, 2, -1 }, + { 5, 3, 200, -1 }, + { 7, 200, 3, -1 }, + { 1, 200, 7, -1 }, + { 5, 200, 8, -1 }, + { 2, 200, 6, -1 }, + { 1, 200, 2, -1 }, + { 1, 8, 200, -1 }, + { 6, 200, 3, -1 }, + { 3, 200, 5, -1 }, + { 1, 200, 0, -1 }, + { 0, 200, 3, -1 }, + { 3, 200, 5, -1 }, + { 5, 200, 8, -1 }, + { 8, 200, 1, -1 }, + { 2, 6, 0, -1 }, + { 5, 3, 7, 8 }, + { 5, 3, 7, 8 }, + { 7, 3, 4, -1 }, + { 3, 200, 6, -1 }, + { 0, 200, 7, -1 }, + { 2, 200, 0, -1 }, + { 2, 6, 200, -1 }, + { 7, 200, 4, -1 }, + { 4, 200, 3, -1 }, + { 1, 4, 3, 0 }, + { 2, 200, 1, -1 }, + { 1, 200, 4, -1 }, + { 4, 200, 3, -1 }, + { 3, 200, 6, -1 }, + { 6, 200, 2, -1 }, + { 7, 200, 1, -1 }, + { 8, 200, 4, -1 }, + { 4, 200, 3, -1 }, + { 3, 200, 7, -1 }, + { 2, 200, 8, -1 }, + { 1, 200, 2, -1 }, + { 0, 7, 1, -1 }, + { 3, 4, 8, 6 }, + { 0, 200, 2, -1 }, + { 3, 200, 0, -1 }, + { 3, 4, 200, -1 }, + { 8, 200, 4, -1 }, + { 2, 200, 8, -1 }, + { 3, 4, 8, 6 }, + { 4, 5, 6, 7 }, + { 4, 200, 5, -1 }, + { 5, 200, 2, -1 }, + { 2, 200, 0, -1 }, + { 0, 200, 7, -1 }, + { 7, 200, 4, -1 }, + { 4, 200, 5, -1 }, + { 1, 200, 4, -1 }, + { 1, 0, 200, -1 }, + { 6, 200, 0, -1 }, + { 5, 200, 6, -1 }, + { 4, 1, 2, 5 }, + { 4, 5, 8, -1 }, + { 1, 7, 6, 2 }, + { 8, 4, 5, -1 }, + { 1, 0, 7, -1 }, + { 6, 0, 2, -1 }, + { 5, 8, 4, -1 }, + { 8, 4, 5, -1 }, + { 8, 4, 5, -1 }, + { 8, 200, 2, -1 }, + { 6, 200, 5, -1 }, + { 5, 200, 4, -1 }, + { 4, 200, 8, -1 }, + { 0, 200, 6, -1 }, + { 2, 200, 0, -1 }, + { 4, 200, 7, -1 }, + { 1, 200, 8, -1 }, + { 0, 200, 1, -1 }, + { 0, 7, 200, -1 }, + { 8, 200, 5, -1 }, + { 5, 200, 4, -1 }, + { 1, 8, 2, -1 }, + { 4, 5, 6, 7 }, + { 2, 5, 4, 1 }, + { 1, 200, 0, -1 }, + { 4, 200, 1, -1 }, + { 4, 5, 200, -1 }, + { 6, 200, 5, -1 }, + { 0, 200, 6, -1 }, + { 0, 200, 2, -1 }, + { 2, 200, 5, -1 }, + { 5, 200, 4, -1 }, + { 4, 200, 7, -1 }, + { 7, 200, 0, -1 }, + { 4, 5, 6, 7 }, + { 3, 4, 8, 6 }, + { 3, 200, 4, -1 }, + { 0, 200, 3, -1 }, + { 0, 2, 200, -1 }, + { 8, 200, 2, -1 }, + { 4, 200, 8, -1 }, + { 3, 4, 7, -1 }, + { 0, 6, 8, 1 }, + { 8, 2, 1, -1 }, + { 4, 7, 3, -1 }, + { 3, 200, 4, -1 }, + { 4, 200, 1, -1 }, + { 1, 200, 2, -1 }, + { 2, 200, 6, -1 }, + { 6, 200, 3, -1 }, + { 3, 0, 1, 4 }, + { 7, 3, 4, -1 }, + { 0, 2, 6, -1 }, + { 7, 3, 4, -1 }, + { 5, 3, 7, 8 }, + { 5, 3, 6, -1 }, + { 2, 8, 7, 0 }, + { 5, 200, 3, -1 }, + { 3, 200, 0, -1 }, + { 0, 200, 1, -1 }, + { 1, 200, 8, -1 }, + { 8, 200, 5, -1 }, + { 6, 5, 3, -1 }, + { 2, 1, 8, -1 }, + { 5, 200, 3, -1 }, + { 2, 200, 5, -1 }, + { 2, 1, 200, -1 }, + { 7, 200, 1, -1 }, + { 3, 200, 7, -1 }, + { 7, 1, 0, -1 }, + { 3, 6, 5, -1 }, + { 5, 2, 0, 3 }, + { 6, 5, 3, -1 }, + { 6, 7, 8, -1 }, + { 2, 8, 7, 0 }, + { 0, 6, 8, 1 }, + { 8, 2, 1, -1 }, + { 1, 7, 6, 2 }, + { 7, 1, 0, -1 }, + { 6, 0, 2, -1 } +}; + +// Special points (e.g. centroid): per-case definition streams +constexpr int special_point_count_interface[64] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +constexpr int special_point_offset_interface[65] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 13, 20, 26, 26, 26, 26, 33, 33, 39, 46, 46, 52, 52, 52, 58, 64, 64, 64, 64, 64, 64, 64, 71, 78, 78, 78, 84, 90, 90, 90, 96, 96, 96, 102, 102, 102, 102, 102, 102, 108, 108, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114, 114 }; +constexpr int special_point_data_interface[114] = { 6, 0, 1, 7, 3, 5, 6, 5, 1, 2, 5, 3, 7, 6, 5, 3, 6, 2, 1, 8, 5, 1, 0, 3, 5, 8, 6, 3, 4, 7, 0, 2, 6, 5, 2, 1, 4, 3, 6, 6, 1, 2, 8, 4, 3, 7, 5, 2, 0, 3, 4, 8, 5, 4, 5, 2, 0, 7, 5, 5, 4, 1, 0, 6, 6, 2, 0, 6, 5, 4, 8, 6, 4, 5, 8, 1, 0, 7, 5, 0, 1, 4, 5, 6, 5, 0, 2, 5, 4, 7, 5, 4, 3, 0, 2, 8, 5, 3, 4, 1, 2, 6, 5, 5, 3, 0, 1, 8, 5, 3, 5, 2, 1, 7 }; + +} // namespace cutcells::cell::prism + +#endif // CUT_CELLS_PRISM_INTERFACE_TABLES_H \ No newline at end of file diff --git a/cpp/src/generated/cut_prism_outside_tables.h b/cpp/src/generated/cut_prism_outside_tables.h new file mode 100644 index 0000000..5101d4f --- /dev/null +++ b/cpp/src/generated/cut_prism_outside_tables.h @@ -0,0 +1,282 @@ +#ifndef CUT_CELLS_PRISM_OUTSIDE_TABLES_H +#define CUT_CELLS_PRISM_OUTSIDE_TABLES_H + +// ----------------------------------------------------------------------------- +// This file is generated by CutCells tablegen. +// +// It contains case tables derived from VTK's vtkTableBasedClipCases.h +// (Visualization Toolkit, TableBasedClip). +// +// VTK is licensed under the BSD 3-Clause License. +// See third_party/VTK-Copyright.txt in this repository. +// ----------------------------------------------------------------------------- + +#include "cell_types.h" + +namespace cutcells::cell::prism { + +// Number of subcells produced for each case (outside volume) +constexpr int num_subcells_outside[64] = { 1, 2, 2, 7, 2, 7, 7, 1, 2, 1, 3, 6, 3, 6, 7, 1, 2, 3, 1, 6, 3, 7, 6, 1, 7, 6, 6, 1, 7, 6, 6, 1, 2, 3, 3, 7, 1, 6, 6, 1, 7, 6, 7, 6, 6, 1, 6, 1, 7, 7, 6, 6, 6, 6, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_outside[65] = { 0, 1, 3, 5, 12, 14, 21, 28, 29, 31, 32, 35, 41, 44, 50, 57, 58, 60, 63, 64, 70, 73, 80, 86, 87, 94, 100, 106, 107, 114, 120, 126, 127, 129, 132, 135, 142, 143, 149, 155, 156, 163, 169, 176, 182, 188, 189, 195, 196, 203, 210, 216, 222, 228, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 243 }; + +// Cell types for outside subcells +constexpr type subcell_type_outside[243] = { cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::hexahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::hexahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::hexahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron }; + +// Subcell vertices (max 8 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, 100..199 = 100+vertex_id, >=200 = 200+special_point_id +constexpr int subcell_verts_outside[243][8] = { + { 100, 101, 102, 103, 104, 105, -1, -1 }, + { 103, 102, 101, 6, 2, 0, -1, -1 }, + { 104, 101, 102, 105, 103, -1, -1, -1 }, + { 104, 100, 102, 7, 0, 1, -1, -1 }, + { 105, 102, 100, 103, 104, -1, -1, -1 }, + { 105, 103, 104, 102, -1, -1, -1, -1 }, + { 1, 7, 6, 2, 200, -1, -1, -1 }, + { 7, 104, 103, 6, 200, -1, -1, -1 }, + { 102, 103, 104, 200, -1, -1, -1, -1 }, + { 102, 1, 2, 200, -1, -1, -1, -1 }, + { 102, 2, 6, 103, 200, -1, -1, -1 }, + { 104, 7, 1, 102, 200, -1, -1, -1 }, + { 105, 101, 100, 8, 1, 2, -1, -1 }, + { 103, 100, 101, 104, 105, -1, -1, -1 }, + { 104, 105, 103, 101, -1, -1, -1, -1 }, + { 0, 6, 8, 1, 200, -1, -1, -1 }, + { 6, 103, 105, 8, 200, -1, -1, -1 }, + { 101, 105, 103, 200, -1, -1, -1, -1 }, + { 101, 0, 1, 200, -1, -1, -1, -1 }, + { 101, 1, 8, 105, 200, -1, -1, -1 }, + { 103, 6, 0, 101, 200, -1, -1, -1 }, + { 103, 104, 105, 100, -1, -1, -1, -1 }, + { 2, 8, 7, 0, 200, -1, -1, -1 }, + { 8, 105, 104, 7, 200, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 100, 2, 0, 200, -1, -1, -1, -1 }, + { 100, 0, 7, 104, 200, -1, -1, -1 }, + { 105, 8, 2, 100, 200, -1, -1, -1 }, + { 6, 7, 8, 103, 104, 105, -1, -1 }, + { 6, 5, 3, 100, 105, 104, -1, -1 }, + { 101, 102, 105, 104, 100, -1, -1, -1 }, + { 104, 105, 5, 3, 101, 102, 2, 0 }, + { 7, 1, 0, 104, 102, 100, -1, -1 }, + { 104, 100, 102, 105, -1, -1, -1, -1 }, + { 3, 6, 5, 104, 100, 105, -1, -1 }, + { 105, 104, 102, 200, -1, -1, -1, -1 }, + { 5, 3, 104, 105, 200, -1, -1, -1 }, + { 5, 105, 102, 2, 200, -1, -1, -1 }, + { 2, 102, 1, 200, -1, -1, -1, -1 }, + { 102, 104, 7, 1, 200, -1, -1, -1 }, + { 104, 3, 7, 200, -1, -1, -1, -1 }, + { 100, 104, 105, 6, 3, 5, -1, -1 }, + { 100, 104, 105, 101, -1, -1, -1, -1 }, + { 100, 105, 101, 2, 8, 1, -1, -1 }, + { 104, 101, 105, 200, -1, -1, -1, -1 }, + { 3, 104, 105, 5, 200, -1, -1, -1 }, + { 3, 0, 101, 104, 200, -1, -1, -1 }, + { 0, 1, 101, 200, -1, -1, -1, -1 }, + { 101, 1, 8, 105, 200, -1, -1, -1 }, + { 105, 8, 5, 200, -1, -1, -1, -1 }, + { 5, 3, 6, 105, 104, 100, -1, -1 }, + { 2, 8, 7, 0, 200, -1, -1, -1 }, + { 7, 8, 105, 104, 200, -1, -1, -1 }, + { 100, 104, 105, 200, -1, -1, -1, -1 }, + { 100, 2, 0, 200, -1, -1, -1, -1 }, + { 0, 7, 104, 100, 200, -1, -1, -1 }, + { 8, 2, 100, 105, 200, -1, -1, -1 }, + { 5, 8, 105, 3, 7, 104, -1, -1 }, + { 7, 3, 4, 101, 103, 105, -1, -1 }, + { 102, 100, 103, 105, 101, -1, -1, -1 }, + { 101, 105, 103, 7, 4, 3, -1, -1 }, + { 101, 105, 103, 102, -1, -1, -1, -1 }, + { 101, 103, 102, 0, 6, 2, -1, -1 }, + { 105, 103, 3, 4, 102, 100, 0, 1 }, + { 105, 102, 103, 200, -1, -1, -1, -1 }, + { 4, 105, 103, 3, 200, -1, -1, -1 }, + { 4, 1, 102, 105, 200, -1, -1, -1 }, + { 1, 2, 102, 200, -1, -1, -1, -1 }, + { 102, 2, 6, 103, 200, -1, -1, -1 }, + { 103, 6, 3, 200, -1, -1, -1, -1 }, + { 8, 2, 1, 105, 100, 101, -1, -1 }, + { 105, 101, 100, 103, -1, -1, -1, -1 }, + { 4, 7, 3, 105, 101, 103, -1, -1 }, + { 3, 4, 7, 103, 105, 101, -1, -1 }, + { 0, 6, 8, 1, 200, -1, -1, -1 }, + { 8, 6, 103, 105, 200, -1, -1, -1 }, + { 101, 105, 103, 200, -1, -1, -1, -1 }, + { 101, 0, 1, 200, -1, -1, -1, -1 }, + { 1, 8, 105, 101, 200, -1, -1, -1 }, + { 6, 0, 101, 103, 200, -1, -1, -1 }, + { 103, 105, 100, 200, -1, -1, -1, -1 }, + { 3, 4, 105, 103, 200, -1, -1, -1 }, + { 3, 103, 100, 0, 200, -1, -1, -1 }, + { 0, 100, 2, 200, -1, -1, -1, -1 }, + { 100, 105, 8, 2, 200, -1, -1, -1 }, + { 105, 4, 8, 200, -1, -1, -1, -1 }, + { 3, 6, 103, 4, 8, 105, -1, -1 }, + { 102, 101, 100, 105, -1, -1, -1, -1 }, + { 4, 5, 6, 7, 200, -1, -1, -1 }, + { 7, 6, 100, 101, 200, -1, -1, -1 }, + { 105, 101, 100, 200, -1, -1, -1, -1 }, + { 105, 5, 4, 200, -1, -1, -1, -1 }, + { 105, 100, 6, 5, 200, -1, -1, -1 }, + { 101, 105, 4, 7, 200, -1, -1, -1 }, + { 102, 105, 101, 200, -1, -1, -1, -1 }, + { 2, 102, 101, 0, 200, -1, -1, -1 }, + { 2, 5, 105, 102, 200, -1, -1, -1 }, + { 5, 4, 105, 200, -1, -1, -1, -1 }, + { 105, 4, 7, 101, 200, -1, -1, -1 }, + { 101, 7, 0, 200, -1, -1, -1, -1 }, + { 102, 100, 105, 200, -1, -1, -1, -1 }, + { 1, 0, 100, 102, 200, -1, -1, -1 }, + { 1, 102, 105, 4, 200, -1, -1, -1 }, + { 4, 105, 5, 200, -1, -1, -1, -1 }, + { 105, 100, 6, 5, 200, -1, -1, -1 }, + { 100, 0, 6, 200, -1, -1, -1, -1 }, + { 102, 2, 1, 105, 5, 4, -1, -1 }, + { 101, 100, 105, 1, 2, 8, -1, -1 }, + { 4, 5, 6, 7, 200, -1, -1, -1 }, + { 6, 100, 101, 7, 200, -1, -1, -1 }, + { 105, 101, 100, 200, -1, -1, -1, -1 }, + { 105, 5, 4, 200, -1, -1, -1, -1 }, + { 5, 105, 100, 6, 200, -1, -1, -1 }, + { 7, 101, 105, 4, 200, -1, -1, -1 }, + { 7, 101, 105, 4, 200, -1, -1, -1 }, + { 101, 1, 8, 105, 200, -1, -1, -1 }, + { 101, 0, 1, 200, -1, -1, -1, -1 }, + { 0, 101, 7, 200, -1, -1, -1, -1 }, + { 105, 8, 5, 200, -1, -1, -1, -1 }, + { 105, 5, 4, 200, -1, -1, -1, -1 }, + { 8, 2, 100, 105, 200, -1, -1, -1 }, + { 105, 100, 6, 5, 200, -1, -1, -1 }, + { 105, 5, 4, 200, -1, -1, -1, -1 }, + { 4, 8, 105, 200, -1, -1, -1, -1 }, + { 100, 0, 6, 200, -1, -1, -1, -1 }, + { 100, 2, 0, 200, -1, -1, -1, -1 }, + { 8, 4, 5, 105, -1, -1, -1, -1 }, + { 8, 4, 5, 102, 104, 103, -1, -1 }, + { 100, 101, 104, 103, 102, -1, -1, -1 }, + { 6, 0, 2, 103, 101, 102, -1, -1 }, + { 103, 102, 101, 104, -1, -1, -1, -1 }, + { 5, 8, 4, 103, 102, 104, -1, -1 }, + { 102, 103, 104, 8, 5, 4, -1, -1 }, + { 102, 103, 104, 100, -1, -1, -1, -1 }, + { 102, 104, 100, 1, 7, 0, -1, -1 }, + { 4, 5, 8, 104, 103, 102, -1, -1 }, + { 1, 7, 6, 2, 200, -1, -1, -1 }, + { 6, 7, 104, 103, 200, -1, -1, -1 }, + { 102, 103, 104, 200, -1, -1, -1, -1 }, + { 102, 1, 2, 200, -1, -1, -1, -1 }, + { 2, 6, 103, 102, 200, -1, -1, -1 }, + { 7, 1, 102, 104, 200, -1, -1, -1 }, + { 103, 104, 4, 5, 100, 101, 1, 2 }, + { 104, 103, 101, 200, -1, -1, -1, -1 }, + { 4, 5, 103, 104, 200, -1, -1, -1 }, + { 4, 104, 101, 1, 200, -1, -1, -1 }, + { 1, 101, 0, 200, -1, -1, -1, -1 }, + { 101, 103, 6, 0, 200, -1, -1, -1 }, + { 103, 5, 6, 200, -1, -1, -1, -1 }, + { 103, 100, 104, 200, -1, -1, -1, -1 }, + { 5, 103, 104, 4, 200, -1, -1, -1 }, + { 5, 2, 100, 103, 200, -1, -1, -1 }, + { 2, 0, 100, 200, -1, -1, -1, -1 }, + { 100, 0, 7, 104, 200, -1, -1, -1 }, + { 104, 7, 4, 200, -1, -1, -1, -1 }, + { 4, 7, 104, 5, 6, 103, -1, -1 }, + { 101, 100, 102, 104, -1, -1, -1, -1 }, + { 3, 4, 8, 6, 200, -1, -1, -1 }, + { 6, 8, 102, 100, 200, -1, -1, -1 }, + { 104, 100, 102, 200, -1, -1, -1, -1 }, + { 104, 4, 3, 200, -1, -1, -1, -1 }, + { 104, 102, 8, 4, 200, -1, -1, -1 }, + { 100, 104, 3, 6, 200, -1, -1, -1 }, + { 101, 102, 104, 200, -1, -1, -1, -1 }, + { 0, 2, 102, 101, 200, -1, -1, -1 }, + { 0, 101, 104, 3, 200, -1, -1, -1 }, + { 3, 104, 4, 200, -1, -1, -1, -1 }, + { 104, 102, 8, 4, 200, -1, -1, -1 }, + { 102, 2, 8, 200, -1, -1, -1, -1 }, + { 100, 102, 104, 0, 1, 7, -1, -1 }, + { 3, 4, 8, 6, 200, -1, -1, -1 }, + { 8, 102, 100, 6, 200, -1, -1, -1 }, + { 104, 100, 102, 200, -1, -1, -1, -1 }, + { 104, 4, 3, 200, -1, -1, -1, -1 }, + { 4, 104, 102, 8, 200, -1, -1, -1 }, + { 6, 100, 104, 3, 200, -1, -1, -1 }, + { 7, 1, 102, 104, 200, -1, -1, -1 }, + { 104, 102, 8, 4, 200, -1, -1, -1 }, + { 104, 4, 3, 200, -1, -1, -1, -1 }, + { 3, 7, 104, 200, -1, -1, -1, -1 }, + { 102, 2, 8, 200, -1, -1, -1, -1 }, + { 102, 1, 2, 200, -1, -1, -1, -1 }, + { 101, 104, 100, 200, -1, -1, -1, -1 }, + { 1, 101, 100, 2, 200, -1, -1, -1 }, + { 1, 4, 104, 101, 200, -1, -1, -1 }, + { 4, 3, 104, 200, -1, -1, -1, -1 }, + { 104, 3, 6, 100, 200, -1, -1, -1 }, + { 100, 6, 2, 200, -1, -1, -1, -1 }, + { 101, 1, 0, 104, 4, 3, -1, -1 }, + { 6, 100, 104, 3, 200, -1, -1, -1 }, + { 100, 0, 7, 104, 200, -1, -1, -1 }, + { 100, 2, 0, 200, -1, -1, -1, -1 }, + { 2, 100, 6, 200, -1, -1, -1, -1 }, + { 104, 7, 4, 200, -1, -1, -1, -1 }, + { 104, 4, 3, 200, -1, -1, -1, -1 }, + { 7, 3, 4, 104, -1, -1, -1, -1 }, + { 100, 102, 101, 103, -1, -1, -1, -1 }, + { 5, 3, 7, 8, 200, -1, -1, -1 }, + { 8, 7, 101, 102, 200, -1, -1, -1 }, + { 103, 102, 101, 200, -1, -1, -1, -1 }, + { 103, 3, 5, 200, -1, -1, -1, -1 }, + { 103, 101, 7, 3, 200, -1, -1, -1 }, + { 102, 103, 5, 8, 200, -1, -1, -1 }, + { 102, 101, 103, 2, 0, 6, -1, -1 }, + { 5, 3, 7, 8, 200, -1, -1, -1 }, + { 7, 101, 102, 8, 200, -1, -1, -1 }, + { 103, 102, 101, 200, -1, -1, -1, -1 }, + { 103, 3, 5, 200, -1, -1, -1, -1 }, + { 3, 103, 101, 7, 200, -1, -1, -1 }, + { 8, 102, 103, 5, 200, -1, -1, -1 }, + { 100, 103, 102, 200, -1, -1, -1, -1 }, + { 0, 100, 102, 1, 200, -1, -1, -1 }, + { 0, 3, 103, 100, 200, -1, -1, -1 }, + { 3, 5, 103, 200, -1, -1, -1, -1 }, + { 103, 5, 8, 102, 200, -1, -1, -1 }, + { 102, 8, 1, 200, -1, -1, -1, -1 }, + { 8, 102, 103, 5, 200, -1, -1, -1 }, + { 102, 2, 6, 103, 200, -1, -1, -1 }, + { 102, 1, 2, 200, -1, -1, -1, -1 }, + { 1, 102, 8, 200, -1, -1, -1, -1 }, + { 103, 6, 3, 200, -1, -1, -1, -1 }, + { 103, 3, 5, 200, -1, -1, -1, -1 }, + { 100, 101, 103, 200, -1, -1, -1, -1 }, + { 2, 1, 101, 100, 200, -1, -1, -1 }, + { 2, 100, 103, 5, 200, -1, -1, -1 }, + { 5, 103, 3, 200, -1, -1, -1, -1 }, + { 103, 101, 7, 3, 200, -1, -1, -1 }, + { 101, 1, 7, 200, -1, -1, -1, -1 }, + { 6, 0, 101, 103, 200, -1, -1, -1 }, + { 103, 101, 7, 3, 200, -1, -1, -1 }, + { 103, 3, 5, 200, -1, -1, -1, -1 }, + { 5, 6, 103, 200, -1, -1, -1, -1 }, + { 101, 1, 7, 200, -1, -1, -1, -1 }, + { 101, 0, 1, 200, -1, -1, -1, -1 }, + { 100, 0, 2, 103, 3, 5, -1, -1 }, + { 6, 5, 3, 103, -1, -1, -1, -1 }, + { 100, 101, 102, 6, 7, 8, -1, -1 }, + { 0, 7, 101, 2, 8, 102, -1, -1 }, + { 1, 8, 102, 0, 6, 100, -1, -1 }, + { 8, 2, 1, 102, -1, -1, -1, -1 }, + { 2, 6, 100, 1, 7, 101, -1, -1 }, + { 7, 1, 0, 101, -1, -1, -1, -1 }, + { 6, 0, 2, 100, -1, -1, -1, -1 } +}; + +// Special points (e.g. centroid): per-case definition streams +constexpr int special_point_count_outside[64] = { 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +constexpr int special_point_offset_outside[65] = { 0, 0, 0, 0, 8, 8, 16, 24, 24, 24, 24, 24, 30, 30, 36, 44, 44, 44, 44, 44, 50, 50, 58, 64, 64, 72, 78, 84, 84, 92, 99, 106, 106, 106, 106, 106, 114, 114, 120, 126, 126, 134, 140, 148, 155, 161, 161, 168, 168, 176, 184, 190, 197, 203, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210, 210 }; +constexpr int special_point_data_outside[210] = { 7, 103, 104, 102, 1, 2, 6, 7, 7, 105, 103, 101, 0, 1, 8, 6, 7, 104, 105, 100, 2, 0, 7, 8, 5, 3, 5, 2, 1, 7, 5, 5, 3, 0, 1, 8, 7, 0, 2, 8, 7, 100, 105, 104, 5, 3, 4, 1, 2, 6, 7, 1, 0, 6, 8, 101, 103, 105, 5, 4, 3, 0, 2, 8, 7, 100, 101, 105, 4, 5, 6, 7, 5, 0, 2, 5, 4, 7, 5, 0, 1, 4, 5, 6, 7, 5, 4, 7, 6, 105, 101, 100, 6, 4, 5, 8, 1, 0, 7, 6, 2, 0, 6, 5, 4, 8, 7, 2, 1, 7, 6, 102, 104, 103, 5, 5, 4, 1, 0, 6, 5, 4, 5, 2, 0, 7, 7, 102, 100, 104, 3, 4, 8, 6, 5, 2, 0, 3, 4, 8, 7, 4, 3, 6, 8, 104, 100, 102, 6, 1, 2, 8, 4, 3, 7, 5, 2, 1, 4, 3, 6, 6, 3, 4, 7, 0, 2, 6, 7, 101, 102, 103, 5, 3, 7, 8, 7, 3, 5, 8, 7, 103, 102, 101, 5, 1, 0, 3, 5, 8, 6, 5, 3, 6, 2, 1, 8, 5, 1, 2, 5, 3, 7, 6, 0, 1, 7, 3, 5, 6 }; + +} // namespace cutcells::cell::prism + +#endif // CUT_CELLS_PRISM_OUTSIDE_TABLES_H \ No newline at end of file diff --git a/cpp/src/generated/cut_pyramid_inside_tables.h b/cpp/src/generated/cut_pyramid_inside_tables.h new file mode 100644 index 0000000..9f8dc23 --- /dev/null +++ b/cpp/src/generated/cut_pyramid_inside_tables.h @@ -0,0 +1,142 @@ +#ifndef CUT_CELLS_PYRAMID_INSIDE_TABLES_H +#define CUT_CELLS_PYRAMID_INSIDE_TABLES_H + +// ----------------------------------------------------------------------------- +// This file is generated by CutCells tablegen. +// +// It contains case tables derived from VTK's vtkTableBasedClipCases.h +// (Visualization Toolkit, TableBasedClip). +// +// VTK is licensed under the BSD 3-Clause License. +// See third_party/VTK-Copyright.txt in this repository. +// ----------------------------------------------------------------------------- + +#include "cell_types.h" + +namespace cutcells::cell::pyramid { + +// Intersected edges per case (1 = intersected, 0 = not intersected) +constexpr int intersected_edges[32][8] = { + { 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, 0, 0, 1, 1, 0, 0, 0 }, + { 1, 1, 0, 0, 0, 1, 0, 0 }, + { 0, 1, 0, 1, 1, 1, 0, 0 }, + { 0, 1, 1, 0, 0, 0, 1, 0 }, + { 1, 1, 1, 1, 1, 0, 1, 0 }, + { 1, 0, 1, 0, 0, 1, 1, 0 }, + { 0, 0, 1, 1, 1, 1, 1, 0 }, + { 0, 0, 1, 1, 0, 0, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 0, 1 }, + { 1, 1, 1, 1, 0, 1, 0, 1 }, + { 0, 1, 1, 0, 1, 1, 0, 1 }, + { 0, 1, 0, 1, 0, 0, 1, 1 }, + { 1, 1, 0, 0, 1, 0, 1, 1 }, + { 1, 0, 0, 1, 0, 1, 1, 1 }, + { 0, 0, 0, 0, 1, 1, 1, 1 }, + { 0, 0, 0, 0, 1, 1, 1, 1 }, + { 1, 0, 0, 1, 0, 1, 1, 1 }, + { 1, 1, 0, 0, 1, 0, 1, 1 }, + { 0, 1, 0, 1, 0, 0, 1, 1 }, + { 0, 1, 1, 0, 1, 1, 0, 1 }, + { 1, 1, 1, 1, 0, 1, 0, 1 }, + { 1, 0, 1, 0, 1, 0, 0, 1 }, + { 0, 0, 1, 1, 0, 0, 0, 1 }, + { 0, 0, 1, 1, 1, 1, 1, 0 }, + { 1, 0, 1, 0, 0, 1, 1, 0 }, + { 1, 1, 1, 1, 1, 0, 1, 0 }, + { 0, 1, 1, 0, 0, 0, 1, 0 }, + { 0, 1, 0, 1, 1, 1, 0, 0 }, + { 1, 1, 0, 0, 0, 1, 0, 0 }, + { 1, 0, 0, 1, 1, 0, 0, 0 }, + { 0, 0, 0, 0, 0, 0, 0, 0 } +}; + +// Number of subcells produced for each case (inside volume) +constexpr int num_subcells_inside[32] = { 0, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 2, 1, 2, 2, 1, 1, 2, 2, 6, 2, 2, 6, 2, 2, 6, 2, 2, 6, 2, 2, 1 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_inside[33] = { 0, 0, 1, 2, 3, 4, 6, 7, 9, 10, 11, 13, 15, 16, 18, 20, 21, 22, 24, 26, 32, 34, 36, 42, 44, 46, 52, 54, 56, 62, 64, 66, 67 }; + +// Cell types for inside subcells +constexpr type subcell_type_inside[67] = { cell::type::tetrahedron, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::hexahedron, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid }; + +// Subcell vertices (max 8 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, 100..199 = 100+vertex_id, >=200 = 200+special_point_id +constexpr int subcell_verts_inside[67][8] = { + { 100, 0, 3, 4, -1, -1, -1, -1 }, + { 101, 1, 0, 5, -1, -1, -1, -1 }, + { 1, 5, 101, 3, 4, 100, -1, -1 }, + { 102, 2, 1, 6, -1, -1, -1, -1 }, + { 100, 0, 4, 102, 1, 6, -1, -1 }, + { 3, 100, 4, 2, 102, 6, -1, -1 }, + { 2, 6, 102, 0, 5, 101, -1, -1 }, + { 4, 5, 6, 100, 101, 102, -1, -1 }, + { 102, 2, 6, 100, 3, 4, -1, -1 }, + { 103, 3, 2, 7, -1, -1, -1, -1 }, + { 0, 4, 100, 2, 7, 103, -1, -1 }, + { 103, 3, 7, 101, 0, 5, -1, -1 }, + { 2, 103, 7, 1, 101, 5, -1, -1 }, + { 7, 4, 5, 103, 100, 101, -1, -1 }, + { 101, 1, 5, 103, 2, 7, -1, -1 }, + { 3, 7, 103, 1, 6, 102, -1, -1 }, + { 6, 7, 4, 102, 103, 100, -1, -1 }, + { 100, 0, 4, 102, 1, 6, -1, -1 }, + { 5, 6, 7, 101, 102, 103, -1, -1 }, + { 103, 3, 7, 101, 0, 5, -1, -1 }, + { 100, 101, 102, 103, 4, 5, 6, 7 }, + { 4, 5, 6, 7, 104, -1, -1, -1 }, + { 104, 5, 7, 100, 0, 3, -1, -1 }, + { 5, 6, 7, 104, -1, -1, -1, -1 }, + { 104, 6, 4, 101, 1, 0, -1, -1 }, + { 6, 7, 4, 104, -1, -1, -1, -1 }, + { 6, 7, 3, 1, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 100, 104, 101, 200, -1, -1, -1, -1 }, + { 7, 6, 104, 200, -1, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 104, 6, 1, 101, 200, -1, -1, -1 }, + { 104, 7, 5, 102, 2, 1, -1, -1 }, + { 7, 4, 5, 104, -1, -1, -1, -1 }, + { 0, 1, 5, 100, 102, 104, -1, -1 }, + { 2, 3, 7, 102, 100, 104, -1, -1 }, + { 7, 4, 0, 2, 200, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 101, 104, 102, 200, -1, -1, -1, -1 }, + { 4, 7, 104, 200, -1, -1, -1, -1 }, + { 4, 104, 101, 0, 200, -1, -1, -1 }, + { 104, 7, 2, 102, 200, -1, -1, -1 }, + { 100, 102, 104, 3, 2, 7, -1, -1 }, + { 100, 101, 102, 104, -1, -1, -1, -1 }, + { 104, 4, 6, 103, 3, 2, -1, -1 }, + { 4, 5, 6, 104, -1, -1, -1, -1 }, + { 5, 6, 2, 0, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 103, 104, 100, 200, -1, -1, -1, -1 }, + { 6, 5, 104, 200, -1, -1, -1, -1 }, + { 6, 104, 103, 2, 200, -1, -1, -1 }, + { 104, 5, 0, 100, 200, -1, -1, -1 }, + { 3, 0, 4, 103, 101, 104, -1, -1 }, + { 1, 2, 6, 101, 103, 104, -1, -1 }, + { 103, 101, 104, 2, 1, 6, -1, -1 }, + { 103, 100, 101, 104, -1, -1, -1, -1 }, + { 4, 5, 1, 3, 200, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 102, 104, 103, 200, -1, -1, -1, -1 }, + { 5, 4, 104, 200, -1, -1, -1, -1 }, + { 5, 104, 102, 1, 200, -1, -1, -1 }, + { 104, 4, 3, 103, 200, -1, -1, -1 }, + { 102, 100, 104, 1, 0, 5, -1, -1 }, + { 102, 103, 100, 104, -1, -1, -1, -1 }, + { 101, 103, 104, 0, 3, 4, -1, -1 }, + { 101, 102, 103, 104, -1, -1, -1, -1 }, + { 100, 101, 102, 103, 104, -1, -1, -1 } +}; + +// Special points (e.g. centroid): per-case definition streams +constexpr int special_point_count_inside[32] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0 }; +constexpr int special_point_offset_inside[33] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 16, 16, 16, 24, 24, 24, 32, 32, 32, 32 }; +constexpr int special_point_data_inside[32] = { 7, 7, 6, 3, 1, 100, 101, 104, 7, 4, 7, 0, 2, 101, 102, 104, 7, 6, 5, 2, 0, 103, 100, 104, 7, 5, 4, 1, 3, 102, 103, 104 }; + +} // namespace cutcells::cell::pyramid + +#endif // CUT_CELLS_PYRAMID_INSIDE_TABLES_H \ No newline at end of file diff --git a/cpp/src/generated/cut_pyramid_interface_tables.h b/cpp/src/generated/cut_pyramid_interface_tables.h new file mode 100644 index 0000000..1610a07 --- /dev/null +++ b/cpp/src/generated/cut_pyramid_interface_tables.h @@ -0,0 +1,76 @@ +#ifndef CUT_CELLS_PYRAMID_INTERFACE_TABLES_H +#define CUT_CELLS_PYRAMID_INTERFACE_TABLES_H + +// ----------------------------------------------------------------------------- +// This file is generated by CutCells tablegen. +// +// It contains case tables derived from VTK's vtkTableBasedClipCases.h +// (Visualization Toolkit, TableBasedClip). +// +// VTK is licensed under the BSD 3-Clause License. +// See third_party/VTK-Copyright.txt in this repository. +// ----------------------------------------------------------------------------- + +#include "cell_types.h" + +namespace cutcells::cell::pyramid { + +// Number of subcells produced for each case (interface volume) +constexpr int num_subcells_interface[32] = { 0, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 2, 1, 2, 2, 1, 1, 2, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 0 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_interface[33] = { 0, 0, 1, 2, 3, 4, 6, 7, 9, 10, 11, 13, 15, 16, 18, 20, 21, 22, 24, 26, 27, 29, 31, 32, 33, 35, 36, 38, 39, 40, 41, 42, 42 }; + +// Cell types for interface subcells +constexpr type subcell_type_interface[42] = { cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle }; + +// Subcell vertices (max 4 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, 100..199 = 100+vertex_id, >=200 = 200+special_point_id +constexpr int subcell_verts_interface[42][4] = { + { 0, 4, 3, -1 }, + { 1, 5, 0, -1 }, + { 1, 3, 4, 5 }, + { 2, 6, 1, -1 }, + { 0, 1, 6, 4 }, + { 4, 6, 2, 3 }, + { 2, 0, 5, 6 }, + { 4, 5, 6, -1 }, + { 2, 3, 4, 6 }, + { 3, 7, 2, -1 }, + { 0, 2, 7, 4 }, + { 3, 0, 5, 7 }, + { 7, 5, 1, 2 }, + { 7, 4, 5, -1 }, + { 1, 2, 7, 5 }, + { 3, 1, 6, 7 }, + { 6, 7, 4, -1 }, + { 0, 1, 6, 4 }, + { 5, 6, 7, -1 }, + { 3, 0, 5, 7 }, + { 4, 7, 6, 5 }, + { 4, 5, 6, 7 }, + { 5, 0, 3, 7 }, + { 5, 6, 7, -1 }, + { 6, 1, 0, 4 }, + { 6, 7, 4, -1 }, + { 6, 7, 3, 1 }, + { 7, 2, 1, 5 }, + { 7, 4, 5, -1 }, + { 0, 1, 5, -1 }, + { 2, 3, 7, -1 }, + { 7, 4, 0, 2 }, + { 3, 7, 2, -1 }, + { 4, 3, 2, 6 }, + { 4, 5, 6, -1 }, + { 5, 6, 2, 0 }, + { 3, 0, 4, -1 }, + { 1, 2, 6, -1 }, + { 2, 6, 1, -1 }, + { 4, 5, 1, 3 }, + { 1, 5, 0, -1 }, + { 0, 4, 3, -1 } +}; + +} // namespace cutcells::cell::pyramid + +#endif // CUT_CELLS_PYRAMID_INTERFACE_TABLES_H \ No newline at end of file diff --git a/cpp/src/generated/cut_pyramid_outside_tables.h b/cpp/src/generated/cut_pyramid_outside_tables.h new file mode 100644 index 0000000..8cfd9b1 --- /dev/null +++ b/cpp/src/generated/cut_pyramid_outside_tables.h @@ -0,0 +1,106 @@ +#ifndef CUT_CELLS_PYRAMID_OUTSIDE_TABLES_H +#define CUT_CELLS_PYRAMID_OUTSIDE_TABLES_H + +// ----------------------------------------------------------------------------- +// This file is generated by CutCells tablegen. +// +// It contains case tables derived from VTK's vtkTableBasedClipCases.h +// (Visualization Toolkit, TableBasedClip). +// +// VTK is licensed under the BSD 3-Clause License. +// See third_party/VTK-Copyright.txt in this repository. +// ----------------------------------------------------------------------------- + +#include "cell_types.h" + +namespace cutcells::cell::pyramid { + +// Number of subcells produced for each case (outside volume) +constexpr int num_subcells_outside[32] = { 1, 2, 2, 6, 2, 2, 6, 2, 2, 6, 2, 2, 6, 2, 2, 1, 1, 2, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 0 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_outside[33] = { 0, 1, 3, 5, 11, 13, 15, 21, 23, 25, 31, 33, 35, 41, 43, 45, 46, 47, 49, 51, 52, 54, 56, 57, 58, 60, 61, 63, 64, 65, 66, 67, 67 }; + +// Cell types for outside subcells +constexpr type subcell_type_outside[67] = { cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::tetrahedron, cell::type::tetrahedron, cell::type::pyramid, cell::type::pyramid, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::pyramid, cell::type::hexahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::prism, cell::type::tetrahedron, cell::type::prism, cell::type::tetrahedron, cell::type::tetrahedron }; + +// Subcell vertices (max 8 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, 100..199 = 100+vertex_id, >=200 = 200+special_point_id +constexpr int subcell_verts_outside[67][8] = { + { 100, 101, 102, 103, 104, -1, -1, -1 }, + { 101, 103, 104, 0, 3, 4, -1, -1 }, + { 101, 102, 103, 104, -1, -1, -1, -1 }, + { 102, 100, 104, 1, 0, 5, -1, -1 }, + { 102, 103, 100, 104, -1, -1, -1, -1 }, + { 4, 5, 1, 3, 200, -1, -1, -1 }, + { 1, 102, 103, 3, 200, -1, -1, -1 }, + { 102, 104, 103, 200, -1, -1, -1, -1 }, + { 5, 4, 104, 200, -1, -1, -1, -1 }, + { 5, 104, 102, 1, 200, -1, -1, -1 }, + { 104, 4, 3, 103, 200, -1, -1, -1 }, + { 103, 101, 104, 2, 1, 6, -1, -1 }, + { 103, 100, 101, 104, -1, -1, -1, -1 }, + { 3, 0, 4, 103, 101, 104, -1, -1 }, + { 1, 2, 6, 101, 103, 104, -1, -1 }, + { 5, 6, 2, 0, 200, -1, -1, -1 }, + { 2, 103, 100, 0, 200, -1, -1, -1 }, + { 103, 104, 100, 200, -1, -1, -1, -1 }, + { 6, 5, 104, 200, -1, -1, -1, -1 }, + { 6, 104, 103, 2, 200, -1, -1, -1 }, + { 104, 5, 0, 100, 200, -1, -1, -1 }, + { 104, 4, 6, 103, 3, 2, -1, -1 }, + { 4, 5, 6, 104, -1, -1, -1, -1 }, + { 100, 102, 104, 3, 2, 7, -1, -1 }, + { 100, 101, 102, 104, -1, -1, -1, -1 }, + { 7, 4, 0, 2, 200, -1, -1, -1 }, + { 0, 101, 102, 2, 200, -1, -1, -1 }, + { 101, 104, 102, 200, -1, -1, -1, -1 }, + { 4, 7, 104, 200, -1, -1, -1, -1 }, + { 4, 104, 101, 0, 200, -1, -1, -1 }, + { 104, 7, 2, 102, 200, -1, -1, -1 }, + { 0, 1, 5, 100, 102, 104, -1, -1 }, + { 2, 3, 7, 102, 100, 104, -1, -1 }, + { 104, 7, 5, 102, 2, 1, -1, -1 }, + { 7, 4, 5, 104, -1, -1, -1, -1 }, + { 6, 7, 3, 1, 200, -1, -1, -1 }, + { 3, 100, 101, 1, 200, -1, -1, -1 }, + { 100, 104, 101, 200, -1, -1, -1, -1 }, + { 7, 6, 104, 200, -1, -1, -1, -1 }, + { 7, 104, 100, 3, 200, -1, -1, -1 }, + { 104, 6, 1, 101, 200, -1, -1, -1 }, + { 104, 6, 4, 101, 1, 0, -1, -1 }, + { 6, 7, 4, 104, -1, -1, -1, -1 }, + { 104, 5, 7, 100, 0, 3, -1, -1 }, + { 5, 6, 7, 104, -1, -1, -1, -1 }, + { 4, 5, 6, 7, 104, -1, -1, -1 }, + { 100, 101, 102, 103, 4, 5, 6, 7 }, + { 5, 6, 7, 101, 102, 103, -1, -1 }, + { 103, 3, 7, 101, 0, 5, -1, -1 }, + { 6, 7, 4, 102, 103, 100, -1, -1 }, + { 100, 0, 4, 102, 1, 6, -1, -1 }, + { 3, 7, 103, 1, 6, 102, -1, -1 }, + { 7, 4, 5, 103, 100, 101, -1, -1 }, + { 101, 1, 5, 103, 2, 7, -1, -1 }, + { 103, 3, 7, 101, 0, 5, -1, -1 }, + { 2, 103, 7, 1, 101, 5, -1, -1 }, + { 0, 4, 100, 2, 7, 103, -1, -1 }, + { 103, 3, 2, 7, -1, -1, -1, -1 }, + { 4, 5, 6, 100, 101, 102, -1, -1 }, + { 102, 2, 6, 100, 3, 4, -1, -1 }, + { 2, 6, 102, 0, 5, 101, -1, -1 }, + { 100, 0, 4, 102, 1, 6, -1, -1 }, + { 3, 100, 4, 2, 102, 6, -1, -1 }, + { 102, 2, 1, 6, -1, -1, -1, -1 }, + { 1, 5, 101, 3, 4, 100, -1, -1 }, + { 101, 1, 0, 5, -1, -1, -1, -1 }, + { 100, 0, 3, 4, -1, -1, -1, -1 } +}; + +// Special points (e.g. centroid): per-case definition streams +constexpr int special_point_count_outside[32] = { 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +constexpr int special_point_offset_outside[33] = { 0, 0, 0, 0, 8, 8, 8, 16, 16, 16, 24, 24, 24, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32 }; +constexpr int special_point_data_outside[32] = { 7, 5, 4, 1, 3, 102, 103, 104, 7, 6, 5, 2, 0, 103, 100, 104, 7, 4, 7, 0, 2, 101, 102, 104, 7, 7, 6, 3, 1, 100, 101, 104 }; + +} // namespace cutcells::cell::pyramid + +#endif // CUT_CELLS_PYRAMID_OUTSIDE_TABLES_H \ No newline at end of file diff --git a/cpp/src/generated/cut_quadrilateral_inside_tables.h b/cpp/src/generated/cut_quadrilateral_inside_tables.h new file mode 100644 index 0000000..cd0c0bf --- /dev/null +++ b/cpp/src/generated/cut_quadrilateral_inside_tables.h @@ -0,0 +1,80 @@ +#ifndef CUT_CELLS_QUADRILATERAL_INSIDE_TABLES_H +#define CUT_CELLS_QUADRILATERAL_INSIDE_TABLES_H + +#include "cell_types.h" +#include + +namespace cutcells::cell::quadrilateral { + +// Topology +constexpr int edges[4][2] = {{0,1}, {1,2}, {2,3}, {3,0}}; + +// Intersected edges per case (1 = intersected, 0 = not intersected) +constexpr int intersected_edges[16][4] = { + { 0, 0, 0, 0 }, + { 1, 0, 0, 1 }, + { 1, 1, 0, 0 }, + { 0, 1, 0, 1 }, + { 0, 1, 1, 0 }, + { 1, 1, 1, 1 }, + { 1, 0, 1, 0 }, + { 0, 0, 1, 1 }, + { 0, 0, 1, 1 }, + { 1, 0, 1, 0 }, + { 1, 1, 1, 1 }, + { 0, 1, 1, 0 }, + { 0, 1, 0, 1 }, + { 1, 1, 0, 0 }, + { 1, 0, 0, 1 }, + { 0, 0, 0, 0 } +}; + +// Ambiguity metadata (opposite-corner cases) +constexpr uint8_t case_is_ambiguous_tbl[16] = { 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0 }; +constexpr int8_t amb_case_id[16] = { -1, -1, -1, -1, -1, 0, -1, -1, -1, -1, 1, -1, -1, -1, -1, -1 }; + +// Number of subcells produced for each case (inside volume) +constexpr int num_subcells_inside[16] = { 0, 1, 1, 1, 1, 2, 1, 2, 1, 1, 2, 2, 1, 2, 2, 1 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_inside[17] = { 0, 0, 1, 2, 3, 4, 6, 7, 9, 10, 11, 13, 15, 16, 18, 20, 21 }; + +// Cell types for inside subcells +constexpr type subcell_type_inside[25] = { cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral }; + +// Subcell vertices (max 4 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, >=100 = 100+vertex_id +constexpr int subcell_verts_inside[25][4] = { + { 100, 0, 3, -1 }, + { 0, 101, 1, -1 }, + { 100, 101, 1, 3 }, + { 1, 102, 2, -1 }, + { 100, 0, 3, -1 }, + { 102, 1, 2, -1 }, + { 0, 101, 102, 2 }, + { 3, 100, 101, -1 }, + { 3, 101, 102, 2 }, + { 2, 103, 3, -1 }, + { 100, 0, 2, 103 }, + { 101, 1, 0, -1 }, + { 103, 3, 2, -1 }, + { 2, 103, 100, -1 }, + { 2, 100, 101, 1 }, + { 1, 102, 103, 3 }, + { 1, 102, 103, -1 }, + { 1, 103, 100, 0 }, + { 0, 101, 102, -1 }, + { 0, 102, 103, 3 }, + { 100, 101, 102, 103 }, + { 100, 0, 1, 102 }, + { 100, 102, 2, 3 }, + { 101, 1, 2, 103 }, + { 101, 103, 3, 0 } +}; + +// Ambiguity override ranges: [begin0,end0,begin1,end1] per ambiguous case +constexpr int amb_range_inside[8] = { 21, 23, 4, 6, 11, 13, 23, 25 }; + +} // namespace cutcells::cell::quadrilateral + +#endif // CUT_CELLS_QUADRILATERAL_INSIDE_TABLES_H \ No newline at end of file diff --git a/cpp/src/generated/cut_quadrilateral_interface_tables.h b/cpp/src/generated/cut_quadrilateral_interface_tables.h new file mode 100644 index 0000000..59c68f2 --- /dev/null +++ b/cpp/src/generated/cut_quadrilateral_interface_tables.h @@ -0,0 +1,43 @@ +#ifndef CUT_CELLS_QUADRILATERAL_INTERFACE_TABLES_H +#define CUT_CELLS_QUADRILATERAL_INTERFACE_TABLES_H + +#include "cell_types.h" + +namespace cutcells::cell::quadrilateral { + +// Number of subcells produced for each case (interface volume) +constexpr int num_subcells_interface[16] = { 0, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 0 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_interface[17] = { 0, 0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 12, 13, 14, 15, 16, 16 }; + +// Cell types for interface subcells +constexpr type subcell_type_interface[16] = { cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval, cell::type::interval }; + +// Subcell vertices (max 2 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, >=100 = 100+vertex_id +constexpr int subcell_verts_interface[16][2] = { + { 0, 3 }, + { 0, 1 }, + { 1, 3 }, + { 1, 2 }, + { 0, 3 }, + { 1, 2 }, + { 0, 2 }, + { 2, 3 }, + { 2, 3 }, + { 0, 2 }, + { 0, 1 }, + { 2, 3 }, + { 1, 2 }, + { 1, 3 }, + { 0, 1 }, + { 0, 3 } +}; + +// Ambiguity override ranges: [begin0,end0,begin1,end1] per ambiguous case +constexpr int amb_range_interface[8] = { 10, 12, 4, 6, 10, 12, 4, 6 }; + +} // namespace cutcells::cell::quadrilateral + +#endif // CUT_CELLS_QUADRILATERAL_INTERFACE_TABLES_H \ No newline at end of file diff --git a/cpp/src/generated/cut_quadrilateral_outside_tables.h b/cpp/src/generated/cut_quadrilateral_outside_tables.h new file mode 100644 index 0000000..8ea445b --- /dev/null +++ b/cpp/src/generated/cut_quadrilateral_outside_tables.h @@ -0,0 +1,52 @@ +#ifndef CUT_CELLS_QUADRILATERAL_OUTSIDE_TABLES_H +#define CUT_CELLS_QUADRILATERAL_OUTSIDE_TABLES_H + +#include "cell_types.h" + +namespace cutcells::cell::quadrilateral { + +// Number of subcells produced for each case (outside volume) +constexpr int num_subcells_outside[16] = { 1, 2, 2, 1, 2, 2, 1, 1, 2, 1, 2, 1, 1, 1, 1, 0 }; + +// Offset into subcell array for each case +constexpr int case_subcell_offset_outside[17] = { 0, 1, 3, 5, 6, 8, 10, 11, 12, 14, 15, 17, 18, 19, 20, 21, 21 }; + +// Cell types for outside subcells +constexpr type subcell_type_outside[25] = { cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::quadrilateral, cell::type::triangle, cell::type::quadrilateral, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle, cell::type::triangle }; + +// Subcell vertices (max 4 vertices per subcell, -1 padding) +// Tokens: <100 = edge id, >=100 = 100+vertex_id +constexpr int subcell_verts_outside[25][4] = { + { 100, 101, 102, 103 }, + { 0, 101, 102, -1 }, + { 0, 102, 103, 3 }, + { 1, 102, 103, -1 }, + { 1, 103, 100, 0 }, + { 1, 102, 103, 3 }, + { 2, 103, 100, -1 }, + { 2, 100, 101, 1 }, + { 101, 1, 2, 103 }, + { 103, 3, 0, 101 }, + { 100, 0, 2, 103 }, + { 2, 103, 3, -1 }, + { 3, 100, 101, -1 }, + { 3, 101, 102, 2 }, + { 0, 101, 102, 2 }, + { 100, 0, 1, 102 }, + { 102, 2, 3, 100 }, + { 1, 102, 2, -1 }, + { 100, 101, 1, 3 }, + { 0, 101, 1, -1 }, + { 100, 0, 3, -1 }, + { 100, 0, 3, -1 }, + { 102, 1, 2, -1 }, + { 101, 0, 1, -1 }, + { 103, 2, 3, -1 } +}; + +// Ambiguity override ranges: [begin0,end0,begin1,end1] per ambiguous case +constexpr int amb_range_outside[8] = { 23, 25, 8, 10, 15, 17, 21, 23 }; + +} // namespace cutcells::cell::quadrilateral + +#endif // CUT_CELLS_QUADRILATERAL_OUTSIDE_TABLES_H \ No newline at end of file diff --git a/cpp/src/utils.h b/cpp/src/utils.h index 25ec07a..f5d6580 100644 --- a/cpp/src/utils.h +++ b/cpp/src/utils.h @@ -60,11 +60,17 @@ namespace cutcells::utils template void create_vertex_parent_entity_map(const std::unordered_map& vertex_case_map, std::vector& vertex_parent_entity) { - vertex_parent_entity.resize(vertex_case_map.size()); + // vertex_case_map maps (token -> local_vertex_index). Tokens encode the origin: + // - edge intersections: 0..(n_edges-1) + // - original vertices: 100+vid + // - special points: 200+sid + // Local indices are expected to refer to indices in CutCell::_vertex_coords. + int max_local = -1; + for (const auto& kv : vertex_case_map) + max_local = std::max(max_local, kv.second); - for (auto &[first,second]: vertex_case_map) //using structured binding - { - vertex_parent_entity[second] = first; // values can also be manipulated as they are refrences - } + vertex_parent_entity.assign(static_cast(max_local + 1), -1); + for (const auto& kv : vertex_case_map) + vertex_parent_entity[static_cast(kv.second)] = kv.first; } } \ No newline at end of file diff --git a/img/cut_hex_gyroid_grid.png b/img/cut_hex_gyroid_grid.png new file mode 100644 index 0000000..7c0ab95 Binary files /dev/null and b/img/cut_hex_gyroid_grid.png differ diff --git a/img/cut_tetra_quad.png b/img/cut_tetra_quad.png new file mode 100644 index 0000000..44b2800 Binary files /dev/null and b/img/cut_tetra_quad.png differ diff --git a/img/cut_tetra_tri.png b/img/cut_tetra_tri.png new file mode 100644 index 0000000..2cf7b4b Binary files /dev/null and b/img/cut_tetra_tri.png differ diff --git a/img/hybrid_flower.png b/img/hybrid_flower.png new file mode 100644 index 0000000..999af7f Binary files /dev/null and b/img/hybrid_flower.png differ diff --git a/img/popcorn_hex_mesh3D.png b/img/popcorn_hex_mesh3D.png new file mode 100644 index 0000000..97d0229 Binary files /dev/null and b/img/popcorn_hex_mesh3D.png differ diff --git a/img/prism_n0_demo.png b/img/prism_n0_demo.png new file mode 100644 index 0000000..5bca82a Binary files /dev/null and b/img/prism_n0_demo.png differ diff --git a/img/pyramid_n0_demo.png b/img/pyramid_n0_demo.png new file mode 100644 index 0000000..b82fb3f Binary files /dev/null and b/img/pyramid_n0_demo.png differ diff --git a/img/quad_cases_with_disambiguation_panels_quads.png b/img/quad_cases_with_disambiguation_panels_quads.png new file mode 100644 index 0000000..4e50590 Binary files /dev/null and b/img/quad_cases_with_disambiguation_panels_quads.png differ diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index d734910..2c7b995 100644 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -16,6 +16,13 @@ if (TARGET cutcells) add_library(CUTCELLS::cutcells ALIAS cutcells) else() # Find CutCells (C++) + # Prefer the in-repo build if present, so `pip install -e python` uses local C++ changes. + if (NOT DEFINED CutCells_DIR) + set(_local_cutcells_prefix "${CMAKE_CURRENT_LIST_DIR}/../cpp/build-dir/prefix") + if (EXISTS "${_local_cutcells_prefix}/lib/cmake/cutcells/CutCellsConfig.cmake") + list(PREPEND CMAKE_PREFIX_PATH "${_local_cutcells_prefix}") + endif() + endif() find_package(CutCells REQUIRED) endif() @@ -46,6 +53,32 @@ endif() get_target_property(_location CUTCELLS::cutcells LOCATION) get_filename_component(_cutcells_dir ${_location} DIRECTORY) -set_target_properties(_cutcellscpp PROPERTIES INSTALL_RPATH ${_cutcells_dir}) + +# Ensure we load the CutCells library we just found/linked against. +# In conda environments it's common to also have a (possibly older) libcutcells.dylib +# available on the default RPATH; if that appears before our in-repo prefix, dyld +# will pick the wrong one at runtime. +set_target_properties(_cutcellscpp PROPERTIES + INSTALL_RPATH "${_cutcells_dir}" + BUILD_RPATH "${_cutcells_dir}" + BUILD_WITH_INSTALL_RPATH TRUE + INSTALL_RPATH_USE_LINK_PATH FALSE) + +if(APPLE AND DEFINED ENV{CONDA_PREFIX}) + # scikit-build/nanobind often injects ${CONDA_PREFIX}/lib as an LC_RPATH ahead of ours. + # If that environment contains another libcutcells.dylib, dyld will load the wrong one. + # Reorder RPATHs post-link so the in-repo CutCells lib directory is searched first. + set(_conda_lib "$ENV{CONDA_PREFIX}/lib") + # If CutCells itself is installed into the conda env lib dir, then _cutcells_dir == _conda_lib + # and reordering is unnecessary (and would attempt to add the same RPATH twice). + if (NOT "${_cutcells_dir}" STREQUAL "${_conda_lib}") + add_custom_command(TARGET _cutcellscpp POST_BUILD + COMMAND install_name_tool -delete_rpath "${_conda_lib}" $ || true + COMMAND install_name_tool -delete_rpath "${_cutcells_dir}" $ || true + COMMAND install_name_tool -add_rpath "${_cutcells_dir}" $ + COMMAND install_name_tool -add_rpath "${_conda_lib}" $ + VERBATIM) + endif() +endif() install(TARGETS _cutcellscpp LIBRARY DESTINATION cutcells) diff --git a/python/cutcells/wrapper.cpp b/python/cutcells/wrapper.cpp index d80d3b5..7cf07f2 100644 --- a/python/cutcells/wrapper.cpp +++ b/python/cutcells/wrapper.cpp @@ -84,29 +84,41 @@ void declare_float(nb::module_& m, std::string type) .def_prop_ro( "vertex_coords", [](const cell::CutCell& self) { - const unsigned long num_vertices = self._vertex_coords.size()/self._gdim; - std::vector vertex_coords(3*num_vertices); - - int idx = 0; - - for(unsigned long i=0;i(self._gdim); + if (gdim == 0) + return nb::ndarray(nullptr, {0, 0}, nb::handle()); + const std::size_t n = self._vertex_coords.size() / gdim; + return nb::ndarray( + self._vertex_coords.data(), + {n, gdim}, + nb::handle()); + }, + nb::rv_policy::reference_internal, + "Zero-copy view of cut-cell vertex coordinates as shape (num_vertices, gdim).") + .def_prop_ro( + "parent_vertex_coords", + [](const cell::CutCell& self) { + const std::size_t gdim = static_cast(self._gdim); + if (gdim == 0) + return nb::ndarray(nullptr, {0, 0}, nb::handle()); + const std::size_t n = self._parent_vertex_coords.size() / gdim; + return nb::ndarray( + self._parent_vertex_coords.data(), + {n, gdim}, + nb::handle()); + }, + nb::rv_policy::reference_internal, + "Zero-copy view of parent-cell vertex coordinates as shape (num_parent_vertices, gdim).") + .def_prop_ro( + "parent_vertex_ids", + [](const cell::CutCell& self) { + return nb::ndarray( + self._parent_vertex_ids.data(), + {self._parent_vertex_ids.size()}, + nb::handle()); + }, + nb::rv_policy::reference_internal, + "Zero-copy view of parent vertex ids (context-global indices when available).") .def_prop_ro( "connectivity", [](const cell::CutCell& self) { @@ -135,6 +147,17 @@ void declare_float(nb::module_& m, std::string type) return types; }) + .def_prop_ro( + "vertex_parent_entity", + [](const cell::CutCell& self) { + return nb::ndarray( + self._vertex_parent_entity.data(), + {self._vertex_parent_entity.size()}, + nb::handle()); + }, + nb::rv_policy::reference_internal, + "Return parent entity token for each cut-cell vertex.\n" + "Tokens encode the origin: edge intersections use edge id, original vertices use 100+vid, special points use 200+sid.") .def("str", [](const cell::CutCell& self) {cell::str(self); return ;}) .def("volume", [](const cell::CutCell& self) {return cell::volume(self);}) .def("write_vtk", [](cell::CutCell& self, std::string fname) {io::write_vtk(fname,self); return ;}); @@ -178,29 +201,17 @@ void declare_float(nb::module_& m, std::string type) .def_prop_ro( "vertex_coords", [](const mesh::CutMesh& self) { - const unsigned long num_vertices = self._vertex_coords.size()/self._gdim; - std::vector vertex_coords(3*num_vertices); - - int idx = 0; - - for(unsigned long i=0;i(self._gdim); + if (gdim == 0) + return nb::ndarray(nullptr, {0, 0}, nb::handle()); + const std::size_t n = self._vertex_coords.size() / gdim; + return nb::ndarray( + self._vertex_coords.data(), + {n, gdim}, + nb::handle()); + }, + nb::rv_policy::reference_internal, + "Zero-copy view of mesh vertex coordinates as shape (num_vertices, gdim).") .def_prop_ro( "connectivity", [](const mesh::CutMesh& self) { @@ -287,14 +298,18 @@ void declare_float(nb::module_& m, std::string type) m.def("cut_vtk_mesh", [](nb::ndarray& ls_vals, nb::ndarray& points, nb::ndarray& connectivity, nb::ndarray& offset, nb::ndarray& vtk_type, - const std::string& cut_type_str){ + const std::string& cut_type_str, + bool triangulate){ return mesh::cut_vtk_mesh(std::span(ls_vals.data(),ls_vals.size()), std::span(points.data(),points.size()), std::span(connectivity.data(),connectivity.size()), std::span(offset.data(),offset.size()), std::span(vtk_type.data(),vtk_type.size()), - cut_type_str); + cut_type_str, + triangulate); } + , nb::arg("ls_vals"), nb::arg("points"), nb::arg("connectivity"), nb::arg("offset"), nb::arg("vtk_type"), + nb::arg("cut_type_str"), nb::arg("triangulate") = true , "cut vtk mesh"); } diff --git a/python/demo/cut_2nd_order_tetrahedron/cut_tetrahedron.py b/python/demo/cut_2nd_order_tetrahedron/cut_tetrahedron.py index bfd34f4..068fe07 100644 --- a/python/demo/cut_2nd_order_tetrahedron/cut_tetrahedron.py +++ b/python/demo/cut_2nd_order_tetrahedron/cut_tetrahedron.py @@ -2,41 +2,45 @@ import numpy as np import pyvista as pv -subdivision = np.array([[2,3], [1,3], [1,2], [0,3], [0,2], [0,1]]) +subdivision = np.array([[2, 3], [1, 3], [1, 2], [0, 3], [0, 2], [0, 1]]) + +# e01 : 4 , e12: 5, e02: 6, e03: 7, e13: 8, e23: 9 +# subdivision_vtk = np.array([[0,1], [1,2], [0,2], [0,3], [1,3], [2,3]]) -#e01 : 4 , e12: 5, e02: 6, e03: 7, e13: 8, e23: 9 -#subdivision_vtk = np.array([[0,1], [1,2], [0,2], [0,3], [1,3], [2,3]]) def level_set(x, c, r): - value = 0 - for i in range(0,3): - value = value + (x[i]-c[i])**2 - value = np.sqrt(value)-r - return value + value = 0 + for i in range(0, 3): + value = value + (x[i] - c[i]) ** 2 + value = np.sqrt(value) - r + return value + -c = np.array([0,0,0]) +c = np.array([0, 0, 0]) r = 0.6 -tetra_vertices = np.array([[0.0, 0.0, 0.0], - [1.0, 0.0, 0.0], - [0.0, 1.0, 0.0], - [0.0, 0.0, 1.0] ]) +tetra_vertices = np.array( + [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] +) mid_points = np.empty([6, 3]) -#obtain edge nodes with vtk ordering -for i in range(0,6): - mid_points[i] = tetra_vertices[subdivision[i,0]] + (tetra_vertices[subdivision[i,1]]-tetra_vertices[subdivision[i,0]])/2.0 +# obtain edge nodes with vtk ordering +for i in range(0, 6): + mid_points[i] = ( + tetra_vertices[subdivision[i, 0]] + + (tetra_vertices[subdivision[i, 1]] - tetra_vertices[subdivision[i, 0]]) / 2.0 + ) # add mid-edge nodes to tetrahedral nodes tetra_nodes = np.concatenate((tetra_vertices, mid_points), axis=0) print(tetra_nodes) -ls_values=np.empty(10) -idx=0 +ls_values = np.empty(10) +idx = 0 for x in tetra_nodes: - ls_values[idx] = level_set(x, c, r) - idx = idx+1 + ls_values[idx] = level_set(x, c, r) + idx = idx + 1 print(ls_values) @@ -44,22 +48,34 @@ def level_set(x, c, r): triangulate = True gdim = 3 -cut_cell_int = cutcells.higher_order_cut(cell_type, tetra_nodes, gdim, ls_values, "phi<0", triangulate) +cut_cell_int = cutcells.higher_order_cut( + cell_type, tetra_nodes, gdim, ls_values, "phi<0", triangulate +) print(cut_cell_int.str()) cut_cell_int.write_vtk("interior.vtu") -cut_cell_ext = cutcells.higher_order_cut(cell_type, tetra_nodes, gdim, ls_values, "phi>0", triangulate) +cut_cell_ext = cutcells.higher_order_cut( + cell_type, tetra_nodes, gdim, ls_values, "phi>0", triangulate +) print(cut_cell_ext.str()) cut_cell_ext.write_vtk("exterior.vtu") -#pv.OFF_SCREEN = True -#pv.start_xvfb() - -grid_int = pv.UnstructuredGrid(cut_cell_int.connectivity, cut_cell_int.types, cut_cell_int.vertex_coords) -grid_ext = pv.UnstructuredGrid(cut_cell_ext.connectivity, cut_cell_ext.types, cut_cell_ext.vertex_coords) - -plotter = pv.Plotter() #off_screen=True -plotter.set_background('white', top='white') -plotter.add_mesh(grid_int, color="blue",show_edges=True) -plotter.add_mesh(grid_ext, color="red",show_edges=True) -plotter.show() #screenshot='cut_triangle.png' +# pv.OFF_SCREEN = True +# pv.start_xvfb() + +grid_int = pv.UnstructuredGrid( + cut_cell_int.connectivity, + cut_cell_int.types, + cut_cell_int.vertex_coords, +) +grid_ext = pv.UnstructuredGrid( + cut_cell_ext.connectivity, + cut_cell_ext.types, + cut_cell_ext.vertex_coords, +) + +plotter = pv.Plotter() # off_screen=True +plotter.set_background("white", top="white") +plotter.add_mesh(grid_int, color="blue", show_edges=True) +plotter.add_mesh(grid_ext, color="red", show_edges=True) +plotter.show() # screenshot='cut_triangle.png' diff --git a/python/demo/cut_2nd_order_triangle/cut_triangle.py b/python/demo/cut_2nd_order_triangle/cut_triangle.py index 33a97fe..95be98c 100644 --- a/python/demo/cut_2nd_order_triangle/cut_triangle.py +++ b/python/demo/cut_2nd_order_triangle/cut_triangle.py @@ -1,34 +1,49 @@ import cutcells import numpy as np -import pyvista as pv +import pyvista as pv + def cut_cell_type_to_pyvista(cut_cell_type): - if(cut_cell_type==cutcells.CellType.triangle): - return pv.CellType.TRIANGLE; + if cut_cell_type == cutcells.CellType.triangle: + return pv.CellType.TRIANGLE + -ls_values = np.array([-0.1,0.1,0.2,-0.3, 0.4, 0.2]) -vertex_coordinates = np.array([0.,0.,1.,0.,0.,1.,0.5,0.5,0.,0.5,0.5,0.0]) +ls_values = np.array([-0.1, 0.1, 0.2, -0.3, 0.4, 0.2]) +vertex_coordinates = np.array( + [0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.5, 0.5, 0.0, 0.5, 0.5, 0.0] +) cell_type = cutcells.CellType.triangle triangulate = True gdim = 2 -cut_cell_int = cutcells.higher_order_cut(cell_type, vertex_coordinates, gdim, ls_values, "phi<0", triangulate) +cut_cell_int = cutcells.higher_order_cut( + cell_type, vertex_coordinates, gdim, ls_values, "phi<0", triangulate +) print(cut_cell_int.str()) cut_cell_int.write_vtk("interior.vtu") -cut_cell_ext = cutcells.higher_order_cut(cell_type, vertex_coordinates, gdim, ls_values, "phi>0", triangulate) +cut_cell_ext = cutcells.higher_order_cut( + cell_type, vertex_coordinates, gdim, ls_values, "phi>0", triangulate +) print(cut_cell_ext.str()) cut_cell_ext.write_vtk("exterior.vtu") -#pv.OFF_SCREEN = True -#pv.start_xvfb() +# pv.OFF_SCREEN = True +# pv.start_xvfb() + +pts_int = np.asarray(cut_cell_int.vertex_coords) +if pts_int.shape[1] == 2: + pts_int = np.c_[pts_int, np.zeros((pts_int.shape[0],), dtype=pts_int.dtype)] +pts_ext = np.asarray(cut_cell_ext.vertex_coords) +if pts_ext.shape[1] == 2: + pts_ext = np.c_[pts_ext, np.zeros((pts_ext.shape[0],), dtype=pts_ext.dtype)] -grid_int = pv.UnstructuredGrid(cut_cell_int.connectivity, cut_cell_int.types, cut_cell_int.vertex_coords) -grid_ext = pv.UnstructuredGrid(cut_cell_ext.connectivity, cut_cell_ext.types, cut_cell_ext.vertex_coords) +grid_int = pv.UnstructuredGrid(cut_cell_int.connectivity, cut_cell_int.types, pts_int) +grid_ext = pv.UnstructuredGrid(cut_cell_ext.connectivity, cut_cell_ext.types, pts_ext) -plotter = pv.Plotter() #off_screen=True -plotter.set_background('white', top='white') -plotter.add_mesh(grid_int, color="blue",show_edges=True) -plotter.add_mesh(grid_ext, color="red",show_edges=True) -plotter.show() #screenshot='cut_triangle.png' +plotter = pv.Plotter() # off_screen=True +plotter.set_background("white", top="white") +plotter.add_mesh(grid_int, color="blue", show_edges=True) +plotter.add_mesh(grid_ext, color="red", show_edges=True) +plotter.show() # screenshot='cut_triangle.png' diff --git a/python/demo/cut_hexahedron/cut_hexahedron_cases_subplots.py b/python/demo/cut_hexahedron/cut_hexahedron_cases_subplots.py new file mode 100644 index 0000000..95afb9d --- /dev/null +++ b/python/demo/cut_hexahedron/cut_hexahedron_cases_subplots.py @@ -0,0 +1,219 @@ +import argparse +import math + +import cutcells +import numpy as np +import pyvista as pv + + +# VTK cell type ids (used by PyVista UnstructuredGrid) +VTK_TETRA = 10 +VTK_HEXAHEDRON = 12 +VTK_WEDGE = 13 +VTK_PYRAMID = 14 + + +def unit_cube_vertices() -> np.ndarray: + # VTK_HEXAHEDRON / CutCells hexahedron vertex order: + # 0:(0,0,0) 1:(1,0,0) 2:(1,1,0) 3:(0,1,0) + # 4:(0,0,1) 5:(1,0,1) 6:(1,1,1) 7:(0,1,1) + return np.array( + [ + [0.0, 0.0, 0.0], + [1.0, 0.0, 0.0], + [1.0, 1.0, 0.0], + [0.0, 1.0, 0.0], + [0.0, 0.0, 1.0], + [1.0, 0.0, 1.0], + [1.0, 1.0, 1.0], + [0.0, 1.0, 1.0], + ], + dtype=float, + ) + + +def ls_values_from_case_id(case_id: int) -> np.ndarray: + # CutCells convention: bit i is set when phi_i < 0. + # We use a simple +/-1 pattern. + ls = np.empty(8, dtype=float) + for i in range(8): + ls[i] = -1.0 if ((case_id >> i) & 1) else 1.0 + return ls + + +def on_unit_cube_edge(p: np.ndarray, tol: float = 1e-12) -> bool: + # A point is on an edge if at least two coordinates are on the boundary {0,1} + on_boundary = np.isclose(p, 0.0, atol=tol) | np.isclose(p, 1.0, atol=tol) + return int(on_boundary.sum()) >= 2 + + +def main() -> None: + parser = argparse.ArgumentParser( + description=( + "Visualize VTK_HEXAHEDRON interface-cut cases in 3x5 interactive subplots (15 at a time). " + "Use 'n'/'p' keys to page through batches." + ) + ) + parser.add_argument( + "--batch", + type=int, + default=0, + help="0-based batch index (each batch shows 15 intersected cases).", + ) + parser.add_argument( + "--screenshot", + default="", + help="Optional screenshot filename (empty disables).", + ) + parser.add_argument( + "--show", + action=argparse.BooleanOptionalAction, + default=True, + help="Show an interactive window (disable for headless runs).", + ) + args = parser.parse_args() + + vertex_coordinates = unit_cube_vertices() + + # Exclude non-intersected masks. + case_ids = [i for i in range(256) if i not in (0, 255)] + batch_size = 15 + num_batches = int(math.ceil(len(case_ids) / batch_size)) + + batch = int(args.batch) + if batch < 0: + batch = 0 + if batch >= num_batches: + batch = num_batches - 1 + + pl = pv.Plotter(shape=(3, 5), off_screen=not args.show) + + cube = pv.Cube(center=(0.5, 0.5, 0.5), x_length=1.0, y_length=1.0, z_length=1.0) + + def render_batch(batch_index: int) -> None: + pl.clear() + + start = batch_index * batch_size + for i in range(batch_size): + global_idx = start + i + row = i // 5 + col = i % 5 + pl.subplot(row, col) + + if global_idx >= len(case_ids): + pl.add_text("(no case)", font_size=10) + pl.add_mesh(cube, style="wireframe", color="black", line_width=1) + pl.camera_position = "iso" + continue + + case_id = case_ids[global_idx] + ls_values = ls_values_from_case_id(case_id) + + try: + # Inside volume (phi<0) + inside_cell = cutcells.cut( + cutcells.CellType.hexahedron, + vertex_coordinates, + 3, + ls_values, + "phi<0", + False, + ) + inside_points = np.asarray(inside_cell.vertex_coords) + inside_grid = pv.UnstructuredGrid( + inside_cell.connectivity, inside_cell.types, inside_points + ) + + # Interface surface (phi=0) + cut_cell = cutcells.cut( + cutcells.CellType.hexahedron, + vertex_coordinates, + 3, + ls_values, + "phi=0", + False, + ) + + points = np.asarray(cut_cell.vertex_coords) + grid = pv.UnstructuredGrid( + cut_cell.connectivity, cut_cell.types, points + ) + + edge_mask = np.array([on_unit_cube_edge(p) for p in points], dtype=bool) + + pl.add_text( + f"case {case_id}", + font_size=10, + ) + pl.add_mesh(cube, style="wireframe", color="black", line_width=1) + + # Render inside composition behind the interface + inside_types = np.asarray(inside_grid.celltypes, dtype=int) + type_specs = [ + (VTK_HEXAHEDRON, "hex", "seagreen"), + (VTK_WEDGE, "prism", "gold"), + (VTK_PYRAMID, "pyr", "orchid"), + (VTK_TETRA, "tet", "lightskyblue"), + ] + + counts = [] + for vtk_id, label, color in type_specs: + cell_ids = np.where(inside_types == vtk_id)[0] + if cell_ids.size == 0: + continue + subgrid = inside_grid.extract_cells(cell_ids) + pl.add_mesh( + subgrid, + color=color, + opacity=0.25, + show_edges=True, + line_width=1, + ) + counts.append(f"{label}:{int(cell_ids.size)}") + + if counts: + pl.add_text("\n".join(counts), position="lower_left", font_size=9) + + pl.add_mesh(grid, show_edges=True, opacity=0.75) + + pc = pv.PolyData(points) + pc["non_edge"] = (~edge_mask).astype(np.int32) + pl.add_mesh( + pc, + scalars="non_edge", + render_points_as_spheres=True, + point_size=10, + cmap=["dodgerblue", "crimson"], + ) + except Exception as e: # pragma: no cover + pl.add_text(f"case {case_id}\nERROR\n{type(e).__name__}", font_size=10) + pl.add_mesh(cube, style="wireframe", color="black", line_width=1) + + pl.camera_position = "iso" + + pl.render() + print( + f"batch {batch_index + 1}/{num_batches} (cases {start}..{min(start + batch_size - 1, len(case_ids) - 1)})" + ) + + def next_batch() -> None: + nonlocal batch + batch = (batch + 1) % num_batches + render_batch(batch) + + def prev_batch() -> None: + nonlocal batch + batch = (batch - 1) % num_batches + render_batch(batch) + + pl.add_key_event("n", next_batch) + pl.add_key_event("p", prev_batch) + + render_batch(batch) + + screenshot = args.screenshot if args.screenshot else None + pl.show(screenshot=screenshot) + + +if __name__ == "__main__": + main() diff --git a/python/demo/cut_hexahedron/cut_hexahedron_gyroid_thick.py b/python/demo/cut_hexahedron/cut_hexahedron_gyroid_thick.py new file mode 100644 index 0000000..a97183c --- /dev/null +++ b/python/demo/cut_hexahedron/cut_hexahedron_gyroid_thick.py @@ -0,0 +1,214 @@ +import argparse + +import cutcells +import numpy as np +import pyvista as pv + + +def gyroid(x: np.ndarray, k: float) -> float: + # Classic gyroid implicit: sin(kx)cos(ky) + sin(ky)cos(kz) + sin(kz)cos(kx) + xx, yy, zz = float(x[0]), float(x[1]), float(x[2]) + return ( + np.sin(k * xx) * np.cos(k * yy) + + np.sin(k * yy) * np.cos(k * zz) + + np.sin(k * zz) * np.cos(k * xx) + ) + + +def level_set_thick_gyroid(x: np.ndarray, k: float, thickness: float) -> float: + # A "thick" gyroid shell: |g(x)| < thickness => phi(x) = |g(x)| - thickness < 0 + return abs(gyroid(x, k)) - thickness + + +def create_structured_hex_mesh( + x0, y0, z0, x1, y1, z1, nx, ny, nz +) -> pv.UnstructuredGrid: + # Use VTK structured grid -> cast to unstructured hex mesh. + xs = np.linspace(x0, x1, num=nx) + ys = np.linspace(y0, y1, num=ny) + zs = np.linspace(z0, z1, num=nz) + + xx, yy, zz = np.meshgrid(xs, ys, zs, indexing="ij") + sg = pv.StructuredGrid(xx, yy, zz) + return sg.cast_to_unstructured_grid() + + +def create_cut_mesh( + grid: pv.UnstructuredGrid, k: float, thickness: float, triangulate: bool +) -> pv.UnstructuredGrid: + points = grid.points + + ls_values = np.zeros(len(points), dtype=float) + for j, point in enumerate(points): + ls_values[j] = level_set_thick_gyroid(point, k=k, thickness=thickness) + + cut_mesh = cutcells.cut_vtk_mesh( + ls_values, + points, + grid.cell_connectivity, + grid.offset, + grid.celltypes, + "phi<0", + triangulate, + ) + + inside_cells = cutcells.locate_cells( + ls_values, + points, + grid.cell_connectivity, + grid.offset, + grid.celltypes, + "phi<0", + ) + + pv_cut = pv.UnstructuredGrid( + cut_mesh.cells, + cut_mesh.types, + cut_mesh.vertex_coords, + ) + extract = grid.extract_cells(inside_cells) + + return extract.merge(pv_cut) + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Cut a thick gyroid (|g(x)| < t) from a hexahedral (VTK_HEXAHEDRON) mesh." + ) + parser.add_argument( + "--n", type=int, default=41, help="Number of points per axis (>= 2)." + ) + parser.add_argument( + "--periods", + type=float, + default=2.0, + help="Number of gyroid periods across the domain.", + ) + parser.add_argument( + "--thickness", + type=float, + default=0.30, + help="Shell half-thickness in gyroid level-set units (phi = |g|-thickness).", + ) + parser.add_argument( + "--triangulate", + action=argparse.BooleanOptionalAction, + default=True, + help="Triangulate cut output (more robust for visualization).", + ) + parser.add_argument( + "--show-grid", + action=argparse.BooleanOptionalAction, + default=False, + help="Overlay the input hex grid (wireframe).", + ) + parser.add_argument( + "--show-edges", + action=argparse.BooleanOptionalAction, + default=True, + help="Show mesh edges (can look very busy for larger N).", + ) + parser.add_argument( + "--screenshot", + default="gyroid_hex_mesh3D.png", + help="Output screenshot filename (set to empty string to disable).", + ) + parser.add_argument( + "--show", + action=argparse.BooleanOptionalAction, + default=True, + help="Show an interactive window (disable for headless runs).", + ) + parser.add_argument( + "--write-prefix", + default="", + help="If set, write interface/inside/outside VTK files using this prefix (e.g. /tmp/gyroid).", + ) + args = parser.parse_args() + + if args.n < 2: + raise ValueError("--n must be >= 2") + + # Domain [-1,1]^3. Choose k so that `periods` periods fit into length 2: + # period = 2*pi/k, so periods = 2 / (2*pi/k) = k/pi => k = periods*pi + k = float(args.periods) * np.pi + + grid = create_structured_hex_mesh(-1, -1, -1, 1, 1, 1, args.n, args.n, args.n) + mesh = create_cut_mesh( + grid, k=k, thickness=float(args.thickness), triangulate=args.triangulate + ) + + print( + f"input: n_points={grid.n_points}, n_cells={grid.n_cells}, unique_celltypes={sorted(set(map(int, grid.celltypes)))}" + ) + print(f"output: n_points={mesh.n_points}, n_cells={mesh.n_cells}") + + pl = pv.Plotter(off_screen=not args.show) + if args.show_grid: + pl.add_mesh(grid, show_edges=True, style="wireframe") + pl.add_mesh(mesh, show_edges=args.show_edges) + pl.camera_position = "iso" + + # Optionally write interface, inside and outside VTK files + if args.write_prefix: + pts = grid.points + ls_values = np.zeros(len(pts), dtype=float) + for j, point in enumerate(pts): + ls_values[j] = level_set_thick_gyroid( + point, k=k, thickness=float(args.thickness) + ) + + conn = grid.cell_connectivity + off = grid.offset + ctypes = grid.celltypes + + # Interface (phi=0) + try: + iface = cutcells.cut_vtk_mesh( + ls_values, pts, conn, off, ctypes, "phi=0", args.triangulate + ) + iface_pv = pv.UnstructuredGrid( + iface.cells, iface.types, iface.vertex_coords + ) + iface_file = f"{args.write_prefix}_interface.vtu" + iface_pv.save(iface_file) + print(f"Wrote interface VTK -> {iface_file}") + except Exception as e: # pragma: no cover + print("Failed to write interface mesh:", e) + + # Inside (phi<0) + try: + inside = cutcells.cut_vtk_mesh( + ls_values, pts, conn, off, ctypes, "phi<0", args.triangulate + ) + inside_pv = pv.UnstructuredGrid( + inside.cells, inside.types, inside.vertex_coords + ) + inside_file = f"{args.write_prefix}_inside.vtu" + inside_pv.save(inside_file) + print(f"Wrote inside VTK -> {inside_file}") + except Exception as e: # pragma: no cover + print("Failed to write inside mesh:", e) + + # Outside (phi>0) + try: + outside = cutcells.cut_vtk_mesh( + ls_values, pts, conn, off, ctypes, "phi>0", args.triangulate + ) + outside_pv = pv.UnstructuredGrid( + outside.cells, outside.types, outside.vertex_coords + ) + outside_file = f"{args.write_prefix}_outside.vtu" + outside_pv.save(outside_file) + print(f"Wrote outside VTK -> {outside_file}") + except Exception as e: # pragma: no cover + print("Failed to write outside mesh:", e) + + if args.screenshot: + pl.show(screenshot=args.screenshot) + else: + pl.show() + + +if __name__ == "__main__": + main() diff --git a/python/demo/cut_hexahedron/cut_hexahedron_n0.py b/python/demo/cut_hexahedron/cut_hexahedron_n0.py new file mode 100644 index 0000000..4574519 --- /dev/null +++ b/python/demo/cut_hexahedron/cut_hexahedron_n0.py @@ -0,0 +1,118 @@ +import argparse + +import cutcells +import numpy as np +import pyvista as pv + + +def unit_cube_vertices() -> np.ndarray: + # VTK_HEXAHEDRON / CutCells hexahedron vertex order: + # 0:(0,0,0) 1:(1,0,0) 2:(1,1,0) 3:(0,1,0) + # 4:(0,0,1) 5:(1,0,1) 6:(1,1,1) 7:(0,1,1) + return np.array( + [ + [0.0, 0.0, 0.0], + [1.0, 0.0, 0.0], + [1.0, 1.0, 0.0], + [0.0, 1.0, 0.0], + [0.0, 0.0, 1.0], + [1.0, 0.0, 1.0], + [1.0, 1.0, 1.0], + [0.0, 1.0, 1.0], + ], + dtype=float, + ) + + +def case_id_from_ls_values(ls_values: np.ndarray) -> int: + # CutCells convention: a vertex contributes bit i if phi_i < 0 + case_id = 0 + for i, v in enumerate(ls_values.tolist()): + if v < 0: + case_id |= 1 << i + return case_id + + +def on_unit_cube_edge(p: np.ndarray, tol: float = 1e-12) -> bool: + # A point is on an edge if at least two coordinates are on the boundary {0,1} + on_boundary = np.isclose(p, 0.0, atol=tol) | np.isclose(p, 1.0, atol=tol) + return int(on_boundary.sum()) >= 2 + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Demonstrate a hexahedron interface cut that introduces an interior special point (VTK's N0)." + ) + parser.add_argument( + "--screenshot", + default="n0_demo.png", + help="Output screenshot filename (set to empty string to disable).", + ) + parser.add_argument( + "--show", + action=argparse.BooleanOptionalAction, + default=True, + help="Show an interactive window (disable for headless runs).", + ) + args = parser.parse_args() + + vertex_coordinates = unit_cube_vertices() + + # This sign pattern corresponds to a VTK hexahedron case known to use N0 in the table. + # (Used in the regression test: vertices 0,1,6 are inside (phi<0), others outside.) + ls_values = np.array([-1.0, -1.1, 1.2, 1.3, 1.4, 1.5, -1.6, 1.7], dtype=float) + case_id = case_id_from_ls_values(ls_values) + + cut_cell = cutcells.cut( + cutcells.CellType.hexahedron, + vertex_coordinates, + 3, + ls_values, + "phi=0", + False, + ) + + points = np.asarray(cut_cell.vertex_coords) + grid = pv.UnstructuredGrid(cut_cell.connectivity, cut_cell.types, points) + + edge_mask = np.array([on_unit_cube_edge(p) for p in points], dtype=bool) + interior_points = points[~edge_mask] + + print(f"hexahedron case_id (phi<0 bits): {case_id}") + print(f"cut_cell: n_vertices={points.shape[0]}, n_cells={grid.n_cells}") + print(f"points on unit-cube edges: {int(edge_mask.sum())}") + print(f"points not on edges (interior/face): {int((~edge_mask).sum())}") + if interior_points.size: + print("example non-edge point(s) (typically includes N0):") + for p in interior_points[:8]: + print(" ", p) + + # Visualization + pl = pv.Plotter(off_screen=not args.show) + + # Show the reference cube as wireframe + cube = pv.Cube(center=(0.5, 0.5, 0.5), x_length=1.0, y_length=1.0, z_length=1.0) + pl.add_mesh(cube, style="wireframe", color="black", line_width=1) + + # Show the interface mesh + pl.add_mesh(grid, show_edges=True, opacity=0.75) + + # Highlight interior/non-edge points (where N0 typically appears) + point_cloud = pv.PolyData(points) + point_cloud["non_edge"] = (~edge_mask).astype(np.int32) + pl.add_mesh( + point_cloud, + scalars="non_edge", + render_points_as_spheres=True, + point_size=14, + cmap=["dodgerblue", "crimson"], + ) + + pl.camera_position = "iso" + + screenshot = args.screenshot if args.screenshot else None + pl.show(screenshot=screenshot) + + +if __name__ == "__main__": + main() diff --git a/python/demo/cut_prism/cut_prism_n0.py b/python/demo/cut_prism/cut_prism_n0.py new file mode 100644 index 0000000..88c04b8 --- /dev/null +++ b/python/demo/cut_prism/cut_prism_n0.py @@ -0,0 +1,125 @@ +import argparse + +import cutcells +import numpy as np +import pyvista as pv + + +def unit_right_triangular_prism_vertices() -> np.ndarray: + # VTK_WEDGE / CutCells prism vertex order: + # bottom tri: 0:(0,0,0) 1:(1,0,0) 2:(0,1,0) + # top tri: 3:(0,0,1) 4:(1,0,1) 5:(0,1,1) + return np.array( + [ + [0.0, 0.0, 0.0], + [1.0, 0.0, 0.0], + [0.0, 1.0, 0.0], + [0.0, 0.0, 1.0], + [1.0, 0.0, 1.0], + [0.0, 1.0, 1.0], + ], + dtype=float, + ) + + +def case_id_from_ls_values(ls_values: np.ndarray) -> int: + # CutCells convention: a vertex contributes bit i if phi_i < 0 + case_id = 0 + for i, v in enumerate(ls_values.tolist()): + if v < 0: + case_id |= 1 << i + return case_id + + +def is_strictly_inside_unit_prism(p: np.ndarray, tol: float = 1e-12) -> bool: + # Strict interior of unit right-triangular prism: + # x>0, y>0, x+y<1, 0 tol and y > tol and (x + y) < (1.0 - tol) and z > tol and z < (1.0 - tol) + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Demonstrate a prism (VTK_WEDGE) interface cut that introduces an interior special point (VTK's N0)." + ) + parser.add_argument( + "--screenshot", + default="prism_n0_demo.png", + help="Output screenshot filename (set to empty string to disable).", + ) + parser.add_argument( + "--show", + action=argparse.BooleanOptionalAction, + default=True, + help="Show an interactive window (disable for headless runs).", + ) + args = parser.parse_args() + + vertex_coordinates = unit_right_triangular_prism_vertices() + + # Case id 10 (mask bits set at vertices {1,3}) is known to use N0 in the interface table. + ls_values = np.array([1.0, -1.0, 1.0, -1.0, 1.0, 1.0], dtype=float) + case_id = case_id_from_ls_values(ls_values) + + cut_cell = cutcells.cut( + cutcells.CellType.prism, + vertex_coordinates, + 3, + ls_values, + "phi=0", + False, + ) + + points = np.asarray(cut_cell.vertex_coords) + grid = pv.UnstructuredGrid(cut_cell.connectivity, cut_cell.types, points) + + interior_mask = np.array( + [is_strictly_inside_unit_prism(p) for p in points], dtype=bool + ) + + print(f"prism case_id (phi<0 bits): {case_id}") + print(f"cut_cell: n_vertices={points.shape[0]}, n_cells={grid.n_cells}") + print(f"strictly interior points: {int(interior_mask.sum())}") + if interior_mask.any(): + print("example interior point(s) (typically includes N0):") + for p in points[interior_mask][:8]: + print(" ", p) + + pl = pv.Plotter(off_screen=not args.show) + + # Reference prism wireframe + ref = pv.PolyData(vertex_coordinates) + # show its convex hull-ish outline via edges of the 5 faces + faces = np.hstack( + [ + [3, 0, 1, 2], + [3, 3, 5, 4], + [4, 0, 1, 4, 3], + [4, 1, 2, 5, 4], + [4, 2, 0, 3, 5], + ] + ).astype(np.int64) + surf = pv.PolyData(vertex_coordinates, faces) + pl.add_mesh(surf, style="wireframe", color="black", line_width=1) + + pl.add_mesh(grid, show_edges=True, opacity=0.75) + + pc = pv.PolyData(points) + pc["interior"] = interior_mask.astype(np.int32) + pl.add_mesh( + pc, + scalars="interior", + render_points_as_spheres=True, + point_size=14, + cmap=["dodgerblue", "crimson"], + ) + + # Frontal perspective: camera in front of the prism, slightly above and to the right + pl.camera_position = [(1.5, 1.5, 1.5), (0.5, 0.5, 0.5), (0, 0, 1)] + + screenshot = args.screenshot if args.screenshot else None + pl.show(screenshot=screenshot) + + +if __name__ == "__main__": + main() diff --git a/python/demo/cut_pyramid/cut_pyramid_n0.py b/python/demo/cut_pyramid/cut_pyramid_n0.py new file mode 100644 index 0000000..42963e2 --- /dev/null +++ b/python/demo/cut_pyramid/cut_pyramid_n0.py @@ -0,0 +1,128 @@ +import argparse + +import cutcells +import numpy as np +import pyvista as pv + + +def unit_square_pyramid_vertices() -> np.ndarray: + # VTK_PYRAMID / CutCells pyramid vertex order: + # base quad: 0:(0,0,0) 1:(1,0,0) 2:(1,1,0) 3:(0,1,0) + # apex: 4:(0.5,0.5,1) + return np.array( + [ + [0.0, 0.0, 0.0], + [1.0, 0.0, 0.0], + [1.0, 1.0, 0.0], + [0.0, 1.0, 0.0], + [0.5, 0.5, 1.0], + ], + dtype=float, + ) + + +def case_id_from_ls_values(ls_values: np.ndarray) -> int: + # CutCells convention: a vertex contributes bit i if phi_i < 0 + case_id = 0 + for i, v in enumerate(ls_values.tolist()): + if v < 0: + case_id |= 1 << i + return case_id + + +def is_strictly_inside_unit_pyramid(p: np.ndarray, tol: float = 1e-12) -> bool: + # Strict interior of the unit square pyramid with apex at (0.5,0.5,1). + # For a horizontal slice at height z, the cross-section is a square centered at (0.5,0.5) + # with half-width 0.5*(1-z). + x, y, z = float(p[0]), float(p[1]), float(p[2]) + if not (z > tol and z < 1.0 - tol): + return False + half = 0.5 * (1.0 - z) + return (abs(x - 0.5) < (half - tol)) and (abs(y - 0.5) < (half - tol)) + + +def main() -> None: + parser = argparse.ArgumentParser( + description=( + "Demonstrate a pyramid (VTK_PYRAMID) volume cut that introduces an interior special point (VTK's N0)." + ) + ) + parser.add_argument( + "--screenshot", + default="pyramid_n0_demo.png", + help="Output screenshot filename (set to empty string to disable).", + ) + parser.add_argument( + "--show", + action=argparse.BooleanOptionalAction, + default=True, + help="Show an interactive window (disable for headless runs).", + ) + args = parser.parse_args() + + vertex_coordinates = unit_square_pyramid_vertices() + + # Pick a concrete case that (per generated pyramid volume tables) uses token 200 (N0). + # Pyramid has 5 vertices => 32 cases; case id 19 corresponds to mask bits set at vertices {0,1,4}. + ls_values = np.array([-1.0, -1.0, 1.0, 1.0, -1.0], dtype=float) + case_id = case_id_from_ls_values(ls_values) + + cut_cell = cutcells.cut( + cutcells.CellType.pyramid, + vertex_coordinates, + 3, + ls_values, + "phi<0", + False, + ) + + points = np.asarray(cut_cell.vertex_coords) + grid = pv.UnstructuredGrid(cut_cell.connectivity, cut_cell.types, points) + + interior_mask = np.array( + [is_strictly_inside_unit_pyramid(p) for p in points], dtype=bool + ) + + print(f"pyramid case_id (phi<0 bits): {case_id}") + print(f"cut_cell: n_vertices={points.shape[0]}, n_cells={grid.n_cells}") + print(f"strictly interior points: {int(interior_mask.sum())}") + if interior_mask.any(): + print("example interior point(s) (typically includes N0):") + for p in points[interior_mask][:8]: + print(" ", p) + + pl = pv.Plotter(off_screen=not args.show) + + # Reference pyramid wireframe + faces = np.hstack( + [ + [4, 0, 1, 2, 3], + [3, 0, 1, 4], + [3, 1, 2, 4], + [3, 2, 3, 4], + [3, 3, 0, 4], + ] + ).astype(np.int64) + surf = pv.PolyData(vertex_coordinates, faces) + pl.add_mesh(surf, style="wireframe", color="black", line_width=1) + + pl.add_mesh(grid, show_edges=True, opacity=0.75) + + pc = pv.PolyData(points) + pc["interior"] = interior_mask.astype(np.int32) + pl.add_mesh( + pc, + scalars="interior", + render_points_as_spheres=True, + point_size=14, + cmap=["dodgerblue", "crimson"], + ) + + pl.camera_position = "iso" + + screenshot = args.screenshot if args.screenshot else None + pl.show(screenshot=screenshot) + + +if __name__ == "__main__": + main() diff --git a/python/demo/cut_quadrilateral/cut_quadrilateral.py b/python/demo/cut_quadrilateral/cut_quadrilateral.py new file mode 100644 index 0000000..c7f373d --- /dev/null +++ b/python/demo/cut_quadrilateral/cut_quadrilateral.py @@ -0,0 +1,94 @@ +"""Demo: cut a level set through quadrilateral cells using CutCells. + +Run (from repo root, fenicsx-dev env): + conda run -n fenicsx-dev python python/demo/cut_quadrilateral/cut_quadrilateral.py + +Optional: + conda run -n fenicsx-dev python python/demo/cut_quadrilateral/cut_quadrilateral.py --write-vtk out_prefix + +This uses the installed CutCells Python bindings, which call the C++ implementation +(and therefore the generated quadrilateral clip tables). +""" + +from __future__ import annotations + +import argparse +from pathlib import Path + +import numpy as np + +import cutcells + + +def cut_one_quad(ls_values: np.ndarray, write_vtk_prefix: str | None = None) -> None: + # Unit square quad: (0,0)->(1,0)->(1,1)->(0,1) + vertex_coordinates = np.array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0], dtype=float) + gdim = 2 + + inside = cutcells.cut( + cutcells.CellType.quadrilateral, + vertex_coordinates, + gdim, + ls_values, + "phi<0", + False, + ) + outside = cutcells.cut( + cutcells.CellType.quadrilateral, + vertex_coordinates, + gdim, + ls_values, + "phi>0", + False, + ) + interface = cutcells.cut( + cutcells.CellType.quadrilateral, + vertex_coordinates, + gdim, + ls_values, + "phi=0", + False, + ) + + print(f"ls={ls_values.tolist()}") + print(f" inside: volume={inside.volume():.6f}, vtk_types={inside.types}") + print(f" outside: volume={outside.volume():.6f}, vtk_types={outside.types}") + print(f" iface: cells={len(interface.types)}, vtk_types={interface.types}") + + if write_vtk_prefix: + inside.write_vtk(f"{write_vtk_prefix}_inside.vtu") + outside.write_vtk(f"{write_vtk_prefix}_outside.vtu") + interface.write_vtk(f"{write_vtk_prefix}_interface.vtu") + print(f" wrote: {write_vtk_prefix}_inside.vtu / _outside.vtu / _interface.vtu") + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Cut a level set through a quadrilateral" + ) + parser.add_argument( + "--write-vtk", + type=str, + default=None, + help="Prefix for VTK output files (writes *_inside.vtu, *_outside.vtu, *_interface.vtu)", + ) + args = parser.parse_args() + + # Two canonical ambiguity checks + a generic slanted cut + cases = [ + (np.array([-0.5, 0.5, -0.5, 0.5], dtype=float), "opp_corners"), + (np.array([0.5, -0.5, -0.5, -0.5], dtype=float), "single_outside_corner"), + (np.array([-1.0, -0.2, 0.7, 1.3], dtype=float), "slanted"), + ] + + for ls, name in cases: + prefix = None + if args.write_vtk: + prefix = str( + Path(args.write_vtk).with_name(f"{Path(args.write_vtk).name}_{name}") + ) + cut_one_quad(ls, prefix) + + +if __name__ == "__main__": + main() diff --git a/python/demo/cut_quadrilateral/plot_quadrilateral_cases.py b/python/demo/cut_quadrilateral/plot_quadrilateral_cases.py new file mode 100644 index 0000000..c0d7b94 --- /dev/null +++ b/python/demo/cut_quadrilateral/plot_quadrilateral_cases.py @@ -0,0 +1,346 @@ +"""Plot marching-squares cases for quadrilateral clipping. + +The two ambiguous opposite-corner masks (0101 and 1010) are shown as *two* +separate subplots (one per asymptotic-decider variant), to avoid overplotting. + +Run from repo root (fenicsx-dev env): + conda run -n fenicsx-dev python python/demo/plot_quadrilateral_cases.py [--save out.png] +""" + +from __future__ import annotations + +import argparse +from dataclasses import dataclass +from pathlib import Path +from typing import Iterable, List, Sequence, Tuple + +import matplotlib.pyplot as plt +import numpy as np + +# Use the tablegen package directly +import sys + +REPO_ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(REPO_ROOT / "tablegen")) + +from cutcells_tablegen.topology import edge_endpoints # noqa: E402 +from cutcells_tablegen.vtk_tables_import import ClipCase, EmittedCell, get_cases # noqa: E402 + +try: + import cutcells # type: ignore + + _HAS_CUTCELLS = True +except Exception: # pragma: no cover + _HAS_CUTCELLS = False + +Point = Tuple[float, float] + + +VTK_LINE = 3 +VTK_TRIANGLE = 5 +VTK_QUAD = 9 + + +def build_vertices(mask: int) -> Tuple[List[Point], List[Point]]: + """Return base vertices and edge intersection points for a given mask. + + Mask bit i=1 means vertex i is inside (phi<0). We assign ls=-1 inside, +1 outside, + so intersections land at the midpoint of sign-changing edges. + """ + verts: List[Point] = [(0.0, 0.0), (1.0, 0.0), (1.0, 1.0), (0.0, 1.0)] + edges = edge_endpoints("quadrilateral") + ls = [-1.0 if (mask >> i) & 1 else 1.0 for i in range(4)] + + ip: List[Point] = [(float("nan"), float("nan")) for _ in range(len(edges))] + for e, (v0, v1) in enumerate(edges): + if (ls[v0] < 0) != (ls[v1] < 0): + t = abs(ls[v0]) / (abs(ls[v0]) + abs(ls[v1])) # with +-1 -> 0.5 + x = verts[v0][0] * (1 - t) + verts[v1][0] * t + y = verts[v0][1] * (1 - t) + verts[v1][1] * t + ip[e] = (x, y) + return verts, ip + + +def ref_to_point( + ref: Tuple[str, int], verts: Sequence[Point], ip: Sequence[Point] +) -> Point: + kind, idx = ref + if kind == "V": + return verts[idx] + if kind == "E": + return ip[idx] + raise ValueError(f"Unknown ref {ref}") + + +def draw_cells( + ax, + cells: Iterable[EmittedCell], + verts: Sequence[Point], + ip: Sequence[Point], + color: str, + label: str, +): + for cell in cells: + coords = [ref_to_point(r, verts, ip) for r in cell.vertices] + xs, ys = zip(*coords) + ax.fill( + xs, + ys, + facecolor=color, + alpha=0.5, + edgecolor="k", + linewidth=0.5, + label=label, + ) + label = "_nolegend_" # only label first patch + + +def draw_segments( + ax, + cells: Iterable[EmittedCell], + verts: Sequence[Point], + ip: Sequence[Point], + color: str, + label: str, +): + for cell in cells: + coords = [ref_to_point(r, verts, ip) for r in cell.vertices] + xs, ys = zip(*coords) + ax.plot(xs, ys, color=color, linewidth=2.0, label=label) + label = "_nolegend_" + + +def _iter_connectivity(connectivity: Sequence[int]) -> Iterable[List[int]]: + i = 0 + n = len(connectivity) + while i < n: + nv = int(connectivity[i]) + verts = [int(connectivity[i + j]) for j in range(1, 1 + nv)] + yield verts + i += 1 + nv + + +def _plot_runtime_cutcell( + ax, + cut_cell, + facecolor: str, + edgecolor: str, + alpha: float, + linestyle: str, + label: str, +): + coords = np.asarray(cut_cell.vertex_coords) + pts = [(float(p[0]), float(p[1])) for p in coords] + connectivity = list(cut_cell.connectivity) + types = list(cut_cell.types) + + for cell_type, verts in zip(types, _iter_connectivity(connectivity)): + poly = [pts[v] for v in verts] + xs, ys = zip(*poly) + + if cell_type == VTK_LINE: + ax.plot( + xs, ys, color=edgecolor, linewidth=2.0, linestyle=linestyle, label=label + ) + else: + ax.fill( + xs, + ys, + facecolor=facecolor, + alpha=alpha, + edgecolor=edgecolor, + linewidth=0.8, + linestyle=linestyle, + label=label, + ) + label = "_nolegend_" + + +def _ambiguous_ls(mask: int, variant: int) -> List[float]: + """Return ls values for an ambiguous mask with a chosen decider variant. + + Variant 0: d = f0*f2 - f1*f3 >= 0 + Variant 1: d < 0 + """ + if mask not in (0b0101, 0b1010): + raise ValueError("mask must be 0101 or 1010") + if variant not in (0, 1): + raise ValueError("variant must be 0 or 1") + + # Set signs per mask + if mask == 0b0101: + # (-, +, -, +) + if variant == 0: + return [-2.0, 1.0, -2.0, 1.0] + return [-1.0, 2.0, -1.0, 2.0] + + # mask == 0b1010 -> (+, -, +, -) + if variant == 0: + return [2.0, -1.0, 2.0, -1.0] + return [1.0, -2.0, 1.0, -2.0] + + +def plot_cases(save: Path | None = None) -> None: + inside_cases: List[ClipCase] = get_cases("quadrilateral", "inside") + outside_cases: List[ClipCase] = get_cases("quadrilateral", "outside") + interface_cases: List[ClipCase] = get_cases("quadrilateral", "interface") + + @dataclass(frozen=True) + class Panel: + kind: str # "tablegen" | "runtime" + mask: int + variant: int | None = None + + panels: List[Panel] = [] + for mask in range(16): + if mask in (0b0101, 0b1010): + panels.append(Panel(kind="runtime", mask=mask, variant=0)) + panels.append(Panel(kind="runtime", mask=mask, variant=1)) + else: + panels.append(Panel(kind="tablegen", mask=mask)) + + n = len(panels) # 14 + 4 = 18 + ncols = 6 + nrows = (n + ncols - 1) // ncols + fig, axes = plt.subplots( + nrows, + ncols, + figsize=(3.0 * ncols, 3.0 * nrows), + constrained_layout=True, + ) + axes_flat = list(axes.ravel()) + + for i, panel in enumerate(panels): + ax = axes_flat[i] + mask = panel.mask + verts, ip = build_vertices(mask) + + # Draw original quad boundary + quad_x = [verts[0][0], verts[1][0], verts[2][0], verts[3][0], verts[0][0]] + quad_y = [verts[0][1], verts[1][1], verts[2][1], verts[3][1], verts[0][1]] + ax.plot( + quad_x, + quad_y, + "k--", + linewidth=1.5, + alpha=0.3, + label="quad" if mask == 0 else "_nolegend_", + ) + + show_legend_labels = i == 0 + outside_label = "outside" if show_legend_labels else "_nolegend_" + inside_label = "inside" if show_legend_labels else "_nolegend_" + iface_label = "interface" if show_legend_labels else "_nolegend_" + + if panel.kind == "tablegen": + # Draw outside first (so inside can overlay) + draw_cells( + ax, + outside_cases[mask].cells, + verts, + ip, + color="red", + label=outside_label, + ) + draw_cells( + ax, + inside_cases[mask].cells, + verts, + ip, + color="blue", + label=inside_label, + ) + draw_segments( + ax, + interface_cases[mask].cells, + verts, + ip, + color="black", + label=iface_label, + ) + ax.set_title(f"mask {mask:04b}") + else: + if not _HAS_CUTCELLS: + ax.set_title(f"mask {mask:04b} (cutcells unavailable)") + else: + assert panel.variant is not None + vertex_coordinates = np.asarray( + [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0], dtype=np.float64 + ) + cell_type = cutcells.CellType.quadrilateral + gdim = 2 + ls = np.asarray(_ambiguous_ls(mask, panel.variant), dtype=np.float64) + + # Keep quads as quads for easier interpretation + inside = cutcells.cut( + cell_type, vertex_coordinates, gdim, ls, "phi<0", False + ) + outside = cutcells.cut( + cell_type, vertex_coordinates, gdim, ls, "phi>0", False + ) + iface = cutcells.cut( + cell_type, vertex_coordinates, gdim, ls, "phi=0", False + ) + + _plot_runtime_cutcell( + ax, + outside, + facecolor="red", + edgecolor="k", + alpha=0.35, + linestyle="-", + label=outside_label, + ) + _plot_runtime_cutcell( + ax, + inside, + facecolor="blue", + edgecolor="k", + alpha=0.35, + linestyle="-", + label=inside_label, + ) + _plot_runtime_cutcell( + ax, + iface, + facecolor="none", + edgecolor="black", + alpha=0.0, + linestyle="-", + label=iface_label, + ) + + ax.set_title(f"mask {mask:04b} (v{panel.variant})") + ax.set_aspect("equal") + ax.set_xlim(-0.1, 1.1) + ax.set_ylim(-0.1, 1.1) + ax.axis("off") + + # Hide any unused axes + for j in range(n, len(axes_flat)): + axes_flat[j].axis("off") + + handles, labels = axes_flat[0].get_legend_handles_labels() + if handles: + fig.legend(handles, labels, loc="upper center", ncol=4) + + if save: + fig.savefig(save, dpi=200) + else: + plt.show() + + +def main() -> None: + parser = argparse.ArgumentParser(description="Plot all quadrilateral clip cases") + parser.add_argument( + "--save", + type=Path, + default=None, + help="Path to save the figure instead of showing", + ) + args = parser.parse_args() + plot_cases(args.save) + + +if __name__ == "__main__": + main() diff --git a/python/demo/cut_tetrahedron/cut_tetrahedron.py b/python/demo/cut_tetrahedron/cut_tetrahedron.py index 1af6dc0..7c138dd 100644 --- a/python/demo/cut_tetrahedron/cut_tetrahedron.py +++ b/python/demo/cut_tetrahedron/cut_tetrahedron.py @@ -2,39 +2,55 @@ import numpy as np import pyvista as pv -ls_values = np.array([0.1,-0.1,-0.2, 0.4]) -vertex_coordinates = np.array([1.,1.,1., 1.,-1., -1., -1, 1., -1., -1., -1, 1]) +ls_values = np.array([0.1, -0.1, -0.2, 0.4]) +vertex_coordinates = np.array( + [1.0, 1.0, 1.0, 1.0, -1.0, -1.0, -1, 1.0, -1.0, -1.0, -1, 1] +) cell_type = cutcells.CellType.tetrahedron triangulate = True gdim = 3 -cut_cell_int = cutcells.cut(cell_type, vertex_coordinates, gdim, ls_values, "phi<0", triangulate) +cut_cell_int = cutcells.cut( + cell_type, vertex_coordinates, gdim, ls_values, "phi<0", triangulate +) print(cut_cell_int.str()) cut_cell_int.write_vtk("interior.vtu") -cut_cell_ext = cutcells.cut(cell_type, vertex_coordinates, gdim, ls_values, "phi>0", triangulate) +cut_cell_ext = cutcells.cut( + cell_type, vertex_coordinates, gdim, ls_values, "phi>0", triangulate +) print(cut_cell_ext.str()) cut_cell_ext.write_vtk("exterior.vtu") -cut_cell = cutcells.cut(cell_type, vertex_coordinates, gdim, ls_values, "phi=0", triangulate) +cut_cell = cutcells.cut( + cell_type, vertex_coordinates, gdim, ls_values, "phi=0", triangulate +) print(cut_cell.str()) cut_cell.write_vtk("interface.vtu") pv.start_xvfb() -grid_int = pv.UnstructuredGrid(cut_cell_int.connectivity, cut_cell_int.types, cut_cell_int.vertex_coords) -grid_ext = pv.UnstructuredGrid(cut_cell_ext.connectivity, cut_cell_ext.types, cut_cell_ext.vertex_coords) +grid_int = pv.UnstructuredGrid( + cut_cell_int.connectivity, + cut_cell_int.types, + cut_cell_int.vertex_coords, +) +grid_ext = pv.UnstructuredGrid( + cut_cell_ext.connectivity, + cut_cell_ext.types, + cut_cell_ext.vertex_coords, +) split_cells_int = grid_int.explode() split_cells_ext = grid_ext.explode() -#split_cells.plot(show_edges=True, ssao=True) +# split_cells.plot(show_edges=True, ssao=True) -split_cells_int = split_cells_int.translate((0,0, -0.4), inplace=False) +split_cells_int = split_cells_int.translate((0, 0, -0.4), inplace=False) plotter = pv.Plotter(off_screen=True) -plotter.set_background('white', top='white') -#plotter.enable_ssao() -plotter.add_mesh(split_cells_int, color="blue",show_edges=True, opacity=0.5) -plotter.add_mesh(split_cells_ext, color="red",show_edges=True, opacity=0.5) -plotter.show(screenshot='cut_tetra.png') +plotter.set_background("white", top="white") +# plotter.enable_ssao() +plotter.add_mesh(split_cells_int, color="blue", show_edges=True, opacity=0.5) +plotter.add_mesh(split_cells_ext, color="red", show_edges=True, opacity=0.5) +plotter.show(screenshot="cut_tetra.png") diff --git a/python/demo/cut_triangle/cut_triangle.py b/python/demo/cut_triangle/cut_triangle.py index 90bb269..9cc41c9 100644 --- a/python/demo/cut_triangle/cut_triangle.py +++ b/python/demo/cut_triangle/cut_triangle.py @@ -1,19 +1,23 @@ import cutcells import numpy as np -import pyvista as pv +import pyvista as pv + def cut_cell_type_to_pyvista(cut_cell_type): - if(cut_cell_type==cutcells.CellType.triangle): - return pv.CellType.TRIANGLE; + if cut_cell_type == cutcells.CellType.triangle: + return pv.CellType.TRIANGLE + -ls_values = np.array([0.1,-0.1,0.2]) -vertex_coordinates = np.array([0.,0.,1.,0.,1.,1.]) +ls_values = np.array([0.1, -0.1, 0.2]) +vertex_coordinates = np.array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0]) cell_type = cutcells.CellType.triangle triangulate = True gdim = 2 -cut_cell_int = cutcells.cut(cell_type, vertex_coordinates, gdim, ls_values, "phi<0", triangulate) +cut_cell_int = cutcells.cut( + cell_type, vertex_coordinates, gdim, ls_values, "phi<0", triangulate +) print(cut_cell_int.str()) cut_cell_int.write_vtk("interior.vtu") vol = cut_cell_int.volume() @@ -22,7 +26,9 @@ def cut_cell_type_to_pyvista(cut_cell_type): print("connectivity=", cut_cell_int.connectivity) print("types=", cut_cell_int.types) -cut_cell_ext = cutcells.cut(cell_type, vertex_coordinates, gdim, ls_values, "phi>0", triangulate) +cut_cell_ext = cutcells.cut( + cell_type, vertex_coordinates, gdim, ls_values, "phi>0", triangulate +) print(cut_cell_ext.str()) cut_cell_ext.write_vtk("exterior.vtu") vol2 = cut_cell_ext.volume() @@ -33,11 +39,18 @@ def cut_cell_type_to_pyvista(cut_cell_type): pv.start_xvfb() -grid_int = pv.UnstructuredGrid(cut_cell_int.connectivity, cut_cell_int.types, cut_cell_int.vertex_coords) -grid_ext = pv.UnstructuredGrid(cut_cell_ext.connectivity, cut_cell_ext.types, cut_cell_ext.vertex_coords) +pts_int = np.asarray(cut_cell_int.vertex_coords) +if pts_int.shape[1] == 2: + pts_int = np.c_[pts_int, np.zeros((pts_int.shape[0],), dtype=pts_int.dtype)] +pts_ext = np.asarray(cut_cell_ext.vertex_coords) +if pts_ext.shape[1] == 2: + pts_ext = np.c_[pts_ext, np.zeros((pts_ext.shape[0],), dtype=pts_ext.dtype)] + +grid_int = pv.UnstructuredGrid(cut_cell_int.connectivity, cut_cell_int.types, pts_int) +grid_ext = pv.UnstructuredGrid(cut_cell_ext.connectivity, cut_cell_ext.types, pts_ext) plotter = pv.Plotter(off_screen=False) -plotter.set_background('white', top='white') -plotter.add_mesh(grid_int, color="blue",show_edges=True) -plotter.add_mesh(grid_ext, color="red",show_edges=True) -plotter.show(screenshot='cut_triangle.png') +plotter.set_background("white", top="white") +plotter.add_mesh(grid_int, color="blue", show_edges=True) +plotter.add_mesh(grid_ext, color="red", show_edges=True) +plotter.show(screenshot="cut_triangle.png") diff --git a/python/demo/cut_vtk_mesh/cut_hex_mesh_3D.py b/python/demo/cut_vtk_mesh/cut_hex_mesh_3D.py new file mode 100644 index 0000000..7ec41c5 --- /dev/null +++ b/python/demo/cut_vtk_mesh/cut_hex_mesh_3D.py @@ -0,0 +1,122 @@ +import argparse + +import cutcells +import numpy as np +import pyvista as pv + + +VTK_HEXAHEDRON = 12 + + +def level_set(x: np.ndarray) -> float: + # A smooth but nontrivial implicit surface: sphere with bumps. + r0 = 0.6 + r = np.sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]) + + s = r0 - r + + for k in range(5): + xk = r0 / np.sqrt(5.0) * 2.0 * np.cos(2.0 * k * np.pi / 5.0) + yk = r0 / np.sqrt(5.0) * 2.0 * np.sin(2.0 * k * np.pi / 5.0) + zk = r0 / np.sqrt(5.0) + d2 = (x[0] - xk) ** 2 + (x[1] - yk) ** 2 + (x[2] - zk) ** 2 + s += 2.0 * np.exp(-d2 / 0.04) + + for k in range(5, 10): + kk = k - 5 + xk = r0 / np.sqrt(5.0) * 2.0 * np.cos((2.0 * kk - 1.0) * np.pi / 5.0) + yk = r0 / np.sqrt(5.0) * 2.0 * np.sin((2.0 * kk - 1.0) * np.pi / 5.0) + zk = -r0 / np.sqrt(5.0) + d2 = (x[0] - xk) ** 2 + (x[1] - yk) ** 2 + (x[2] - zk) ** 2 + s += 2.0 * np.exp(-d2 / 0.04) + + # Flip sign so phi<0 picks the "inside" of the bumpy shape. + return -s + + +def _vertex_id(i: int, j: int, k: int, nx: int, ny: int) -> int: + return i + (nx + 1) * (j + (ny + 1) * k) + + +def create_structured_hex_grid(x0, y0, z0, x1, y1, z1, nx, ny, nz): + xs = np.linspace(x0, x1, nx + 1) + ys = np.linspace(y0, y1, ny + 1) + zs = np.linspace(z0, z1, nz + 1) + + xx, yy, zz = np.meshgrid(xs, ys, zs, indexing="ij") + points = np.c_[xx.ravel(), yy.ravel(), zz.ravel()].astype(float) + + num_cells = nx * ny * nz + connectivity = np.empty(num_cells * 8, dtype=np.int32) + offset = np.empty(num_cells, dtype=np.int32) + celltypes = np.full(num_cells, VTK_HEXAHEDRON, dtype=np.int32) + + c = 0 + for k in range(nz): + for j in range(ny): + for i in range(nx): + v0 = _vertex_id(i, j, k, nx, ny) + v1 = _vertex_id(i + 1, j, k, nx, ny) + v2 = _vertex_id(i + 1, j + 1, k, nx, ny) + v3 = _vertex_id(i, j + 1, k, nx, ny) + v4 = _vertex_id(i, j, k + 1, nx, ny) + v5 = _vertex_id(i + 1, j, k + 1, nx, ny) + v6 = _vertex_id(i + 1, j + 1, k + 1, nx, ny) + v7 = _vertex_id(i, j + 1, k + 1, nx, ny) + + offset[c] = 8 * c + connectivity[8 * c : 8 * c + 8] = [v0, v1, v2, v3, v4, v5, v6, v7] + c += 1 + + return points, connectivity, offset, celltypes + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("--n", type=int, default=14, help="Cells per axis") + parser.add_argument( + "--triangulate", + action=argparse.BooleanOptionalAction, + default=True, + help="Triangulate interface quads (default: True)", + ) + args = parser.parse_args() + + n = args.n + points, connectivity, offset, celltypes = create_structured_hex_grid( + -1.0, -1.0, -1.0, 1.0, 1.0, 1.0, n, n, n + ) + + ls_values = np.array([level_set(p) for p in points], dtype=float) + + cut_mesh = cutcells.cut_vtk_mesh( + ls_values, + points, + connectivity, + offset, + celltypes, + "phi<0", + triangulate=args.triangulate, + ) + + # PyVista expects VTK "cells" layout: [n0, ids..., n1, ids..., ...] + cells = np.empty(celltypes.size * 9, dtype=np.int32) + cells[0::9] = 8 + cells.reshape(-1, 9)[:, 1:] = connectivity.reshape(-1, 8) + + pv_in = pv.UnstructuredGrid(cells, celltypes, points) + pv_cut = pv.UnstructuredGrid( + cut_mesh.cells, + cut_mesh.types, + cut_mesh.vertex_coords, + ) + + pl = pv.Plotter() + pl.add_mesh(pv_in, show_edges=True, style="wireframe", opacity=0.15) + pl.add_mesh(pv_cut, show_edges=True) + pl.camera_position = "xy" + pl.show() + + +if __name__ == "__main__": + main() diff --git a/python/demo/cut_vtk_mesh/cut_hybrid_flower_2D.py b/python/demo/cut_vtk_mesh/cut_hybrid_flower_2D.py new file mode 100644 index 0000000..2079263 --- /dev/null +++ b/python/demo/cut_vtk_mesh/cut_hybrid_flower_2D.py @@ -0,0 +1,138 @@ +import numpy as np +import pyvista as pv +import cutcells + + +import numpy as np + + +def level_set(xs, R0=1.0, a=0.25, k=6, center=(0.0, 0.0), sdf_like=True, eps=1e-12): + """ + Flower-shaped level set. + Negative inside, positive outside. + + Parameters + ---------- + x, y : array_like + Coordinates (scalars or numpy arrays). + R0 : float + Mean radius. + a : float + Petal amplitude (keep a < R0 to avoid self-intersections). + k : int + Number of petals. + center : (float, float) + Center of the flower. + sdf_like : bool + If True, applies a local scaling so that |grad(phi)| ~ 1 near the interface. + eps : float + Small number to avoid division by zero. + + Returns + ------- + phi : ndarray + Level set values (approx signed distance). + """ + x = xs[0] + y = xs[1] + cx, cy = center + dx = np.asarray(x) - cx + dy = np.asarray(y) - cy + + r = np.hypot(dx, dy) + theta = np.arctan2(dy, dx) + + R = R0 + a * np.cos(k * theta) + phi = r - R # simple (radial) signed distance approximation + + if not sdf_like: + return phi + + # First-order correction: scale so that |∇phi| ≈ 1 near the boundary + r_safe = np.maximum(r, eps) + denom = np.maximum(dx * dx + dy * dy, eps) + + dtheta_dx = -dy / denom + dtheta_dy = dx / denom + + dR_dtheta = -a * k * np.sin(k * theta) + + dphi_dx = dx / r_safe - dR_dtheta * dtheta_dx + dphi_dy = dy / r_safe - dR_dtheta * dtheta_dy + + g = np.sqrt(dphi_dx * dphi_dx + dphi_dy * dphi_dy) + g = np.maximum(g, eps) + + return phi / g # more “signed-distance-like” near φ=0 + + +def create_cut_mesh(grid): + points = grid.points + ls_values = np.zeros(len(points)) + j = 0 + for point in points: + ls_values[j] = level_set(point) + j = j + 1 + + cut_mesh = cutcells.cut_vtk_mesh( + ls_values, points, grid.cell_connectivity, grid.offset, grid.celltypes, "phi<0" + ) + inside_cells = cutcells.locate_cells( + ls_values, points, grid.cell_connectivity, grid.offset, grid.celltypes, "phi<0" + ) + + pv_cut = pv.UnstructuredGrid( + cut_mesh.cells, cut_mesh.types, np.asarray(cut_mesh.vertex_coords) + ) + extract = grid.extract_cells(inside_cells) + + return extract.merge(pv_cut) + + +# Mesh parameters +nx, ny = 21, 21 +x = np.linspace(-1.5, 1.5, nx + 1) +y = np.linspace(-1.5, 1.5, ny + 1) +X, Y = np.meshgrid(x, y) +points = np.column_stack([X.ravel(), Y.ravel()]) + +cells = [] +celltypes = [] +vtk_tri = pv.CellType.TRIANGLE +vtk_quad = pv.CellType.QUAD + +# Lower half: triangles, Upper half: quads +for j in range(ny): + for i in range(nx): + n0 = j * (nx + 1) + i + n1 = n0 + 1 + n2 = n0 + (nx + 1) + n3 = n2 + 1 + y_center = (Y[j, i] + Y[j + 1, i] + Y[j, i + 1] + Y[j + 1, i + 1]) / 4 + if y_center < 0: + # Two triangles per cell + cells.append([3, n0, n1, n2]) + celltypes.append(vtk_tri) + cells.append([3, n1, n3, n2]) + celltypes.append(vtk_tri) + else: + # One quad per cell + cells.append([4, n0, n1, n3, n2]) + celltypes.append(vtk_quad) + +# Flatten cells for VTK +flat_cells = np.array([v for cell in cells for v in cell], dtype=np.int64) +celltypes = np.array(celltypes, dtype=np.uint8) + +# Build a VTK mesh and cut it (ensures parent_map is populated). +points3 = np.c_[points, np.zeros((points.shape[0],), dtype=points.dtype)] +grid = pv.UnstructuredGrid(flat_cells, celltypes, points3) +mesh = create_cut_mesh(grid) + +mesh.plot(cpos="xy", show_edges=True) + +pl = pv.Plotter() +pl.add_mesh(grid, show_edges=True, color="white") +pl.add_mesh(mesh, show_edges=True) +pl.camera_position = "xy" +pl.show(screenshot="hybrid_flower.png") diff --git a/python/demo/cut_vtk_mesh/cut_mesh_2D.py b/python/demo/cut_vtk_mesh/cut_mesh_2D.py index 2eb5a4e..1a9411d 100644 --- a/python/demo/cut_vtk_mesh/cut_mesh_2D.py +++ b/python/demo/cut_vtk_mesh/cut_mesh_2D.py @@ -3,55 +3,62 @@ import pyvista as pv import time + def level_set(x): - r = 0.7 - c = np.array([0,0,0]) - value = 0 - for i in range(0,3): - value = value + (x[i]-c[i])**2 - value = np.sqrt(value)-r - return value - -def create_rectangle_mesh(x0,y0,x1,y1,Nx,Ny): - x = np.linspace(x0, x1, num=Nx) - y = np.linspace(y0,y1, num=Ny) - #produce grid of points by tensor product - xx, yy, zz = np.meshgrid(x, y, [0]) - points = np.c_[xx.reshape(-1), yy.reshape(-1), zz.reshape(-1)] - poly_points = pv.PolyData(points) - poly_mesh = poly_points.delaunay_2d() - grid = pv.UnstructuredGrid(poly_mesh) - - return grid + r = 0.7 + c = np.array([0, 0, 0]) + value = 0 + for i in range(0, 3): + value = value + (x[i] - c[i]) ** 2 + value = np.sqrt(value) - r + return value + + +def create_rectangle_mesh(x0, y0, x1, y1, Nx, Ny): + x = np.linspace(x0, x1, num=Nx) + y = np.linspace(y0, y1, num=Ny) + # produce grid of points by tensor product + xx, yy, zz = np.meshgrid(x, y, [0]) + points = np.c_[xx.reshape(-1), yy.reshape(-1), zz.reshape(-1)] + poly_points = pv.PolyData(points) + poly_mesh = poly_points.delaunay_2d() + grid = pv.UnstructuredGrid(poly_mesh) + + return grid + def create_cut_mesh(grid): - points = grid.points - ls_values = np.zeros(len(points)) - j = 0 - for point in points: - ls_values[j] = level_set(point) - j = j+1 + points = grid.points + ls_values = np.zeros(len(points)) + j = 0 + for point in points: + ls_values[j] = level_set(point) + j = j + 1 - cut_mesh = cutcells.cut_vtk_mesh(ls_values,points,grid.cell_connectivity,grid.offset,grid.celltypes,"phi<0") - inside_cells = cutcells.locate_cells(ls_values,points,grid.cell_connectivity,grid.offset,grid.celltypes,"phi<0") + cut_mesh = cutcells.cut_vtk_mesh( + ls_values, points, grid.cell_connectivity, grid.offset, grid.celltypes, "phi<0" + ) + inside_cells = cutcells.locate_cells( + ls_values, points, grid.cell_connectivity, grid.offset, grid.celltypes, "phi<0" + ) - pv_cut = pv.UnstructuredGrid(cut_mesh.cells,cut_mesh.types,cut_mesh.vertex_coords) - extract = grid.extract_cells(inside_cells) + pv_cut = pv.UnstructuredGrid( + cut_mesh.cells, cut_mesh.types, np.asarray(cut_mesh.vertex_coords) + ) + extract = grid.extract_cells(inside_cells) - return extract.merge(pv_cut) + return extract.merge(pv_cut) N = 22 -grid = create_rectangle_mesh(-1,-1,1,1,N,N) +grid = create_rectangle_mesh(-1, -1, 1, 1, N, N) mesh = create_cut_mesh(grid) mesh.plot(cpos="xy", show_edges=True) pl = pv.Plotter() -pl.add_mesh(grid, show_edges=True, color = 'white') +pl.add_mesh(grid, show_edges=True, color="white") pl.add_mesh(mesh, show_edges=True) -pl.camera_position = 'xy' +pl.camera_position = "xy" pl.show() - - diff --git a/python/demo/cut_vtk_mesh/cut_mesh_3D.py b/python/demo/cut_vtk_mesh/cut_mesh_3D.py index 71375ad..7e70f2e 100644 --- a/python/demo/cut_vtk_mesh/cut_mesh_3D.py +++ b/python/demo/cut_vtk_mesh/cut_mesh_3D.py @@ -2,88 +2,108 @@ import numpy as np import pyvista as pv -def level_set(x): - r0 = 0.6 - r = np.sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]) - - sum = r0 - r - for k in range(0,5): - xk = r0/np.sqrt(5.0)*2*np.cos(2*k*np.pi/5) - yk = r0/np.sqrt(5.0)*2*np.sin(2*k*np.pi/5) - zk = r0/np.sqrt(5.0) - tmp = (x[0] - xk)*(x[0] - xk) + (x[1] - yk)*(x[1] - yk) \ - + (x[2] - zk)*(x[2] - zk) - sum += 2*np.exp(-tmp/(0.04)) - - for k in range(5,10): - xk = r0/np.sqrt(5.0)*2*np.cos((2*(k-5)-1)*np.pi/5) - yk = r0/np.sqrt(5.0)*2*np.sin((2*(k-5)-1)*np.pi/5) - zk = -r0/np.sqrt(5.0); - tmp = (x[0] - xk)*(x[0] - xk) + (x[1] - yk)*(x[1] - yk) \ - + (x[2] - zk)*(x[2] - zk) - sum += 2*np.exp(-tmp/(0.04)) - - for k in range(10,11): - xk = 0 - yk = 0 - zk = r0 - tmp = (x[0] - xk)*(x[0] - xk) + (x[1] - yk)*(x[1] - yk) \ - + (x[2] - zk)*(x[2] - zk) - sum += 2*np.exp(-tmp/(0.04)) - - for k in range(11,12): - xk = 0 - yk = 0 - zk = -r0 - tmp = (x[0] - xk)*(x[0] - xk) + (x[1] - yk)*(x[1] - yk) \ - + (x[2] - zk)*(x[2] - zk); - sum += 2*np.exp(-tmp/(0.04)); - - value = -1.0*sum; - - return value - -def create_box_mesh(x0,y0,z0,x1,y1,z1,Nx,Ny,Nz): - x = np.linspace(x0, x1, num=Nx) - y = np.linspace(y0,y1, num=Ny) - z = np.linspace(z0,z1, num=Nz) - #produce grid of points by tensor product - xx, yy, zz = np.meshgrid(x, y, z) - points = np.c_[xx.reshape(-1), yy.reshape(-1), zz.reshape(-1)] - poly_points = pv.PolyData(points) - poly_mesh = poly_points.delaunay_3d() - grid = pv.UnstructuredGrid(poly_mesh) - - return grid -def create_cut_mesh(grid): - points = grid.points - ls_values = np.zeros(len(points)) - j = 0 - for point in points: - ls_values[j] = level_set(point) - j = j+1 +def level_set(x): + r0 = 0.6 + r = np.sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]) + + sum = r0 - r + for k in range(0, 5): + xk = r0 / np.sqrt(5.0) * 2 * np.cos(2 * k * np.pi / 5) + yk = r0 / np.sqrt(5.0) * 2 * np.sin(2 * k * np.pi / 5) + zk = r0 / np.sqrt(5.0) + tmp = ( + (x[0] - xk) * (x[0] - xk) + + (x[1] - yk) * (x[1] - yk) + + (x[2] - zk) * (x[2] - zk) + ) + sum += 2 * np.exp(-tmp / (0.04)) + + for k in range(5, 10): + xk = r0 / np.sqrt(5.0) * 2 * np.cos((2 * (k - 5) - 1) * np.pi / 5) + yk = r0 / np.sqrt(5.0) * 2 * np.sin((2 * (k - 5) - 1) * np.pi / 5) + zk = -r0 / np.sqrt(5.0) + tmp = ( + (x[0] - xk) * (x[0] - xk) + + (x[1] - yk) * (x[1] - yk) + + (x[2] - zk) * (x[2] - zk) + ) + sum += 2 * np.exp(-tmp / (0.04)) + + for k in range(10, 11): + xk = 0 + yk = 0 + zk = r0 + tmp = ( + (x[0] - xk) * (x[0] - xk) + + (x[1] - yk) * (x[1] - yk) + + (x[2] - zk) * (x[2] - zk) + ) + sum += 2 * np.exp(-tmp / (0.04)) + + for k in range(11, 12): + xk = 0 + yk = 0 + zk = -r0 + tmp = ( + (x[0] - xk) * (x[0] - xk) + + (x[1] - yk) * (x[1] - yk) + + (x[2] - zk) * (x[2] - zk) + ) + sum += 2 * np.exp(-tmp / (0.04)) + + value = -1.0 * sum + return value + + +def create_box_mesh(x0, y0, z0, x1, y1, z1, Nx, Ny, Nz): + x = np.linspace(x0, x1, num=Nx) + y = np.linspace(y0, y1, num=Ny) + z = np.linspace(z0, z1, num=Nz) + # produce grid of points by tensor product + xx, yy, zz = np.meshgrid(x, y, z) + points = np.c_[xx.reshape(-1), yy.reshape(-1), zz.reshape(-1)] + poly_points = pv.PolyData(points) + poly_mesh = poly_points.delaunay_3d() + grid = pv.UnstructuredGrid(poly_mesh) + + return grid - cut_mesh = cutcells.cut_vtk_mesh(ls_values,points,grid.cell_connectivity,grid.offset,grid.celltypes,"phi<0") - inside_cells = cutcells.locate_cells(ls_values,points,grid.cell_connectivity,grid.offset,grid.celltypes,"phi<0") - pv_cut = pv.UnstructuredGrid(cut_mesh.cells,cut_mesh.types,cut_mesh.vertex_coords) - extract = grid.extract_cells(inside_cells) +def create_cut_mesh(grid): + points = grid.points + ls_values = np.zeros(len(points)) + j = 0 + for point in points: + ls_values[j] = level_set(point) + j = j + 1 + + cut_mesh = cutcells.cut_vtk_mesh( + ls_values, points, grid.cell_connectivity, grid.offset, grid.celltypes, "phi<0" + ) + inside_cells = cutcells.locate_cells( + ls_values, points, grid.cell_connectivity, grid.offset, grid.celltypes, "phi<0" + ) + + pv_cut = pv.UnstructuredGrid( + cut_mesh.cells, + cut_mesh.types, + cut_mesh.vertex_coords, + ) + extract = grid.extract_cells(inside_cells) + + return extract.merge(pv_cut) - return extract.merge(pv_cut) N = 21 -grid = create_box_mesh(-1,-1,-1, 1,1,1, N,N,N) +grid = create_box_mesh(-1, -1, -1, 1, 1, 1, N, N, N) mesh = create_cut_mesh(grid) -mesh.plot(cpos="xy", show_edges=True) +# View from the side so the top/bottom features (z-direction) are visible +mesh.plot(cpos="xz", show_edges=True) pl = pv.Plotter() -pl.add_mesh(grid, show_edges=True, style = 'wireframe') +pl.add_mesh(grid, show_edges=True, style="wireframe") pl.add_mesh(mesh, show_edges=True) -pl.camera_position = 'xy' -pl.show() -pl.screenshot('mesh3D.png') - - - +pl.camera_position = "xz" +pl.show(screenshot="mesh3D.png") diff --git a/python/demo/cut_vtk_mesh/cut_popcorn_hex_mesh_3D.py b/python/demo/cut_vtk_mesh/cut_popcorn_hex_mesh_3D.py new file mode 100644 index 0000000..3937e72 --- /dev/null +++ b/python/demo/cut_vtk_mesh/cut_popcorn_hex_mesh_3D.py @@ -0,0 +1,167 @@ +import argparse + +import cutcells +import numpy as np +import pyvista as pv + + +def level_set(x): + r0 = 0.6 + r = np.sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]) + + s = r0 - r + for k in range(0, 5): + xk = r0 / np.sqrt(5.0) * 2 * np.cos(2 * k * np.pi / 5) + yk = r0 / np.sqrt(5.0) * 2 * np.sin(2 * k * np.pi / 5) + zk = r0 / np.sqrt(5.0) + tmp = ( + (x[0] - xk) * (x[0] - xk) + + (x[1] - yk) * (x[1] - yk) + + (x[2] - zk) * (x[2] - zk) + ) + s += 2 * np.exp(-tmp / (0.04)) + + for k in range(5, 10): + xk = r0 / np.sqrt(5.0) * 2 * np.cos((2 * (k - 5) - 1) * np.pi / 5) + yk = r0 / np.sqrt(5.0) * 2 * np.sin((2 * (k - 5) - 1) * np.pi / 5) + zk = -r0 / np.sqrt(5.0) + tmp = ( + (x[0] - xk) * (x[0] - xk) + + (x[1] - yk) * (x[1] - yk) + + (x[2] - zk) * (x[2] - zk) + ) + s += 2 * np.exp(-tmp / (0.04)) + + for k in range(10, 11): + xk = 0 + yk = 0 + zk = r0 + tmp = ( + (x[0] - xk) * (x[0] - xk) + + (x[1] - yk) * (x[1] - yk) + + (x[2] - zk) * (x[2] - zk) + ) + s += 2 * np.exp(-tmp / (0.04)) + + for k in range(11, 12): + xk = 0 + yk = 0 + zk = -r0 + tmp = ( + (x[0] - xk) * (x[0] - xk) + + (x[1] - yk) * (x[1] - yk) + + (x[2] - zk) * (x[2] - zk) + ) + s += 2 * np.exp(-tmp / (0.04)) + + return -1.0 * s + + +def create_hex_box_mesh(x0, y0, z0, x1, y1, z1, nx, ny, nz) -> pv.UnstructuredGrid: + xs = np.linspace(x0, x1, num=nx) + ys = np.linspace(y0, y1, num=ny) + zs = np.linspace(z0, z1, num=nz) + + xx, yy, zz = np.meshgrid(xs, ys, zs, indexing="ij") + sg = pv.StructuredGrid(xx, yy, zz) + return sg.cast_to_unstructured_grid() + + +def create_cut_mesh( + grid: pv.UnstructuredGrid, triangulate: bool +) -> pv.UnstructuredGrid: + points = grid.points + + ls_values = np.zeros(len(points), dtype=float) + for j, point in enumerate(points): + ls_values[j] = level_set(point) + + cut_mesh = cutcells.cut_vtk_mesh( + ls_values, + points, + grid.cell_connectivity, + grid.offset, + grid.celltypes, + "phi<0", + triangulate, + ) + inside_cells = cutcells.locate_cells( + ls_values, + points, + grid.cell_connectivity, + grid.offset, + grid.celltypes, + "phi<0", + ) + + pv_cut = pv.UnstructuredGrid( + cut_mesh.cells, + cut_mesh.types, + cut_mesh.vertex_coords, + ) + extract = grid.extract_cells(inside_cells) + + return extract.merge(pv_cut) + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Cut a popcorn level set from a hexahedral (VTK_HEXAHEDRON) mesh." + ) + parser.add_argument( + "--n", type=int, default=21, help="Number of points per axis (>= 2)." + ) + parser.add_argument( + "--triangulate", + action=argparse.BooleanOptionalAction, + default=True, + help="Triangulate cut output (more robust for visualization).", + ) + parser.add_argument( + "--show-grid", + action=argparse.BooleanOptionalAction, + default=False, + help="Overlay the input hex grid (wireframe).", + ) + parser.add_argument( + "--show-edges", + action=argparse.BooleanOptionalAction, + default=True, + help="Show mesh edges (can look very busy for larger N).", + ) + parser.add_argument( + "--screenshot", + default="popcorn_hex_mesh3D.png", + help="Output screenshot filename (set to empty string to disable).", + ) + parser.add_argument( + "--show", + action=argparse.BooleanOptionalAction, + default=True, + help="Show an interactive window (disable for headless runs).", + ) + args = parser.parse_args() + + grid = create_hex_box_mesh(-1, -1, -1, 1, 1, 1, args.n, args.n, args.n) + mesh = create_cut_mesh(grid, triangulate=args.triangulate) + + # Quick diagnostics (helps distinguish "too many cells" from bad geometry). + print( + f"input: n_points={grid.n_points}, n_cells={grid.n_cells}, unique_celltypes={sorted(set(map(int, grid.celltypes)))}" + ) + print(f"output: n_points={mesh.n_points}, n_cells={mesh.n_cells}") + + pl = pv.Plotter(off_screen=not args.show) + if args.show_grid: + pl.add_mesh(grid, show_edges=True, style="wireframe") + pl.add_mesh(mesh, show_edges=args.show_edges) + pl.camera_position = "xz" + + if args.screenshot: + pl.show(screenshot=args.screenshot) + else: + pl.show() + + +if __name__ == "__main__": + main() diff --git a/python/demo/cut_vtk_mesh/cut_quad_mesh_2D.py b/python/demo/cut_vtk_mesh/cut_quad_mesh_2D.py new file mode 100644 index 0000000..2d1bd5a --- /dev/null +++ b/python/demo/cut_vtk_mesh/cut_quad_mesh_2D.py @@ -0,0 +1,166 @@ +"""Demo: cut a complex level set through a *quadrilateral* (VTK_QUAD) mesh. + +Run (from repo root): + conda run -n fenicsx-dev python python/demo/cut_vtk_mesh/cut_quad_mesh_2D.py + +Optional: + conda run -n fenicsx-dev python python/demo/cut_vtk_mesh/cut_quad_mesh_2D.py --n 60 --save cut_quad_mesh.vtu + +Notes: +- Uses `cutcells.cut_vtk_mesh` (C++ implementation + generated quad tables). +- Requires `pyvista` for plotting/saving VTU in Python. +""" + +from __future__ import annotations + +import argparse + +import numpy as np + +import cutcells + + +def level_set_popcorn_2d(xyz: np.ndarray) -> float: + """2D 'popcorn'-like implicit function on z=0 plane. + + Negative values are "inside". + """ + x, y = float(xyz[0]), float(xyz[1]) + + r0 = 0.65 + r = (x * x + y * y) ** 0.5 + + value = r - r0 + + # Add bumps around a ring (gaussian perturbations) + sigma2 = 0.02 + for k in range(10): + ang = 2.0 * np.pi * k / 10.0 + cx = 0.9 * r0 * np.cos(ang) + cy = 0.9 * r0 * np.sin(ang) + d2 = (x - cx) ** 2 + (y - cy) ** 2 + value -= 0.22 * np.exp(-d2 / sigma2) + + # Add mild sinusoidal ripples to make the interface less symmetric + value += 0.05 * np.sin(6.0 * x) * np.cos(5.0 * y) + + return value + + +def create_quad_mesh(x0: float, y0: float, x1: float, y1: float, nx: int, ny: int): + """Create a structured quad mesh in VTK-unstructured-array form. + + Returns: + points: (npts, 3) + connectivity: (ncells*4,) + offset: (ncells,) + celltypes: (ncells,) filled with VTK_QUAD (9) + """ + xs = np.linspace(x0, x1, nx) + ys = np.linspace(y0, y1, ny) + + points = np.zeros((nx * ny, 3), dtype=float) + p = 0 + for j in range(ny): + for i in range(nx): + points[p, 0] = xs[i] + points[p, 1] = ys[j] + points[p, 2] = 0.0 + p += 1 + + def vid(i: int, j: int) -> int: + return j * nx + i + + ncx = nx - 1 + ncy = ny - 1 + ncells = ncx * ncy + + connectivity = np.zeros((ncells * 4,), dtype=np.int32) + offset = np.zeros((ncells,), dtype=np.int32) + celltypes = np.full((ncells,), 9, dtype=np.int32) # VTK_QUAD + + c = 0 + k = 0 + for j in range(ncy): + for i in range(ncx): + offset[c] = k + # (i,j)->(i+1,j)->(i+1,j+1)->(i,j+1) + connectivity[k + 0] = vid(i, j) + connectivity[k + 1] = vid(i + 1, j) + connectivity[k + 2] = vid(i + 1, j + 1) + connectivity[k + 3] = vid(i, j + 1) + k += 4 + c += 1 + + return points, connectivity, offset, celltypes + + +def main() -> None: + parser = argparse.ArgumentParser( + description="Cut a complex level set through a quadrilateral mesh" + ) + parser.add_argument( + "--n", type=int, default=45, help="Points per axis (mesh is (n x n) points)" + ) + parser.add_argument( + "--save", type=str, default=None, help="Optional output VTU filename" + ) + parser.add_argument( + "--triangulate", + action=argparse.BooleanOptionalAction, + default=True, + help="Triangulate cut cells (default: True). Use --no-triangulate to preserve quads.", + ) + args = parser.parse_args() + + try: + import pyvista as pv + except Exception as exc: # pragma: no cover + raise SystemExit( + "pyvista is required for this demo. Install with: `python -m pip install pyvista`\n" + f"Import error: {exc}" + ) + + n = int(args.n) + points, conn, off, celltypes = create_quad_mesh(-1.0, -1.0, 1.0, 1.0, n, n) + + # level set at points + ls = np.array([level_set_popcorn_2d(p) for p in points], dtype=float) + + # Cut mesh and also extract all inside (phi<0) background cells for context + cut_mesh = cutcells.cut_vtk_mesh( + ls, points, conn, off, celltypes, "phi<0", triangulate=bool(args.triangulate) + ) + inside_cells = cutcells.locate_cells(ls, points, conn, off, celltypes, "phi<0") + + # Build a pyvista grid for visualization + cells_with_counts = np.empty((len(off) * 5,), dtype=np.int32) + cells_with_counts[0::5] = 4 + cells_with_counts[1::5] = conn[0::4] + cells_with_counts[2::5] = conn[1::4] + cells_with_counts[3::5] = conn[2::4] + cells_with_counts[4::5] = conn[3::4] + + bg = pv.UnstructuredGrid(cells_with_counts, celltypes, points) + + cut_points = np.asarray(cut_mesh.vertex_coords) + cut_cells = np.asarray(cut_mesh.cells, dtype=np.int32) + cut_types = np.asarray(cut_mesh.types, dtype=np.int32) + pv_cut = pv.UnstructuredGrid(cut_cells, cut_types, cut_points) + extract = bg.extract_cells(inside_cells) + merged = extract.merge(pv_cut) + + pl = pv.Plotter() + pl.add_mesh(bg, color="white", show_edges=True, opacity=0.25) + pl.add_mesh(merged, show_edges=True) + pl.camera_position = "xy" + + if args.save: + merged.save(args.save) + print(f"Saved: {args.save}") + + pl.show() + + +if __name__ == "__main__": + main() diff --git a/python/tests/test_cut_vtk_mesh_hexahedron_smoke.py b/python/tests/test_cut_vtk_mesh_hexahedron_smoke.py new file mode 100644 index 0000000..4aa3acb --- /dev/null +++ b/python/tests/test_cut_vtk_mesh_hexahedron_smoke.py @@ -0,0 +1,63 @@ +# Copyright (c) 2025 ONERA +# Authors: Susanne Claus +# This file is part of CutCells +# +# SPDX-License-Identifier: MIT + +import numpy as np + +import cutcells + +VTK_TETRA = 10 +VTK_HEXAHEDRON = 12 + + +def _single_unit_hex_vtk(): + """One VTK_HEXAHEDRON cell on the unit cube in VTK vertex order.""" + points = np.array( + [ + [0.0, 0.0, 0.0], # 0 + [1.0, 0.0, 0.0], # 1 + [1.0, 1.0, 0.0], # 2 + [0.0, 1.0, 0.0], # 3 + [0.0, 0.0, 1.0], # 4 + [1.0, 0.0, 1.0], # 5 + [1.0, 1.0, 1.0], # 6 + [0.0, 1.0, 1.0], # 7 + ], + dtype=float, + ) + + connectivity = np.array([0, 1, 2, 3, 4, 5, 6, 7], dtype=np.int32) + offset = np.array([0], dtype=np.int32) + vtk_type = np.array([VTK_HEXAHEDRON], dtype=np.int32) + + return points, connectivity, offset, vtk_type + + +def test_cut_vtk_mesh_single_hexahedron_smoke(): + points, connectivity, offset, vtk_type = _single_unit_hex_vtk() + + # Intersecting cut: split by plane x=0.3 + ls_vals = points[:, 0] - 0.3 + + cut_mesh = cutcells.cut_vtk_mesh( + ls_vals, + points, + connectivity, + offset, + vtk_type, + "phi<0", + triangulate=True, + ) + + coords = np.asarray(cut_mesh.vertex_coords) + # All generated vertices must stay within the parent unit cube (tolerant for FP noise). + tol = 1e-10 + assert coords[:, 0].min() >= -tol and coords[:, 0].max() <= 1.0 + tol + assert coords[:, 1].min() >= -tol and coords[:, 1].max() <= 1.0 + tol + assert coords[:, 2].min() >= -tol and coords[:, 2].max() <= 1.0 + tol + + assert len(cut_mesh.types) > 0 + # Do not constrain emitted cell types here; the table-driven hex cutter may emit + # hex/prism/pyramid/tet depending on the case. diff --git a/python/tests/test_cut_vtk_mesh_prism_smoke.py b/python/tests/test_cut_vtk_mesh_prism_smoke.py new file mode 100644 index 0000000..a4ad210 --- /dev/null +++ b/python/tests/test_cut_vtk_mesh_prism_smoke.py @@ -0,0 +1,51 @@ +import numpy as np + +import cutcells + +VTK_WEDGE = 13 + + +def _single_unit_prism_vtk(): + """One VTK_WEDGE cell on a unit right triangular prism in VTK vertex order.""" + points = np.array( + [ + [0.0, 0.0, 0.0], # 0 + [1.0, 0.0, 0.0], # 1 + [0.0, 1.0, 0.0], # 2 + [0.0, 0.0, 1.0], # 3 + [1.0, 0.0, 1.0], # 4 + [0.0, 1.0, 1.0], # 5 + ], + dtype=float, + ) + + connectivity = np.array([0, 1, 2, 3, 4, 5], dtype=np.int32) + offset = np.array([0], dtype=np.int32) + vtk_type = np.array([VTK_WEDGE], dtype=np.int32) + + return points, connectivity, offset, vtk_type + + +def test_cut_vtk_mesh_single_prism_smoke(): + points, connectivity, offset, vtk_type = _single_unit_prism_vtk() + + # Intersecting cut: split by plane z=0.3 + ls_vals = points[:, 2] - 0.3 + + cut_mesh = cutcells.cut_vtk_mesh( + ls_vals, + points, + connectivity, + offset, + vtk_type, + "phi<0", + triangulate=True, + ) + + coords = np.asarray(cut_mesh.vertex_coords) + tol = 1e-10 + assert coords[:, 0].min() >= -tol and coords[:, 0].max() <= 1.0 + tol + assert coords[:, 1].min() >= -tol and coords[:, 1].max() <= 1.0 + tol + assert coords[:, 2].min() >= -tol and coords[:, 2].max() <= 1.0 + tol + + assert len(cut_mesh.types) > 0 diff --git a/python/tests/test_cut_vtk_mesh_pyramid_smoke.py b/python/tests/test_cut_vtk_mesh_pyramid_smoke.py new file mode 100644 index 0000000..a87aede --- /dev/null +++ b/python/tests/test_cut_vtk_mesh_pyramid_smoke.py @@ -0,0 +1,50 @@ +import numpy as np + +import cutcells + +VTK_PYRAMID = 14 + + +def _single_unit_pyramid_vtk(): + """One VTK_PYRAMID cell on a unit square pyramid in VTK vertex order.""" + points = np.array( + [ + [0.0, 0.0, 0.0], # 0 + [1.0, 0.0, 0.0], # 1 + [1.0, 1.0, 0.0], # 2 + [0.0, 1.0, 0.0], # 3 + [0.5, 0.5, 1.0], # 4 apex + ], + dtype=float, + ) + + connectivity = np.array([0, 1, 2, 3, 4], dtype=np.int32) + offset = np.array([0], dtype=np.int32) + vtk_type = np.array([VTK_PYRAMID], dtype=np.int32) + + return points, connectivity, offset, vtk_type + + +def test_cut_vtk_mesh_single_pyramid_smoke(): + points, connectivity, offset, vtk_type = _single_unit_pyramid_vtk() + + # Intersecting cut: split by plane z=0.3 + ls_vals = points[:, 2] - 0.3 + + cut_mesh = cutcells.cut_vtk_mesh( + ls_vals, + points, + connectivity, + offset, + vtk_type, + "phi<0", + triangulate=True, + ) + + coords = np.asarray(cut_mesh.vertex_coords) + tol = 1e-10 + assert coords[:, 0].min() >= -tol and coords[:, 0].max() <= 1.0 + tol + assert coords[:, 1].min() >= -tol and coords[:, 1].max() <= 1.0 + tol + assert coords[:, 2].min() >= -tol and coords[:, 2].max() <= 1.0 + tol + + assert len(cut_mesh.types) > 0 diff --git a/python/tests/test_cut_vtk_mesh_triangulate_flag.py b/python/tests/test_cut_vtk_mesh_triangulate_flag.py new file mode 100644 index 0000000..1925710 --- /dev/null +++ b/python/tests/test_cut_vtk_mesh_triangulate_flag.py @@ -0,0 +1,50 @@ +# Copyright (c) 2025 ONERA +# Authors: Susanne Claus +# This file is part of CutCells +# +# SPDX-License-Identifier: MIT + +import numpy as np + +import cutcells + +VTK_TRIANGLE = 5 +VTK_QUAD = 9 + + +def _quad_mesh_2x2_single_cell(): + """One VTK_QUAD cell on [0,1]x[0,1] in z=0 plane.""" + points = np.array( + [ + [0.0, 0.0, 0.0], + [1.0, 0.0, 0.0], + [1.0, 1.0, 0.0], + [0.0, 1.0, 0.0], + ], + dtype=float, + ) + + connectivity = np.array([0, 1, 2, 3], dtype=np.int32) + offset = np.array([0], dtype=np.int32) + vtk_type = np.array([VTK_QUAD], dtype=np.int32) + + return points, connectivity, offset, vtk_type + + +def test_cut_vtk_mesh_triangulate_flag_controls_output_types(): + points, connectivity, offset, vtk_type = _quad_mesh_2x2_single_cell() + + # Level set: phi = x - 0.3 produces a vertical cut line inside the quad. + # This is a 2-inside/2-outside case that can naturally produce a quad when not triangulated. + ls_vals = points[:, 0] - 0.3 + + cut_mesh_quads = cutcells.cut_vtk_mesh( + ls_vals, points, connectivity, offset, vtk_type, "phi<0", triangulate=False + ) + assert VTK_QUAD in list(cut_mesh_quads.types) + + cut_mesh_tris = cutcells.cut_vtk_mesh( + ls_vals, points, connectivity, offset, vtk_type, "phi<0", triangulate=True + ) + assert VTK_QUAD not in list(cut_mesh_tris.types) + assert VTK_TRIANGLE in list(cut_mesh_tris.types) diff --git a/python/tests/test_cutcell_original_info.py b/python/tests/test_cutcell_original_info.py new file mode 100644 index 0000000..23dfc7f --- /dev/null +++ b/python/tests/test_cutcell_original_info.py @@ -0,0 +1,30 @@ +"""Test that CutCell stores original cell information.""" + +import cutcells +import numpy as np + + +def test_cutcell_original_info(): + """Verify CutCell stores original vertex coords and IDs.""" + # Create a simple quad + vertices = np.array([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]], dtype=float) + ls_values = np.array([-0.5, -0.5, 0.5, 0.5], dtype=float) + + # Cut it + cut = cutcells.cut( + cutcells.CellType.quadrilateral, vertices, 2, ls_values, "phi<0", False + ) + + # For now, just verify the cut doesn't crash + # TODO: Once Python bindings expose _parent_* fields, verify: + # - cut._parent_cell_type == cutcells.CellType.quadrilateral + # - cut._parent_vertex_coords matches vertices + # - cut._parent_vertex_ids is [0,1,2,3] (or similar default) + + assert len(cut.types) > 0, "Should produce some cut cells" + assert cut.vertex_coords is not None, "Should have vertex coordinates" + + +if __name__ == "__main__": + test_cutcell_original_info() + print("✓ test_cutcell_original_info passed") diff --git a/python/tests/test_cutcontext_edge_reuse.py b/python/tests/test_cutcontext_edge_reuse.py new file mode 100644 index 0000000..137a3f4 --- /dev/null +++ b/python/tests/test_cutcontext_edge_reuse.py @@ -0,0 +1,42 @@ +"""Test CutContext for edge-owned intersection vertices.""" + +import numpy as np + + +def test_cutcontext_edge_reuse(): + """Test that CutContext correctly deduplicates edge intersections. + + This is a placeholder test until CutContext is exposed to Python. + The actual functionality will be tested in C++ or through integration tests. + """ + # TODO: Once CutContext is exposed to Python bindings, implement: + # 1. Create CutContext with num_original_vertices=4, gdim=2 + # 2. Insert edge (0,1) with phi values → get vid1 + # 3. Insert same edge again → get same vid (reuse) + # 4. Insert edge with endpoint phi==0 → returns original vertex id + # 5. Verify ip_coords has exactly one entry per unique intersection + + # For now, just verify the concept works through existing cut operations + # which should internally use similar logic + import cutcells + + # Create a quad and cut it + vertices = np.array([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]], dtype=float) + ls_values = np.array([-0.5, 0.5, 0.5, -0.5], dtype=float) + + cut = cutcells.cut( + cutcells.CellType.quadrilateral, vertices, 2, ls_values, "phi<0", False + ) + + # Basic sanity: cut should produce cells + assert len(cut.types) > 0 + assert cut.vertex_coords is not None + + # TODO: When CutContext is integrated, verify: + # - Same edge intersections produce same vertex ids + # - No duplicate vertices for shared edges + + +if __name__ == "__main__": + test_cutcontext_edge_reuse() + print("✓ test_cutcontext_edge_reuse passed (placeholder)") diff --git a/python/tests/test_hex_classify.py b/python/tests/test_hex_classify.py new file mode 100644 index 0000000..59ccde8 --- /dev/null +++ b/python/tests/test_hex_classify.py @@ -0,0 +1,94 @@ +import random + +import pytest + +pytest.importorskip( + "tools.cutcells_tables", + reason="Legacy table-tooling package is not part of this repo layout.", +) + +from tools.cutcells_tables.classify.hex_mc33 import ( + classify_hex, + permute_mask, + RAW_TO_BASE_ID, + CANONICAL_MASKS, + ambiguous_faces_mask, + edges_mask_from_cell_mask, + body_saddle_sign_hex, + asymptotic_decider_quad, +) +from tools.cutcells_tables.symmetry.cube import SYMMETRIES + + +def test_orbit_canonicalization_exhaustive(): + # Every raw mask maps to canonical mask present in CANONICAL_MASKS + canonical_set = set(CANONICAL_MASKS) + for m in range(256): + info = classify_hex(m) + assert info.canonical_mask in canonical_set + # Check RAW_TO_* consistency + c2 = classify_hex(info.canonical_mask) + assert RAW_TO_BASE_ID[m] == c2.base_id + + +def test_symmetry_equivalence_random(): + rng = random.Random(1234) + for _ in range(200): + m = rng.randrange(256) + info = classify_hex(m) + for sid in rng.sample(range(len(SYMMETRIES)), 5): + pm = permute_mask(m, sid) + info_p = classify_hex(pm) + assert info.base_id == info_p.base_id + + +def test_ambiguous_faces_patterns(): + # Construct masks with one ambiguous face (face 0) pattern 0101 / 1010 + # Face 0 assumed (0,1,2,3) + pattern_0101 = 0 + pattern_1010 = 0 + # set bits: v0=1,v1=0,v2=1,v3=0 -> 0b0101 -> vertices 0,2 + pattern_0101 |= (1 << 0) | (1 << 2) + # 1010 -> vertices 1,3 + pattern_1010 |= (1 << 1) | (1 << 3) + assert ambiguous_faces_mask(pattern_0101) & 1 + assert ambiguous_faces_mask(pattern_1010) & 1 + + +def test_edges_mask_parity_random(): + for m in range(256): + em = edges_mask_from_cell_mask(m) + # For each edge bit set ensure its endpoints differ + for ei, (a, b) in enumerate( + ( + (0, 1), + (1, 2), + (2, 3), + (3, 0), + (4, 5), + (5, 6), + (6, 7), + (7, 4), + (0, 4), + (1, 5), + (2, 6), + (3, 7), + ) + ): + if (em >> ei) & 1: + assert ((m >> a) & 1) != ((m >> b) & 1) + + +def test_body_saddle_sign_center_consistency(): + # If all phi are symmetric around zero, interior sign should align with center + phi = [-1.0, 1.0, 1.0, -1.0, -1.0, 1.0, 1.0, -1.0] + s = body_saddle_sign_hex(phi) + # center value is ~0 so sign may be 1 (>=0). Accept either but function should return int 0/1 + assert s in (0, 1) + + +def test_asymptotic_decider_basic(): + # Values produce center < 0 -> returns 1 + assert asymptotic_decider_quad(-1, 1, 1, -1) == 1 + # values produce center > 0 -> returns 0 + assert asymptotic_decider_quad(1, 1, 1, 1) == 0 diff --git a/python/tests/test_hex_emit.py b/python/tests/test_hex_emit.py new file mode 100644 index 0000000..8939656 --- /dev/null +++ b/python/tests/test_hex_emit.py @@ -0,0 +1,140 @@ +from pathlib import Path +import pytest + +pytest.importorskip( + "tools.cutcells_tables", + reason="Legacy table-tooling package is not part of this repo layout.", +) + +from tools.cutcells_tables.emit.hex_emit import write_hex_header, generate_hex_tables +from tools.cutcells_tables.build.hex_variant import build_hex_variant +from tools.cutcells_tables.classify.hex_mc33 import classify_hex +from tools.cutcells_tables.cells.hex import EDGES as HEX_EDGES + + +def _loop_nz(loop): + # replicate heuristic from variant builder for test validation + coords = [ + (0.0, 0.0, 0.0), + (1.0, 0.0, 0.0), + (1.0, 1.0, 0.0), + (0.0, 1.0, 0.0), + (0.0, 0.0, 1.0), + (1.0, 0.0, 1.0), + (1.0, 1.0, 1.0), + (0.0, 1.0, 1.0), + ] + for a, b in HEX_EDGES: + ax, ay, az = coords[a] + bx, by, bz = coords[b] + coords.append(((ax + bx) * 0.5, (ay + by) * 0.5, (az + bz) * 0.5)) + vs = loop.verts + nz = 0.0 + for i in range(len(vs)): + x1, y1, z1 = coords[vs[i]] + x2, y2, z2 = coords[vs[(i + 1) % len(vs)]] + nz += (x1 - x2) * (y1 + y2) + return nz + + +def test_generate_hex_tables_basic(tmp_path: Path): + acc = generate_hex_tables() + # 256 raw masks covered indirectly via base groupings; ensure some content + assert len(acc.poly_descs) > 0 + # variant_lut_offsets length == NUM_BASES + # monotonic offsets + assert all( + x <= y for x, y in zip(acc.variant_lut_offsets, acc.variant_lut_offsets[1:]) + ) + out = tmp_path / "hex.hpp" + write_hex_header(out) + assert out.exists() + text_full = out.read_text() + assert "hex_canon_base" in text_full + lines = text_full.splitlines() + assert any(line.startswith("// Hash:") for line in lines[:3]) + # New pools & fields + assert "hex_surface_pool" in text_full + assert "hex_inside_pool" in text_full + assert "hex_outside_pool" in text_full + assert "surf_off" in text_full + assert "in_off" in text_full + assert "out_off" in text_full + + +def test_inside_outside_faces_nonempty_for_mixed_masks(): + # pick some masks with both inside/outside bits (not all 0 or all 1) + samples = [0b00001111, 0b01010101, 0b00111100, 0b10011001] + for m in samples: + info = classify_hex(m) + # choose variant bits 0 for simplicity + vp = build_hex_variant(m, 0) + # If there is at least one crossing we expect at least one inside or outside face polygon + if info.edges_mask != 0: + assert len(vp.inside_faces) + len(vp.outside_faces) >= 1 + + +def test_iso_loop_orientation_samples(): + # sample masks with various configurations + samples = [0b00001111, 0b00110011, 0b01011010, 0b11110000, 0b10100101] + for m in samples: + vp = build_hex_variant(m, 0) + # All loops should have non-negative nz after orientation normalization + for L in vp.iso_loops: + assert _loop_nz(L) >= -1e-9 + + +def test_hash_stability(tmp_path: Path): + out1 = tmp_path / "hex1.hpp" + out2 = tmp_path / "hex2.hpp" + write_hex_header(out1) + write_hex_header(out2) + h1 = out1.read_text().splitlines()[0] + h2 = out2.read_text().splitlines()[0] + assert h1 == h2 + + +def test_watertight_edge_degree_samples(): + # sample several masks to ensure each iso vertex appears degree 2 in loops + masks = [i for i in range(1, 255, 17)] # sparse sampling + for m in masks: + vp = build_hex_variant(m, 0) + # build adjacency counts + for L in vp.iso_loops: + n = len(L.verts) + for i in range(n): + a = L.verts[i] + b = L.verts[(i + 1) % n] + assert a != b + # Previous degree>=2 aggregate test fails for single triangles (each vertex listed once). + # Instead ensure no vertex appears only once across *multiple* loops causing open chains. + counts = {} + for L in vp.iso_loops: + for v in L.verts: + counts[v] = counts.get(v, 0) + 1 + if len(vp.iso_loops) > 1: + # Only enforce for vertices that appear in more than one distinct loop + loop_membership = {} + for li, L in enumerate(vp.iso_loops): + for v in set(L.verts): + loop_membership.setdefault(v, set()).add(li) + for v, loops in loop_membership.items(): + if len(loops) > 1: + assert counts[v] >= 2 + + +def test_interior_bit_presence_variant_doubling(): + # Find a mask whose base sets needs_interior_bit + candidates = [] + for m in range(256): + info = classify_hex(m) + if info.needs_interior_bit: + candidates.append((m, info)) + break + if not candidates: + # Heuristic may not mark any mask in some configurations; skip gracefully + return + m, info = candidates[0] + # K should include interior bit; ensure at least one variant beyond face-only combinations + face_bits = bin(info.ambiguous_faces_mask).count("1") + assert info.K == face_bits + 1 diff --git a/python/tests/test_hex_polyhedron_export.py b/python/tests/test_hex_polyhedron_export.py new file mode 100644 index 0000000..0c921c3 --- /dev/null +++ b/python/tests/test_hex_polyhedron_export.py @@ -0,0 +1,26 @@ +import pytest + +pytest.importorskip( + "tools.cutcells_tables", + reason="Legacy table-tooling package is not part of this repo layout.", +) + +from tools.cutcells_tables.export.hex_polyhedron import build_hex_polyhedra + + +def test_single_corner_tetra_inside_polyhedron(): + # Mask with only corner 0 inside + m = 1 + data = build_hex_polyhedra(m, 0) + assert data.inside is not None, "Inside tetra should be watertight" + # Tetra has 4 faces (iso + 3 corner faces) + assert data.inside.n_faces == 4 + assert sum(data.inside.face_sizes) == len(data.inside.faces_stream) + + +def test_full_or_empty_masks_no_polyhedra(): + # No iso surface => boundaries not mixed (pure hex/no cut) -> cannot form cut polyhedra + for m in (0, 0xFF): + data = build_hex_polyhedra(m, 0) + # Either inside or outside degenerates; both can't be polyhedron with iso surface absent + assert data.inside is None or data.outside is None diff --git a/python/tests/test_hex_variant.py b/python/tests/test_hex_variant.py new file mode 100644 index 0000000..d66136f --- /dev/null +++ b/python/tests/test_hex_variant.py @@ -0,0 +1,56 @@ +import pytest + +pytest.importorskip( + "tools.cutcells_tables", + reason="Legacy table-tooling package is not part of this repo layout.", +) + +from tools.cutcells_tables.build.hex_variant import build_hex_variant +from tools.cutcells_tables.classify.hex_mc33 import ( + edges_mask_from_cell_mask, + classify_hex, +) + + +def test_variant_loops_basic(): + for mask in (0, 0xFF, 0b00001111, 0b11110000, 0b01011010): + vp = build_hex_variant(mask, 0) + em = edges_mask_from_cell_mask(mask) + if em == 0: + assert len(vp.iso_loops) == 0 + else: + # loops may be >1 now; ensure each closed and edge-vertex indices + for loop in vp.iso_loops: + assert loop.is_closed() + assert all(v >= 8 for v in loop.verts) + + +def test_vertex_mask_matches_loop(): + mask = 0b01011010 + vp = build_hex_variant(mask, 0) + bits = 0 + for coll in (vp.iso_loops, vp.inside_faces, vp.outside_faces): + for L in coll: + for v in L.verts: + bits |= 1 << v + assert bits == vp.vmask + + +def test_deterministic_ordering(): + mask = 0b01011010 + v1 = build_hex_variant(mask, 0) + v2 = build_hex_variant(mask, 0) + assert [L.verts for L in v1.iso_loops] == [L.verts for L in v2.iso_loops] + + +def test_variant_bit_effect_when_ambiguous(): + # Construct an ambiguous face mask: bottom face 0101 (vertices 0,2 active) + mask = (1 << 0) | (1 << 2) + info = classify_hex(mask) + if info.K == 0: + return # no ambiguous faces in this mask; skip + vA = build_hex_variant(mask, 0) + vB = build_hex_variant(mask, 1) + # Either different loops or identical if degenerate; ensure deterministic order regardless + assert [L.verts for L in vA.iso_loops] == sorted([L.verts for L in vA.iso_loops]) + assert [L.verts for L in vB.iso_loops] == sorted([L.verts for L in vB.iso_loops]) diff --git a/python/tests/test_hexahedron_special_point.py b/python/tests/test_hexahedron_special_point.py new file mode 100644 index 0000000..8cc649f --- /dev/null +++ b/python/tests/test_hexahedron_special_point.py @@ -0,0 +1,65 @@ +import numpy as np +import cutcells + + +def _is_on_unit_cube_edge(p: np.ndarray, tol: float = 1e-12) -> bool: + # On a unit-cube edge => at least two coordinates are on {0,1} (within tol) + on01 = [abs(p[i] - 0.0) < tol or abs(p[i] - 1.0) < tol for i in range(3)] + return sum(on01) >= 2 + + +def test_hexahedron_interface_uses_special_point_n0(): + # Pick a concrete VTK case that is known (from generated tables) to reference token 200 (N0). + # Case id 67 corresponds to mask bits set at vertices {0,1,6}. + ls_values = np.array([-1.0, -1.1, 1.2, 1.3, 1.4, 1.5, -1.6, 1.7], dtype=np.float64) + + # VTK hexahedron vertex ordering: + # 0:(0,0,0) 1:(1,0,0) 2:(1,1,0) 3:(0,1,0) 4:(0,0,1) 5:(1,0,1) 6:(1,1,1) 7:(0,1,1) + vertex_coordinates = np.array( + [ + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + 1.0, + 0.0, + 1.0, + 1.0, + 1.0, + 1.0, + 0.0, + 1.0, + 1.0, + ], + dtype=np.float64, + ) + + cut_cell = cutcells.cut( + cutcells.CellType.hexahedron, + vertex_coordinates, + 3, + ls_values, + "phi=0", + False, + ) + + coords = np.asarray(cut_cell.vertex_coords) + + tol = 1e-10 + assert coords[:, 0].min() >= -tol and coords[:, 0].max() <= 1.0 + tol + assert coords[:, 1].min() >= -tol and coords[:, 1].max() <= 1.0 + tol + assert coords[:, 2].min() >= -tol and coords[:, 2].max() <= 1.0 + tol + + # All edge-intersection points lie on unit-cube edges; the special point should not. + assert any(not _is_on_unit_cube_edge(p) for p in coords) diff --git a/python/tests/test_prism_special_point.py b/python/tests/test_prism_special_point.py new file mode 100644 index 0000000..fce40c7 --- /dev/null +++ b/python/tests/test_prism_special_point.py @@ -0,0 +1,61 @@ +import numpy as np +import cutcells + + +def test_prism_interface_uses_special_point_n0_case10(): + # Pick a concrete case that (per generated prism interface tables) uses token 200 (N0). + # Wedge/prism has 6 vertices => 64 cases; case id 10 corresponds to mask bits set at vertices {1,3}. + ls_values = np.array([1.0, -1.0, 1.0, -1.0, 1.0, 1.0], dtype=np.float64) + + # VTK_WEDGE / prism vertex ordering: + # bottom tri: 0:(0,0,0) 1:(1,0,0) 2:(0,1,0) + # top tri: 3:(0,0,1) 4:(1,0,1) 5:(0,1,1) + vertex_coordinates = np.array( + [ + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + 1.0, + 0.0, + 1.0, + 0.0, + 1.0, + 1.0, + ], + dtype=np.float64, + ) + + cut_cell = cutcells.cut( + cutcells.CellType.prism, + vertex_coordinates, + 3, + ls_values, + "phi=0", + False, + ) + + coords = np.asarray(cut_cell.vertex_coords) + + tol = 1e-10 + assert coords[:, 0].min() >= -tol and coords[:, 0].max() <= 1.0 + tol + assert coords[:, 1].min() >= -tol and coords[:, 1].max() <= 1.0 + tol + assert coords[:, 2].min() >= -tol and coords[:, 2].max() <= 1.0 + tol + + # Edge intersections live on the prism boundary. N0 should be strictly interior for this case. + inside = ( + (coords[:, 0] > tol) + & (coords[:, 1] > tol) + & (coords[:, 0] + coords[:, 1] < 1.0 - tol) + & (coords[:, 2] > tol) + & (coords[:, 2] < 1.0 - tol) + ) + assert bool(np.any(inside)) diff --git a/python/tests/test_pyramid_special_point.py b/python/tests/test_pyramid_special_point.py new file mode 100644 index 0000000..69ae3db --- /dev/null +++ b/python/tests/test_pyramid_special_point.py @@ -0,0 +1,65 @@ +import numpy as np +import cutcells + + +def test_pyramid_uses_special_point_n0_case19(): + # Pyramid has 5 vertices => 32 cases; case id 19 corresponds to mask bits set at vertices {0,1,4}. + # (CutCells convention: bit i set when phi_i < 0.) + ls_values = np.array([-1.0, -1.0, 1.0, 1.0, -1.0], dtype=np.float64) + + # VTK_PYRAMID vertex ordering: + # base quad: 0:(0,0,0) 1:(1,0,0) 2:(1,1,0) 3:(0,1,0) + # apex: 4:(0.5,0.5,1) + vertex_coordinates = np.array( + [ + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.5, + 0.5, + 1.0, + ], + dtype=np.float64, + ) + + cut_cell = cutcells.cut( + cutcells.CellType.pyramid, + vertex_coordinates, + 3, + ls_values, + "phi<0", + False, + ) + + coords = np.asarray(cut_cell.vertex_coords) + + # Basic bounds + tol = 1e-10 + assert coords[:, 0].min() >= -tol and coords[:, 0].max() <= 1.0 + tol + assert coords[:, 1].min() >= -tol and coords[:, 1].max() <= 1.0 + tol + assert coords[:, 2].min() >= -tol and coords[:, 2].max() <= 1.0 + tol + + # Edge intersections lie on edges/faces. N0 should be strictly interior for this case. + # For this unit pyramid (apex centered), the interior condition at height z is: + # |x-0.5| < 0.5*(1-z) and |y-0.5| < 0.5*(1-z). + x = coords[:, 0] + y = coords[:, 1] + z = coords[:, 2] + + half = 0.5 * (1.0 - z) + inside = ( + (z > tol) + & (z < 1.0 - tol) + & (np.abs(x - 0.5) < half - tol) + & (np.abs(y - 0.5) < half - tol) + ) + assert bool(np.any(inside)) diff --git a/python/tests/test_quad_table_sanity.py b/python/tests/test_quad_table_sanity.py new file mode 100644 index 0000000..b450ce0 --- /dev/null +++ b/python/tests/test_quad_table_sanity.py @@ -0,0 +1,42 @@ +"""Test quad table sanity checks.""" + + +def test_quad_table_sanity(): + """Validate quad tables structure and token encoding. + + This is a C++-level validation that would check: + - Offsets are monotonic + - Last offset equals TOTAL subcells + - Vert offsets monotonic + - Every token is either edge_id in [0,3] or 100+vid with vid in [0,3] + + For now, this is a placeholder. The actual validation happens in C++ + through compilation and existing integration tests. + """ + # TODO: When table validation utilities are exposed to Python, implement: + # 1. Load quad_case_subcell_offset_inside + # 2. Verify monotonic: offset[i] <= offset[i+1] + # 3. Verify offset[16] == 21 (total subcells) + # 4. Load quad_subcell_verts_inside + # 5. For each token != -1: verify token < 4 OR 100 <= token <= 103 + + # The quad tables are now defined in cut_quadrilateral_tables.h + # and are validated through successful compilation and existing tests + import cutcells + import numpy as np + + # Run a basic cut to ensure tables work + vertices = np.array([[0.0, 0.0], [1.0, 0.0], [1.0, 1.0], [0.0, 1.0]], dtype=float) + ls_values = np.array([-0.5, 0.5, 0.5, -0.5], dtype=float) + + cut = cutcells.cut( + cutcells.CellType.quadrilateral, vertices, 2, ls_values, "phi<0", False + ) + + # Should produce valid output + assert len(cut.types) > 0 + assert cut.vertex_coords is not None + + # Basic validation passed if we got here + print(f"Produced {len(cut.types)} subcells") + print("✓ test_quad_table_sanity passed") diff --git a/python/tests/test_quadrilateral.py b/python/tests/test_quadrilateral.py new file mode 100644 index 0000000..7809167 --- /dev/null +++ b/python/tests/test_quadrilateral.py @@ -0,0 +1,50 @@ +# Copyright (c) 2025 ONERA +# Authors: Susanne Claus +# This file is part of CutCells +# +# SPDX-License-Identifier: MIT +import numpy as np +import pytest + +import cutcells + +VTK_TRIANGLE = 5 +VTK_QUAD = 9 + + +def _square_vertices(): + return np.array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0], dtype=float) + + +def test_quadrilateral_opposite_corners_disconnected(): + vertices = _square_vertices() + ls_values = np.array([-0.5, 0.5, -0.5, 0.5], dtype=float) + + cut_inside = cutcells.cut( + cutcells.CellType.quadrilateral, vertices, 2, ls_values, "phi<0", False + ) + assert cut_inside.types == [VTK_TRIANGLE, VTK_TRIANGLE] + assert np.isclose(cut_inside.volume(), 0.25) + + cut_outside = cutcells.cut( + cutcells.CellType.quadrilateral, vertices, 2, ls_values, "phi>0", False + ) + assert cut_outside.types == [VTK_QUAD, VTK_QUAD] + assert np.isclose(cut_outside.volume(), 0.75) + + +def test_quadrilateral_pentagon_splits_triangle_quad(): + vertices = _square_vertices() + ls_values = np.array([0.5, -0.5, -0.5, -0.5], dtype=float) + + cut_inside = cutcells.cut( + cutcells.CellType.quadrilateral, vertices, 2, ls_values, "phi<0", False + ) + assert cut_inside.types == [VTK_TRIANGLE, VTK_QUAD] + assert np.isclose(cut_inside.volume(), 0.875) + + cut_outside = cutcells.cut( + cutcells.CellType.quadrilateral, vertices, 2, ls_values, "phi>0", False + ) + assert cut_outside.types == [VTK_TRIANGLE] + assert np.isclose(cut_outside.volume(), 0.125) diff --git a/python/tests/test_quadrilateral_ambiguity.py b/python/tests/test_quadrilateral_ambiguity.py new file mode 100644 index 0000000..e7918f0 --- /dev/null +++ b/python/tests/test_quadrilateral_ambiguity.py @@ -0,0 +1,135 @@ +# Copyright (c) 2025 ONERA +# Authors: Susanne Claus +# This file is part of CutCells +# +# SPDX-License-Identifier: MIT +import cutcells +import numpy as np +import pytest + + +def marching_squares_flag(ls_values: np.ndarray) -> int: + flag = 0 + for i, v in enumerate(ls_values): + if v < 0.0: + flag |= 1 << i + return flag + + +def asymptotic_decider(ls_values: np.ndarray) -> bool: + f0, f1, f2, f3 = ls_values + return f0 * f2 - f1 * f3 >= 0.0 + + +def test_opposite_corner_masks_are_ambiguous(): + ls_a = np.array([-1.0, 1.0, -1.0, 1.0]) + ls_b = np.array([1.0, -1.0, 1.0, -1.0]) + + assert marching_squares_flag(ls_a) == 0b0101 + assert marching_squares_flag(ls_b) == 0b1010 + + +def test_asymptotic_decider_scale_invariant_and_different_diagonals(): + base = np.array([-1.0, 0.5, 1.2, -0.25]) + scaled = 7.5 * base + + decision_base = asymptotic_decider(base) + decision_scaled = asymptotic_decider(scaled) + + assert decision_base == decision_scaled + + # Flip sign on one corner to flip the diagonal choice + flipped = base.copy() + flipped[2] *= -1.0 + decision_flipped = asymptotic_decider(flipped) + + assert decision_base != decision_flipped + + +def _segments_from_cutcell(cut_cell): + coords = np.asarray(cut_cell.vertex_coords) + conn = list(cut_cell.connectivity) + segments = [] + i = 0 + while i < len(conn): + n = int(conn[i]) + assert n == 2 + a = int(conn[i + 1]) + b = int(conn[i + 2]) + segments.append((coords[a], coords[b])) + i += 1 + n + return segments + + +def _edge_id_for_point(p, tol=1e-12): + x, y = float(p[0]), float(p[1]) + if abs(y - 0.0) < tol: + return 0 # edge 0: v0-v1 + if abs(x - 1.0) < tol: + return 1 # edge 1: v1-v2 + if abs(y - 1.0) < tol: + return 2 # edge 2: v2-v3 + if abs(x - 0.0) < tol: + return 3 # edge 3: v3-v0 + raise AssertionError(f"Point not on boundary: {p}") + + +@pytest.mark.parametrize( + "ls_values, expected_pairs", + [ + # d = f0*f2 - f1*f3 > 0 -> connect diagonal (0,2) -> segments (0,1) and (2,3) + (np.array([-1.0, 0.1, -1.0, 0.1]), {frozenset({0, 1}), frozenset({2, 3})}), + # d < 0 -> connect diagonal (1,3) -> segments (0,3) and (1,2) + (np.array([-0.1, 1.0, -0.1, 1.0]), {frozenset({0, 3}), frozenset({1, 2})}), + ], +) +def test_quad_interface_ambiguous_pairs_follow_decider(ls_values, expected_pairs): + vertex_coordinates = np.array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]) + cell_type = cutcells.CellType.quadrilateral + gdim = 2 + + cut_cell = cutcells.cut( + cell_type, vertex_coordinates, gdim, ls_values, "phi=0", True + ) + segments = _segments_from_cutcell(cut_cell) + assert len(segments) == 2 + + pairs = set() + for a, b in segments: + ea = _edge_id_for_point(a) + eb = _edge_id_for_point(b) + pairs.add(frozenset({ea, eb})) + + assert pairs == expected_pairs + + +@pytest.mark.parametrize( + "ls_values, expected_mask", + [ + # mask 0101: connected variant is d>=0 (variant 0) + (np.array([-2.0, 1.0, -2.0, 1.0]), 0b0101), + # mask 1010: connected variant is d<0 (variant 1) + (np.array([1.0, -2.0, 1.0, -2.0]), 0b1010), + ], +) +def test_quad_ambiguous_connected_variant_keeps_quads(ls_values, expected_mask): + vertex_coordinates = np.array([0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0]) + cell_type = cutcells.CellType.quadrilateral + gdim = 2 + + assert marching_squares_flag(ls_values) == expected_mask + + inside = cutcells.cut( + cell_type, vertex_coordinates, gdim, ls_values, "phi<0", False + ) + types = list(inside.types) + + # VTK_QUAD = 9 + assert types == [9, 9] + + conn = list(inside.connectivity) + i = 0 + for _ in range(2): + assert int(conn[i]) == 4 + i += 5 + assert i == len(conn) diff --git a/python/tests/test_single_corner.py b/python/tests/test_single_corner.py new file mode 100644 index 0000000..090182f --- /dev/null +++ b/python/tests/test_single_corner.py @@ -0,0 +1,18 @@ +import pytest + +pytest.importorskip( + "tools.cutcells_tables", + reason="Legacy table-tooling package is not part of this repo layout.", +) + +from tools.cutcells_tables.build.hex_variant import build_hex_variant + + +def test_single_inside_corner_triangle(): + mask = 1 # only corner 0 inside + vp = build_hex_variant(mask, 0) + assert len(vp.iso_loops) == 1, f"expected 1 iso loop, got {len(vp.iso_loops)}" + L = vp.iso_loops[0] + assert len(L.verts) == 3, f"expected triangle, got {L.verts}" + assert all(v >= 8 for v in L.verts), "loop should use edge vertices only" + assert len(set(L.verts)) == 3, "triangle vertices must be distinct" diff --git a/python/tests/test_single_corner_basic.py b/python/tests/test_single_corner_basic.py new file mode 100644 index 0000000..090182f --- /dev/null +++ b/python/tests/test_single_corner_basic.py @@ -0,0 +1,18 @@ +import pytest + +pytest.importorskip( + "tools.cutcells_tables", + reason="Legacy table-tooling package is not part of this repo layout.", +) + +from tools.cutcells_tables.build.hex_variant import build_hex_variant + + +def test_single_inside_corner_triangle(): + mask = 1 # only corner 0 inside + vp = build_hex_variant(mask, 0) + assert len(vp.iso_loops) == 1, f"expected 1 iso loop, got {len(vp.iso_loops)}" + L = vp.iso_loops[0] + assert len(L.verts) == 3, f"expected triangle, got {L.verts}" + assert all(v >= 8 for v in L.verts), "loop should use edge vertices only" + assert len(set(L.verts)) == 3, "triangle vertices must be distinct" diff --git a/python/tests/test_tables_cli.py b/python/tests/test_tables_cli.py new file mode 100644 index 0000000..23ed065 --- /dev/null +++ b/python/tests/test_tables_cli.py @@ -0,0 +1,50 @@ +"""Test CLI functionality.""" + +import subprocess +import sys + +import pytest + +pytest.importorskip( + "tools.cutcells_tables", + reason="Legacy table-tooling package is not part of this repo layout.", +) +from pathlib import Path + +# Add tools directory to path for imports +tools_dir = Path(__file__).parent.parent.parent +sys.path.insert(0, str(tools_dir)) + + +def test_cli_list(): + """Test CLI list command.""" + result = subprocess.run( + [sys.executable, "-m", "tools.cutcells_tables.cli", "list"], + capture_output=True, + text=True, + cwd=tools_dir.parent, + ) + + assert result.returncode == 0 + assert "generate-hex" in result.stdout + + +def test_cli_dump_hex_base(): + """Test CLI dump-hex-base command.""" + result = subprocess.run( + [ + sys.executable, + "-m", + "tools.cutcells_tables.cli", + "dump-hex-base", + "--mask", + "173", + ], + capture_output=True, + text=True, + cwd=tools_dir.parent, + ) + + assert result.returncode == 0 + assert "Mask: 173" in result.stdout + assert "Base ID:" in result.stdout diff --git a/python/tests/test_vertex_parent_entity_tokens.py b/python/tests/test_vertex_parent_entity_tokens.py new file mode 100644 index 0000000..04bf7c1 --- /dev/null +++ b/python/tests/test_vertex_parent_entity_tokens.py @@ -0,0 +1,138 @@ +import numpy as np +import cutcells + + +def test_quadrilateral_vertex_parent_entity_tokens_are_valid(): + # Unit square quad, intersected. + vertex_coordinates = np.array( + [0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0], dtype=np.float64 + ) + ls_values = np.array([-0.1, 0.2, -0.2, 0.3], dtype=np.float64) + + cut_cell = cutcells.cut( + cutcells.CellType.quadrilateral, + vertex_coordinates, + 2, + ls_values, + "phi<0", + False, + ) + + parents = np.asarray(cut_cell.vertex_parent_entity, dtype=np.int32) + assert parents.ndim == 1 + coords = np.asarray(cut_cell.vertex_coords) + assert coords.ndim == 2 + assert parents.size == coords.shape[0] + + # For quads we only expect edge tokens 0..3 and original-vertex tokens 100..103. + assert np.all( + ((0 <= parents) & (parents < 4)) | ((100 <= parents) & (parents < 104)) + ) + + +def test_hexahedron_vertex_parent_entity_includes_special_point_token_200(): + # Same case as test_hexahedron_interface_uses_special_point_n0, but assert the token appears. + ls_values = np.array([-1.0, -1.1, 1.2, 1.3, 1.4, 1.5, -1.6, 1.7], dtype=np.float64) + vertex_coordinates = np.array( + [ + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 1.0, + 1.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + 1.0, + 0.0, + 1.0, + 1.0, + 1.0, + 1.0, + 0.0, + 1.0, + 1.0, + ], + dtype=np.float64, + ) + + cut_cell = cutcells.cut( + cutcells.CellType.hexahedron, vertex_coordinates, 3, ls_values, "phi=0", False + ) + parents = np.asarray(cut_cell.vertex_parent_entity, dtype=np.int32) + assert 200 in set(map(int, parents)) + + +def test_triangle_vertex_parent_entity_tokens_are_valid(): + # Unit right-triangle, intersected. + vertex_coordinates = np.array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0], dtype=np.float64) + ls_values = np.array([-0.1, 0.2, -0.3], dtype=np.float64) + + cut_cell = cutcells.cut( + cutcells.CellType.triangle, + vertex_coordinates, + 2, + ls_values, + "phi<0", + False, + ) + + parents = np.asarray(cut_cell.vertex_parent_entity, dtype=np.int32) + assert parents.ndim == 1 + coords = np.asarray(cut_cell.vertex_coords) + assert coords.ndim == 2 + assert parents.size == coords.shape[0] + + # Triangles have 3 edges and 3 vertices; no special points. + assert np.all( + ((0 <= parents) & (parents < 3)) | ((100 <= parents) & (parents < 103)) + ) + + +def test_tetrahedron_vertex_parent_entity_tokens_are_valid(): + # Unit tetrahedron, intersected. + vertex_coordinates = np.array( + [ + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + ], + dtype=np.float64, + ) + ls_values = np.array([-0.1, 0.2, -0.3, 0.4], dtype=np.float64) + + cut_cell = cutcells.cut( + cutcells.CellType.tetrahedron, + vertex_coordinates, + 3, + ls_values, + "phi<0", + False, + ) + + parents = np.asarray(cut_cell.vertex_parent_entity, dtype=np.int32) + assert parents.ndim == 1 + coords = np.asarray(cut_cell.vertex_coords) + assert coords.ndim == 2 + assert parents.size == coords.shape[0] + + # Tets have 6 edges and 4 vertices; no special points. + assert np.all( + ((0 <= parents) & (parents < 6)) | ((100 <= parents) & (parents < 104)) + ) diff --git a/tablegen/cutcells_tablegen/__init__.py b/tablegen/cutcells_tablegen/__init__.py new file mode 100644 index 0000000..37a97ae --- /dev/null +++ b/tablegen/cutcells_tablegen/__init__.py @@ -0,0 +1,11 @@ +"""Table generation utilities for CutCells (VTK TableBasedClip style). + +Use with `conda activate fenicsx-dev` before running tablegen scripts. +""" + +__all__ = [ + "topology", + "vtk_tables_import", + "normalize", + "emit_c_headers", +] diff --git a/tablegen/cutcells_tablegen/emit_c_headers.py b/tablegen/cutcells_tablegen/emit_c_headers.py new file mode 100644 index 0000000..b379b4a --- /dev/null +++ b/tablegen/cutcells_tablegen/emit_c_headers.py @@ -0,0 +1,522 @@ +"""Emit CutCells-style C++ headers from normalized tables.""" + +from __future__ import annotations + +from pathlib import Path +from typing import Dict, List, Optional + +from .topology import num_edges + +CELL_ENUM_LITERALS = [ + "cell::type::point", + "cell::type::interval", + "cell::type::triangle", + "cell::type::tetrahedron", + "cell::type::quadrilateral", + "cell::type::hexahedron", + "cell::type::prism", + "cell::type::pyramid", +] + + +def _vtk_derived_notice_lines( + vtk_ref: Optional[str] = None, vtk_header_path: Optional[str] = None +) -> List[str]: + lines = [ + "// -----------------------------------------------------------------------------", + "// This file is generated by CutCells tablegen.", + "//", + "// It contains case tables derived from VTK's vtkTableBasedClipCases.h", + "// (Visualization Toolkit, TableBasedClip).", + "//", + f"// VTK ref: {vtk_ref}" if vtk_ref else "// VTK ref: (not recorded)", + f"// VTK header path override: {vtk_header_path}" + if vtk_header_path + else "// VTK header path override: (none)", + "//", + "// VTK is licensed under the BSD 3-Clause License.", + "// See third_party/VTK-Copyright.txt in this repository.", + "// -----------------------------------------------------------------------------", + ] + return lines + + +def _brace_join(rows: List[str]) -> str: + return "{ " + ", ".join(rows) + " }" + + +def _format_int_list(values: List[int]) -> str: + return _brace_join([str(v) for v in values]) + + +def _format_cell_type_list(values: List[int]) -> str: + mapped = [] + for v in values: + if v < 0 or v >= len(CELL_ENUM_LITERALS): + raise ValueError(f"Cell type enum value {v} out of range") + mapped.append(CELL_ENUM_LITERALS[v]) + return _brace_join(mapped) + + +def _format_matrix(matrix: List[List[int]]) -> str: + inner = ["{ " + ", ".join(str(v) for v in row) + " }" for row in matrix] + return "{\n" + ",\n".join(f" {row}" for row in inner) + "\n}" + + +def _header_guard(cell_type: str, table_kind: str) -> str: + return f"CUT_CELLS_{cell_type.upper()}_{table_kind.upper()}_TABLES_H" + + +def emit_header( + cell_type: str, table_kind: str, arrays: Dict[str, List], output_dir: Path +) -> Path: + """Write a single header for one cell type + table kind (inside/outside/interface).""" + output_dir.mkdir(parents=True, exist_ok=True) + path = output_dir / f"cut_{cell_type}_{table_kind}_tables.h" + + n_cases = len(arrays["intersected_edges"]) + n_edges = num_edges(cell_type) + guard = _header_guard(cell_type, table_kind) + + lines: List[str] = [] + lines.append(f"#ifndef {guard}") + lines.append(f"#define {guard}") + lines.append("") + lines.append('#include "cell_types.h"') + if cell_type == "quadrilateral" and table_kind == "inside": + # For uint8_t / int8_t in ambiguity metadata + lines.append("#include ") + if cell_type == "quadrilateral" and table_kind == "inside": + # For uint8_t / int8_t in ambiguity metadata + lines.append("#include ") + lines.append("") + lines.append("namespace cutcells::cell::generated {") + lines.append("") + lines.append( + f"constexpr int cut_{cell_type}_{table_kind}_intersected_edges[{n_cases}][{n_edges}] = " + + _format_matrix(arrays["intersected_edges"]) + + ";" + ) + lines.append("") + lines.append( + f"constexpr int cut_{cell_type}_{table_kind}_sub_element_offset[{n_cases + 1}] = " + + _format_int_list(arrays["sub_element_offset"]) + + ";" + ) + lines.append("") + lines.append( + f"constexpr cell::type cut_{cell_type}_{table_kind}_sub_element_cell_types[{len(arrays['sub_element_cell_types'])}] = " + + _format_cell_type_list(arrays["sub_element_cell_types"]) + + ";" + ) + lines.append("") + lines.append( + f"constexpr int cut_{cell_type}_{table_kind}_sub_element[{len(arrays['sub_element'])}] = " + + _format_int_list(arrays["sub_element"]) + + ";" + ) + + extra_coords = arrays.get("extra_coords", []) + if extra_coords: + lines.append("") + lines.append( + f"constexpr double cut_{cell_type}_{table_kind}_extra_coords[{len(extra_coords)}] = " + + _format_int_list(extra_coords) + + ";" + ) + + lines.append("") + lines.append("} // namespace cutcells::cell::generated") + lines.append("") + lines.append(f"#endif // {guard}") + + path.write_text("\n".join(lines)) + return path + + +def emit_all( + cell_type: str, tables_by_kind: Dict[str, Dict[str, List]], output_dir: Path +) -> List[Path]: + written: List[Path] = [] + for kind, arrays in tables_by_kind.items(): + written.append(emit_header(cell_type, kind, arrays, output_dir)) + return written + + +def _emit_tet_like_header( + cell_type: str, + table_kind: str, + arrays: Dict[str, List], + output_dir: Path, + provenance: Optional[str] = None, + vtk_ref: Optional[str] = None, + vtk_header_path: Optional[str] = None, +) -> Path: + """Write header in tetrahedron-like format with fixed-width 2D arrays.""" + output_dir.mkdir(parents=True, exist_ok=True) + path = output_dir / f"cut_{cell_type}_{table_kind}_tables.h" + + # Copy lists so we can safely mutate for augmentation (e.g. quad ambiguity) + arrays = {k: (v.copy() if isinstance(v, list) else v) for k, v in arrays.items()} + + n_cases = len(arrays["intersected_edges"]) + n_edges = num_edges(cell_type) + guard = _header_guard(cell_type, table_kind) + + # Convert VTK flat format to tet-like format + # Extract subcells from flat stream + subcells_data = _extract_subcells_from_flat(arrays) + + quad_amb_meta = None + if cell_type == "quadrilateral": + quad_amb_meta = _augment_quadrilateral_ambiguity(table_kind, arrays) + # Re-extract after augmentation + subcells_data = _extract_subcells_from_flat(arrays) + + lines: List[str] = [] + lines.append(f"#ifndef {guard}") + lines.append(f"#define {guard}") + lines.append("") + + if provenance == "vtk": + lines.extend( + _vtk_derived_notice_lines(vtk_ref=vtk_ref, vtk_header_path=vtk_header_path) + ) + lines.append("") + + lines.append('#include "cell_types.h"') + if cell_type == "quadrilateral" and table_kind == "inside": + # For uint8_t / int8_t in ambiguity metadata + lines.append("#include ") + lines.append("") + lines.append(f"namespace cutcells::cell::{cell_type} {{") + lines.append("") + + # Topology and intersected_edges only in the "inside" header to avoid redefinition + if table_kind == "inside": + # Topology (if quad/hex) + if cell_type == "quadrilateral": + lines.append("// Topology") + lines.append("constexpr int edges[4][2] = {{0,1}, {1,2}, {2,3}, {3,0}};") + lines.append("") + elif cell_type == "hexahedron": + lines.append("// Topology") + lines.append("constexpr int edges[12][2] = {") + lines.append(" {0,1}, {1,2}, {2,3}, {3,0}, // bottom face") + lines.append(" {4,5}, {5,6}, {6,7}, {7,4}, // top face") + lines.append( + " {0,4}, {1,5}, {3,7}, {2,6} // vertical edges (VTK TableBasedClip ordering)" + ) + lines.append("};") + lines.append("") + lines.append("constexpr int faces[6][4] = {") + lines.append(" {0,3,2,1}, {4,5,6,7}, // bottom, top") + lines.append(" {0,1,5,4}, {1,2,6,5}, // front, right") + lines.append(" {2,3,7,6}, {3,0,4,7} // back, left") + lines.append("};") + lines.append("") + + # Intersected edges + lines.append( + f"// Intersected edges per case (1 = intersected, 0 = not intersected)" + ) + lines.append( + f"constexpr int intersected_edges[{n_cases}][{n_edges}] = " + + _format_matrix(arrays["intersected_edges"]) + + ";" + ) + lines.append("") + + if cell_type == "quadrilateral" and quad_amb_meta is not None: + # Ambiguity metadata used by runtime asymptotic-decider selection + lines.append("// Ambiguity metadata (opposite-corner cases)") + lines.append( + f"constexpr uint8_t case_is_ambiguous_tbl[16] = " + + _format_int_list(quad_amb_meta["case_is_ambiguous_tbl"]) + + ";" + ) + lines.append( + f"constexpr int8_t amb_case_id[16] = " + + _format_int_list(quad_amb_meta["amb_case_id"]) + + ";" + ) + lines.append("") + + # Number of subcells per case + num_subcells_per_case = [] + for i in range(n_cases): + start = arrays["sub_element_offset"][i] + end = arrays["sub_element_offset"][i + 1] + num_subcells_per_case.append(end - start) + + lines.append(f"// Number of subcells produced for each case ({table_kind} volume)") + lines.append( + f"constexpr int num_subcells_{table_kind}[{n_cases}] = " + + _format_int_list(num_subcells_per_case) + + ";" + ) + lines.append("") + + # Offset into subcell array + lines.append(f"// Offset into subcell array for each case") + lines.append( + f"constexpr int case_subcell_offset_{table_kind}[{n_cases + 1}] = " + + _format_int_list(arrays["sub_element_offset"]) + + ";" + ) + lines.append("") + + # Cell types + total_subcells = len(arrays["sub_element_cell_types"]) + lines.append(f"// Cell types for {table_kind} subcells") + lines.append( + f"constexpr type subcell_type_{table_kind}[{total_subcells}] = " + + _format_cell_type_list(arrays["sub_element_cell_types"]) + + ";" + ) + lines.append("") + + # Subcell vertices (fixed-width 2D array with -1 padding) + max_verts = subcells_data["max_verts_per_subcell"] + padded_verts = subcells_data["padded_vertices"] + + lines.append( + f"// Subcell vertices (max {max_verts} vertices per subcell, -1 padding)" + ) + lines.append( + f"// Tokens: <100 = edge id, 100..199 = 100+vertex_id, >=200 = 200+special_point_id" + ) + lines.append( + f"constexpr int subcell_verts_{table_kind}[{total_subcells}][{max_verts}] = " + + _format_matrix(padded_verts) + + ";" + ) + + # Special (derived) points, e.g. VTK centroid N0 + sp_count = arrays.get("special_point_count", []) + sp_offset = arrays.get("special_point_offset", []) + sp_data = arrays.get("special_point_data", []) + if sp_count: + lines.append("") + lines.append("// Special points (e.g. centroid): per-case definition streams") + lines.append( + f"constexpr int special_point_count_{table_kind}[{len(sp_count)}] = " + + _format_int_list(sp_count) + + ";" + ) + lines.append( + f"constexpr int special_point_offset_{table_kind}[{len(sp_offset)}] = " + + _format_int_list(sp_offset) + + ";" + ) + lines.append( + f"constexpr int special_point_data_{table_kind}[{len(sp_data)}] = " + + _format_int_list(sp_data) + + ";" + ) + + if cell_type == "quadrilateral" and quad_amb_meta is not None: + if table_kind == "inside": + lines.append("") + lines.append( + "// Ambiguity override ranges: [begin0,end0,begin1,end1] per ambiguous case" + ) + lines.append( + f"constexpr int amb_range_inside[{len(quad_amb_meta['amb_range_inside'])}] = " + + _format_int_list(quad_amb_meta["amb_range_inside"]) + + ";" + ) + elif table_kind == "outside": + lines.append("") + lines.append( + "// Ambiguity override ranges: [begin0,end0,begin1,end1] per ambiguous case" + ) + lines.append( + f"constexpr int amb_range_outside[{len(quad_amb_meta['amb_range_outside'])}] = " + + _format_int_list(quad_amb_meta["amb_range_outside"]) + + ";" + ) + elif table_kind == "interface": + lines.append("") + lines.append( + "// Ambiguity override ranges: [begin0,end0,begin1,end1] per ambiguous case" + ) + lines.append( + f"constexpr int amb_range_interface[{len(quad_amb_meta['amb_range_interface'])}] = " + + _format_int_list(quad_amb_meta["amb_range_interface"]) + + ";" + ) + + lines.append("") + lines.append(f"}} // namespace cutcells::cell::{cell_type}") + lines.append("") + lines.append(f"#endif // {guard}") + + path.write_text("\n".join(lines)) + return path + + +def _append_triangle(arrays: Dict[str, List], tokens: List[int]) -> None: + # arrays["sub_element_cell_types"] uses CutCells enum mapping (triangle=2) + arrays["sub_element_cell_types"].append(2) + arrays["sub_element"].append(len(tokens)) + arrays["sub_element"].extend(tokens) + + +def _append_quad(arrays: Dict[str, List], tokens: List[int]) -> None: + # arrays["sub_element_cell_types"] uses CutCells enum mapping (quadrilateral=4) + arrays["sub_element_cell_types"].append(4) + arrays["sub_element"].append(len(tokens)) + arrays["sub_element"].extend(tokens) + + +def _augment_quadrilateral_ambiguity( + table_kind: str, arrays: Dict[str, List] +) -> Dict[str, List] | None: + """Augment quad tables with asymptotic-decider ambiguity variants. + + Variant 0: choose diagonal (0,2) connectivity + Variant 1: choose diagonal (1,3) connectivity + """ + amb_masks = [0b0101, 0b1010] + n_amb = len(amb_masks) + + offsets = arrays["sub_element_offset"] + total_before = len(arrays["sub_element_cell_types"]) + + def case_range(mask: int) -> tuple[int, int]: + return offsets[mask], offsets[mask + 1] + + # Metadata tables (only emitted once in inside header) + case_is_ambiguous_tbl = [0] * 16 + amb_case_id = [-1] * 16 + for amb_id, m in enumerate(amb_masks): + case_is_ambiguous_tbl[m] = 1 + amb_case_id[m] = amb_id + + meta: Dict[str, List] = { + "case_is_ambiguous_tbl": case_is_ambiguous_tbl, + "amb_case_id": amb_case_id, + "amb_range_inside": [], + "amb_range_outside": [], + "amb_range_interface": [], + } + + if table_kind == "interface": + # No new subcells needed; both pairings already exist in base tables. + v0_begin, v0_end = case_range(0b1010) # edges (0,1) and (2,3) + v1_begin, v1_end = case_range(0b0101) # edges (0,3) and (1,2) + for _ in amb_masks: + meta["amb_range_interface"].extend([v0_begin, v0_end, v1_begin, v1_end]) + return meta + + if table_kind == "inside": + # Append connected-region decompositions for both diagonals. + # Connected diagonal (0,2): polygon (V0,E0,E1,V2,E2,E3) split into two quads. + conn_02_begin = len(arrays["sub_element_cell_types"]) + _append_quad(arrays, [100, 0, 1, 102]) + _append_quad(arrays, [100, 102, 2, 3]) + conn_02_end = len(arrays["sub_element_cell_types"]) + + # Connected diagonal (1,3): polygon (V1,E1,E2,V3,E3,E0) split into two quads. + conn_13_begin = len(arrays["sub_element_cell_types"]) + _append_quad(arrays, [101, 1, 2, 103]) + _append_quad(arrays, [101, 103, 3, 0]) + conn_13_end = len(arrays["sub_element_cell_types"]) + + base_05 = case_range(0b0101) + base_10 = case_range(0b1010) + + # For mask 0101, inside vertices lie on diagonal (0,2) + meta["amb_range_inside"].extend( + [conn_02_begin, conn_02_end, base_05[0], base_05[1]] + ) + # For mask 1010, inside vertices lie on diagonal (1,3) + meta["amb_range_inside"].extend( + [base_10[0], base_10[1], conn_13_begin, conn_13_end] + ) + + return meta + + if table_kind == "outside": + # Append disconnected-region triangulations for both diagonals. + # Disconnected diagonal (0,2): triangles at V0 and V2 + disc_02_begin = len(arrays["sub_element_cell_types"]) + for tri in ([100, 0, 3], [102, 1, 2]): + _append_triangle(arrays, tri) + disc_02_end = len(arrays["sub_element_cell_types"]) + + # Disconnected diagonal (1,3): triangles at V1 and V3 + disc_13_begin = len(arrays["sub_element_cell_types"]) + for tri in ([101, 0, 1], [103, 2, 3]): + _append_triangle(arrays, tri) + disc_13_end = len(arrays["sub_element_cell_types"]) + + base_05 = case_range(0b0101) + base_10 = case_range(0b1010) + + # For mask 0101, outside vertices lie on diagonal (1,3) + meta["amb_range_outside"].extend( + [disc_13_begin, disc_13_end, base_05[0], base_05[1]] + ) + # For mask 1010, outside vertices lie on diagonal (0,2) + meta["amb_range_outside"].extend( + [base_10[0], base_10[1], disc_02_begin, disc_02_end] + ) + + return meta + + return None + + +def _extract_subcells_from_flat(arrays: Dict[str, List]) -> Dict: + """Extract subcell data from VTK flat format.""" + sub_element = arrays["sub_element"] + num_subcells = len(arrays["sub_element_cell_types"]) + + subcells = [] + idx = 0 + for _ in range(num_subcells): + nverts = sub_element[idx] + verts = sub_element[idx + 1 : idx + 1 + nverts] + subcells.append(verts) + idx += 1 + nverts + + # Find max vertices + max_verts = max(len(v) for v in subcells) if subcells else 0 + + # Pad with -1 + padded = [] + for verts in subcells: + row = list(verts) + [-1] * (max_verts - len(verts)) + padded.append(row) + + return { + "max_verts_per_subcell": max_verts, + "padded_vertices": padded, + } + + +def emit_all_tet_like( + cell_type: str, + tables_by_kind: Dict[str, Dict[str, List]], + output_dir: Path, + provenance: Optional[str] = None, + vtk_ref: Optional[str] = None, + vtk_header_path: Optional[str] = None, +) -> List[Path]: + """Emit tables in tetrahedron-like format (fixed-width 2D arrays).""" + written: List[Path] = [] + for kind, arrays in tables_by_kind.items(): + written.append( + _emit_tet_like_header( + cell_type, + kind, + arrays, + output_dir, + provenance=provenance, + vtk_ref=vtk_ref, + vtk_header_path=vtk_header_path, + ) + ) + return written diff --git a/tablegen/cutcells_tablegen/normalize.py b/tablegen/cutcells_tablegen/normalize.py new file mode 100644 index 0000000..7e0496e --- /dev/null +++ b/tablegen/cutcells_tablegen/normalize.py @@ -0,0 +1,95 @@ +"""Normalize VTK clip tables to CutCells token streams.""" + +from __future__ import annotations + +from typing import Dict, List, Sequence + +from .topology import num_edges +from .vtk_tables_import import ClipCase, PointRef + +# Mapping matches enum order in cpp/src/cell_types.h +CELL_TYPE_TO_ENUM: Dict[str, int] = { + "point": 0, + "interval": 1, + "triangle": 2, + "tetrahedron": 3, + "quadrilateral": 4, + "hexahedron": 5, + "prism": 6, + "pyramid": 7, +} + + +def token_from_ref(ref: PointRef) -> int: + kind, idx = ref + if kind == "V": + return 100 + idx + if kind == "E": + return idx + if kind == "N": + return 200 + idx + raise ValueError(f"Unsupported point reference: {ref}") + + +def build_intersected_edges(case: ClipCase, num_edges_in_cell: int) -> List[int]: + flags = [0] * num_edges_in_cell + for e in case.intersected_edges: + if e < 0 or e >= num_edges_in_cell: + raise ValueError(f"Edge id {e} outside range 0..{num_edges_in_cell - 1}") + flags[e] = 1 + return flags + + +def normalize_cases(cell_type: str, cases: Sequence[ClipCase]) -> Dict[str, List]: + n_edges = num_edges(cell_type) + + intersected_edges: List[List[int]] = [] + sub_element_offset: List[int] = [0] + sub_element_cell_types: List[int] = [] + sub_element: List[int] = [] + + special_point_count: List[int] = [] + special_point_offset: List[int] = [0] + special_point_data: List[int] = [] + + for case in cases: + intersected_edges.append(build_intersected_edges(case, n_edges)) + + # Special points (e.g. VTK centroid N0) + # Encoding per case: repeated blocks [nrefs, ref0, ref1, ...] + sp_list = list(case.special_points) + sp_list.sort(key=lambda sp: sp.point_id) + special_point_count.append(len(sp_list)) + for sp in sp_list: + # Token for the special point itself is implicit: 200 + sp.point_id + # References must not include other special points. + for ref in sp.refs: + if ref[0] == "N": + raise ValueError("Special point refs must not include 'N' refs") + special_point_data.append(len(sp.refs)) + special_point_data.extend(token_from_ref(r) for r in sp.refs) + special_point_offset.append(len(special_point_data)) + + for emitted in case.cells: + if emitted.cell_type not in CELL_TYPE_TO_ENUM: + raise ValueError(f"Unknown emitted cell type: {emitted.cell_type}") + sub_element_cell_types.append(CELL_TYPE_TO_ENUM[emitted.cell_type]) + sub_element.append(len(emitted.vertices)) + sub_element.extend(token_from_ref(ref) for ref in emitted.vertices) + + sub_element_offset.append(len(sub_element_cell_types)) + + out = { + "intersected_edges": intersected_edges, + "sub_element_offset": sub_element_offset, + "sub_element_cell_types": sub_element_cell_types, + "sub_element": sub_element, + "extra_coords": [], # placeholder; fill if Steiner points are added later + } + + if any(c > 0 for c in special_point_count): + out["special_point_count"] = special_point_count + out["special_point_offset"] = special_point_offset + out["special_point_data"] = special_point_data + + return out diff --git a/tablegen/cutcells_tablegen/topology.py b/tablegen/cutcells_tablegen/topology.py new file mode 100644 index 0000000..4c2dc3f --- /dev/null +++ b/tablegen/cutcells_tablegen/topology.py @@ -0,0 +1,99 @@ +"""VTK-consistent topology helpers for CutCells table generation.""" + +from __future__ import annotations + +from dataclasses import dataclass +from typing import List, Tuple + + +@dataclass(frozen=True) +class CellTopology: + name: str + num_vertices: int + edges: Tuple[Tuple[int, int], ...] + + +# VTK edge numbering (matches cut_tetrahedron conventions already used elsewhere). +CELL_TOPOLOGY = { + "quadrilateral": CellTopology( + name="quadrilateral", + num_vertices=4, + edges=((0, 1), (1, 2), (2, 3), (3, 0)), + ), + "hexahedron": CellTopology( + name="hexahedron", + num_vertices=8, + edges=( + (0, 1), # 0 + (1, 2), # 1 + (2, 3), # 2 + (3, 0), # 3 + (4, 5), # 4 + (5, 6), # 5 + (6, 7), # 6 + (7, 4), # 7 + (0, 4), # 8 + (1, 5), # 9 + # NOTE: VTK's TableBasedClipCases.h uses (3,7) as edge 10 and (2,6) as edge 11 + # for VTK_HEXAHEDRON (see vtkTableBasedClipCasesBase::CellEdges). + (3, 7), # 10 + (2, 6), # 11 + ), + ), + "prism": CellTopology( + name="prism", + num_vertices=6, + edges=( + (0, 1), # 0 + (1, 2), # 1 + (2, 0), # 2 + (3, 4), # 3 + (4, 5), # 4 + (5, 3), # 5 + (0, 3), # 6 + (1, 4), # 7 + (2, 5), # 8 + ), + ), + "pyramid": CellTopology( + name="pyramid", + num_vertices=5, + edges=( + (0, 1), # 0 + (1, 2), # 1 + (2, 3), # 2 + (3, 0), # 3 + (0, 4), # 4 + (1, 4), # 5 + (2, 4), # 6 + (3, 4), # 7 + ), + ), +} + + +def get_topology(cell_type: str) -> CellTopology: + topo = CELL_TOPOLOGY.get(cell_type) + if topo is None: + raise ValueError(f"Unsupported cell type: {cell_type}") + return topo + + +def edge_endpoints(cell_type: str) -> Tuple[Tuple[int, int], ...]: + return get_topology(cell_type).edges + + +def num_vertices(cell_type: str) -> int: + return get_topology(cell_type).num_vertices + + +def num_edges(cell_type: str) -> int: + return len(get_topology(cell_type).edges) + + +def edge_count(cell_type: str) -> int: + return num_edges(cell_type) + + +def supported_cell_types() -> List[str]: + return list(CELL_TOPOLOGY.keys()) diff --git a/tablegen/cutcells_tablegen/vtk_tablebasedclip_parser.py b/tablegen/cutcells_tablegen/vtk_tablebasedclip_parser.py new file mode 100644 index 0000000..f2b718d --- /dev/null +++ b/tablegen/cutcells_tablegen/vtk_tablebasedclip_parser.py @@ -0,0 +1,274 @@ +"""Parse VTK TableBasedClip case tables. + +This module is intentionally lightweight: it only extracts the VTK_HEXAHEDRON +case stream from VTK's `Filters/General/vtkTableBasedClipCases.h`. + +We do not depend on VTK headers/libraries; instead we parse the published +header text (either from a local file path or downloaded URL). + +The extracted structure is converted into CutCells tablegen `ClipCase` objects. + +License/provenance: + The case tables parsed by this module are derived from VTK's + `Filters/General/vtkTableBasedClipCases.h`. + VTK is licensed under the BSD 3-Clause license; see + `third_party/VTK-Copyright.txt` in this repository. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from typing import List, Sequence + +import os +import re +import urllib.request + + +_VTK_DEFAULT_URL = "https://raw.githubusercontent.com/Kitware/VTK/{ref}/Filters/General/vtkTableBasedClipCases.h" + + +@dataclass(frozen=True) +class VtkCaseRecord: + case_id: int + items: Sequence[Sequence[str]] + # Each item is a token list: [ST_*, n, p0, p1, ...] + + +def _strip_comments(text: str) -> str: + # Remove /* ... */ comments and // line comments + text = re.sub(r"/\*.*?\*/", " ", text, flags=re.DOTALL) + text = re.sub(r"//.*?$", " ", text, flags=re.MULTILINE) + return text + + +def _read_header_text(path: str | None, ref: str) -> str: + if path: + with open(path, "r", encoding="utf-8") as f: + return f.read() + + url = _VTK_DEFAULT_URL.format(ref=ref) + with urllib.request.urlopen(url) as resp: + return resp.read().decode("utf-8") + + +def _find_hex_block(text: str) -> str: + # VTK's header contains multiple hexahedron-related tables *and* several + # earlier occurrences of the string "VTK_HEXAHEDRON" (e.g. in topology + # comments). We must select the actual hexahedron case stream inside the + # big CellCases array. + # + # Robust approach: + # - search for the *case table marker* line: "// VTK_HEXAHEDRON" + # - require it to be followed by the 256-case stream starting at + # "/* case 0 */ 0," + # - validate a couple of hexahedron-specific signatures to avoid matching + # other tables. + marker_pat = re.compile(r"\n\s*//\s*VTK_HEXAHEDRON\s*\n") + + # Signature checks within the hexahedron volume clip case stream. + case0_pat = re.compile(r"/\*\s*case\s*0\s*\*/\s*(\d+)\s*,") + case1_sig = re.compile( + r"/\*\s*case\s*1\s*\*/\s*1\s*,\s*ST_TET\s*,\s*4\s*,\s*P0\s*,\s*EA\s*,\s*ED\s*,\s*EI\s*," + ) + # A second signature that differs between various hex-related tables. + # In the VTK_HEXAHEDRON clip table, case 153 is a single hex: + # ST_HEX, 8, EA, EE, EG, EC, P0, P4, P7, P3 + case153_sig = re.compile( + r"/\*\s*case\s*153\s*\*/\s*1\s*,\s*ST_HEX\s*,\s*8\s*,\s*EA\s*,\s*EE\s*,\s*EG\s*,\s*EC\s*,\s*P0\s*,\s*P4\s*,\s*P7\s*,\s*P3\s*," + ) + + for m in marker_pat.finditer(text): + # Look ahead; the full 256-case table is large. + window = text[m.end() : m.end() + 250000] + + m0 = case0_pat.search(window) + if not m0 or m0.group(1) != "0": + continue + + # Bind signatures to the specific candidate stream. + tail = window[m0.start() : m0.start() + 60000] + if not case1_sig.search(tail): + continue + if not case153_sig.search(tail): + continue + + # Important: later we strip comments before tokenizing; the "// VTK_*" + # marker would be removed, so we return a slice starting exactly at the + # numeric case stream (the count following "/* case 0 */"). + start = m.end() + m0.start(1) + return text[start : start + 250000] + + raise RuntimeError( + "Could not locate the VTK_HEXAHEDRON clip case stream (expected '/* case 0 */ 0' and known signatures)" + ) + + +def _tokenize_case_block(block: str) -> List[str]: + # Keep identifiers like ST_TET, P0, EA, N0 and integers. + # Strip comments first to avoid commas in comments. + block = _strip_comments(block) + + # Reduce to comma-separated tokens. + tokens = [t.strip() for t in block.split(",")] + return [t for t in tokens if t] + + +def _parse_cases_from_tokens(tokens: Sequence[str]) -> List[VtkCaseRecord]: + # The provided token stream is expected to start at the numeric case stream + # (i.e. the count for case 0). Parse n cases sequentially. + return _parse_n_cases_from_tokens(tokens, 256) + + +def _parse_n_cases_from_tokens( + tokens: Sequence[str], n_cases: int +) -> List[VtkCaseRecord]: + i = 0 + if i >= len(tokens) or not re.fullmatch(r"\d+", tokens[i]): + raise RuntimeError("Token stream does not start with a case count") + + cases: List[VtkCaseRecord] = [] + for case_id in range(n_cases): + if i >= len(tokens): + raise RuntimeError(f"Unexpected end of tokens while parsing case {case_id}") + n_items = int(tokens[i]) + i += 1 + + items: List[List[str]] = [] + for _ in range(n_items): + st = tokens[i] + i += 1 + n = int(tokens[i]) + i += 1 + pts = list(tokens[i : i + n]) + i += n + items.append([st, str(n), *pts]) + + cases.append(VtkCaseRecord(case_id=case_id, items=tuple(items))) + + return cases + + +def load_hexahedron_cases( + *, + vtk_header_path: str | None = None, + vtk_ref: str | None = None, +) -> List[VtkCaseRecord]: + """Load VTK_HEXAHEDRON case records. + + If `vtk_header_path` is not provided, the header is downloaded from GitHub. + + Environment variables: + - CUT_CELLS_VTK_HEADER: local path override + - CUT_CELLS_VTK_REF: Git ref (default: master) + """ + + if vtk_header_path is None: + vtk_header_path = os.environ.get("CUT_CELLS_VTK_HEADER") + if vtk_ref is None: + vtk_ref = os.environ.get("CUT_CELLS_VTK_REF", "master") + + text = _read_header_text(vtk_header_path, vtk_ref) + block = _find_hex_block(text) + tokens = _tokenize_case_block(block) + return _parse_n_cases_from_tokens(tokens, 256) + + +def _find_wedge_block(text: str) -> str: + # Select the VTK_WEDGE case stream inside the CellCases array. + marker_pat = re.compile(r"\n\s*//\s*VTK_WEDGE\s*\n") + + case0_pat = re.compile(r"/\*\s*case\s*0\s*\*/\s*(\d+)\s*,") + # Signature anchored to the wedge case table: case 1 is a tet containing P0 + # and the three edge points around vertex 0. + case1_sig = re.compile( + r"/\*\s*case\s*1\s*\*/\s*1\s*,\s*ST_TET\s*,\s*4\s*,\s*EG\s*,\s*EA\s*,\s*EC\s*,\s*P0\s*," + ) + case63_sig = re.compile(r"/\*\s*case\s*63\s*\*/") + + for m in marker_pat.finditer(text): + window = text[m.end() : m.end() + 80000] + m0 = case0_pat.search(window) + if not m0 or m0.group(1) != "0": + continue + + # Bind checks to the candidate stream. + tail = window[m0.start() : m0.start() + 20000] + if not case1_sig.search(tail): + continue + if not case63_sig.search(tail): + continue + + start = m.end() + m0.start(1) + return text[start : start + 80000] + + raise RuntimeError( + "Could not locate the VTK_WEDGE clip case stream (expected '/* case 0 */ 0' and known signatures)" + ) + + +def load_wedge_cases( + *, + vtk_header_path: str | None = None, + vtk_ref: str | None = None, +) -> List[VtkCaseRecord]: + """Load VTK_WEDGE (prism) case records (64 cases).""" + + if vtk_header_path is None: + vtk_header_path = os.environ.get("CUT_CELLS_VTK_HEADER") + if vtk_ref is None: + vtk_ref = os.environ.get("CUT_CELLS_VTK_REF", "master") + + text = _read_header_text(vtk_header_path, vtk_ref) + block = _find_wedge_block(text) + tokens = _tokenize_case_block(block) + return _parse_n_cases_from_tokens(tokens, 64) + + +def _find_pyramid_block(text: str) -> str: + # Select the VTK_PYRAMID case stream inside the CellCases array. + marker_pat = re.compile(r"\n\s*//\s*VTK_PYRAMID\s*\n") + + case0_pat = re.compile(r"/\*\s*case\s*0\s*\*/\s*(\d+)\s*,") + # Pyramid signature: case 1 is a tet containing P0 and the three edge points around vertex 0. + case1_sig = re.compile( + r"/\*\s*case\s*1\s*\*/\s*1\s*,\s*ST_TET\s*,\s*4\s*,\s*P0\s*,\s*EA\s*,\s*ED\s*,\s*EE\s*," + ) + case31_sig = re.compile(r"/\*\s*case\s*31\s*\*/") + + for m in marker_pat.finditer(text): + window = text[m.end() : m.end() + 120000] + m0 = case0_pat.search(window) + if not m0 or m0.group(1) != "0": + continue + + tail = window[m0.start() : m0.start() + 30000] + if not case1_sig.search(tail): + continue + if not case31_sig.search(tail): + continue + + start = m.end() + m0.start(1) + return text[start : start + 120000] + + raise RuntimeError( + "Could not locate the VTK_PYRAMID clip case stream (expected '/* case 0 */ 0' and known signatures)" + ) + + +def load_pyramid_cases( + *, + vtk_header_path: str | None = None, + vtk_ref: str | None = None, +) -> List[VtkCaseRecord]: + """Load VTK_PYRAMID case records (32 cases).""" + + if vtk_header_path is None: + vtk_header_path = os.environ.get("CUT_CELLS_VTK_HEADER") + if vtk_ref is None: + vtk_ref = os.environ.get("CUT_CELLS_VTK_REF", "master") + + text = _read_header_text(vtk_header_path, vtk_ref) + block = _find_pyramid_block(text) + tokens = _tokenize_case_block(block) + return _parse_n_cases_from_tokens(tokens, 32) diff --git a/tablegen/cutcells_tablegen/vtk_tables_import.py b/tablegen/cutcells_tablegen/vtk_tables_import.py new file mode 100644 index 0000000..c58207d --- /dev/null +++ b/tablegen/cutcells_tablegen/vtk_tables_import.py @@ -0,0 +1,660 @@ +"""Adapters for VTK TableBasedClip tables. + +Populate the stubs with canonical VTK connectivity to regenerate CutCells tables. + +License/provenance: + The clip/cut case tables used here are derived from VTK's + `Filters/General/vtkTableBasedClipCases.h`. + VTK is licensed under the BSD 3-Clause license; see + `third_party/VTK-Copyright.txt` in this repository. +""" + +from __future__ import annotations + +from dataclasses import dataclass +from typing import List, Literal, Sequence, Tuple + +import re + +from .topology import edge_endpoints + +PointRef = Tuple[Literal["V", "E", "N"], int] + + +@dataclass(frozen=True) +class SpecialPoint: + # Currently only VTK's centroid point N0 is expected. + point_id: int + refs: Tuple[PointRef, ...] + + +@dataclass(frozen=True) +class EmittedCell: + cell_type: str + vertices: Tuple[PointRef, ...] + + +@dataclass(frozen=True) +class ClipCase: + intersected_edges: Tuple[int, ...] + cells: Tuple[EmittedCell, ...] + special_points: Tuple[SpecialPoint, ...] = () + + +TableKind = Literal["inside", "outside", "interface"] + + +@dataclass(frozen=True) +class ClipTables: + inside: List[ClipCase] + outside: List[ClipCase] + interface: List[ClipCase] + + +# TODO: replace stubs with actual VTK TableBasedClip data for each cell type. +VTK_TABLES: dict[str, ClipTables] = {} + + +def register_tables(cell_type: str, tables: ClipTables) -> None: + VTK_TABLES[cell_type] = tables + + +def get_tables(cell_type: str) -> ClipTables: + tables = VTK_TABLES.get(cell_type) + if tables is None: + raise NotImplementedError( + f"VTK TableBasedClip data for '{cell_type}' not registered yet" + ) + return tables + + +def get_cases(cell_type: str, table_kind: TableKind) -> List[ClipCase]: + tables = get_tables(cell_type) + if table_kind == "inside": + return tables.inside + if table_kind == "outside": + return tables.outside + if table_kind == "interface": + return tables.interface + raise ValueError(f"Unknown table kind: {table_kind}") + + +def registered_cell_types() -> List[str]: + return list(VTK_TABLES.keys()) + + +# --- Hexahedron TableBasedClip (VTK header parse) ------------------------- + + +def _intersected_edges_from_mask(cell_type: str, mask: int) -> Tuple[int, ...]: + edges = edge_endpoints(cell_type) + out: List[int] = [] + for eid, (a, b) in enumerate(edges): + sa = (mask >> a) & 1 + sb = (mask >> b) & 1 + if sa != sb: + out.append(eid) + return tuple(out) + + +def _vtk_name_to_point_ref(name: str) -> PointRef: + # Vertices + if re.fullmatch(r"P[0-7]", name): + return ("V", int(name[1])) + + # Edges for hex: EA..EL correspond to 12 edges, contiguous. + if re.fullmatch(r"E[A-L]", name): + return ("E", ord(name[1]) - ord("A")) + + # Centroid + if name == "N0": + return ("N", 0) + + raise ValueError(f"Unsupported VTK point name: {name}") + + +def _vtk_st_to_cell_type(st: str) -> str: + # We only need 3D volume cell types here. + if st == "ST_TET": + return "tetrahedron" + if st == "ST_PYR": + return "pyramid" + if st == "ST_WDG": + return "prism" + if st == "ST_HEX": + return "hexahedron" + if st == "ST_PNT": + return "__point__" + # VTK tables sometimes contain lower-dimensional primitives (e.g. vertex-only + # artifacts) that are not representable in CutCells' volume tables. + if st in {"ST_VTX", "ST_LN", "ST_LIN", "ST_TRI", "ST_QUA", "ST_POLY"}: + return "__skip__" + raise ValueError(f"Unsupported VTK shape token: {st}") + + +def _faces_for_cell(cell_type: str) -> Tuple[Tuple[int, ...], ...]: + # Face templates in VTK point ordering. + if cell_type == "tetrahedron": + return ((0, 1, 2), (0, 3, 1), (1, 3, 2), (0, 2, 3)) + if cell_type == "pyramid": + return ((0, 1, 2, 3), (0, 4, 1), (1, 4, 2), (2, 4, 3), (3, 4, 0)) + if cell_type == "prism": + return ((0, 1, 2), (3, 5, 4), (0, 3, 4, 1), (1, 4, 5, 2), (2, 5, 3, 0)) + if cell_type == "hexahedron": + return ( + (0, 1, 2, 3), + (4, 7, 6, 5), + (0, 4, 5, 1), + (1, 5, 6, 2), + (2, 6, 7, 3), + (3, 7, 4, 0), + ) + raise ValueError(f"Unsupported cell type for face extraction: {cell_type}") + + +def _derive_interface_case_from_inside(inside: ClipCase) -> ClipCase: + # Collect boundary faces from inside volume cells. + face_counts: dict[Tuple[int, ...], int] = {} + face_oriented: dict[Tuple[int, ...], Tuple[PointRef, ...]] = {} + + def key_for_face(face: Sequence[PointRef]) -> Tuple[int, ...]: + # Stable key: sort by a numeric encoding of PointRef. + def enc(ref: PointRef) -> int: + kind, idx = ref + if kind == "E": + return idx + if kind == "V": + return 100 + idx + if kind == "N": + return 200 + idx + raise ValueError(ref) + + return tuple(sorted(enc(r) for r in face)) + + for cell in inside.cells: + templ = _faces_for_cell(cell.cell_type) + for f in templ: + face = tuple(cell.vertices[i] for i in f) + k = key_for_face(face) + face_counts[k] = face_counts.get(k, 0) + 1 + face_oriented.setdefault(k, face) + + iface_cells: List[EmittedCell] = [] + for k, count in face_counts.items(): + if count != 1: + continue + face = face_oriented[k] + + # In the generic (phi!=0) case, interface faces should contain no original vertices. + if any(kind == "V" for (kind, _) in face): + continue + + if len(face) == 3: + iface_cells.append(EmittedCell(cell_type="triangle", vertices=face)) + elif len(face) == 4: + iface_cells.append(EmittedCell(cell_type="quadrilateral", vertices=face)) + + # Only keep special points if referenced by interface faces. + used_special: set[PointRef] = set() + for c in iface_cells: + for r in c.vertices: + if r[0] == "N": + used_special.add(r) + special_points = tuple( + sp for sp in inside.special_points if ("N", sp.point_id) in used_special + ) + + return ClipCase( + intersected_edges=inside.intersected_edges, + cells=tuple(iface_cells), + special_points=special_points, + ) + + +def _build_hexahedron_tables() -> ClipTables: + """Build hexahedron tables by parsing VTK's published case tables. + + This supports VTK's centroid point (ST_PNT -> N0) by storing its defining + references in `ClipCase.special_points`. + """ + + from .vtk_tablebasedclip_parser import load_hexahedron_cases + + inside_cases: List[ClipCase] = [] + + vtk_cases = load_hexahedron_cases() + if len(vtk_cases) != 256: + raise RuntimeError(f"Expected 256 hexahedron cases, got {len(vtk_cases)}") + + for case_id, vtk_case in enumerate(vtk_cases): + if case_id != vtk_case.case_id: + raise RuntimeError("Case ids not sequential") + + special_points: List[SpecialPoint] = [] + emitted: List[EmittedCell] = [] + + for item in vtk_case.items: + st = item[0] + n = int(item[1]) + pts = item[2:] + if len(pts) != n: + raise RuntimeError("Malformed case item") + + cell_type = _vtk_st_to_cell_type(st) + if cell_type == "__skip__": + continue + + if cell_type == "__point__": + # Define N0 as an unweighted average (duplicates => weights). + refs = tuple(_vtk_name_to_point_ref(p) for p in pts) + special_points.append(SpecialPoint(point_id=0, refs=refs)) + continue + + verts = tuple(_vtk_name_to_point_ref(p) for p in pts) + emitted.append(EmittedCell(cell_type=cell_type, vertices=verts)) + + # Derive intersected edges from the actual VTK case stream. + # + # Rationale: VTK's hexahedron case index does not appear to map 1:1 to a + # simple vertex-bitmask in P0..P7 order (e.g. case 188 references EL, but + # a naive mask-based edge test would miss it). By collecting all edge + # references used by the emitted volume cells (and by special-point + # definitions), we guarantee runtime will create every intersection token + # that the tables may reference. + used_edges: set[int] = set() + for cell in emitted: + for kind, idx in cell.vertices: + if kind == "E": + used_edges.add(idx) + for sp in special_points: + for kind, idx in sp.refs: + if kind == "E": + used_edges.add(idx) + + inside_cases.append( + ClipCase( + intersected_edges=tuple(sorted(used_edges)), + cells=tuple(emitted), + special_points=tuple(special_points), + ) + ) + + # Outside is just the inside of the complemented mask. + outside_cases = [inside_cases[mask ^ 0xFF] for mask in range(256)] + + # Interface faces derived from inside volume boundary. + interface_cases = [_derive_interface_case_from_inside(c) for c in inside_cases] + + return ClipTables( + inside=inside_cases, + outside=outside_cases, + interface=interface_cases, + ) + + +def _build_prism_tables() -> ClipTables: + """Build prism (VTK_WEDGE) tables by parsing VTK's published case tables. + + Like the hexahedron tables, this supports VTK's centroid point (ST_PNT -> N0) + by storing its defining references in `ClipCase.special_points`. + """ + + from .vtk_tablebasedclip_parser import load_wedge_cases + + inside_cases: List[ClipCase] = [] + + vtk_cases = load_wedge_cases() + if len(vtk_cases) != 64: + raise RuntimeError(f"Expected 64 wedge cases, got {len(vtk_cases)}") + + for case_id, vtk_case in enumerate(vtk_cases): + if case_id != vtk_case.case_id: + raise RuntimeError("Case ids not sequential") + + special_points: List[SpecialPoint] = [] + emitted: List[EmittedCell] = [] + + for item in vtk_case.items: + st = item[0] + n = int(item[1]) + pts = item[2:] + if len(pts) != n: + raise RuntimeError("Malformed case item") + + cell_type = _vtk_st_to_cell_type(st) + if cell_type == "__skip__": + continue + + if cell_type == "__point__": + refs = tuple(_vtk_name_to_point_ref(p) for p in pts) + special_points.append(SpecialPoint(point_id=0, refs=refs)) + continue + + verts = tuple(_vtk_name_to_point_ref(p) for p in pts) + emitted.append(EmittedCell(cell_type=cell_type, vertices=verts)) + + used_edges: set[int] = set() + for cell in emitted: + for kind, idx in cell.vertices: + if kind == "E": + used_edges.add(idx) + for sp in special_points: + for kind, idx in sp.refs: + if kind == "E": + used_edges.add(idx) + + # Sanity: wedge has 9 edges (EA..EI). If we ever see larger edge ids, + # it likely indicates we parsed the wrong table block. + if any(eid >= 9 for eid in used_edges): + raise RuntimeError( + f"Wedge table references invalid edge id(s): {sorted(used_edges)}" + ) + + inside_cases.append( + ClipCase( + intersected_edges=tuple(sorted(used_edges)), + cells=tuple(emitted), + special_points=tuple(special_points), + ) + ) + + # Outside is just the inside of the complemented mask. + outside_cases = [inside_cases[mask ^ 0x3F] for mask in range(64)] + + # Interface faces derived from inside volume boundary. + interface_cases = [_derive_interface_case_from_inside(c) for c in inside_cases] + + return ClipTables( + inside=inside_cases, + outside=outside_cases, + interface=interface_cases, + ) + + +def _build_pyramid_tables() -> ClipTables: + """Build pyramid (VTK_PYRAMID) tables by parsing VTK's published case tables. + + Like the hexahedron/prism tables, this supports VTK's centroid point + (ST_PNT -> N0) by storing its defining references in `ClipCase.special_points`. + """ + + from .vtk_tablebasedclip_parser import load_pyramid_cases + + inside_cases: List[ClipCase] = [] + + vtk_cases = load_pyramid_cases() + if len(vtk_cases) != 32: + raise RuntimeError(f"Expected 32 pyramid cases, got {len(vtk_cases)}") + + for case_id, vtk_case in enumerate(vtk_cases): + if case_id != vtk_case.case_id: + raise RuntimeError("Case ids not sequential") + + special_points: List[SpecialPoint] = [] + emitted: List[EmittedCell] = [] + + for item in vtk_case.items: + st = item[0] + n = int(item[1]) + pts = item[2:] + if len(pts) != n: + raise RuntimeError("Malformed case item") + + cell_type = _vtk_st_to_cell_type(st) + if cell_type == "__skip__": + continue + + if cell_type == "__point__": + refs = tuple(_vtk_name_to_point_ref(p) for p in pts) + special_points.append(SpecialPoint(point_id=0, refs=refs)) + continue + + verts = tuple(_vtk_name_to_point_ref(p) for p in pts) + emitted.append(EmittedCell(cell_type=cell_type, vertices=verts)) + + used_edges: set[int] = set() + for cell in emitted: + for kind, idx in cell.vertices: + if kind == "E": + used_edges.add(idx) + for sp in special_points: + for kind, idx in sp.refs: + if kind == "E": + used_edges.add(idx) + + # Sanity: pyramid has 8 edges (EA..EH) + if any(eid >= 8 for eid in used_edges): + raise RuntimeError( + f"Pyramid table references invalid edge id(s): {sorted(used_edges)}" + ) + + inside_cases.append( + ClipCase( + intersected_edges=tuple(sorted(used_edges)), + cells=tuple(emitted), + special_points=tuple(special_points), + ) + ) + + # Outside is just the inside of the complemented mask. + outside_cases = [inside_cases[mask ^ 0x1F] for mask in range(32)] + + # Interface faces derived from inside volume boundary. + interface_cases = [_derive_interface_case_from_inside(c) for c in inside_cases] + + return ClipTables( + inside=inside_cases, + outside=outside_cases, + interface=interface_cases, + ) + + +# --- Quadrilateral TableBasedClip (marching squares style) ----------------- + + +def _mask_bits(mask: int) -> List[bool]: + return [(mask >> i) & 1 == 1 for i in range(4)] + + +def _intersected_edges(mask: int) -> Tuple[int, ...]: + inside = _mask_bits(mask) + edges = [] + for e, (v0, v1) in enumerate(edge_endpoints("quadrilateral")): + if inside[v0] != inside[v1]: + edges.append(e) + return tuple(edges) + + +def _polygon_for_mask(mask: int) -> List[PointRef]: + inside = _mask_bits(mask) + poly: List[PointRef] = [] + for i in range(4): + if inside[i]: + poly.append(("V", i)) + j = (i + 1) % 4 + if inside[i] != inside[j]: + poly.append(("E", i)) + return poly + + +def _triangulate(poly: List[PointRef]) -> List[EmittedCell]: + if len(poly) < 3: + return [] + if len(poly) == 3: + return [EmittedCell(cell_type="triangle", vertices=tuple(poly))] + if len(poly) == 4: + return [EmittedCell(cell_type="quadrilateral", vertices=tuple(poly))] + # fan triangulation for n>4 + tris: List[EmittedCell] = [] + anchor = poly[0] + for i in range(1, len(poly) - 1): + tris.append( + EmittedCell(cell_type="triangle", vertices=(anchor, poly[i], poly[i + 1])) + ) + return tris + + +def _build_inside_case(mask: int) -> ClipCase: + inside = _mask_bits(mask) + inside_count = sum(inside) + edges = _intersected_edges(mask) + + cells: List[EmittedCell] = [] + + if inside_count == 0: + return ClipCase(intersected_edges=edges, cells=tuple(cells)) + + if inside_count == 4: + cells.append( + EmittedCell( + cell_type="quadrilateral", + vertices=(("V", 0), ("V", 1), ("V", 2), ("V", 3)), + ) + ) + return ClipCase(intersected_edges=edges, cells=tuple(cells)) + + if inside_count == 3: + # Split pentagon into triangle + quad using diagonal from outside corner to opposite + outside_vertex = next(i for i, flag in enumerate(inside) if not flag) + prev_vertex = (outside_vertex + 3) % 4 + next_vertex = (outside_vertex + 1) % 4 + opp_vertex = (outside_vertex + 2) % 4 + edge_prev = prev_vertex + edge_next = outside_vertex + + cells.append( + EmittedCell( + cell_type="triangle", + vertices=(("E", edge_next), ("V", next_vertex), ("V", opp_vertex)), + ) + ) + cells.append( + EmittedCell( + cell_type="quadrilateral", + vertices=( + ("E", edge_next), + ("V", opp_vertex), + ("V", prev_vertex), + ("E", edge_prev), + ), + ) + ) + return ClipCase(intersected_edges=edges, cells=tuple(cells)) + + # Opposite corners: emit two disjoint triangles to avoid ambiguity + if mask == 0b0101: + cells.append( + EmittedCell(cell_type="triangle", vertices=(("V", 0), ("E", 0), ("E", 3))) + ) + cells.append( + EmittedCell(cell_type="triangle", vertices=(("V", 2), ("E", 1), ("E", 2))) + ) + return ClipCase(intersected_edges=edges, cells=tuple(cells)) + + if mask == 0b1010: + cells.append( + EmittedCell(cell_type="triangle", vertices=(("V", 1), ("E", 1), ("E", 0))) + ) + cells.append( + EmittedCell(cell_type="triangle", vertices=(("V", 3), ("E", 3), ("E", 2))) + ) + return ClipCase(intersected_edges=edges, cells=tuple(cells)) + + poly = _polygon_for_mask(mask) + cells.extend(_triangulate(poly)) + return ClipCase(intersected_edges=edges, cells=tuple(cells)) + + +def _build_outside_case(mask: int) -> ClipCase: + # Ambiguous opposite-corner cases: emit outside as two quads (hex split) + if mask == 0b0101: + # inside corners: v0, v2; outside polygon (hex) order: V1, E1, E2, V3, E3, E0 + cells = ( + EmittedCell( + cell_type="quadrilateral", + vertices=(("V", 1), ("E", 1), ("E", 2), ("V", 3)), + ), + EmittedCell( + cell_type="quadrilateral", + vertices=(("V", 3), ("E", 3), ("E", 0), ("V", 1)), + ), + ) + return ClipCase(intersected_edges=_intersected_edges(mask), cells=cells) + + if mask == 0b1010: + # inside corners: v1, v3; outside hex order: V0, E0, E1, V2, E2, E3 + cells = ( + EmittedCell( + cell_type="quadrilateral", + vertices=(("V", 0), ("E", 0), ("E", 1), ("V", 2)), + ), + EmittedCell( + cell_type="quadrilateral", + vertices=(("V", 2), ("E", 2), ("E", 3), ("V", 0)), + ), + ) + return ClipCase(intersected_edges=_intersected_edges(mask), cells=cells) + + # For general cases, use phi>0 polygon (complement of inside mask). + # Invert the mask to get the outside region + return _build_inside_case(mask ^ 0b1111) + + +def _build_interface_case(mask: int) -> ClipCase: + edges = _intersected_edges(mask) + cells: List[EmittedCell] = [] + + if len(edges) == 0: + return ClipCase(intersected_edges=edges, cells=tuple(cells)) + + # Opposite corners -> two disjoint segments + if mask == 0b0101: + cells.append(EmittedCell(cell_type="interval", vertices=(("E", 0), ("E", 3)))) + cells.append(EmittedCell(cell_type="interval", vertices=(("E", 1), ("E", 2)))) + return ClipCase(intersected_edges=edges, cells=tuple(cells)) + + if mask == 0b1010: + cells.append(EmittedCell(cell_type="interval", vertices=(("E", 0), ("E", 1)))) + cells.append(EmittedCell(cell_type="interval", vertices=(("E", 2), ("E", 3)))) + return ClipCase(intersected_edges=edges, cells=tuple(cells)) + + # All other cases: single segment connecting the two intersection edges in order + if len(edges) == 2: + cells.append( + EmittedCell( + cell_type="interval", vertices=(("E", edges[0]), ("E", edges[1])) + ) + ) + else: + # Should not happen for marching squares, fallback to empty + cells = [] + + return ClipCase(intersected_edges=edges, cells=tuple(cells)) + + +def _build_quadrilateral_tables() -> ClipTables: + inside_cases: List[ClipCase] = [] + outside_cases: List[ClipCase] = [] + interface_cases: List[ClipCase] = [] + + for mask in range(16): + inside_cases.append(_build_inside_case(mask)) + outside_cases.append(_build_outside_case(mask)) + interface_cases.append(_build_interface_case(mask)) + + return ClipTables( + inside=inside_cases, outside=outside_cases, interface=interface_cases + ) + + +# Register quad tables eagerly +register_tables("quadrilateral", _build_quadrilateral_tables()) + +# Register hex tables eagerly (requires VTK at runtime) +register_tables("hexahedron", _build_hexahedron_tables()) + +# Register prism (wedge) tables eagerly (requires VTK at runtime) +register_tables("prism", _build_prism_tables()) + +# Register pyramid tables eagerly (requires VTK at runtime) +register_tables("pyramid", _build_pyramid_tables()) diff --git a/tablegen/scripts/gen_tables.py b/tablegen/scripts/gen_tables.py new file mode 100644 index 0000000..43673fa --- /dev/null +++ b/tablegen/scripts/gen_tables.py @@ -0,0 +1,113 @@ +"""Generate CutCells clip tables (tetrahedron-like format). + +Usage: + conda activate fenicsx-dev + python tablegen/scripts/gen_tables.py --cell-type quadrilateral + +Generates tables in tet-like format (fixed-width 2D arrays with -1 padding) +instead of VTK's variable-length format. +Default output: cpp/src/generated/ +""" + +from __future__ import annotations + +import argparse +import os +from pathlib import Path +import sys + +# Allow running this script without installing the tablegen package +_THIS_DIR = Path(__file__).resolve().parent +_TABLEGEN_ROOT = _THIS_DIR.parent +sys.path.insert(0, str(_TABLEGEN_ROOT)) + + +_VTK_DERIVED_CELL_TYPES = {"hexahedron", "prism", "pyramid"} + + +def _import_tablegen(): + # Import after we potentially set CUT_CELLS_VTK_REF/CUT_CELLS_VTK_HEADER + # so vtk_tables_import loads tables from the intended VTK source. + from cutcells_tablegen.emit_c_headers import emit_all_tet_like + from cutcells_tablegen.normalize import normalize_cases + from cutcells_tablegen.vtk_tables_import import get_cases, registered_cell_types + + return emit_all_tet_like, normalize_cases, get_cases, registered_cell_types + + +def generate_for_cell( + cell_type: str, + out_dir: Path, + vtk_ref: str | None, + vtk_header_path: str | None, +) -> None: + emit_all_tet_like, normalize_cases, get_cases, _ = _import_tablegen() + + tables = {} + for kind in ("inside", "outside", "interface"): + cases = get_cases(cell_type, kind) + tables[kind] = normalize_cases(cell_type, cases) + provenance = "vtk" if cell_type in _VTK_DERIVED_CELL_TYPES else None + emit_all_tet_like( + cell_type, + tables, + out_dir, + provenance=provenance, + vtk_ref=vtk_ref if provenance == "vtk" else None, + vtk_header_path=vtk_header_path if provenance == "vtk" else None, + ) + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Generate CutCells clip tables (tet-like format)" + ) + parser.add_argument( + "--cell-type", + nargs="*", + default=None, + help="Cell types to generate (default: all registered types)", + ) + parser.add_argument( + "--out", + type=Path, + default=Path("cpp/src/generated"), + help="Output directory for generated headers", + ) + parser.add_argument( + "--vtk-ref", + default=None, + help="VTK git ref/tag/commit to download vtkTableBasedClipCases.h from (default: env CUT_CELLS_VTK_REF or 'master')", + ) + parser.add_argument( + "--vtk-header-path", + default=None, + help="Local path to vtkTableBasedClipCases.h (default: env CUT_CELLS_VTK_HEADER)", + ) + return parser.parse_args() + + +def main() -> None: + args = parse_args() + + if args.vtk_ref is not None: + os.environ["CUT_CELLS_VTK_REF"] = str(args.vtk_ref) + if args.vtk_header_path is not None: + os.environ["CUT_CELLS_VTK_HEADER"] = str(args.vtk_header_path) + + emit_all_tet_like, _, _, registered_cell_types = _import_tablegen() + vtk_ref = os.environ.get("CUT_CELLS_VTK_REF", "master") + vtk_header_path = os.environ.get("CUT_CELLS_VTK_HEADER") + + cell_types = args.cell_type + if not cell_types: + cell_types = registered_cell_types() + + for cell_type in cell_types: + generate_for_cell( + cell_type, args.out, vtk_ref=vtk_ref, vtk_header_path=vtk_header_path + ) + + +if __name__ == "__main__": + main() diff --git a/third_party/THIRD_PARTY_NOTICES.md b/third_party/THIRD_PARTY_NOTICES.md new file mode 100644 index 0000000..a1849e7 --- /dev/null +++ b/third_party/THIRD_PARTY_NOTICES.md @@ -0,0 +1,10 @@ +# Third-Party Notices + +## VTK (Visualization Toolkit) + +CutCells includes *generated* clipping/cutting case tables that are derived from VTK's `vtkTableBasedClipCases.h` (TableBasedClip). + +VTK is licensed under the BSD 3-Clause License. + +- License text: `third_party/VTK-Copyright.txt` +- Upstream: https://github.com/Kitware/VTK diff --git a/third_party/VTK-Copyright.txt b/third_party/VTK-Copyright.txt new file mode 100644 index 0000000..8226ed7 --- /dev/null +++ b/third_party/VTK-Copyright.txt @@ -0,0 +1,34 @@ +/*========================================================================== + + Program: Visualization Toolkit + Module: Copyright.txt + +Copyright (c) 1993-2015 Ken Martin, Will Schroeder, Bill Lorensen +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + * Neither name of Ken Martin, Will Schroeder, or Bill Lorensen nor the names + of any contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +==========================================================================*/